307 lines
10 KiB
Fortran
307 lines
10 KiB
Fortran
!Contains information about output
|
|
MODULE moduleOutput
|
|
! Path and folder for the output
|
|
CHARACTER(:), ALLOCATABLE:: path
|
|
CHARACTER(:), ALLOCATABLE:: folder
|
|
! Number of digits for step files
|
|
INTEGER:: iterationDigits
|
|
CHARACTER(:), ALLOCATABLE:: iterationFormat
|
|
! Triggers and counters for output
|
|
INTEGER:: triggerOutput, counterOutput = 0
|
|
INTEGER:: triggerCPUTime, counterCPUTime = 0
|
|
! logicals to activate file output
|
|
LOGICAL:: timeOutput = .FALSE.
|
|
LOGICAL:: collOutput = .FALSE.
|
|
LOGICAL:: emOutput = .FALSE.
|
|
logical:: boundaryParticleOutput = .false.
|
|
|
|
! Prefix for iteration files
|
|
character(len=*), parameter:: prefix = 'Step'
|
|
|
|
! Column separator
|
|
character(len=*), parameter:: colSep = '","'
|
|
|
|
! General format for file outputs
|
|
character(len=*), parameter:: fmtColReal = 'ES0.6E3,:,'//colSep ! Column with real
|
|
character(len=*), parameter:: fmtColInt = 'I0,:,'//colSep ! Column with integer
|
|
character(len=*), parameter:: fmtColStr = 'A,:,'//colSep ! Column with text
|
|
character(len=*), parameter:: fmtReal = 'ES14.6E3' ! Fixed size real
|
|
character(len=*), parameter:: fmtInt = 'I14' ! Fixed size real
|
|
|
|
! File IDs for different input/output
|
|
integer, parameter:: fileID_mesh = 10 ! Base id for mesh files
|
|
integer, parameter:: fileID_output = 20 ! Base id for species/collisions/EM output
|
|
integer, parameter:: fileID_boundaryParticle = 30 ! Particle boundaries
|
|
integer, parameter:: fileID_boundaryEM = 31 ! EM boundaries
|
|
integer, parameter:: fileID_reference = 40 ! Reference values
|
|
integer, parameter:: fileID_time =50 ! Computation time
|
|
|
|
!Output for each node
|
|
TYPE, PUBLIC:: outputNode
|
|
REAL(8):: den = 0.D0, mom(1:3) = 0.D0, tensorS(1:3,1:3) = 0.D0
|
|
CONTAINS
|
|
PROCEDURE, PASS(self), PRIVATE:: outputNode_equal_outputNode
|
|
PROCEDURE, PASS(self), PRIVATE:: outputNode_equal_real
|
|
PROCEDURE, PASS(self), PRIVATE:: outputNode_add_outputNode
|
|
PROCEDURE, PASS(self), PRIVATE:: outputNode_sub_outputNode
|
|
PROCEDURE, PASS(self), PRIVATE:: outputNode_mul_outputNode
|
|
PROCEDURE, PASS(self), PRIVATE:: outputNode_div_int
|
|
GENERIC, PUBLIC :: ASSIGNMENT(=) => outputNode_equal_outputNode, outputNode_equal_real
|
|
GENERIC, PUBLIC :: OPERATOR(+) => outputNode_add_outputNode
|
|
GENERIC, PUBLIC :: OPERATOR(-) => outputNode_sub_outputNode
|
|
GENERIC, PUBLIC :: OPERATOR(*) => outputNode_mul_outputNode
|
|
GENERIC, PUBLIC :: OPERATOR(/) => outputNode_div_int
|
|
|
|
END TYPE
|
|
|
|
!Type for EM data in node
|
|
TYPE emNode
|
|
REAL(8):: phi
|
|
REAL(8):: B(1:3)
|
|
|
|
END TYPE emNode
|
|
|
|
!Output in dimensional units to print
|
|
TYPE outputFormat
|
|
REAL(8):: density, velocity(1:3), pressure, temperature
|
|
|
|
END TYPE
|
|
|
|
CONTAINS
|
|
PURE FUNCTION formatFileName(pref, suff, extension, timeStep) RESULT(fileName)
|
|
IMPLICIT NONE
|
|
|
|
CHARACTER(*), INTENT(in):: pref, suff, extension
|
|
INTEGER, INTENT(in), OPTIONAL:: timeStep
|
|
CHARACTER (LEN=iterationDigits):: tString
|
|
CHARACTER(:), ALLOCATABLE:: fileName
|
|
|
|
IF (PRESENT(timeStep)) THEN
|
|
WRITE(tString, iterationFormat) timeStep
|
|
fileName = pref // '_' // tString // '_' // suff // '.' // extension
|
|
|
|
ELSE
|
|
fileName = pref // '_' // suff // '.' // extension
|
|
|
|
END IF
|
|
|
|
END FUNCTION formatFileName
|
|
|
|
subroutine createOutputFolder()
|
|
implicit none
|
|
|
|
call execute_command_line('mkdir ' // path // folder )
|
|
|
|
end subroutine createOutputFolder
|
|
|
|
subroutine copyFileToOutput(fileName)
|
|
implicit none
|
|
|
|
character(*), intent(in):: fileName
|
|
|
|
call execute_command_line('cp ' // fileName // ' ' // path // folder)
|
|
|
|
end subroutine copyFileToOutput
|
|
|
|
subroutine writeCommit()
|
|
implicit none
|
|
|
|
call system('git rev-parse HEAD > ' // path // folder // '/' // 'fpakc_commit.txt')
|
|
|
|
end subroutine writeCommit
|
|
|
|
pure function generateFilePath(filename) result(completePath)
|
|
implicit none
|
|
|
|
character(*), intent(in):: fileName
|
|
character(:), allocatable:: completePath
|
|
|
|
completePath = path // folder // '/' // fileName
|
|
|
|
end function generateFilePath
|
|
|
|
subroutine informFileCreation(filename)
|
|
implicit none
|
|
|
|
character(*), intent(in):: fileName
|
|
|
|
write(*, "(6X,A15,A)") "Creating file: ", fileName
|
|
|
|
end subroutine informFileCreation
|
|
|
|
PURE SUBROUTINE outputNode_equal_outputNode(self, from)
|
|
IMPLICIT NONE
|
|
|
|
CLASS(outputNode), INTENT(inout):: self
|
|
CLASS(outputNode), INTENT(in):: from
|
|
|
|
self%den = from%den
|
|
self%mom = from%mom
|
|
self%tensorS = from%tensorS
|
|
|
|
END SUBROUTINE outputNode_equal_outputNode
|
|
|
|
PURE ELEMENTAL SUBROUTINE outputNode_equal_real(self, from)
|
|
IMPLICIT NONE
|
|
|
|
CLASS(outputNode), INTENT(inout):: self
|
|
REAL(8), INTENT(in):: from
|
|
|
|
self%den = from
|
|
self%mom = from
|
|
self%tensorS = from
|
|
|
|
END SUBROUTINE outputNode_equal_real
|
|
|
|
PURE ELEMENTAL FUNCTION outputNode_add_outputNode(self, that) RESULT(total)
|
|
IMPLICIT NONE
|
|
|
|
CLASS(outputNode), INTENT(in):: self
|
|
CLASS(outputNode), INTENT(in):: that
|
|
TYPE(outputNode):: total
|
|
|
|
total%den = self%den + that%den
|
|
total%mom = self%mom + that%mom
|
|
total%tensorS = self%tensorS + that%tensorS
|
|
|
|
END FUNCTION outputNode_add_outputNode
|
|
|
|
PURE ELEMENTAL FUNCTION outputNode_sub_outputNode(self, that) RESULT(total)
|
|
IMPLICIT NONE
|
|
|
|
CLASS(outputNode), INTENT(in):: self
|
|
CLASS(outputNode), INTENT(in):: that
|
|
TYPE(outputNode):: total
|
|
|
|
total%den = self%den - that%den
|
|
total%mom = self%mom - that%mom
|
|
total%tensorS = self%tensorS - that%tensorS
|
|
|
|
END FUNCTION outputNode_sub_outputNode
|
|
|
|
PURE ELEMENTAL FUNCTION outputNode_mul_outputNode(self, that) RESULT(total)
|
|
IMPLICIT NONE
|
|
|
|
CLASS(outputNode), INTENT(in):: self
|
|
CLASS(outputNode), INTENT(in):: that
|
|
TYPE(outputNode):: total
|
|
|
|
total%den = self%den * that%den
|
|
total%mom = self%mom * that%mom
|
|
total%tensorS = self%tensorS * that%tensorS
|
|
|
|
END FUNCTION outputNode_mul_outputNode
|
|
|
|
PURE ELEMENTAL FUNCTION outputNode_div_int(self, that) RESULT(total)
|
|
IMPLICIT NONE
|
|
|
|
CLASS(outputNode), INTENT(in):: self
|
|
INTEGER, INTENT(in):: that
|
|
TYPE(outputNode):: total
|
|
|
|
total%den = self%den / REAL(that)
|
|
total%mom = self%mom / REAL(that)
|
|
total%tensorS = self%tensorS / REAL(that)
|
|
|
|
END FUNCTION outputNode_div_int
|
|
|
|
SUBROUTINE calculateOutput(rawValues, formatValues, nodeVol, speciesIn)
|
|
USE moduleConstParam
|
|
USE moduleRefParam
|
|
USE moduleSpecies
|
|
USE moduleMath
|
|
IMPLICIT NONE
|
|
|
|
TYPE(outputNode), INTENT(in):: rawValues
|
|
TYPE(outputFormat), INTENT(out):: formatValues
|
|
REAL(8), INTENT(in):: nodeVol
|
|
CLASS(speciesGeneric), INTENT(in):: speciesIn
|
|
REAL(8), DIMENSION(1:3,1:3):: tensorTemp
|
|
REAL(8), DIMENSION(1:3):: tempVel
|
|
REAL(8):: tempVol
|
|
|
|
!Resets the node outputs
|
|
formatValues%density = 0.D0
|
|
formatValues%velocity = 0.D0
|
|
formatValues%pressure = 0.D0
|
|
formatValues%temperature = 0.D0
|
|
tempVol = 1.D0/(nodeVol*Vol_ref)
|
|
IF (rawValues%den > 0.D0) THEN
|
|
tempVel = rawValues%mom(:)/rawValues%den
|
|
tensorTemp = (rawValues%tensorS(:,:) - rawValues%den*outerProduct(tempVel,tempVel))
|
|
formatValues%density = rawValues%den*tempVol
|
|
formatValues%velocity(:) = tempVel
|
|
IF (tensorTrace(tensorTemp) > 0.D0) THEN
|
|
formatValues%pressure = speciesIn%m*tensorTrace(tensorTemp)*tempVol/3.D0
|
|
formatValues%temperature = formatValues%pressure/(formatValues%density*kb)
|
|
|
|
END IF
|
|
END IF
|
|
|
|
formatValues%velocity = formatValues%velocity*v_ref
|
|
formatValues%pressure = formatValues%pressure*m_ref*v_ref**2
|
|
formatValues%temperature = formatValues%temperature*m_ref*v_ref**2
|
|
|
|
END SUBROUTINE calculateOutput
|
|
|
|
SUBROUTINE writeTime(first)
|
|
USE moduleSpecies
|
|
USE moduleCompTime
|
|
USE moduleCaseParam, ONLY: timeStep
|
|
IMPLICIT NONE
|
|
|
|
LOGICAL, INTENT(in), OPTIONAL:: first
|
|
CHARACTER(:), ALLOCATABLE:: fileName
|
|
|
|
fileName = 'cpuTime.csv'
|
|
|
|
IF (timeOutput) THEN
|
|
IF (PRESENT(first)) THEN
|
|
IF (first) THEN
|
|
OPEN(fileID_time, file = generateFilePath(fileName), action = 'write')
|
|
WRITE(fileID_time, "(*("//fmtColStr//"))") "t","n","total (s)","push (s)","reset (s)", &
|
|
"collision (s)","coulomb (s)", &
|
|
"weighting (s)","EMField (s)"
|
|
call informFileCreation(fileName)
|
|
CLOSE(fileID_time)
|
|
|
|
END IF
|
|
|
|
END IF
|
|
|
|
OPEN(fileID_time, file = generateFilePath(fileName), position = 'append', action = 'write')
|
|
|
|
WRITE (fileID_time, "(*("//fmtColInt//"),*("//fmtColReal//"))") timeStep, nPartOld, tStep, tPush, tReset, tColl, tCoul, tWeight, tEMField
|
|
|
|
CLOSE(fileID_time)
|
|
|
|
END IF
|
|
|
|
END SUBROUTINE writeTime
|
|
|
|
! Write file with reference values
|
|
subroutine writeReference()
|
|
use moduleRefParam
|
|
implicit none
|
|
|
|
open (fileID_reference, file=generateFilePath('reference.csv'))
|
|
write(fileID_reference, "(*("//fmtColStr//"))") '"L_ref (m)"', &
|
|
'"v_ref (m s^-1)"', &
|
|
'"ti_ref (s)"', &
|
|
'"Vol_ref (m^3)"', &
|
|
'"EF_ref (V m^-1)"', &
|
|
'"Volt_ref (V)"', &
|
|
'"B_ref (T)"'
|
|
write(fileID_reference, "(*("//fmtColReal//"))") L_ref, &
|
|
v_ref, &
|
|
ti_ref, &
|
|
Vol_ref, &
|
|
EF_ref, &
|
|
Volt_ref, &
|
|
B_ref
|
|
close(fileID_reference)
|
|
|
|
end subroutine writeReference
|
|
|
|
END MODULE moduleOutput
|
|
|