xref: /libCEED/examples/solids/src/misc.c (revision 17f0843f67ecf218e5d91454f4fa3c6a433ccc04)
1ccaff030SJeremy L Thompson /// @file
2ccaff030SJeremy L Thompson /// Helper functions for solid mechanics example using PETSc
3ccaff030SJeremy L Thompson 
45754ecacSJeremy L Thompson #include "../include/misc.h"
55754ecacSJeremy 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
315754ecacSJeremy L Thompson   jacobian_ctx->op = ceed_data->op_jacobian;
325754ecacSJeremy 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
90*17f0843fSJeremy L Thompson   CeedOperatorLinearAssemble(form_jacob_ctx->op_coarse,
91*17f0843fSJeremy L Thompson                              form_jacob_ctx->coo_values);
92*17f0843fSJeremy L Thompson   const CeedScalar *values;
93*17f0843fSJeremy L Thompson   CeedVectorGetArrayRead(form_jacob_ctx->coo_values, CEED_MEM_HOST, &values);
94*17f0843fSJeremy L Thompson   ierr = MatSetValuesCOO(form_jacob_ctx->jacob_mat_coarse, values, ADD_VALUES);
95ccaff030SJeremy L Thompson   CHKERRQ(ierr);
96*17f0843fSJeremy L Thompson   CeedVectorRestoreArrayRead(form_jacob_ctx->coo_values, &values);
97ccaff030SJeremy L Thompson 
98d1d35e2fSjeremylt   // J_pre might be AIJ (e.g., when using coloring), so we need to assemble it
99d1d35e2fSjeremylt   ierr = MatAssemblyBegin(J_pre, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
100d1d35e2fSjeremylt   ierr = MatAssemblyEnd(J_pre, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
101d1d35e2fSjeremylt   if (J != J_pre) {
1020e0d204cSJed Brown     ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1030e0d204cSJed Brown     ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1040e0d204cSJed Brown   }
105ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
106ccaff030SJeremy L Thompson };
107ccaff030SJeremy L Thompson 
108ccaff030SJeremy L Thompson // -----------------------------------------------------------------------------
109ccaff030SJeremy L Thompson // Output solution for visualization
110ccaff030SJeremy L Thompson // -----------------------------------------------------------------------------
111d1d35e2fSjeremylt PetscErrorCode ViewSolution(MPI_Comm comm, AppCtx app_ctx, Vec U,
112d1d35e2fSjeremylt                             PetscInt increment, PetscScalar load_increment) {
113ccaff030SJeremy L Thompson   PetscErrorCode ierr;
114ccaff030SJeremy L Thompson   DM dm;
115ccaff030SJeremy L Thompson   PetscViewer viewer;
116d1d35e2fSjeremylt   char output_filename[PETSC_MAX_PATH_LEN];
117d99129b9SLeila Ghaffari   PetscMPIInt rank;
118ccaff030SJeremy L Thompson 
119ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
120ccaff030SJeremy L Thompson 
121d99129b9SLeila Ghaffari   // Create output directory
122d99129b9SLeila Ghaffari   MPI_Comm_rank(comm, &rank);
123d1d35e2fSjeremylt   if (!rank) {ierr = PetscMkdir(app_ctx->output_dir); CHKERRQ(ierr);}
124d99129b9SLeila Ghaffari 
125ccaff030SJeremy L Thompson   // Build file name
126d1d35e2fSjeremylt   ierr = PetscSNPrintf(output_filename, sizeof output_filename,
127d1d35e2fSjeremylt                        "%s/solution-%03D.vtu", app_ctx->output_dir,
128d99129b9SLeila Ghaffari                        increment); CHKERRQ(ierr);
129ccaff030SJeremy L Thompson 
130050e48ebSJeremy L Thompson   // Increment sequence
131ccaff030SJeremy L Thompson   ierr = VecGetDM(U, &dm); CHKERRQ(ierr);
132d1d35e2fSjeremylt   ierr = DMSetOutputSequenceNumber(dm, increment, load_increment); CHKERRQ(ierr);
133ccaff030SJeremy L Thompson 
134ccaff030SJeremy L Thompson   // Output solution vector
135d1d35e2fSjeremylt   ierr = PetscViewerVTKOpen(comm, output_filename, FILE_MODE_WRITE, &viewer);
136ccaff030SJeremy L Thompson   CHKERRQ(ierr);
137ccaff030SJeremy L Thompson   ierr = VecView(U, viewer); CHKERRQ(ierr);
138ccaff030SJeremy L Thompson   ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
139ccaff030SJeremy L Thompson 
140ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
141ccaff030SJeremy L Thompson };
1425c25879aSJeremy L Thompson 
1435c25879aSJeremy L Thompson // -----------------------------------------------------------------------------
1445c25879aSJeremy L Thompson // Output diagnostic quantities for visualization
1455c25879aSJeremy L Thompson // -----------------------------------------------------------------------------
1465c25879aSJeremy L Thompson PetscErrorCode ViewDiagnosticQuantities(MPI_Comm comm, DM dmU,
147d1d35e2fSjeremylt                                         UserMult user, AppCtx app_ctx, Vec U,
148d1d35e2fSjeremylt                                         CeedElemRestriction elem_restr_diagnostic) {
1495c25879aSJeremy L Thompson   PetscErrorCode ierr;
150d1d35e2fSjeremylt   Vec Diagnostic, Y_loc, mult_vec;
151d1d35e2fSjeremylt   CeedVector y_ceed;
1525c25879aSJeremy L Thompson   CeedScalar *x, *y;
153d1d35e2fSjeremylt   PetscMemType x_mem_type, y_mem_type;
154d1d35e2fSjeremylt   PetscInt loc_size;
1555c25879aSJeremy L Thompson   PetscViewer viewer;
156d1d35e2fSjeremylt   char output_filename[PETSC_MAX_PATH_LEN];
1575c25879aSJeremy L Thompson 
1585c25879aSJeremy L Thompson   PetscFunctionBeginUser;
1595c25879aSJeremy L Thompson 
1605c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
1615c25879aSJeremy L Thompson   // PETSc and libCEED vectors
1625c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
1635c25879aSJeremy L Thompson   ierr = DMCreateGlobalVector(user->dm, &Diagnostic); CHKERRQ(ierr);
164f81c27eaSJed Brown   ierr = PetscObjectSetName((PetscObject)Diagnostic, ""); CHKERRQ(ierr);
165d1d35e2fSjeremylt   ierr = DMCreateLocalVector(user->dm, &Y_loc); CHKERRQ(ierr);
166d1d35e2fSjeremylt   ierr = VecGetSize(Y_loc, &loc_size); CHKERRQ(ierr);
167d1d35e2fSjeremylt   CeedVectorCreate(user->ceed, loc_size, &y_ceed);
1685c25879aSJeremy L Thompson 
1695c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
1705c25879aSJeremy L Thompson   // Compute quantities
1715c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
1725c25879aSJeremy L Thompson   // -- Global-to-local
173d1d35e2fSjeremylt   ierr = VecZeroEntries(user->X_loc); CHKERRQ(ierr);
174d1d35e2fSjeremylt   ierr = DMPlexInsertBoundaryValues(dmU, PETSC_TRUE, user->X_loc,
175d1d35e2fSjeremylt                                     user->load_increment, NULL, NULL, NULL);
1765c25879aSJeremy L Thompson   CHKERRQ(ierr);
177d1d35e2fSjeremylt   ierr = DMGlobalToLocal(dmU, U, INSERT_VALUES, user->X_loc); CHKERRQ(ierr);
178d1d35e2fSjeremylt   ierr = VecZeroEntries(Y_loc); CHKERRQ(ierr);
1795c25879aSJeremy L Thompson 
1805c25879aSJeremy L Thompson   // -- Setup CEED vectors
181d1d35e2fSjeremylt   ierr = VecGetArrayReadAndMemType(user->X_loc, (const PetscScalar **)&x,
182d1d35e2fSjeremylt                                    &x_mem_type); CHKERRQ(ierr);
183d1d35e2fSjeremylt   ierr = VecGetArrayAndMemType(Y_loc, &y, &y_mem_type); CHKERRQ(ierr);
184d1d35e2fSjeremylt   CeedVectorSetArray(user->x_ceed, MemTypeP2C(x_mem_type), CEED_USE_POINTER, x);
185d1d35e2fSjeremylt   CeedVectorSetArray(y_ceed, MemTypeP2C(y_mem_type), CEED_USE_POINTER, y);
1865c25879aSJeremy L Thompson 
1875c25879aSJeremy L Thompson   // -- Apply CEED operator
188d1d35e2fSjeremylt   CeedOperatorApply(user->op, user->x_ceed, y_ceed, CEED_REQUEST_IMMEDIATE);
1895c25879aSJeremy L Thompson 
190d1d35e2fSjeremylt   // -- Restore PETSc vector; keep y_ceed viewing memory of Y_loc for use below
191d1d35e2fSjeremylt   CeedVectorTakeArray(user->x_ceed, MemTypeP2C(x_mem_type), NULL);
192d1d35e2fSjeremylt   ierr = VecRestoreArrayReadAndMemType(user->X_loc, (const PetscScalar **)&x);
1935c25879aSJeremy L Thompson   CHKERRQ(ierr);
1945c25879aSJeremy L Thompson 
1955c25879aSJeremy L Thompson   // -- Local-to-global
1965c25879aSJeremy L Thompson   ierr = VecZeroEntries(Diagnostic); CHKERRQ(ierr);
197d1d35e2fSjeremylt   ierr = DMLocalToGlobal(user->dm, Y_loc, ADD_VALUES, Diagnostic);
1985c25879aSJeremy L Thompson   CHKERRQ(ierr);
1995c25879aSJeremy L Thompson 
2005c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
2015c25879aSJeremy L Thompson   // Scale for multiplicity
2025c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
2035c25879aSJeremy L Thompson   // -- Setup vectors
204d1d35e2fSjeremylt   ierr = VecDuplicate(Diagnostic, &mult_vec); CHKERRQ(ierr);
205d1d35e2fSjeremylt   ierr = VecZeroEntries(Y_loc); CHKERRQ(ierr);
2065c25879aSJeremy L Thompson 
2075c25879aSJeremy L Thompson   // -- Compute multiplicity
208d1d35e2fSjeremylt   CeedElemRestrictionGetMultiplicity(elem_restr_diagnostic, y_ceed);
2095c25879aSJeremy L Thompson 
2105c25879aSJeremy L Thompson   // -- Restore vectors
211d1d35e2fSjeremylt   CeedVectorTakeArray(y_ceed, MemTypeP2C(y_mem_type), NULL);
212d1d35e2fSjeremylt   ierr = VecRestoreArrayAndMemType(Y_loc, &y); CHKERRQ(ierr);
2135c25879aSJeremy L Thompson 
2145c25879aSJeremy L Thompson   // -- Local-to-global
215d1d35e2fSjeremylt   ierr = VecZeroEntries(mult_vec); CHKERRQ(ierr);
216d1d35e2fSjeremylt   ierr = DMLocalToGlobal(user->dm, Y_loc, ADD_VALUES, mult_vec);
2175c25879aSJeremy L Thompson   CHKERRQ(ierr);
2185c25879aSJeremy L Thompson 
2195c25879aSJeremy L Thompson   // -- Scale
220d1d35e2fSjeremylt   ierr = VecReciprocal(mult_vec); CHKERRQ(ierr);
221d1d35e2fSjeremylt   ierr = VecPointwiseMult(Diagnostic, Diagnostic, mult_vec);
2225c25879aSJeremy L Thompson 
2235c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
2245c25879aSJeremy L Thompson   // Output solution vector
2255c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
226d1d35e2fSjeremylt   ierr = PetscSNPrintf(output_filename, sizeof output_filename,
227d99129b9SLeila Ghaffari                        "%s/diagnostic_quantities.vtu",
228d1d35e2fSjeremylt                        app_ctx->output_dir); CHKERRQ(ierr);
229d1d35e2fSjeremylt   ierr = PetscViewerVTKOpen(comm, output_filename, FILE_MODE_WRITE, &viewer);
2305c25879aSJeremy L Thompson   CHKERRQ(ierr);
2315c25879aSJeremy L Thompson   ierr = VecView(Diagnostic, viewer); CHKERRQ(ierr);
2325c25879aSJeremy L Thompson   ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
2335c25879aSJeremy L Thompson 
2345c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
2355c25879aSJeremy L Thompson   // Cleanup
2365c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
2375c25879aSJeremy L Thompson   ierr = VecDestroy(&Diagnostic); CHKERRQ(ierr);
238d1d35e2fSjeremylt   ierr = VecDestroy(&mult_vec); CHKERRQ(ierr);
239d1d35e2fSjeremylt   ierr = VecDestroy(&Y_loc); CHKERRQ(ierr);
240d1d35e2fSjeremylt   CeedVectorDestroy(&y_ceed);
2415c25879aSJeremy L Thompson 
2425c25879aSJeremy L Thompson   PetscFunctionReturn(0);
2435c25879aSJeremy L Thompson };
2445754ecacSJeremy L Thompson 
2455754ecacSJeremy L Thompson // -----------------------------------------------------------------------------
2465754ecacSJeremy L Thompson // Regression testing
2475754ecacSJeremy L Thompson // -----------------------------------------------------------------------------
2485754ecacSJeremy L Thompson // test option change. could remove the loading step. Run only with one loading step and compare relatively to ref file
2495754ecacSJeremy 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
2505754ecacSJeremy L Thompson PetscErrorCode RegressionTests_solids(AppCtx app_ctx, PetscReal energy) {
2515754ecacSJeremy L Thompson   PetscFunctionBegin;
2525754ecacSJeremy L Thompson 
2535754ecacSJeremy L Thompson   if (app_ctx->expect_final_strain >= 0.) {
2545754ecacSJeremy L Thompson     PetscReal energy_ref = app_ctx->expect_final_strain;
2555754ecacSJeremy L Thompson     PetscReal error = PetscAbsReal(energy - energy_ref) / energy_ref;
2565754ecacSJeremy L Thompson 
2575754ecacSJeremy L Thompson     if (error > app_ctx->test_tol) {
2585754ecacSJeremy L Thompson       PetscErrorCode ierr;
2595754ecacSJeremy L Thompson       ierr = PetscPrintf(PETSC_COMM_WORLD,
2605754ecacSJeremy L Thompson                          "Energy %e does not match expected energy %e: relative tolerance %e > %e\n",
2615754ecacSJeremy L Thompson                          (double)energy, (double)energy_ref, (double)error, app_ctx->test_tol);
2625754ecacSJeremy L Thompson       CHKERRQ(ierr);
2635754ecacSJeremy L Thompson     }
2645754ecacSJeremy L Thompson   }
2655754ecacSJeremy L Thompson   PetscFunctionReturn(0);
2665754ecacSJeremy L Thompson };
267