!moduleMesh1D: 0D mesh. No coordinates are relevant. No edges are used
MODULE moduleMesh0D
  USE moduleMesh
  IMPLICIT NONE

  TYPE, PUBLIC, EXTENDS(meshNode):: meshNode0D
    INTEGER:: n1
    CONTAINS
      !meshNode DEFERRED PROCEDURES
      PROCEDURE, PASS:: init           => initNode0D
      PROCEDURE, PASS:: getCoordinates => getCoord0D

  END TYPE meshNode0D

  TYPE, PUBLIC, EXTENDS(meshCell):: meshCell0D
    CLASS(meshNode), POINTER:: n1
    CONTAINS
      PROCEDURE, PASS::   init                => initCell0D
      PROCEDURE, PASS::   getNodes            => getNodes0D
      PROCEDURE, PASS::   randPos             => randPos0D
      PROCEDURE, NOPASS:: fPsi                => fPsi0D
      PROCEDURE, NOPASS:: dPsi                => dPsi0D
      PROCEDURE, PASS::   partialDer          => partialDer0D
      PROCEDURE, NOPASS:: detJac              => detJ0D
      PROCEDURE, NOPASS:: invJac              => invJ0D
      PROCEDURE, PASS::   gatherElectricField => gatherEF0D
      PROCEDURE, PASS::   gatherMagneticField => gatherMF0D
      PROCEDURE, PASS::   elemK               => elemK0D
      PROCEDURE, PASS::   elemF               => elemF0D
      PROCEDURE, PASS::   phy2log             => phy2log0D
      PROCEDURE, NOPASS:: inside              => inside0D
      PROCEDURE, PASS::   neighbourElement    => neighbourElement0D

  END TYPE meshCell0D

  CONTAINS
    !NODE FUNCTIONS
    !Init node
    SUBROUTINE initNode0D(self, n, r)
      USE moduleSpecies
      USE OMP_LIB
      IMPLICIT NONE

      CLASS(meshNode0D), INTENT(out):: self
      INTEGER, INTENT(in):: n
      REAL(8), INTENT(in):: r(1:3) ! NOTE: Required by interface but unused

      self%n = n

      ALLOCATE(self%output(1:nSpecies))

      CALL OMP_INIT_LOCK(self%lock)

    END SUBROUTINE initNode0D

    !Get node coordinates
    PURE FUNCTION getCoord0D(self) RESULT(r)
      IMPLICIT NONE

      CLASS(meshNode0D), INTENT(in):: self
      REAL(8):: r(1:3)

      r = 0.D0

    END FUNCTION

    !VOLUME FUNCTIONS
    !Inits dummy 0D volume
    SUBROUTINE initCell0D(self, n, p, nodes)
      USE moduleRefParam
      USE moduleSpecies
      IMPLICIT NONE

      CLASS(meshCell0D), INTENT(out):: self
      INTEGER, INTENT(in):: n
      INTEGER, INTENT(in):: p(:)
      TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)

      self%n = n

      self%nNodes = SIZE(p)

      self%n1 => nodes(p(1))%obj
      self%volume = 1.D0
      self%n1%v = 1.D0

      CALL OMP_INIT_LOCK(self%lock)

      ALLOCATE(self%listPart_in(1:nSpecies))
      ALLOCATE(self%totalWeight(1:nSpecies))

    END SUBROUTINE initCell0D

    !Get the nodes of the volume
    PURE FUNCTION getNodes0D(self, nNodes) RESULT(n)
      IMPLICIT NONE

      CLASS(meshCell0D), INTENT(in):: self
      INTEGER, INTENT(in):: nNodes
      INTEGER:: n(1:nNodes)

      n = self%n1%n

    END FUNCTION getNodes0D

    !Calculate random position inside the volume
    FUNCTION randPos0D(self) RESULT(r)
      IMPLICIT NONE

      CLASS(meshCell0D), INTENT(in):: self
      REAL(8):: r(1:3)

      r = 0.D0

    END FUNCTION randPos0D

    PURE FUNCTION fPsi0D(Xi, nNodes) RESULT(fPsi)
      IMPLICIT NONE

      REAL(8), INTENT(in):: Xi(1:3) ! NOTE: Required by interface but unused
      INTEGER, INTENT(in):: nNodes
      REAL(8):: fPsi(1:nNodes)

      fPsi = 1.D0

    END FUNCTION fPsi0D

    PURE FUNCTION dPsi0D(Xi, nNodes) RESULT(dPsi)
      IMPLICIT NONE

      REAL(8), INTENT(in):: Xi(1:3) ! NOTE: Required by interface but unused
      INTEGER, INTENT(in):: nNodes
      REAL(8):: dPsi(1:3,1:nNodes)

      dPsi = 0.D0

    END FUNCTION dPsi0D

    PURE FUNCTION partialDer0D(self, nNodes, dPsi) RESULT(pDer)
      IMPLICIT NONE

      CLASS(meshCell0D), INTENT(in):: self
      INTEGER, INTENT(in):: nNodes
      REAL(8), INTENT(in):: dPsi(1:3,1:nNodes)
      REAL(8):: pDer(1:3, 1:3) ! NOTE: Required by interface but unused

      pDer = 0.D0

    END FUNCTION partialDer0D

    PURE FUNCTION elemK0D(self, nNodes) RESULT(localK)
      IMPLICIT NONE

      CLASS(meshCell0D), INTENT(in):: self
      INTEGER, INTENT(in):: nNodes
      REAL(8):: localK(1:nNodes,1:nNodes)

      localK = 0.D0

    END FUNCTION elemK0D

    PURE FUNCTION elemF0D(self, nNodes, source) RESULT(localF)
      IMPLICIT NONE

      CLASS(meshCell0D), INTENT(in):: self
      INTEGER, INTENT(in):: nNodes
      REAL(8), INTENT(in):: source(1:nNodes)
      REAL(8):: localF(1:nNodes)

      localF = 0.D0

    END FUNCTION elemF0D

    PURE FUNCTION gatherEF0D(self, Xi) RESULT(array)
      IMPLICIT NONE
      CLASS(meshCell0D), INTENT(in):: self
      REAL(8), INTENT(in):: Xi(1:3)
      REAL(8):: array(1:3)
      REAL(8):: phi(1:1)

      phi = (/ self%n1%emData%phi /)

      array = -self%gatherDF(Xi, 1, phi)

    END FUNCTION gatherEF0D

    PURE FUNCTION gatherMF0D(self, Xi) RESULT(array)
      IMPLICIT NONE
      CLASS(meshCell0D), INTENT(in):: self
      REAL(8), INTENT(in):: Xi(1:3)
      REAL(8):: array(1:3)
      REAL(8):: B(1:1,1:3)

      B(:,1) = (/ self%n1%emData%B(1) /)

      B(:,2) = (/ self%n1%emData%B(2) /)

      B(:,3) = (/ self%n1%emData%B(3) /)

      array = self%gatherF(Xi, 1, B)

    END FUNCTION gatherMF0D

    PURE FUNCTION phy2log0D(self,r) RESULT(xN) 
      IMPLICIT NONE

      CLASS(meshCell0D), INTENT(in):: self
      REAL(8), INTENT(in):: r(1:3) ! NOTE: Required by interface but unused
      REAL(8):: xN(1:3)

      xN = 0.D0

    END FUNCTION phy2log0D

    PURE FUNCTION inside0D(Xi) RESULT(ins)
      IMPLICIT NONE

      REAL(8), INTENT(in):: Xi(1:3) ! NOTE: Required by interface but unused
      LOGICAL:: ins

      ins = .TRUE.

    END FUNCTION inside0D

    SUBROUTINE neighbourElement0D(self, Xi, neighbourElement)
      IMPLICIT NONE

      CLASS(meshCell0D), INTENT(in):: self
      REAL(8), INTENT(in):: Xi(1:3) ! NOTE: Required by interface but unused
      CLASS(meshElement), POINTER, INTENT(out):: neighbourElement

      neighbourElement => NULL()

    END SUBROUTINE neighbourElement0D

    !COMMON FUNCTIONS
    PURE FUNCTION detJ0D(pDer) RESULT(dJ)
      IMPLICIT NONE

      REAL(8), INTENT(in):: pDer(1:3, 1:3) ! NOTE: Required by interface but unused
      REAL(8):: dJ

      dJ = 0.D0

    END FUNCTION detJ0D

    PURE FUNCTION invJ0D(pDer) RESULT(invJ)
      IMPLICIT NONE

      REAL(8), INTENT(in):: pDer(1:3, 1:3) ! NOTE: Required by interface but unused
      REAL(8):: invJ(1:3,1:3)

      invJ = 0.D0

    END FUNCTION invJ0D

END MODULE moduleMesh0D
