Actual source code: dmplexcomputecellgeometryfem.F90

  1: !     Contributed by Noem T
  2: #include <petsc/finclude/petscdmplex.h>
  3: program test
  4:   use petscdm
  5:   use petscdmplex
  6:   implicit none
  7:   DM       :: dm
  8:   PetscInt :: numCells = 1
  9:   PetscInt :: cStart
 10:   PetscInt :: numVertices = 3, numCorners = 3
 11:   PetscErrorCode :: ierr
 12:   PetscInt, parameter :: numDim = 2
 13:   PetscReal, parameter :: eps = 5.0*epsilon(1.0)
 14:   PetscCallA(PetscInitialize(ierr))
 15:   triangle: block

 17: !
 18: ! Single triangle element
 19: ! Corner coordinates (1, 1), (5, 5), (3, 6)
 20: ! Using a 3-point quadrature rule
 21: !
 22:     PetscInt :: i
 23:     PetscInt :: zero = 0

 25: ! Number of quadrature points
 26:     PetscInt, parameter :: tria_qpts = 3
 27: ! Quadrature order
 28:     PetscInt, parameter :: tria_qorder = 2
 29: ! Mapped quadrature points
 30:     PetscReal, parameter :: tria_v(tria_qpts*numDim) = [2.0, 2.5, 3.0, 5.0, 4.0, 4.5]
 31: ! Jacobian (constant, repeated tria_qpts times)
 32:     PetscReal, parameter :: tria_J(tria_qpts*numDim**2) = [([2.0, 1.0, 2.0, 2.5], i=1, tria_qpts)]

 34:     PetscQuadrature :: q
 35:     PetscReal :: J(tria_qpts*numDim**2), invJ(tria_qpts*numDim**2), v(tria_qpts*numDim), detJ(tria_qpts)
 36:     PetscReal :: vertexCoords(6) = 1.0*[1.0, 1.0, 5.0, 5.0, 3.0, 6.0]
 37:     PetscInt  :: cells(3) = [0, 1, 2]

 39:     PetscCallA(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, numDim, numCells, numVertices, numCorners, PETSC_FALSE, cells, numDim, vertexCoords, dm, ierr))
 40:     PetscCallA(PetscDTSimplexQuadrature(numDim, tria_qorder, PETSCDTSIMPLEXQUAD_DEFAULT, q, ierr))
 41:     PetscCallA(DMPlexGetHeightStratum(dm, zero, cStart, PETSC_NULL_INTEGER, ierr))
 42:     PetscCallA(DMPlexComputeCellGeometryFEM(dm, cStart, q, v, J, invJ, detJ, ierr))
 43:     PetscCheckA(all(abs(v - tria_v) < eps), PETSC_COMM_WORLD, PETSC_ERR_PLIB, 'Wrong mapped quadrature points (triangle)')
 44:     PetscCheckA(all(abs(J - tria_J) < eps), PETSC_COMM_WORLD, PETSC_ERR_PLIB, 'Wrong jacobian (triangle)')
 45:     PetscCallA(PetscQuadratureDestroy(q, ierr))
 46:     PetscCallA(DMDestroy(dm, ierr))
 47:   end block triangle

 49:   quadrilateral: block

 51: !
 52: ! Single quadrilateral element
 53: ! Corner coordinates (-3, -2), (3, -1), (2, 4), (-2, 3)
 54: ! Using a 4-point (2x2) Gauss quadrature rule
 55: !

 57: ! Number of quadrature points
 58:     PetscInt, parameter :: quad_qpts = 4

 60:     PetscQuadrature :: q
 61:     PetscReal :: vertexCoords(8) = [-3.0, -2.0, 3.0, -1.0, 2.0, 4.0, -2.0, 3.0]
 62:     PetscReal :: J(quad_qpts*numDim**2), invJ(quad_qpts*numDim**2), v(quad_qpts*numDim), detJ(quad_qpts)
 63:     PetscReal :: a = -1.0, b = 1.0
 64:     PetscInt  :: cells(4) = [0, 1, 2, 3]
 65:     PetscInt  :: nc = 1, npoints = 2
 66:     PetscInt  :: k
 67:     PetscInt :: zero = 0

 69:     numCells = 1
 70:     numCorners = 4
 71:     numVertices = 4

 73:     PetscCallA(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, numDim, numCells, numVertices, numCorners, PETSC_FALSE, cells, numDim, vertexCoords, dm, ierr))
 74:     PetscCallA(PetscDTGaussTensorQuadrature(numDim, nc, npoints, a, b, q, ierr))
 75:     PetscCallA(DMPlexGetHeightStratum(dm, zero, cStart, PETSC_NULL_INTEGER, ierr))
 76:     PetscCallA(DMPlexComputeCellGeometryFEM(dm, cStart, q, v, J, invJ, detJ, ierr))
 77:     do k = 1, quad_qpts
 78:       PetscCheckA(all(abs(v((k - 1)*numDim + 1:k*numDim) - quad_v(Gauss_rs(k))) < eps), PETSC_COMM_WORLD, PETSC_ERR_PLIB, 'Wrong mapped quadrature points (quadrilateral)')
 79:       PetscCheckA(all(abs(J((k - 1)*numDim**2 + 1:k*numDim**2) - quad_J(Gauss_rs(k))) < eps), PETSC_COMM_WORLD, PETSC_ERR_PLIB, 'Wrong jacobian (quadrilateral)')
 80:     end do
 81:     PetscCallA(PetscQuadratureDestroy(q, ierr))
 82:     PetscCallA(DMDestroy(dm, ierr))
 83:   end block quadrilateral
 84:   PetscCallA(PetscFinalize(ierr))

 86: contains
 87: ! Quadrature points in a quadrilateral in [-1,+1]
 88:   function Gauss_rs(n)
 89:     PetscInt, intent(in) :: n
 90:     PetscReal :: Gauss_rs(2)

 92:     PetscReal, parameter :: p = 1.0/sqrt(3.0)

 94:     select case (n)
 95:     case (1)
 96:       Gauss_rs = [-p, -p]
 97:     case (2)
 98:       Gauss_rs = [-p, +p]
 99:     case (3)
100:       Gauss_rs = [+p, -p]
101:     case (4)
102:       Gauss_rs = [+p, +p]
103:     end select
104:   end function Gauss_rs
105: ! Mapped quadrature points
106:   function quad_v(rs)
107:     PetscReal, intent(in) :: rs(2)
108:     PetscReal :: quad_v(2)

110:     PetscReal :: r, s

112:     r = rs(1)
113:     s = rs(2)
114:     quad_v(1) = -0.5*r*(s - 5)       ! sum N_i * x_i
115:     quad_v(2) = 0.5*(r + 5*s + 2)      ! sum N_i * y_i

117:   end function quad_v
118: ! Jacobian
119:   function quad_J(rs)
120:     PetscReal, intent(in) :: rs(2)
121:     PetscReal :: quad_J(4)

123:     PetscReal :: r, s
124:     PetscReal :: pfive = .5, twopfive = 2.5

126:     r = rs(1)
127:     s = rs(2)
128:     quad_J = [-0.5*(s - 5), -0.5*r, pfive, twopfive]
129:   end function quad_J
130: end program test

132: ! /*TEST
133: !
134: ! test:
135: !   output_file: output/empty.out
136: !
137: ! TEST*/