xref: /libCEED/examples/solids/src/misc.c (revision 3d8e882215d238700cdceb37404f76ca7fa24eaa)
1*3d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
2*3d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3*3d8e8822SJeremy L Thompson //
4*3d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
5*3d8e8822SJeremy L Thompson //
6*3d8e8822SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
7*3d8e8822SJeremy L Thompson 
8ccaff030SJeremy L Thompson /// @file
9ccaff030SJeremy L Thompson /// Helper functions for solid mechanics example using PETSc
10ccaff030SJeremy L Thompson 
115754ecacSJeremy L Thompson #include "../include/misc.h"
125754ecacSJeremy L Thompson #include "../include/utils.h"
13ccaff030SJeremy L Thompson 
14ccaff030SJeremy L Thompson // -----------------------------------------------------------------------------
15ccaff030SJeremy L Thompson // Create libCEED operator context
16ccaff030SJeremy L Thompson // -----------------------------------------------------------------------------
17ccaff030SJeremy L Thompson // Setup context data for Jacobian evaluation
18d1d35e2fSjeremylt PetscErrorCode SetupJacobianCtx(MPI_Comm comm, AppCtx app_ctx, DM dm, Vec V,
19d1d35e2fSjeremylt                                 Vec V_loc, CeedData ceed_data, Ceed ceed,
20d1d35e2fSjeremylt                                 CeedQFunctionContext ctx_phys,
21d1d35e2fSjeremylt                                 CeedQFunctionContext ctx_phys_smoother,
22d1d35e2fSjeremylt                                 UserMult jacobian_ctx) {
23ccaff030SJeremy L Thompson   PetscErrorCode ierr;
24ccaff030SJeremy L Thompson 
25ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
26ccaff030SJeremy L Thompson 
27ccaff030SJeremy L Thompson   // PETSc objects
28d1d35e2fSjeremylt   jacobian_ctx->comm = comm;
29d1d35e2fSjeremylt   jacobian_ctx->dm = dm;
30ccaff030SJeremy L Thompson 
31ccaff030SJeremy L Thompson   // Work vectors
32d1d35e2fSjeremylt   jacobian_ctx->X_loc = V_loc;
33d1d35e2fSjeremylt   ierr = VecDuplicate(V_loc, &jacobian_ctx->Y_loc); CHKERRQ(ierr);
34d1d35e2fSjeremylt   jacobian_ctx->x_ceed = ceed_data->x_ceed;
35d1d35e2fSjeremylt   jacobian_ctx->y_ceed = ceed_data->y_ceed;
36ccaff030SJeremy L Thompson 
37ccaff030SJeremy L Thompson   // libCEED operator
385754ecacSJeremy L Thompson   jacobian_ctx->op = ceed_data->op_jacobian;
395754ecacSJeremy L Thompson   jacobian_ctx->qf = ceed_data->qf_jacobian;
40ccaff030SJeremy L Thompson 
41ccaff030SJeremy L Thompson   // Ceed
42d1d35e2fSjeremylt   jacobian_ctx->ceed = ceed;
43ccaff030SJeremy L Thompson 
44f7b4142eSJeremy L Thompson   // Physics
45d1d35e2fSjeremylt   jacobian_ctx->ctx_phys = ctx_phys;
46d1d35e2fSjeremylt   jacobian_ctx->ctx_phys_smoother = ctx_phys_smoother;
47ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
48ccaff030SJeremy L Thompson };
49ccaff030SJeremy L Thompson 
50ccaff030SJeremy L Thompson // Setup context data for prolongation and restriction operators
51d1d35e2fSjeremylt PetscErrorCode SetupProlongRestrictCtx(MPI_Comm comm, AppCtx app_ctx, DM dm_c,
52d1d35e2fSjeremylt                                        DM dm_f, Vec V_f, Vec V_loc_c, Vec V_loc_f,
53d1d35e2fSjeremylt                                        CeedData ceed_data_c, CeedData ceed_data_f,
54d1d35e2fSjeremylt                                        Ceed ceed, UserMultProlongRestr prolong_restr_ctx) {
55ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
56ccaff030SJeremy L Thompson 
57ccaff030SJeremy L Thompson   // PETSc objects
58d1d35e2fSjeremylt   prolong_restr_ctx->comm = comm;
59d1d35e2fSjeremylt   prolong_restr_ctx->dm_c = dm_c;
60d1d35e2fSjeremylt   prolong_restr_ctx->dm_f = dm_f;
61ccaff030SJeremy L Thompson 
62ccaff030SJeremy L Thompson   // Work vectors
63d1d35e2fSjeremylt   prolong_restr_ctx->loc_vec_c = V_loc_c;
64d1d35e2fSjeremylt   prolong_restr_ctx->loc_vec_f = V_loc_f;
65d1d35e2fSjeremylt   prolong_restr_ctx->ceed_vec_c = ceed_data_c->x_ceed;
66d1d35e2fSjeremylt   prolong_restr_ctx->ceed_vec_f = ceed_data_f->x_ceed;
67ccaff030SJeremy L Thompson 
68ccaff030SJeremy L Thompson   // libCEED operators
69d1d35e2fSjeremylt   prolong_restr_ctx->op_prolong = ceed_data_f->op_prolong;
70d1d35e2fSjeremylt   prolong_restr_ctx->op_restrict = ceed_data_f->op_restrict;
71ccaff030SJeremy L Thompson 
72ccaff030SJeremy L Thompson   // Ceed
73d1d35e2fSjeremylt   prolong_restr_ctx->ceed = ceed;
74ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
75ccaff030SJeremy L Thompson };
76ccaff030SJeremy L Thompson 
77ccaff030SJeremy L Thompson // -----------------------------------------------------------------------------
78ccaff030SJeremy L Thompson // Jacobian setup
79ccaff030SJeremy L Thompson // -----------------------------------------------------------------------------
80d1d35e2fSjeremylt PetscErrorCode FormJacobian(SNES snes, Vec U, Mat J, Mat J_pre, void *ctx) {
81ccaff030SJeremy L Thompson   PetscErrorCode ierr;
82ccaff030SJeremy L Thompson 
83ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
84ccaff030SJeremy L Thompson 
85ccaff030SJeremy L Thompson   // Context data
86d1d35e2fSjeremylt   FormJacobCtx  form_jacob_ctx = (FormJacobCtx)ctx;
87d1d35e2fSjeremylt   PetscInt      num_levels = form_jacob_ctx->num_levels;
88d1d35e2fSjeremylt   Mat           *jacob_mat = form_jacob_ctx->jacob_mat;
89ccaff030SJeremy L Thompson 
90e3e3df41Sjeremylt   // Update Jacobian on each level
91d1d35e2fSjeremylt   for (PetscInt level = 0; level < num_levels; level++) {
92d1d35e2fSjeremylt     ierr = MatAssemblyBegin(jacob_mat[level], MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
93d1d35e2fSjeremylt     ierr = MatAssemblyEnd(jacob_mat[level], MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
94ccaff030SJeremy L Thompson   }
95ccaff030SJeremy L Thompson 
96ccaff030SJeremy L Thompson   // Form coarse assembled matrix
9717f0843fSJeremy L Thompson   CeedOperatorLinearAssemble(form_jacob_ctx->op_coarse,
9817f0843fSJeremy L Thompson                              form_jacob_ctx->coo_values);
9917f0843fSJeremy L Thompson   const CeedScalar *values;
10017f0843fSJeremy L Thompson   CeedVectorGetArrayRead(form_jacob_ctx->coo_values, CEED_MEM_HOST, &values);
10117f0843fSJeremy L Thompson   ierr = MatSetValuesCOO(form_jacob_ctx->jacob_mat_coarse, values, ADD_VALUES);
102ccaff030SJeremy L Thompson   CHKERRQ(ierr);
10317f0843fSJeremy L Thompson   CeedVectorRestoreArrayRead(form_jacob_ctx->coo_values, &values);
104ccaff030SJeremy L Thompson 
105d1d35e2fSjeremylt   // J_pre might be AIJ (e.g., when using coloring), so we need to assemble it
106d1d35e2fSjeremylt   ierr = MatAssemblyBegin(J_pre, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
107d1d35e2fSjeremylt   ierr = MatAssemblyEnd(J_pre, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
108d1d35e2fSjeremylt   if (J != J_pre) {
1090e0d204cSJed Brown     ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1100e0d204cSJed Brown     ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1110e0d204cSJed Brown   }
112ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
113ccaff030SJeremy L Thompson };
114ccaff030SJeremy L Thompson 
115ccaff030SJeremy L Thompson // -----------------------------------------------------------------------------
116ccaff030SJeremy L Thompson // Output solution for visualization
117ccaff030SJeremy L Thompson // -----------------------------------------------------------------------------
118d1d35e2fSjeremylt PetscErrorCode ViewSolution(MPI_Comm comm, AppCtx app_ctx, Vec U,
119d1d35e2fSjeremylt                             PetscInt increment, PetscScalar load_increment) {
120ccaff030SJeremy L Thompson   PetscErrorCode ierr;
121ccaff030SJeremy L Thompson   DM dm;
122ccaff030SJeremy L Thompson   PetscViewer viewer;
123d1d35e2fSjeremylt   char output_filename[PETSC_MAX_PATH_LEN];
124d99129b9SLeila Ghaffari   PetscMPIInt rank;
125ccaff030SJeremy L Thompson 
126ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
127ccaff030SJeremy L Thompson 
128d99129b9SLeila Ghaffari   // Create output directory
129d99129b9SLeila Ghaffari   MPI_Comm_rank(comm, &rank);
130d1d35e2fSjeremylt   if (!rank) {ierr = PetscMkdir(app_ctx->output_dir); CHKERRQ(ierr);}
131d99129b9SLeila Ghaffari 
132ccaff030SJeremy L Thompson   // Build file name
133d1d35e2fSjeremylt   ierr = PetscSNPrintf(output_filename, sizeof output_filename,
134d1d35e2fSjeremylt                        "%s/solution-%03D.vtu", app_ctx->output_dir,
135d99129b9SLeila Ghaffari                        increment); CHKERRQ(ierr);
136ccaff030SJeremy L Thompson 
137050e48ebSJeremy L Thompson   // Increment sequence
138ccaff030SJeremy L Thompson   ierr = VecGetDM(U, &dm); CHKERRQ(ierr);
139d1d35e2fSjeremylt   ierr = DMSetOutputSequenceNumber(dm, increment, load_increment); CHKERRQ(ierr);
140ccaff030SJeremy L Thompson 
141ccaff030SJeremy L Thompson   // Output solution vector
142d1d35e2fSjeremylt   ierr = PetscViewerVTKOpen(comm, output_filename, FILE_MODE_WRITE, &viewer);
143ccaff030SJeremy L Thompson   CHKERRQ(ierr);
144ccaff030SJeremy L Thompson   ierr = VecView(U, viewer); CHKERRQ(ierr);
145ccaff030SJeremy L Thompson   ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
146ccaff030SJeremy L Thompson 
147ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
148ccaff030SJeremy L Thompson };
1495c25879aSJeremy L Thompson 
1505c25879aSJeremy L Thompson // -----------------------------------------------------------------------------
1515c25879aSJeremy L Thompson // Output diagnostic quantities for visualization
1525c25879aSJeremy L Thompson // -----------------------------------------------------------------------------
1535c25879aSJeremy L Thompson PetscErrorCode ViewDiagnosticQuantities(MPI_Comm comm, DM dmU,
154d1d35e2fSjeremylt                                         UserMult user, AppCtx app_ctx, Vec U,
155d1d35e2fSjeremylt                                         CeedElemRestriction elem_restr_diagnostic) {
1565c25879aSJeremy L Thompson   PetscErrorCode ierr;
157d1d35e2fSjeremylt   Vec Diagnostic, Y_loc, mult_vec;
158d1d35e2fSjeremylt   CeedVector y_ceed;
1595c25879aSJeremy L Thompson   CeedScalar *x, *y;
160d1d35e2fSjeremylt   PetscMemType x_mem_type, y_mem_type;
161d1d35e2fSjeremylt   PetscInt loc_size;
1625c25879aSJeremy L Thompson   PetscViewer viewer;
163d1d35e2fSjeremylt   char output_filename[PETSC_MAX_PATH_LEN];
1645c25879aSJeremy L Thompson 
1655c25879aSJeremy L Thompson   PetscFunctionBeginUser;
1665c25879aSJeremy L Thompson 
1675c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
1685c25879aSJeremy L Thompson   // PETSc and libCEED vectors
1695c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
1705c25879aSJeremy L Thompson   ierr = DMCreateGlobalVector(user->dm, &Diagnostic); CHKERRQ(ierr);
171f81c27eaSJed Brown   ierr = PetscObjectSetName((PetscObject)Diagnostic, ""); CHKERRQ(ierr);
172d1d35e2fSjeremylt   ierr = DMCreateLocalVector(user->dm, &Y_loc); CHKERRQ(ierr);
173d1d35e2fSjeremylt   ierr = VecGetSize(Y_loc, &loc_size); CHKERRQ(ierr);
174d1d35e2fSjeremylt   CeedVectorCreate(user->ceed, loc_size, &y_ceed);
1755c25879aSJeremy L Thompson 
1765c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
1775c25879aSJeremy L Thompson   // Compute quantities
1785c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
1795c25879aSJeremy L Thompson   // -- Global-to-local
180d1d35e2fSjeremylt   ierr = VecZeroEntries(user->X_loc); CHKERRQ(ierr);
181d1d35e2fSjeremylt   ierr = DMPlexInsertBoundaryValues(dmU, PETSC_TRUE, user->X_loc,
182d1d35e2fSjeremylt                                     user->load_increment, NULL, NULL, NULL);
1835c25879aSJeremy L Thompson   CHKERRQ(ierr);
184d1d35e2fSjeremylt   ierr = DMGlobalToLocal(dmU, U, INSERT_VALUES, user->X_loc); CHKERRQ(ierr);
185d1d35e2fSjeremylt   ierr = VecZeroEntries(Y_loc); CHKERRQ(ierr);
1865c25879aSJeremy L Thompson 
1875c25879aSJeremy L Thompson   // -- Setup CEED vectors
188d1d35e2fSjeremylt   ierr = VecGetArrayReadAndMemType(user->X_loc, (const PetscScalar **)&x,
189d1d35e2fSjeremylt                                    &x_mem_type); CHKERRQ(ierr);
190d1d35e2fSjeremylt   ierr = VecGetArrayAndMemType(Y_loc, &y, &y_mem_type); CHKERRQ(ierr);
191d1d35e2fSjeremylt   CeedVectorSetArray(user->x_ceed, MemTypeP2C(x_mem_type), CEED_USE_POINTER, x);
192d1d35e2fSjeremylt   CeedVectorSetArray(y_ceed, MemTypeP2C(y_mem_type), CEED_USE_POINTER, y);
1935c25879aSJeremy L Thompson 
1945c25879aSJeremy L Thompson   // -- Apply CEED operator
195d1d35e2fSjeremylt   CeedOperatorApply(user->op, user->x_ceed, y_ceed, CEED_REQUEST_IMMEDIATE);
1965c25879aSJeremy L Thompson 
197d1d35e2fSjeremylt   // -- Restore PETSc vector; keep y_ceed viewing memory of Y_loc for use below
198d1d35e2fSjeremylt   CeedVectorTakeArray(user->x_ceed, MemTypeP2C(x_mem_type), NULL);
199d1d35e2fSjeremylt   ierr = VecRestoreArrayReadAndMemType(user->X_loc, (const PetscScalar **)&x);
2005c25879aSJeremy L Thompson   CHKERRQ(ierr);
2015c25879aSJeremy L Thompson 
2025c25879aSJeremy L Thompson   // -- Local-to-global
2035c25879aSJeremy L Thompson   ierr = VecZeroEntries(Diagnostic); CHKERRQ(ierr);
204d1d35e2fSjeremylt   ierr = DMLocalToGlobal(user->dm, Y_loc, ADD_VALUES, Diagnostic);
2055c25879aSJeremy L Thompson   CHKERRQ(ierr);
2065c25879aSJeremy L Thompson 
2075c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
2085c25879aSJeremy L Thompson   // Scale for multiplicity
2095c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
2105c25879aSJeremy L Thompson   // -- Setup vectors
211d1d35e2fSjeremylt   ierr = VecDuplicate(Diagnostic, &mult_vec); CHKERRQ(ierr);
212d1d35e2fSjeremylt   ierr = VecZeroEntries(Y_loc); CHKERRQ(ierr);
2135c25879aSJeremy L Thompson 
2145c25879aSJeremy L Thompson   // -- Compute multiplicity
215d1d35e2fSjeremylt   CeedElemRestrictionGetMultiplicity(elem_restr_diagnostic, y_ceed);
2165c25879aSJeremy L Thompson 
2175c25879aSJeremy L Thompson   // -- Restore vectors
218d1d35e2fSjeremylt   CeedVectorTakeArray(y_ceed, MemTypeP2C(y_mem_type), NULL);
219d1d35e2fSjeremylt   ierr = VecRestoreArrayAndMemType(Y_loc, &y); CHKERRQ(ierr);
2205c25879aSJeremy L Thompson 
2215c25879aSJeremy L Thompson   // -- Local-to-global
222d1d35e2fSjeremylt   ierr = VecZeroEntries(mult_vec); CHKERRQ(ierr);
223d1d35e2fSjeremylt   ierr = DMLocalToGlobal(user->dm, Y_loc, ADD_VALUES, mult_vec);
2245c25879aSJeremy L Thompson   CHKERRQ(ierr);
2255c25879aSJeremy L Thompson 
2265c25879aSJeremy L Thompson   // -- Scale
227d1d35e2fSjeremylt   ierr = VecReciprocal(mult_vec); CHKERRQ(ierr);
228d1d35e2fSjeremylt   ierr = VecPointwiseMult(Diagnostic, Diagnostic, mult_vec);
2295c25879aSJeremy L Thompson 
2305c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
2315c25879aSJeremy L Thompson   // Output solution vector
2325c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
233d1d35e2fSjeremylt   ierr = PetscSNPrintf(output_filename, sizeof output_filename,
234d99129b9SLeila Ghaffari                        "%s/diagnostic_quantities.vtu",
235d1d35e2fSjeremylt                        app_ctx->output_dir); CHKERRQ(ierr);
236d1d35e2fSjeremylt   ierr = PetscViewerVTKOpen(comm, output_filename, FILE_MODE_WRITE, &viewer);
2375c25879aSJeremy L Thompson   CHKERRQ(ierr);
2385c25879aSJeremy L Thompson   ierr = VecView(Diagnostic, viewer); CHKERRQ(ierr);
2395c25879aSJeremy L Thompson   ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
2405c25879aSJeremy L Thompson 
2415c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
2425c25879aSJeremy L Thompson   // Cleanup
2435c25879aSJeremy L Thompson   // ---------------------------------------------------------------------------
2445c25879aSJeremy L Thompson   ierr = VecDestroy(&Diagnostic); CHKERRQ(ierr);
245d1d35e2fSjeremylt   ierr = VecDestroy(&mult_vec); CHKERRQ(ierr);
246d1d35e2fSjeremylt   ierr = VecDestroy(&Y_loc); CHKERRQ(ierr);
247d1d35e2fSjeremylt   CeedVectorDestroy(&y_ceed);
2485c25879aSJeremy L Thompson 
2495c25879aSJeremy L Thompson   PetscFunctionReturn(0);
2505c25879aSJeremy L Thompson };
2515754ecacSJeremy L Thompson 
2525754ecacSJeremy L Thompson // -----------------------------------------------------------------------------
2535754ecacSJeremy L Thompson // Regression testing
2545754ecacSJeremy L Thompson // -----------------------------------------------------------------------------
2555754ecacSJeremy L Thompson // test option change. could remove the loading step. Run only with one loading step and compare relatively to ref file
2565754ecacSJeremy 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
2575754ecacSJeremy L Thompson PetscErrorCode RegressionTests_solids(AppCtx app_ctx, PetscReal energy) {
2585754ecacSJeremy L Thompson   PetscFunctionBegin;
2595754ecacSJeremy L Thompson 
2605754ecacSJeremy L Thompson   if (app_ctx->expect_final_strain >= 0.) {
2615754ecacSJeremy L Thompson     PetscReal energy_ref = app_ctx->expect_final_strain;
2625754ecacSJeremy L Thompson     PetscReal error = PetscAbsReal(energy - energy_ref) / energy_ref;
2635754ecacSJeremy L Thompson 
2645754ecacSJeremy L Thompson     if (error > app_ctx->test_tol) {
2655754ecacSJeremy L Thompson       PetscErrorCode ierr;
2665754ecacSJeremy L Thompson       ierr = PetscPrintf(PETSC_COMM_WORLD,
2675754ecacSJeremy L Thompson                          "Energy %e does not match expected energy %e: relative tolerance %e > %e\n",
2685754ecacSJeremy L Thompson                          (double)energy, (double)energy_ref, (double)error, app_ctx->test_tol);
2695754ecacSJeremy L Thompson       CHKERRQ(ierr);
2705754ecacSJeremy L Thompson     }
2715754ecacSJeremy L Thompson   }
2725754ecacSJeremy L Thompson   PetscFunctionReturn(0);
2735754ecacSJeremy L Thompson };
274