xref: /petsc/src/dm/impls/plex/tests/dmplexcomputecellgeometryfem.F90 (revision 9b88ac225e01f016352a5f4cd90e158abe5f5675)
1243b716aSBarry Smith!     Contributed by Noem T
2243b716aSBarry Smith#include <petsc/finclude/petscdmplex.h>
3c5e229c2SMartin Diehlprogram test
4*02c639afSMartin Diehl  use petscdm
5*02c639afSMartin Diehl  use petscdmplex
6243b716aSBarry Smith  implicit none
7243b716aSBarry Smith  DM       :: dm
8243b716aSBarry Smith  PetscInt :: numCells = 1
9243b716aSBarry Smith  PetscInt :: cStart
10243b716aSBarry Smith  PetscInt :: numVertices = 3, numCorners = 3
11243b716aSBarry Smith  PetscErrorCode :: ierr
12243b716aSBarry Smith  PetscInt, parameter :: numDim = 2
13243b716aSBarry Smith  PetscReal, parameter :: eps = 5.0*epsilon(1.0)
14243b716aSBarry Smith  PetscCallA(PetscInitialize(ierr))
15243b716aSBarry Smith  triangle: block
16243b716aSBarry Smith
17243b716aSBarry Smith!
18243b716aSBarry Smith! Single triangle element
19243b716aSBarry Smith! Corner coordinates (1, 1), (5, 5), (3, 6)
20243b716aSBarry Smith! Using a 3-point quadrature rule
21243b716aSBarry Smith!
22243b716aSBarry Smith    PetscInt :: i
23243b716aSBarry Smith    PetscInt :: zero = 0
24243b716aSBarry Smith
25243b716aSBarry Smith! Number of quadrature points
26243b716aSBarry Smith    PetscInt, parameter :: tria_qpts = 3
27243b716aSBarry Smith! Quadrature order
28243b716aSBarry Smith    PetscInt, parameter :: tria_qorder = 2
29243b716aSBarry Smith! Mapped quadrature points
30243b716aSBarry Smith    PetscReal, parameter :: tria_v(tria_qpts*numDim) = [2.0, 2.5, 3.0, 5.0, 4.0, 4.5]
31243b716aSBarry Smith! Jacobian (constant, repeated tria_qpts times)
32243b716aSBarry Smith    PetscReal, parameter :: tria_J(tria_qpts*numDim**2) = [([2.0, 1.0, 2.0, 2.5], i=1, tria_qpts)]
33243b716aSBarry Smith
34243b716aSBarry Smith    PetscQuadrature :: q
35243b716aSBarry Smith    PetscReal :: J(tria_qpts*numDim**2), invJ(tria_qpts*numDim**2), v(tria_qpts*numDim), detJ(tria_qpts)
36243b716aSBarry Smith    PetscReal :: vertexCoords(6) = 1.0*[1.0, 1.0, 5.0, 5.0, 3.0, 6.0]
37243b716aSBarry Smith    PetscInt  :: cells(3) = [0, 1, 2]
38243b716aSBarry Smith
39243b716aSBarry Smith    PetscCallA(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, numDim, numCells, numVertices, numCorners, PETSC_FALSE, cells, numDim, vertexCoords, dm, ierr))
40243b716aSBarry Smith    PetscCallA(PetscDTSimplexQuadrature(numDim, tria_qorder, PETSCDTSIMPLEXQUAD_DEFAULT, q, ierr))
41243b716aSBarry Smith    PetscCallA(DMPlexGetHeightStratum(dm, zero, cStart, PETSC_NULL_INTEGER, ierr))
42243b716aSBarry Smith    PetscCallA(DMPlexComputeCellGeometryFEM(dm, cStart, q, v, J, invJ, detJ, ierr))
43243b716aSBarry Smith    PetscCheckA(all(abs(v - tria_v) < eps), PETSC_COMM_WORLD, PETSC_ERR_PLIB, 'Wrong mapped quadrature points (triangle)')
44243b716aSBarry Smith    PetscCheckA(all(abs(J - tria_J) < eps), PETSC_COMM_WORLD, PETSC_ERR_PLIB, 'Wrong jacobian (triangle)')
45243b716aSBarry Smith    PetscCallA(PetscQuadratureDestroy(q, ierr))
46243b716aSBarry Smith    PetscCallA(DMDestroy(dm, ierr))
47243b716aSBarry Smith  end block triangle
48243b716aSBarry Smith
49243b716aSBarry Smith  quadrilateral: block
50243b716aSBarry Smith
51243b716aSBarry Smith!
52243b716aSBarry Smith! Single quadrilateral element
53243b716aSBarry Smith! Corner coordinates (-3, -2), (3, -1), (2, 4), (-2, 3)
54243b716aSBarry Smith! Using a 4-point (2x2) Gauss quadrature rule
55243b716aSBarry Smith!
56243b716aSBarry Smith
57243b716aSBarry Smith! Number of quadrature points
58243b716aSBarry Smith    PetscInt, parameter :: quad_qpts = 4
59243b716aSBarry Smith
60243b716aSBarry Smith    PetscQuadrature :: q
61243b716aSBarry Smith    PetscReal :: vertexCoords(8) = [-3.0, -2.0, 3.0, -1.0, 2.0, 4.0, -2.0, 3.0]
62243b716aSBarry Smith    PetscReal :: J(quad_qpts*numDim**2), invJ(quad_qpts*numDim**2), v(quad_qpts*numDim), detJ(quad_qpts)
63243b716aSBarry Smith    PetscReal :: a = -1.0, b = 1.0
64243b716aSBarry Smith    PetscInt  :: cells(4) = [0, 1, 2, 3]
65243b716aSBarry Smith    PetscInt  :: nc = 1, npoints = 2
66243b716aSBarry Smith    PetscInt  :: k
67243b716aSBarry Smith    PetscInt :: zero = 0
68243b716aSBarry Smith
69243b716aSBarry Smith    numCells = 1
70243b716aSBarry Smith    numCorners = 4
71243b716aSBarry Smith    numVertices = 4
72243b716aSBarry Smith
73243b716aSBarry Smith    PetscCallA(DMPlexCreateFromCellListPetsc(PETSC_COMM_WORLD, numDim, numCells, numVertices, numCorners, PETSC_FALSE, cells, numDim, vertexCoords, dm, ierr))
74243b716aSBarry Smith    PetscCallA(PetscDTGaussTensorQuadrature(numDim, nc, npoints, a, b, q, ierr))
75243b716aSBarry Smith    PetscCallA(DMPlexGetHeightStratum(dm, zero, cStart, PETSC_NULL_INTEGER, ierr))
76243b716aSBarry Smith    PetscCallA(DMPlexComputeCellGeometryFEM(dm, cStart, q, v, J, invJ, detJ, ierr))
77243b716aSBarry Smith    do k = 1, quad_qpts
78243b716aSBarry Smith      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)')
79243b716aSBarry Smith      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)')
80243b716aSBarry Smith    end do
81243b716aSBarry Smith    PetscCallA(PetscQuadratureDestroy(q, ierr))
82243b716aSBarry Smith    PetscCallA(DMDestroy(dm, ierr))
83243b716aSBarry Smith  end block quadrilateral
84243b716aSBarry Smith  PetscCallA(PetscFinalize(ierr))
85243b716aSBarry Smith
86243b716aSBarry Smithcontains
87243b716aSBarry Smith! Quadrature points in a quadrilateral in [-1,+1]
88243b716aSBarry Smith  function Gauss_rs(n)
89243b716aSBarry Smith    PetscInt, intent(in) :: n
90243b716aSBarry Smith    PetscReal :: Gauss_rs(2)
91243b716aSBarry Smith
92243b716aSBarry Smith    PetscReal, parameter :: p = 1.0/sqrt(3.0)
93243b716aSBarry Smith
94243b716aSBarry Smith    select case (n)
95243b716aSBarry Smith    case (1)
96243b716aSBarry Smith      Gauss_rs = [-p, -p]
97243b716aSBarry Smith    case (2)
98243b716aSBarry Smith      Gauss_rs = [-p, +p]
99243b716aSBarry Smith    case (3)
100243b716aSBarry Smith      Gauss_rs = [+p, -p]
101243b716aSBarry Smith    case (4)
102243b716aSBarry Smith      Gauss_rs = [+p, +p]
103243b716aSBarry Smith    end select
104243b716aSBarry Smith  end function Gauss_rs
105243b716aSBarry Smith! Mapped quadrature points
106243b716aSBarry Smith  function quad_v(rs)
107243b716aSBarry Smith    PetscReal, intent(in) :: rs(2)
108243b716aSBarry Smith    PetscReal :: quad_v(2)
109243b716aSBarry Smith
110243b716aSBarry Smith    PetscReal :: r, s
111243b716aSBarry Smith
112243b716aSBarry Smith    r = rs(1)
113243b716aSBarry Smith    s = rs(2)
114243b716aSBarry Smith    quad_v(1) = -0.5*r*(s - 5)       ! sum N_i * x_i
115243b716aSBarry Smith    quad_v(2) = 0.5*(r + 5*s + 2)      ! sum N_i * y_i
116243b716aSBarry Smith
117243b716aSBarry Smith  end function quad_v
118243b716aSBarry Smith! Jacobian
119243b716aSBarry Smith  function quad_J(rs)
120243b716aSBarry Smith    PetscReal, intent(in) :: rs(2)
121243b716aSBarry Smith    PetscReal :: quad_J(4)
122243b716aSBarry Smith
123243b716aSBarry Smith    PetscReal :: r, s
124243b716aSBarry Smith    PetscReal :: pfive = .5, twopfive = 2.5
125243b716aSBarry Smith
126243b716aSBarry Smith    r = rs(1)
127243b716aSBarry Smith    s = rs(2)
128243b716aSBarry Smith    quad_J = [-0.5*(s - 5), -0.5*r, pfive, twopfive]
129243b716aSBarry Smith  end function quad_J
130243b716aSBarry Smithend program test
131243b716aSBarry Smith
132243b716aSBarry Smith! /*TEST
133243b716aSBarry Smith!
134243b716aSBarry Smith! test:
135e0008caeSPierre Jolivet!   output_file: output/empty.out
136243b716aSBarry Smith!
137243b716aSBarry Smith! TEST*/
138