MODULE moduleMeshOutputGmsh2

  CONTAINS
    !Header for mesh format
    SUBROUTINE writeGmsh2HeaderMesh(fileID)
      IMPLICIT NONE

      INTEGER, INTENT(in):: fileID

      WRITE(fileID, "(A)") '$MeshFormat'
      WRITE(fileID, "(A)") '2.2 0 8'
      WRITE(fileID, "(A)") '$EndMeshFormat'

    END SUBROUTINE writeGmsh2HeaderMesh

    !Node data subroutines
    !Header
    SUBROUTINE writeGmsh2HeaderNodeData(fileID, title, iteration, time, dimensions, nNodes)
      IMPLICIT NONE

      INTEGER, INTENT(in):: fileID
      CHARACTER(*), INTENT(in):: title
      INTEGER, INTENT(in):: iteration, dimensions, nNodes
      REAL(8), INTENT(in):: time


      WRITE(fileID, "(A)") '$NodeData'
      WRITE(fileID, "(I10)") 1
      WRITE(fileID, "(A1, A, A1)") '"' , title , '"'
      WRITE(fileID, "(I10)") 1
      WRITE(fileID, "(ES20.6E3)") time
      WRITE(fileID, "(I10)") 3
      WRITE(fileID, "(I10)") iteration
      WRITE(fileID, "(I10)") dimensions
      WRITE(fileID, "(I10)") nNodes

    END SUBROUTINE writeGmsh2HeaderNodeData

    !Footer
    SUBROUTINE writeGmsh2FooterNodeData(fileID)
      IMPLICIT NONE

      INTEGER, INTENT(in):: fileID

      WRITE(fileID, "(A)") '$EndNodeData'

    END SUBROUTINE writeGmsh2FooterNodeData

    !Element data subroutines
    !Header
    SUBROUTINE writeGmsh2HeaderElementData(fileID, title, iteration, time, dimensions, nVols)
      IMPLICIT NONE

      INTEGER, INTENT(in):: fileID
      CHARACTER(*), INTENT(in):: title
      INTEGER, INTENT(in):: iteration, dimensions, nVols
      REAL(8), INTENT(in):: time


      WRITE(fileID, "(A)") '$ElementData'
      WRITE(fileID, "(I10)") 1
      WRITE(fileID, "(A1, A, A1)") '"' , title , '"'
      WRITE(fileID, "(I10)") 1
      WRITE(fileID, "(ES20.6E3)") time
      WRITE(fileID, "(I10)") 3
      WRITE(fileID, "(I10)") iteration
      WRITE(fileID, "(I10)") dimensions
      WRITE(fileID, "(I10)") nVols

    END SUBROUTINE writeGmsh2HeaderElementData

    !Footer
    SUBROUTINE writeGmsh2FooterElementData(fileID)
      IMPLICIT NONE

      INTEGER, INTENT(in):: fileID

      WRITE(fileID, "(A)") '$EndElementData'

    END SUBROUTINE writeGmsh2FooterElementData

    !Prints the scattered properties of particles into the nodes
    SUBROUTINE printOutputGmsh2(self)
      USE moduleMesh
      USE moduleRefParam
      USE moduleSpecies
      USE moduleOutput
      USE moduleMeshInoutCommon
      USE moduleCaseParam, ONLY: timeStep
      IMPLICIT NONE

      CLASS(meshParticles), INTENT(in):: self
      INTEGER:: n, i
      TYPE(outputFormat):: output(1:self%numNodes)
      REAL(8):: time
      CHARACTER(:), ALLOCATABLE:: fileName

      time = DBLE(timeStep)*tauMin*ti_ref

      DO i = 1, nSpecies
        fileName = formatFileName(prefix, species(i)%obj%name, 'msh', timeStep)
        WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
        OPEN (60, file = path // folder // '/' //  fileName)

        CALL writeGmsh2HeaderMesh(60)

        CALL writeGmsh2HeaderNodeData(60, species(i)%obj%name // ' density (m^-3)', timeStep, time, 1, self%numNodes)
        DO n=1, self%numNodes
          CALL calculateOutput(self%nodes(n)%obj%output(i), output(n), self%nodes(n)%obj%v, species(i)%obj)
          WRITE(60, "(I6,ES20.6E3)") n, output(n)%density
        END DO
        CALL writeGmsh2FooterNodeData(60)

        CALL writeGmsh2HeaderNodeData(60, species(i)%obj%name // ' velocity (m s^-1)', timeStep, time, 3, self%numNodes)
        DO n=1, self%numNodes
          WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%velocity
        END DO
        CALL writeGmsh2FooterNodeData(60)

        CALL writeGmsh2HeaderNodeData(60, species(i)%obj%name // ' Pressure (Pa)', timeStep, time, 1, self%numNodes)
        DO n=1, self%numNodes
          WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%pressure
        END DO
        CALL writeGmsh2FooterNodeData(60)

        CALL writeGmsh2HeaderNodeData(60, species(i)%obj%name // ' Temperature (K)', timeStep, time, 1, self%numNodes)
        DO n=1, self%numNodes
          WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%temperature
        END DO
        CALL writeGmsh2FooterNodeData(60)
        CLOSE (60)

      END DO

    END SUBROUTINE printOutputGmsh2

    !Prints the number of collisions into the volumes
    SUBROUTINE printCollGmsh2(self)
      USE moduleMesh
      USE moduleRefParam
      USE moduleCaseParam
      USE moduleCollisions
      USE moduleOutput
      USE moduleMeshInoutCommon
      IMPLICIT NONE

      CLASS(meshGeneric), INTENT(in):: self
      INTEGER:: numEdges
      INTEGER:: k, c
      INTEGER:: n
      REAL(8):: time
      CHARACTER(:), ALLOCATABLE:: fileName
      CHARACTER(:), ALLOCATABLE:: title
      CHARACTER (LEN=2):: cString

      SELECT TYPE(self)
      TYPE IS(meshParticles)
        numEdges = self%numEdges

      TYPE IS(meshCollisions)
        numEdges = 0

      CLASS DEFAULT
        numEdges = 0

      END SELECT

      IF (collOutput) THEN
        time = DBLE(timeStep)*tauMin*ti_ref

        fileName = formatFileName(prefix, 'Collisions', 'msh', timeStep)
        WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
        OPEN (60, file = path // folder // '/' //  fileName)

        CALL writeGmsh2HeaderMesh(60)

        DO k = 1, nCollPairs
          DO c = 1, interactionMatrix(k)%amount
            WRITE(cString, "(I2)") c
            title = '"Pair ' // interactionMatrix(k)%sp_i%name // '-' // interactionMatrix(k)%sp_j%name // ' collision ' // cString
            CALL writeGmsh2HeaderElementData(60, title, timeStep, time, 1, self%numCells)
            DO n=1, self%numCells
              WRITE(60, "(I6,I10)") n + numEdges, self%cells(n)%obj%tallyColl(k)%tally(c)
            END DO
            CALL writeGmsh2FooterElementData(60)

          END DO

        END DO

        CLOSE(60)

      END IF

    END SUBROUTINE printCollGmsh2

    !Prints the electrostatic EM properties into the nodes and volumes
    SUBROUTINE printEMGmsh2(self)
      USE moduleMesh
      USE moduleRefParam
      USE moduleCaseParam
      USE moduleOutput
      USE moduleMeshInoutCommon
      IMPLICIT NONE

      CLASS(meshParticles), INTENT(in):: self
      INTEGER:: n, e
      REAL(8):: time
      CHARACTER(:), ALLOCATABLE:: fileName
      REAL(8):: Xi(1:3)

      Xi = (/ 0.D0, 0.D0, 0.D0 /)

      IF (emOutput) THEN
        time = DBLE(timeStep)*tauMin*ti_ref

        fileName = formatFileName(prefix, 'EMField', 'msh', timeStep)
        WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
        OPEN (20, file = path // folder // '/' //  fileName)

        CALL writeGmsh2HeaderMesh(20)

        CALL writeGmsh2HeaderNodeData(20, 'Potential (V)', timeStep, time, 1, self%numNodes)
        DO n=1, self%numNodes
          WRITE(20, *) n, self%nodes(n)%obj%emData%phi*Volt_ref
        END DO
        CALL writeGmsh2FooterNodeData(20)
        
        CALL writeGmsh2HeaderElementData(20, 'Electric Field (V m^-1)', timeStep, time, 3, self%numCells)
        DO e=1, self%numCells
          WRITE(20, *) e+self%numEdges, self%cells(e)%obj%gatherElectricField(Xi)*EF_ref
        END DO
        CALL writeGmsh2FooterElementData(20)

        CALL writeGmsh2HeaderNodeData(20, 'Magnetic Field (T)', timeStep, time, 3, self%numNodes)
        DO n=1, self%numNodes
          WRITE(20, *) n, self%nodes(n)%obj%emData%B * B_ref
        END DO
        CALL writeGmsh2FooterNodeData(20)

        CLOSE(20)

      END IF

    END SUBROUTINE printEMGmsh2

    !Prints the average properties of particles into the nodes
    SUBROUTINE printAverageGmsh2(self)
      USE moduleMesh
      USE moduleRefParam
      USE moduleSpecies
      USE moduleOutput
      USE moduleAverage
      USE moduleMeshInoutCommon
      IMPLICIT NONE

      CLASS(meshParticles), INTENT(in):: self
      INTEGER:: n, i
      TYPE(outputFormat), DIMENSION(1:self%numNodes):: outputMean, outputDeviation
      CHARACTER(:), ALLOCATABLE:: fileName
      INTEGER:: fileMean=10, fileDeviation=20

      DO i = 1, nSpecies
        fileName = formatFileName('Average_mean', species(i)%obj%name, 'msh')
        WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
        OPEN (fileMean, file = path // folder // '/' //  fileName)

        fileName = formatFileName('Average_deviation', species(i)%obj%name, 'msh')
        WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
        OPEN (filedeviation, file = path // folder // '/' //  fileName)

        CALL writeGmsh2HeaderMesh(fileMean)
        CALL writeGmsh2HeaderMesh(fileDeviation)

        CALL writeGmsh2HeaderNodeData(fileMean,      species(i)%obj%name // ' density, mean (m^-3)', 0, 0.D0, 1, self%numNodes)
        CALL writeGmsh2HeaderNodeData(fileDeviation, species(i)%obj%name // ' density, sd (m^-3)', 0, 0.D0, 1, self%numNodes)
        DO n=1, self%numNodes
          CALL calculateOutput(averageScheme(n)%mean%output(i),      outputMean(n),      self%nodes(n)%obj%v, species(i)%obj)
          WRITE(fileMean,      "(I6,ES20.6E3)") n, outputMean(n)%density
          CALL calculateOutput(averageScheme(n)%deviation%output(i), outputDeviation(n), self%nodes(n)%obj%v, species(i)%obj)
          WRITE(fileDeviation, "(I6,ES20.6E3)") n, outputDeviation(n)%density
        END DO
        CALL writeGmsh2FooterNodeData(fileMean)
        CALL writeGmsh2FooterNodeData(fileDeviation)

        CALL writeGmsh2HeaderNodeData(fileMean,      species(i)%obj%name // ' velocity, mean (m s^-1)', 0, 0.D0, 3, self%numNodes)
        CALL writeGmsh2HeaderNodeData(fileDeviation, species(i)%obj%name // ' velocity, sd (m s^-1)', 0, 0.D0, 3, self%numNodes)
        DO n=1, self%numNodes
          WRITE(fileMean,      "(I6,3(ES20.6E3))") n, outputMean(n)%velocity
          WRITE(fileDeviation, "(I6,3(ES20.6E3))") n, outputDeviation(n)%velocity
        END DO
        CALL writeGmsh2FooterNodeData(fileMean)
        CALL writeGmsh2FooterNodeData(fileDeviation)

        CALL writeGmsh2HeaderNodeData(fileMean,      species(i)%obj%name // ' Pressure, mean (Pa)', 0, 0.D0, 1, self%numNodes)
        CALL writeGmsh2HeaderNodeData(fileDeviation, species(i)%obj%name // ' Pressure, sd (Pa)', 0, 0.D0, 1, self%numNodes)
        DO n=1, self%numNodes
          WRITE(fileMean,      "(I6,3(ES20.6E3))") n, outputMean(n)%pressure
          WRITE(fileDeviation, "(I6,3(ES20.6E3))") n, outputDeviation(n)%pressure
        END DO
        CALL writeGmsh2FooterNodeData(fileMean)
        CALL writeGmsh2FooterNodeData(fileDeviation)

        CALL writeGmsh2HeaderNodeData(fileMean,      species(i)%obj%name // ' Temperature, mean (K)', 0, 0.D0, 1, self%numNodes)
        CALL writeGmsh2HeaderNodeData(fileDeviation, species(i)%obj%name // ' Temperature, sd (K)', 0, 0.D0, 1, self%numNodes)
        DO n=1, self%numNodes
          WRITE(fileMean,      "(I6,3(ES20.6E3))") n, outputMean(n)%temperature
          WRITE(fileDeviation, "(I6,3(ES20.6E3))") n, outputDeviation(n)%temperature
        END DO
        CALL writeGmsh2FooterNodeData(fileMean)
        CALL writeGmsh2FooterNodeData(fileDeviation)

        CLOSE (fileMean)
        CLOSE(fileDeviation)

      END DO

    END SUBROUTINE printAverageGmsh2

END MODULE moduleMeshOutputGmsh2
