!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