Actual source code: dmplexcomputecellgeometryfem.F90
1: ! Contributed by Noem T
2: #include <petsc/finclude/petscdmplex.h>
3: module dmplexcomputecellgeometryfemmodule
4: use petscdm
5: use petscdmplex
6: implicit none
8: contains
9: ! Quadrature points in a quadrilateral in [-1,+1]
10: pure function Gauss_rs(n)
11: PetscInt, intent(in) :: n
12: PetscReal :: Gauss_rs(2)
14: PetscReal, parameter :: p = 1.0/sqrt(3.0)
16: select case (n)
17: case (1)
18: Gauss_rs = [-p, -p]
19: case (2)
20: Gauss_rs = [-p, +p]
21: case (3)
22: Gauss_rs = [+p, -p]
23: case (4)
24: Gauss_rs = [+p, +p]
25: end select
26: end function Gauss_rs
28: ! Mapped quadrature points
29: pure function quad_v(rs)
30: PetscReal, intent(in) :: rs(2)
31: PetscReal :: quad_v(2)
33: PetscReal :: r, s
35: r = rs(1)
36: s = rs(2)
37: quad_v(1) = -0.5*r*(s - 5) ! sum N_i * x_i
38: quad_v(2) = 0.5*(r + 5*s + 2) ! sum N_i * y_i
39: end function quad_v
41: ! Jacobian
42: pure function quad_J(rs)
43: PetscReal, intent(in) :: rs(2)
44: PetscReal :: quad_J(4)
46: PetscReal :: r, s
48: r = rs(1)
49: s = rs(2)
50: quad_J = [-0.5*(s - 5), -0.5*r, .5_PETSC_REAL_KIND, 2.5_PETSC_REAL_KIND]
51: end function quad_J
52: end module dmplexcomputecellgeometryfemmodule
54: program test
55: use petscdm
56: use petscdmplex
57: use dmplexcomputecellgeometryfemmodule
59: implicit none
60: DM :: dm
61: PetscInt, parameter :: numCells = 1
62: PetscInt :: cStart
63: PetscErrorCode :: ierr
64: PetscInt, parameter :: numDim = 2
65: PetscReal, parameter :: eps = 5.0*epsilon(1.0)
66: PetscQuadrature :: q
67: PetscInt :: i
69: PetscCallA(PetscInitialize(ierr))
71: triangle: block
72: !
73: ! Single triangle element
74: ! Corner coordinates (1, 1), (5, 5), (3, 6)
75: ! Using a 3-point quadrature rule
76: !
77: PetscInt, parameter :: numVertices = 3, numCorners = 3
79: ! Number of quadrature points
80: PetscInt, parameter :: tria_qpts = 3
81: ! Quadrature order
82: PetscInt, parameter :: tria_qorder = 2
83: ! Mapped quadrature points
84: PetscReal, parameter :: tria_v(tria_qpts*numDim) = [2.0, 2.5, 3.0, 5.0, 4.0, 4.5]
85: ! Jacobian (constant, repeated tria_qpts times)
86: PetscReal, parameter :: tria_J(tria_qpts*numDim**2) = [([2.0, 1.0, 2.0, 2.5], i=1, tria_qpts)]
88: PetscReal :: J(tria_qpts*numDim**2), invJ(tria_qpts*numDim**2), v(tria_qpts*numDim), detJ(tria_qpts)
89: PetscReal, parameter :: vertexCoords(6) = [1.0, 1.0, 5.0, 5.0, 3.0, 6.0]
90: PetscInt, parameter :: cells(3) = [0, 1, 2]
92: PetscCallA(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, numDim, numCells, numVertices, numCorners, PETSC_FALSE, cells, numDim, vertexCoords, dm, ierr))
93: PetscCallA(PetscDTSimplexQuadrature(numDim, tria_qorder, PETSCDTSIMPLEXQUAD_DEFAULT, q, ierr))
94: PetscCallA(DMPlexGetHeightStratum(dm, 0_PETSC_INT_KIND, cStart, PETSC_NULL_INTEGER, ierr))
95: PetscCallA(DMPlexComputeCellGeometryFEM(dm, cStart, q, v, J, invJ, detJ, ierr))
96: PetscCheckA(all(abs(v - tria_v) < eps), PETSC_COMM_WORLD, PETSC_ERR_PLIB, 'Wrong mapped quadrature points (triangle)')
97: PetscCheckA(all(abs(J - tria_J) < eps), PETSC_COMM_WORLD, PETSC_ERR_PLIB, 'Wrong jacobian (triangle)')
98: PetscCallA(PetscQuadratureDestroy(q, ierr))
99: PetscCallA(DMDestroy(dm, ierr))
100: end block triangle
102: quadrilateral: block
103: !
104: ! Single quadrilateral element
105: ! Corner coordinates (-3, -2), (3, -1), (2, 4), (-2, 3)
106: ! Using a 4-point (2x2) Gauss quadrature rule
107: !
108: PetscInt, parameter :: numVertices = 4, numCorners = 4
110: ! Number of quadrature points
111: PetscInt, parameter :: quad_qpts = 4
113: PetscReal :: J(quad_qpts*numDim**2), invJ(quad_qpts*numDim**2), v(quad_qpts*numDim), detJ(quad_qpts)
114: PetscReal, parameter :: vertexCoords(8) = [-3.0, -2.0, 3.0, -1.0, 2.0, 4.0, -2.0, 3.0]
115: PetscInt, parameter :: cells(4) = [0, 1, 2, 3]
116: PetscReal, parameter :: a = -1.0, b = 1.0
117: PetscInt, parameter :: nc = 1, npoints = 2
119: PetscCallA(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, numDim, numCells, numVertices, numCorners, PETSC_FALSE, cells, numDim, vertexCoords, dm, ierr))
120: PetscCallA(PetscDTGaussTensorQuadrature(numDim, nc, npoints, a, b, q, ierr))
121: PetscCallA(DMPlexGetHeightStratum(dm, 0_PETSC_INT_KIND, cStart, PETSC_NULL_INTEGER, ierr))
122: PetscCallA(DMPlexComputeCellGeometryFEM(dm, cStart, q, v, J, invJ, detJ, ierr))
123: do i = 1, quad_qpts
124: PetscCheckA(all(abs(v((i - 1)*numDim + 1:i*numDim) - quad_v(Gauss_rs(i))) < eps), PETSC_COMM_WORLD, PETSC_ERR_PLIB, 'Wrong mapped quadrature points (quadrilateral)')
125: PetscCheckA(all(abs(J((i - 1)*numDim**2 + 1:i*numDim**2) - quad_J(Gauss_rs(i))) < eps), PETSC_COMM_WORLD, PETSC_ERR_PLIB, 'Wrong jacobian (quadrilateral)')
126: end do
127: PetscCallA(PetscQuadratureDestroy(q, ierr))
128: PetscCallA(DMDestroy(dm, ierr))
129: end block quadrilateral
130: PetscCallA(PetscFinalize(ierr))
132: end program test
134: ! /*TEST
135: !
136: ! test:
137: ! output_file: output/empty.out
138: !
139: ! TEST*/