xref: /libCEED/examples/solids/src/matops.c (revision 6a6c615b31508fbb9571bc7a279f860841ca2097)
1ccaff030SJeremy L Thompson // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2ccaff030SJeremy L Thompson // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3ccaff030SJeremy L Thompson // reserved. See files LICENSE and NOTICE for details.
4ccaff030SJeremy L Thompson //
5ccaff030SJeremy L Thompson // This file is part of CEED, a collection of benchmarks, miniapps, software
6ccaff030SJeremy L Thompson // libraries and APIs for efficient high-order finite element and spectral
7ccaff030SJeremy L Thompson // element discretizations for exascale applications. For more information and
8ccaff030SJeremy L Thompson // source code availability see http://github.com/ceed.
9ccaff030SJeremy L Thompson //
10ccaff030SJeremy L Thompson // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11ccaff030SJeremy L Thompson // a collaborative effort of two U.S. Department of Energy organizations (Office
12ccaff030SJeremy L Thompson // of Science and the National Nuclear Security Administration) responsible for
13ccaff030SJeremy L Thompson // the planning and preparation of a capable exascale ecosystem, including
14ccaff030SJeremy L Thompson // software, applications, hardware, advanced system engineering and early
15ccaff030SJeremy L Thompson // testbed platforms, in support of the nation's exascale computing imperative.
16ccaff030SJeremy L Thompson 
17ccaff030SJeremy L Thompson /// @file
18ccaff030SJeremy L Thompson /// Matrix shell operations for solid mechanics example using PETSc
19ccaff030SJeremy L Thompson 
20ccaff030SJeremy L Thompson #include "../elasticity.h"
21ccaff030SJeremy L Thompson 
22ccaff030SJeremy L Thompson // -----------------------------------------------------------------------------
23ccaff030SJeremy L Thompson // libCEED Operators for MatShell
24ccaff030SJeremy L Thompson // -----------------------------------------------------------------------------
25ccaff030SJeremy L Thompson // This function uses libCEED to compute the local action of an operator
26ccaff030SJeremy L Thompson PetscErrorCode ApplyLocalCeedOp(Vec X, Vec Y, UserMult user) {
27ccaff030SJeremy L Thompson   PetscErrorCode ierr;
28ccaff030SJeremy L Thompson   PetscScalar *x, *y;
29ccaff030SJeremy L Thompson 
30ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
31ccaff030SJeremy L Thompson 
32ccaff030SJeremy L Thompson   // Global-to-local
33ccaff030SJeremy L Thompson   ierr = DMGlobalToLocal(user->dm, X, INSERT_VALUES, user->Xloc); CHKERRQ(ierr);
34ccaff030SJeremy L Thompson   ierr = VecZeroEntries(user->Yloc); CHKERRQ(ierr);
35ccaff030SJeremy L Thompson 
36ccaff030SJeremy L Thompson   // Setup CEED vectors
3762e9c006SJeremy L Thompson   ierr = user->VecGetArrayRead(user->Xloc, (const PetscScalar **)&x);
3862e9c006SJeremy L Thompson   CHKERRQ(ierr);
3962e9c006SJeremy L Thompson   ierr = user->VecGetArray(user->Yloc, &y); CHKERRQ(ierr);
4062e9c006SJeremy L Thompson   CeedVectorSetArray(user->Xceed, user->memType, CEED_USE_POINTER, x);
4162e9c006SJeremy L Thompson   CeedVectorSetArray(user->Yceed, user->memType, CEED_USE_POINTER, y);
42ccaff030SJeremy L Thompson 
43ccaff030SJeremy L Thompson   // Apply CEED operator
44*6a6c615bSJeremy L Thompson   // Note: We could use VecGetArrayInPlace. Instead, we use SetArray/TakeArray
45*6a6c615bSJeremy L Thompson   //         so we can request host memory for easier debugging.
46ccaff030SJeremy L Thompson   CeedOperatorApply(user->op, user->Xceed, user->Yceed, CEED_REQUEST_IMMEDIATE);
47ccaff030SJeremy L Thompson 
48ccaff030SJeremy L Thompson   // Restore PETSc vectors
49*6a6c615bSJeremy L Thompson   CeedVectorTakeArray(user->Xceed, user->memType, NULL);
50*6a6c615bSJeremy L Thompson   CeedVectorTakeArray(user->Yceed, user->memType, NULL);
5162e9c006SJeremy L Thompson   ierr = user->VecRestoreArrayRead(user->Xloc, (const PetscScalar **)&x);
52ccaff030SJeremy L Thompson   CHKERRQ(ierr);
5362e9c006SJeremy L Thompson   ierr = user->VecRestoreArray(user->Yloc, &y); CHKERRQ(ierr);
54ccaff030SJeremy L Thompson 
55ccaff030SJeremy L Thompson   // Local-to-global
56ccaff030SJeremy L Thompson   ierr = VecZeroEntries(Y); CHKERRQ(ierr);
57ccaff030SJeremy L Thompson   ierr = DMLocalToGlobal(user->dm, user->Yloc, ADD_VALUES, Y); CHKERRQ(ierr);
58ccaff030SJeremy L Thompson 
59ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
60ccaff030SJeremy L Thompson };
61ccaff030SJeremy L Thompson 
62ccaff030SJeremy L Thompson // This function uses libCEED to compute the non-linear residual
63ccaff030SJeremy L Thompson PetscErrorCode FormResidual_Ceed(SNES snes, Vec X, Vec Y, void *ctx) {
64ccaff030SJeremy L Thompson   PetscErrorCode ierr;
65ccaff030SJeremy L Thompson   UserMult user = (UserMult)ctx;
66ccaff030SJeremy L Thompson 
67ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
68ccaff030SJeremy L Thompson 
69ccaff030SJeremy L Thompson   // Use computed BCs
70ccaff030SJeremy L Thompson   ierr = VecZeroEntries(user->Xloc); CHKERRQ(ierr);
71ccaff030SJeremy L Thompson   ierr = DMPlexInsertBoundaryValues(user->dm, PETSC_TRUE, user->Xloc,
72ccaff030SJeremy L Thompson                                     user->loadIncrement, NULL, NULL, NULL);
73ccaff030SJeremy L Thompson   CHKERRQ(ierr);
74ccaff030SJeremy L Thompson 
75ccaff030SJeremy L Thompson   // libCEED for local action of residual evaluator
76ccaff030SJeremy L Thompson   ierr = ApplyLocalCeedOp(X, Y, user); CHKERRQ(ierr);
77ccaff030SJeremy L Thompson 
78ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
79ccaff030SJeremy L Thompson };
80ccaff030SJeremy L Thompson 
81ccaff030SJeremy L Thompson // This function uses libCEED to apply the Jacobian for assembly via a SNES
82ccaff030SJeremy L Thompson PetscErrorCode ApplyJacobianCoarse_Ceed(SNES snes, Vec X, Vec Y, void *ctx) {
83ccaff030SJeremy L Thompson   PetscErrorCode ierr;
84ccaff030SJeremy L Thompson   UserMult user = (UserMult)ctx;
85ccaff030SJeremy L Thompson 
86ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
87ccaff030SJeremy L Thompson 
8862e9c006SJeremy L Thompson   // Zero boundary values
89ccaff030SJeremy L Thompson   ierr = VecZeroEntries(user->Xloc); CHKERRQ(ierr);
90ccaff030SJeremy L Thompson 
91ccaff030SJeremy L Thompson   // libCEED for local action of residual evaluator
92ccaff030SJeremy L Thompson   ierr = ApplyLocalCeedOp(X, Y, user); CHKERRQ(ierr);
93ccaff030SJeremy L Thompson 
94ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
95ccaff030SJeremy L Thompson };
96ccaff030SJeremy L Thompson 
97ccaff030SJeremy L Thompson // This function uses libCEED to compute the action of the Jacobian
98ccaff030SJeremy L Thompson PetscErrorCode ApplyJacobian_Ceed(Mat A, Vec X, Vec Y) {
99ccaff030SJeremy L Thompson   PetscErrorCode ierr;
100ccaff030SJeremy L Thompson   UserMult user;
101ccaff030SJeremy L Thompson 
102ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
103ccaff030SJeremy L Thompson 
104ccaff030SJeremy L Thompson   // Zero boundary values
105ccaff030SJeremy L Thompson   ierr = MatShellGetContext(A, &user); CHKERRQ(ierr);
106ccaff030SJeremy L Thompson   ierr = VecZeroEntries(user->Xloc); CHKERRQ(ierr);
107ccaff030SJeremy L Thompson 
108ccaff030SJeremy L Thompson   // libCEED for local action of Jacobian
109ccaff030SJeremy L Thompson   ierr = ApplyLocalCeedOp(X, Y, user); CHKERRQ(ierr);
110ccaff030SJeremy L Thompson 
111ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
112ccaff030SJeremy L Thompson };
113ccaff030SJeremy L Thompson 
114ccaff030SJeremy L Thompson // This function uses libCEED to compute the action of the prolongation operator
115ccaff030SJeremy L Thompson PetscErrorCode Prolong_Ceed(Mat A, Vec X, Vec Y) {
116ccaff030SJeremy L Thompson   PetscErrorCode ierr;
117ccaff030SJeremy L Thompson   UserMultProlongRestr user;
118ccaff030SJeremy L Thompson   PetscScalar *c, *f;
119ccaff030SJeremy L Thompson 
120ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
121ccaff030SJeremy L Thompson 
122ccaff030SJeremy L Thompson   ierr = MatShellGetContext(A, &user); CHKERRQ(ierr);
123ccaff030SJeremy L Thompson 
124ccaff030SJeremy L Thompson   // Global-to-local
125ccaff030SJeremy L Thompson   ierr = VecZeroEntries(user->locVecC); CHKERRQ(ierr);
126ccaff030SJeremy L Thompson   ierr = DMGlobalToLocal(user->dmC, X, INSERT_VALUES, user->locVecC);
127ccaff030SJeremy L Thompson   CHKERRQ(ierr);
128ccaff030SJeremy L Thompson   ierr = VecZeroEntries(user->locVecF); CHKERRQ(ierr);
129ccaff030SJeremy L Thompson 
130ccaff030SJeremy L Thompson   // Setup CEED vectors
13162e9c006SJeremy L Thompson   ierr = user->VecGetArrayRead(user->locVecC, (const PetscScalar **)&c);
132ccaff030SJeremy L Thompson   CHKERRQ(ierr);
13362e9c006SJeremy L Thompson   ierr = user->VecGetArray(user->locVecF, &f); CHKERRQ(ierr);
13462e9c006SJeremy L Thompson   CeedVectorSetArray(user->ceedVecC, user->memType, CEED_USE_POINTER, c);
13562e9c006SJeremy L Thompson   CeedVectorSetArray(user->ceedVecF, user->memType, CEED_USE_POINTER, f);
136ccaff030SJeremy L Thompson 
137ccaff030SJeremy L Thompson   // Apply CEED operator
138ccaff030SJeremy L Thompson   CeedOperatorApply(user->opProlong, user->ceedVecC, user->ceedVecF,
139ccaff030SJeremy L Thompson                     CEED_REQUEST_IMMEDIATE);
140ccaff030SJeremy L Thompson 
141ccaff030SJeremy L Thompson   // Restore PETSc vectors
142*6a6c615bSJeremy L Thompson   CeedVectorTakeArray(user->ceedVecC, user->memType, NULL);
143*6a6c615bSJeremy L Thompson   CeedVectorTakeArray(user->ceedVecF, user->memType, NULL);
144cd11335eSJeremy L Thompson   ierr = user->VecRestoreArrayRead(user->locVecC, (const PetscScalar **)&c);
145ccaff030SJeremy L Thompson   CHKERRQ(ierr);
14662e9c006SJeremy L Thompson   ierr = user->VecRestoreArray(user->locVecF, &f); CHKERRQ(ierr);
147ccaff030SJeremy L Thompson 
148ccaff030SJeremy L Thompson   // Multiplicity
149ccaff030SJeremy L Thompson   ierr = VecPointwiseMult(user->locVecF, user->locVecF, user->multVec);
150ccaff030SJeremy L Thompson 
151ccaff030SJeremy L Thompson   // Local-to-global
152ccaff030SJeremy L Thompson   ierr = VecZeroEntries(Y); CHKERRQ(ierr);
153ccaff030SJeremy L Thompson   ierr = DMLocalToGlobal(user->dmF, user->locVecF, ADD_VALUES, Y);
154ccaff030SJeremy L Thompson   CHKERRQ(ierr);
155ccaff030SJeremy L Thompson 
156ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
157ccaff030SJeremy L Thompson }
158ccaff030SJeremy L Thompson 
159ccaff030SJeremy L Thompson // This function uses libCEED to compute the action of the restriction operator
160ccaff030SJeremy L Thompson PetscErrorCode Restrict_Ceed(Mat A, Vec X, Vec Y) {
161ccaff030SJeremy L Thompson   PetscErrorCode ierr;
162ccaff030SJeremy L Thompson   UserMultProlongRestr user;
163ccaff030SJeremy L Thompson   PetscScalar *c, *f;
164ccaff030SJeremy L Thompson 
165ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
166ccaff030SJeremy L Thompson 
167ccaff030SJeremy L Thompson   ierr = MatShellGetContext(A, &user); CHKERRQ(ierr);
168ccaff030SJeremy L Thompson 
169ccaff030SJeremy L Thompson   // Global-to-local
170ccaff030SJeremy L Thompson   ierr = VecZeroEntries(user->locVecF); CHKERRQ(ierr);
171ccaff030SJeremy L Thompson   ierr = DMGlobalToLocal(user->dmF, X, INSERT_VALUES, user->locVecF);
172ccaff030SJeremy L Thompson   CHKERRQ(ierr);
173ccaff030SJeremy L Thompson   ierr = VecZeroEntries(user->locVecC); CHKERRQ(ierr);
174ccaff030SJeremy L Thompson 
175ccaff030SJeremy L Thompson   // Multiplicity
176ccaff030SJeremy L Thompson   ierr = VecPointwiseMult(user->locVecF, user->locVecF, user->multVec);
177ccaff030SJeremy L Thompson   CHKERRQ(ierr);
178ccaff030SJeremy L Thompson 
179ccaff030SJeremy L Thompson   // Setup CEED vectors
18062e9c006SJeremy L Thompson   ierr = user->VecGetArrayRead(user->locVecF, (const PetscScalar **)&f);
18162e9c006SJeremy L Thompson   CHKERRQ(ierr);
18262e9c006SJeremy L Thompson   ierr = user->VecGetArray(user->locVecC, &c); CHKERRQ(ierr);
18362e9c006SJeremy L Thompson   CeedVectorSetArray(user->ceedVecF, user->memType, CEED_USE_POINTER, f);
18462e9c006SJeremy L Thompson   CeedVectorSetArray(user->ceedVecC, user->memType, CEED_USE_POINTER, c);
185ccaff030SJeremy L Thompson 
186ccaff030SJeremy L Thompson   // Apply CEED operator
187ccaff030SJeremy L Thompson   CeedOperatorApply(user->opRestrict, user->ceedVecF, user->ceedVecC,
188ccaff030SJeremy L Thompson                     CEED_REQUEST_IMMEDIATE);
189ccaff030SJeremy L Thompson 
190ccaff030SJeremy L Thompson   // Restore PETSc vectors
191*6a6c615bSJeremy L Thompson   CeedVectorTakeArray(user->ceedVecF, user->memType, NULL);
192*6a6c615bSJeremy L Thompson   CeedVectorTakeArray(user->ceedVecC, user->memType, NULL);
19362e9c006SJeremy L Thompson   ierr = user->VecRestoreArrayRead(user->locVecF, (const PetscScalar **)&f);
194ccaff030SJeremy L Thompson   CHKERRQ(ierr);
19562e9c006SJeremy L Thompson   ierr = user->VecRestoreArray(user->locVecC, &c); CHKERRQ(ierr);
196ccaff030SJeremy L Thompson 
197ccaff030SJeremy L Thompson   // Local-to-global
198ccaff030SJeremy L Thompson   ierr = VecZeroEntries(Y); CHKERRQ(ierr);
199ccaff030SJeremy L Thompson   ierr = DMLocalToGlobal(user->dmC, user->locVecC, ADD_VALUES, Y);
200ccaff030SJeremy L Thompson   CHKERRQ(ierr);
201ccaff030SJeremy L Thompson 
202ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
203ccaff030SJeremy L Thompson };
2042d93065eSjeremylt 
205ccaff030SJeremy L Thompson // This function returns the computed diagonal of the operator
206ccaff030SJeremy L Thompson PetscErrorCode GetDiag_Ceed(Mat A, Vec D) {
207ccaff030SJeremy L Thompson   PetscErrorCode ierr;
208ccaff030SJeremy L Thompson   UserMult user;
209ccaff030SJeremy L Thompson 
210ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
211ccaff030SJeremy L Thompson 
212ccaff030SJeremy L Thompson   ierr = MatShellGetContext(A, &user); CHKERRQ(ierr);
213ccaff030SJeremy L Thompson 
214f7b4142eSJeremy L Thompson   // -- Set physics context
215f7b4142eSJeremy L Thompson   if (user->physSmoother)
216f7b4142eSJeremy L Thompson     CeedQFunctionSetContext(user->qf, user->physSmoother,
217f7b4142eSJeremy L Thompson                             sizeof(*user->physSmoother));
218f7b4142eSJeremy L Thompson 
2192bba3ffaSJeremy L Thompson   // Compute Diagonal via libCEED
2202bba3ffaSJeremy L Thompson   PetscScalar *x;
2212bba3ffaSJeremy L Thompson 
2222bba3ffaSJeremy L Thompson   // -- Place PETSc vector in libCEED vector
22362e9c006SJeremy L Thompson   ierr = user->VecGetArray(user->Xloc, &x); CHKERRQ(ierr);
22462e9c006SJeremy L Thompson   CeedVectorSetArray(user->Xceed, user->memType, CEED_USE_POINTER, x);
2252bba3ffaSJeremy L Thompson 
2262bba3ffaSJeremy L Thompson   // -- Compute Diagonal
2272bba3ffaSJeremy L Thompson   CeedOperatorLinearAssembleDiagonal(user->op, user->Xceed,
228ccaff030SJeremy L Thompson                                      CEED_REQUEST_IMMEDIATE);
229ccaff030SJeremy L Thompson 
230f7b4142eSJeremy L Thompson   // -- Reset physics context
231f7b4142eSJeremy L Thompson   if (user->physSmoother)
232f7b4142eSJeremy L Thompson     CeedQFunctionSetContext(user->qf, user->phys, sizeof(*user->phys));
233f7b4142eSJeremy L Thompson 
234ccaff030SJeremy L Thompson   // -- Local-to-Global
235*6a6c615bSJeremy L Thompson   CeedVectorTakeArray(user->Xceed, user->memType, NULL);
23662e9c006SJeremy L Thompson   ierr = user->VecRestoreArray(user->Xloc, &x); CHKERRQ(ierr);
237ccaff030SJeremy L Thompson   ierr = VecZeroEntries(D); CHKERRQ(ierr);
238ccaff030SJeremy L Thompson   ierr = DMLocalToGlobal(user->dm, user->Xloc, ADD_VALUES, D); CHKERRQ(ierr);
239ccaff030SJeremy L Thompson 
2402bba3ffaSJeremy L Thompson   // Cleanup
2412bba3ffaSJeremy L Thompson   ierr = VecZeroEntries(user->Xloc); CHKERRQ(ierr);
242ccaff030SJeremy L Thompson 
243ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
244ccaff030SJeremy L Thompson };
2452d93065eSjeremylt 
2462d93065eSjeremylt // This function calculates the strain energy in the final solution
247a3c02c40SJeremy L Thompson PetscErrorCode ComputeStrainEnergy(DM dmEnergy, UserMult user,
248a3c02c40SJeremy L Thompson                                    CeedOperator opEnergy, Vec X,
249a3c02c40SJeremy L Thompson                                    PetscReal *energy) {
2502d93065eSjeremylt   PetscErrorCode ierr;
2512d93065eSjeremylt   PetscScalar *x;
2522d93065eSjeremylt   CeedInt length;
2532d93065eSjeremylt 
2542d93065eSjeremylt   PetscFunctionBeginUser;
2552d93065eSjeremylt 
2562d93065eSjeremylt   // Global-to-local
2572d93065eSjeremylt   ierr = VecZeroEntries(user->Xloc); CHKERRQ(ierr);
2582d93065eSjeremylt   ierr = DMGlobalToLocal(user->dm, X, INSERT_VALUES, user->Xloc); CHKERRQ(ierr);
2592d93065eSjeremylt   ierr = DMPlexInsertBoundaryValues(user->dm, PETSC_TRUE, user->Xloc,
2602d93065eSjeremylt                                     user->loadIncrement, NULL, NULL, NULL);
2615c25879aSJeremy L Thompson   CHKERRQ(ierr);
2622d93065eSjeremylt 
263a3c02c40SJeremy L Thompson   // Setup libCEED input vector
26462e9c006SJeremy L Thompson   ierr = user->VecGetArrayRead(user->Xloc, (const PetscScalar **)&x);
2652d93065eSjeremylt   CHKERRQ(ierr);
26662e9c006SJeremy L Thompson   CeedVectorSetArray(user->Xceed, user->memType, CEED_USE_POINTER, x);
2672d93065eSjeremylt 
268a3c02c40SJeremy L Thompson   // Setup libCEED output vector
269a3c02c40SJeremy L Thompson   Vec Eloc;
270a3c02c40SJeremy L Thompson   CeedVector eloc;
271a3c02c40SJeremy L Thompson   ierr = DMCreateLocalVector(dmEnergy, &Eloc); CHKERRQ(ierr);
272a3c02c40SJeremy L Thompson   ierr = VecGetSize(Eloc, &length); CHKERRQ(ierr);
273a3c02c40SJeremy L Thompson   ierr = VecDestroy(&Eloc); CHKERRQ(ierr);
274a3c02c40SJeremy L Thompson   CeedVectorCreate(user->ceed, length, &eloc);
275a3c02c40SJeremy L Thompson 
2762d93065eSjeremylt   // Apply libCEED operator
277a3c02c40SJeremy L Thompson   CeedOperatorApply(opEnergy, user->Xceed, eloc, CEED_REQUEST_IMMEDIATE);
2782d93065eSjeremylt 
2792d93065eSjeremylt   // Restore PETSc vector
28062e9c006SJeremy L Thompson   ierr = user->VecRestoreArrayRead(user->Xloc, (const PetscScalar **)&x);
2812d93065eSjeremylt   CHKERRQ(ierr);
2822d93065eSjeremylt 
2832d93065eSjeremylt   // Reduce max error
2842d93065eSjeremylt   const CeedScalar *e;
285a3c02c40SJeremy L Thompson   CeedVectorGetArrayRead(eloc, CEED_MEM_HOST, &e);
2862d93065eSjeremylt   (*energy) = 0;
2872d93065eSjeremylt   for (CeedInt i=0; i<length; i++)
2882d93065eSjeremylt     (*energy) += e[i];
289a3c02c40SJeremy L Thompson   CeedVectorRestoreArrayRead(eloc, &e);
290a3c02c40SJeremy L Thompson   CeedVectorDestroy(&eloc);
2912d93065eSjeremylt 
2922d93065eSjeremylt   ierr = MPI_Allreduce(MPI_IN_PLACE, energy, 1, MPIU_REAL, MPIU_SUM,
2932d93065eSjeremylt                        user->comm); CHKERRQ(ierr);
2942d93065eSjeremylt 
2952d93065eSjeremylt   PetscFunctionReturn(0);
2962d93065eSjeremylt };
297