xref: /libCEED/examples/solids/src/misc.c (revision 5754ecac3b7d1ff97b39b25dc78c06350f2c900d)
1ccaff030SJeremy L Thompson /// @file
2ccaff030SJeremy L Thompson /// Helper functions for solid mechanics example using PETSc
3ccaff030SJeremy L Thompson 
4*5754ecacSJeremy L Thompson #include "../include/misc.h"
5*5754ecacSJeremy L Thompson #include "../include/utils.h"
6ccaff030SJeremy L Thompson 
7ccaff030SJeremy L Thompson // -----------------------------------------------------------------------------
8ccaff030SJeremy L Thompson // Create libCEED operator context
9ccaff030SJeremy L Thompson // -----------------------------------------------------------------------------
10ccaff030SJeremy L Thompson // Setup context data for Jacobian evaluation
11d1d35e2fSjeremylt PetscErrorCode SetupJacobianCtx(MPI_Comm comm, AppCtx app_ctx, DM dm, Vec V,
12d1d35e2fSjeremylt                                 Vec V_loc, CeedData ceed_data, Ceed ceed,
13d1d35e2fSjeremylt                                 CeedQFunctionContext ctx_phys,
14d1d35e2fSjeremylt                                 CeedQFunctionContext ctx_phys_smoother,
15d1d35e2fSjeremylt                                 UserMult jacobian_ctx) {
16ccaff030SJeremy L Thompson   PetscErrorCode ierr;
17ccaff030SJeremy L Thompson 
18ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
19ccaff030SJeremy L Thompson 
20ccaff030SJeremy L Thompson   // PETSc objects
21d1d35e2fSjeremylt   jacobian_ctx->comm = comm;
22d1d35e2fSjeremylt   jacobian_ctx->dm = dm;
23ccaff030SJeremy L Thompson 
24ccaff030SJeremy L Thompson   // Work vectors
25d1d35e2fSjeremylt   jacobian_ctx->X_loc = V_loc;
26d1d35e2fSjeremylt   ierr = VecDuplicate(V_loc, &jacobian_ctx->Y_loc); CHKERRQ(ierr);
27d1d35e2fSjeremylt   jacobian_ctx->x_ceed = ceed_data->x_ceed;
28d1d35e2fSjeremylt   jacobian_ctx->y_ceed = ceed_data->y_ceed;
29ccaff030SJeremy L Thompson 
30ccaff030SJeremy L Thompson   // libCEED operator
31*5754ecacSJeremy L Thompson   jacobian_ctx->op = ceed_data->op_jacobian;
32*5754ecacSJeremy L Thompson   jacobian_ctx->qf = ceed_data->qf_jacobian;
33ccaff030SJeremy L Thompson 
34ccaff030SJeremy L Thompson   // Ceed
35d1d35e2fSjeremylt   jacobian_ctx->ceed = ceed;
36ccaff030SJeremy L Thompson 
37f7b4142eSJeremy L Thompson   // Physics
38d1d35e2fSjeremylt   jacobian_ctx->ctx_phys = ctx_phys;
39d1d35e2fSjeremylt   jacobian_ctx->ctx_phys_smoother = ctx_phys_smoother;
40ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
41ccaff030SJeremy L Thompson };
42ccaff030SJeremy L Thompson 
43ccaff030SJeremy L Thompson // Setup context data for prolongation and restriction operators
44d1d35e2fSjeremylt PetscErrorCode SetupProlongRestrictCtx(MPI_Comm comm, AppCtx app_ctx, DM dm_c,
45d1d35e2fSjeremylt                                        DM dm_f, Vec V_f, Vec V_loc_c, Vec V_loc_f,
46d1d35e2fSjeremylt                                        CeedData ceed_data_c, CeedData ceed_data_f,
47d1d35e2fSjeremylt                                        Ceed ceed, UserMultProlongRestr prolong_restr_ctx) {
48ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
49ccaff030SJeremy L Thompson 
50ccaff030SJeremy L Thompson   // PETSc objects
51d1d35e2fSjeremylt   prolong_restr_ctx->comm = comm;
52d1d35e2fSjeremylt   prolong_restr_ctx->dm_c = dm_c;
53d1d35e2fSjeremylt   prolong_restr_ctx->dm_f = dm_f;
54ccaff030SJeremy L Thompson 
55ccaff030SJeremy L Thompson   // Work vectors
56d1d35e2fSjeremylt   prolong_restr_ctx->loc_vec_c = V_loc_c;
57d1d35e2fSjeremylt   prolong_restr_ctx->loc_vec_f = V_loc_f;
58d1d35e2fSjeremylt   prolong_restr_ctx->ceed_vec_c = ceed_data_c->x_ceed;
59d1d35e2fSjeremylt   prolong_restr_ctx->ceed_vec_f = ceed_data_f->x_ceed;
60ccaff030SJeremy L Thompson 
61ccaff030SJeremy L Thompson   // libCEED operators
62d1d35e2fSjeremylt   prolong_restr_ctx->op_prolong = ceed_data_f->op_prolong;
63d1d35e2fSjeremylt   prolong_restr_ctx->op_restrict = ceed_data_f->op_restrict;
64ccaff030SJeremy L Thompson 
65ccaff030SJeremy L Thompson   // Ceed
66d1d35e2fSjeremylt   prolong_restr_ctx->ceed = ceed;
67ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
68ccaff030SJeremy L Thompson };
69ccaff030SJeremy L Thompson 
70ccaff030SJeremy L Thompson // -----------------------------------------------------------------------------
71ccaff030SJeremy L Thompson // Jacobian setup
72ccaff030SJeremy L Thompson // -----------------------------------------------------------------------------
73d1d35e2fSjeremylt PetscErrorCode FormJacobian(SNES snes, Vec U, Mat J, Mat J_pre, void *ctx) {
74ccaff030SJeremy L Thompson   PetscErrorCode ierr;
75ccaff030SJeremy L Thompson 
76ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
77ccaff030SJeremy L Thompson 
78ccaff030SJeremy L Thompson   // Context data
79d1d35e2fSjeremylt   FormJacobCtx  form_jacob_ctx = (FormJacobCtx)ctx;
80d1d35e2fSjeremylt   PetscInt      num_levels = form_jacob_ctx->num_levels;
81d1d35e2fSjeremylt   Mat           *jacob_mat = form_jacob_ctx->jacob_mat;
82ccaff030SJeremy L Thompson 
83e3e3df41Sjeremylt   // Update Jacobian on each level
84d1d35e2fSjeremylt   for (PetscInt level = 0; level < num_levels; level++) {
85d1d35e2fSjeremylt     ierr = MatAssemblyBegin(jacob_mat[level], MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
86d1d35e2fSjeremylt     ierr = MatAssemblyEnd(jacob_mat[level], MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
87ccaff030SJeremy L Thompson   }
88ccaff030SJeremy L Thompson 
89ccaff030SJeremy L Thompson   // Form coarse assembled matrix
90d1d35e2fSjeremylt   ierr = VecZeroEntries(form_jacob_ctx->u_coarse); CHKERRQ(ierr);
91d1d35e2fSjeremylt   ierr = SNESComputeJacobianDefaultColor(form_jacob_ctx->snes_coarse,
92d1d35e2fSjeremylt                                          form_jacob_ctx->u_coarse,
93d1d35e2fSjeremylt                                          form_jacob_ctx->jacob_mat[0],
94d1d35e2fSjeremylt                                          form_jacob_ctx->jacob_mat_coarse, NULL);
95ccaff030SJeremy L Thompson   CHKERRQ(ierr);
96ccaff030SJeremy L Thompson 
97d1d35e2fSjeremylt   // J_pre might be AIJ (e.g., when using coloring), so we need to assemble it
98d1d35e2fSjeremylt   ierr = MatAssemblyBegin(J_pre, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
99d1d35e2fSjeremylt   ierr = MatAssemblyEnd(J_pre, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
100d1d35e2fSjeremylt   if (J != J_pre) {
1010e0d204cSJed Brown     ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1020e0d204cSJed Brown     ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1030e0d204cSJed Brown   }
104ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
105ccaff030SJeremy L Thompson };
106ccaff030SJeremy L Thompson 
107ccaff030SJeremy L Thompson // -----------------------------------------------------------------------------
108ccaff030SJeremy L Thompson // Output solution for visualization
109ccaff030SJeremy L Thompson // -----------------------------------------------------------------------------
110d1d35e2fSjeremylt PetscErrorCode ViewSolution(MPI_Comm comm, AppCtx app_ctx, Vec U,
111d1d35e2fSjeremylt                             PetscInt increment, PetscScalar load_increment) {
112ccaff030SJeremy L Thompson   PetscErrorCode ierr;
113ccaff030SJeremy L Thompson   DM dm;
114ccaff030SJeremy L Thompson   PetscViewer viewer;
115d1d35e2fSjeremylt   char output_filename[PETSC_MAX_PATH_LEN];
116d99129b9SLeila Ghaffari   PetscMPIInt rank;
117ccaff030SJeremy L Thompson 
118ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
119ccaff030SJeremy L Thompson 
120d99129b9SLeila Ghaffari   // Create output directory
121d99129b9SLeila Ghaffari   MPI_Comm_rank(comm, &rank);
122d1d35e2fSjeremylt   if (!rank) {ierr = PetscMkdir(app_ctx->output_dir); CHKERRQ(ierr);}
123d99129b9SLeila Ghaffari 
124ccaff030SJeremy L Thompson   // Build file name
125d1d35e2fSjeremylt   ierr = PetscSNPrintf(output_filename, sizeof output_filename,
126d1d35e2fSjeremylt                        "%s/solution-%03D.vtu", app_ctx->output_dir,
127d99129b9SLeila Ghaffari                        increment); CHKERRQ(ierr);
128ccaff030SJeremy L Thompson 
129050e48ebSJeremy L Thompson   // Increment sequence
130ccaff030SJeremy L Thompson   ierr = VecGetDM(U, &dm); CHKERRQ(ierr);
131d1d35e2fSjeremylt   ierr = DMSetOutputSequenceNumber(dm, increment, load_increment); CHKERRQ(ierr);
132ccaff030SJeremy L Thompson 
133ccaff030SJeremy L Thompson   // Output solution vector
134d1d35e2fSjeremylt   ierr = PetscViewerVTKOpen(comm, output_filename, FILE_MODE_WRITE, &viewer);
135ccaff030SJeremy L Thompson   CHKERRQ(ierr);
136ccaff030SJeremy L Thompson   ierr = VecView(U, viewer); CHKERRQ(ierr);
137ccaff030SJeremy L Thompson   ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
138ccaff030SJeremy L Thompson 
139ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
140ccaff030SJeremy L Thompson };
1415c25879aSJeremy L Thompson 
1425c25879aSJeremy L Thompson // -----------------------------------------------------------------------------
1435c25879aSJeremy L Thompson // Output diagnostic quantities for visualization
1445c25879aSJeremy L Thompson // -----------------------------------------------------------------------------
1455c25879aSJeremy L Thompson PetscErrorCode ViewDiagnosticQuantities(MPI_Comm comm, DM dmU,
146d1d35e2fSjeremylt                                         UserMult user, AppCtx app_ctx, Vec U,
147d1d35e2fSjeremylt                                         CeedElemRestriction elem_restr_diagnostic) {
1485c25879aSJeremy L Thompson   PetscErrorCode ierr;
149d1d35e2fSjeremylt   Vec Diagnostic, Y_loc, mult_vec;
150d1d35e2fSjeremylt   CeedVector y_ceed;
1515c25879aSJeremy L Thompson   CeedScalar *x, *y;
152d1d35e2fSjeremylt   PetscMemType x_mem_type, y_mem_type;
153d1d35e2fSjeremylt   PetscInt loc_size;
1545c25879aSJeremy L Thompson   PetscViewer viewer;
155d1d35e2fSjeremylt   char output_filename[PETSC_MAX_PATH_LEN];
1565c25879aSJeremy L Thompson 
1575c25879aSJeremy L Thompson   PetscFunctionBeginUser;
1585c25879aSJeremy L Thompson 
1595c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
1605c25879aSJeremy L Thompson   // PETSc and libCEED vectors
1615c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
1625c25879aSJeremy L Thompson   ierr = DMCreateGlobalVector(user->dm, &Diagnostic); CHKERRQ(ierr);
163f81c27eaSJed Brown   ierr = PetscObjectSetName((PetscObject)Diagnostic, ""); CHKERRQ(ierr);
164d1d35e2fSjeremylt   ierr = DMCreateLocalVector(user->dm, &Y_loc); CHKERRQ(ierr);
165d1d35e2fSjeremylt   ierr = VecGetSize(Y_loc, &loc_size); CHKERRQ(ierr);
166d1d35e2fSjeremylt   CeedVectorCreate(user->ceed, loc_size, &y_ceed);
1675c25879aSJeremy L Thompson 
1685c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
1695c25879aSJeremy L Thompson   // Compute quantities
1705c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
1715c25879aSJeremy L Thompson   // -- Global-to-local
172d1d35e2fSjeremylt   ierr = VecZeroEntries(user->X_loc); CHKERRQ(ierr);
173d1d35e2fSjeremylt   ierr = DMPlexInsertBoundaryValues(dmU, PETSC_TRUE, user->X_loc,
174d1d35e2fSjeremylt                                     user->load_increment, NULL, NULL, NULL);
1755c25879aSJeremy L Thompson   CHKERRQ(ierr);
176d1d35e2fSjeremylt   ierr = DMGlobalToLocal(dmU, U, INSERT_VALUES, user->X_loc); CHKERRQ(ierr);
177d1d35e2fSjeremylt   ierr = VecZeroEntries(Y_loc); CHKERRQ(ierr);
1785c25879aSJeremy L Thompson 
1795c25879aSJeremy L Thompson   // -- Setup CEED vectors
180d1d35e2fSjeremylt   ierr = VecGetArrayReadAndMemType(user->X_loc, (const PetscScalar **)&x,
181d1d35e2fSjeremylt                                    &x_mem_type); CHKERRQ(ierr);
182d1d35e2fSjeremylt   ierr = VecGetArrayAndMemType(Y_loc, &y, &y_mem_type); CHKERRQ(ierr);
183d1d35e2fSjeremylt   CeedVectorSetArray(user->x_ceed, MemTypeP2C(x_mem_type), CEED_USE_POINTER, x);
184d1d35e2fSjeremylt   CeedVectorSetArray(y_ceed, MemTypeP2C(y_mem_type), CEED_USE_POINTER, y);
1855c25879aSJeremy L Thompson 
1865c25879aSJeremy L Thompson   // -- Apply CEED operator
187d1d35e2fSjeremylt   CeedOperatorApply(user->op, user->x_ceed, y_ceed, CEED_REQUEST_IMMEDIATE);
1885c25879aSJeremy L Thompson 
189d1d35e2fSjeremylt   // -- Restore PETSc vector; keep y_ceed viewing memory of Y_loc for use below
190d1d35e2fSjeremylt   CeedVectorTakeArray(user->x_ceed, MemTypeP2C(x_mem_type), NULL);
191d1d35e2fSjeremylt   ierr = VecRestoreArrayReadAndMemType(user->X_loc, (const PetscScalar **)&x);
1925c25879aSJeremy L Thompson   CHKERRQ(ierr);
1935c25879aSJeremy L Thompson 
1945c25879aSJeremy L Thompson   // -- Local-to-global
1955c25879aSJeremy L Thompson   ierr = VecZeroEntries(Diagnostic); CHKERRQ(ierr);
196d1d35e2fSjeremylt   ierr = DMLocalToGlobal(user->dm, Y_loc, ADD_VALUES, Diagnostic);
1975c25879aSJeremy L Thompson   CHKERRQ(ierr);
1985c25879aSJeremy L Thompson 
1995c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
2005c25879aSJeremy L Thompson   // Scale for multiplicity
2015c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
2025c25879aSJeremy L Thompson   // -- Setup vectors
203d1d35e2fSjeremylt   ierr = VecDuplicate(Diagnostic, &mult_vec); CHKERRQ(ierr);
204d1d35e2fSjeremylt   ierr = VecZeroEntries(Y_loc); CHKERRQ(ierr);
2055c25879aSJeremy L Thompson 
2065c25879aSJeremy L Thompson   // -- Compute multiplicity
207d1d35e2fSjeremylt   CeedElemRestrictionGetMultiplicity(elem_restr_diagnostic, y_ceed);
2085c25879aSJeremy L Thompson 
2095c25879aSJeremy L Thompson   // -- Restore vectors
210d1d35e2fSjeremylt   CeedVectorTakeArray(y_ceed, MemTypeP2C(y_mem_type), NULL);
211d1d35e2fSjeremylt   ierr = VecRestoreArrayAndMemType(Y_loc, &y); CHKERRQ(ierr);
2125c25879aSJeremy L Thompson 
2135c25879aSJeremy L Thompson   // -- Local-to-global
214d1d35e2fSjeremylt   ierr = VecZeroEntries(mult_vec); CHKERRQ(ierr);
215d1d35e2fSjeremylt   ierr = DMLocalToGlobal(user->dm, Y_loc, ADD_VALUES, mult_vec);
2165c25879aSJeremy L Thompson   CHKERRQ(ierr);
2175c25879aSJeremy L Thompson 
2185c25879aSJeremy L Thompson   // -- Scale
219d1d35e2fSjeremylt   ierr = VecReciprocal(mult_vec); CHKERRQ(ierr);
220d1d35e2fSjeremylt   ierr = VecPointwiseMult(Diagnostic, Diagnostic, mult_vec);
2215c25879aSJeremy L Thompson 
2225c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
2235c25879aSJeremy L Thompson   // Output solution vector
2245c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
225d1d35e2fSjeremylt   ierr = PetscSNPrintf(output_filename, sizeof output_filename,
226d99129b9SLeila Ghaffari                        "%s/diagnostic_quantities.vtu",
227d1d35e2fSjeremylt                        app_ctx->output_dir); CHKERRQ(ierr);
228d1d35e2fSjeremylt   ierr = PetscViewerVTKOpen(comm, output_filename, FILE_MODE_WRITE, &viewer);
2295c25879aSJeremy L Thompson   CHKERRQ(ierr);
2305c25879aSJeremy L Thompson   ierr = VecView(Diagnostic, viewer); CHKERRQ(ierr);
2315c25879aSJeremy L Thompson   ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
2325c25879aSJeremy L Thompson 
2335c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
2345c25879aSJeremy L Thompson   // Cleanup
2355c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
2365c25879aSJeremy L Thompson   ierr = VecDestroy(&Diagnostic); CHKERRQ(ierr);
237d1d35e2fSjeremylt   ierr = VecDestroy(&mult_vec); CHKERRQ(ierr);
238d1d35e2fSjeremylt   ierr = VecDestroy(&Y_loc); CHKERRQ(ierr);
239d1d35e2fSjeremylt   CeedVectorDestroy(&y_ceed);
2405c25879aSJeremy L Thompson 
2415c25879aSJeremy L Thompson   PetscFunctionReturn(0);
2425c25879aSJeremy L Thompson };
243*5754ecacSJeremy L Thompson 
244*5754ecacSJeremy L Thompson // -----------------------------------------------------------------------------
245*5754ecacSJeremy L Thompson // Regression testing
246*5754ecacSJeremy L Thompson // -----------------------------------------------------------------------------
247*5754ecacSJeremy L Thompson // test option change. could remove the loading step. Run only with one loading step and compare relatively to ref file
248*5754ecacSJeremy L Thompson // option: expect_final_strain_energy and check against the relative error to ref is within tolerance (10^-5) I.e. one Newton solve then check final energy
249*5754ecacSJeremy L Thompson PetscErrorCode RegressionTests_solids(AppCtx app_ctx, PetscReal energy) {
250*5754ecacSJeremy L Thompson   PetscFunctionBegin;
251*5754ecacSJeremy L Thompson 
252*5754ecacSJeremy L Thompson   if (app_ctx->expect_final_strain >= 0.) {
253*5754ecacSJeremy L Thompson     PetscReal energy_ref = app_ctx->expect_final_strain;
254*5754ecacSJeremy L Thompson     PetscReal error = PetscAbsReal(energy - energy_ref) / energy_ref;
255*5754ecacSJeremy L Thompson 
256*5754ecacSJeremy L Thompson     if (error > app_ctx->test_tol) {
257*5754ecacSJeremy L Thompson       PetscErrorCode ierr;
258*5754ecacSJeremy L Thompson       ierr = PetscPrintf(PETSC_COMM_WORLD,
259*5754ecacSJeremy L Thompson                          "Energy %e does not match expected energy %e: relative tolerance %e > %e\n",
260*5754ecacSJeremy L Thompson                          (double)energy, (double)energy_ref, (double)error, app_ctx->test_tol);
261*5754ecacSJeremy L Thompson       CHKERRQ(ierr);
262*5754ecacSJeremy L Thompson     }
263*5754ecacSJeremy L Thompson   }
264*5754ecacSJeremy L Thompson   PetscFunctionReturn(0);
265*5754ecacSJeremy L Thompson };
266