13d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 33d8e8822SJeremy L Thompson // 43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 53d8e8822SJeremy L Thompson // 63d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 73d8e8822SJeremy 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" 122b730f8bSJeremy L Thompson 13*49aac155SJeremy L Thompson #include <ceed.h> 14*49aac155SJeremy L Thompson #include <petscdmplex.h> 15*49aac155SJeremy L Thompson #include <petscmat.h> 16*49aac155SJeremy L Thompson 175754ecacSJeremy L Thompson #include "../include/utils.h" 18ccaff030SJeremy L Thompson 19ccaff030SJeremy L Thompson // ----------------------------------------------------------------------------- 20ccaff030SJeremy L Thompson // Create libCEED operator context 21ccaff030SJeremy L Thompson // ----------------------------------------------------------------------------- 22ccaff030SJeremy L Thompson // Setup context data for Jacobian evaluation 232b730f8bSJeremy L Thompson PetscErrorCode SetupJacobianCtx(MPI_Comm comm, AppCtx app_ctx, DM dm, Vec V, Vec V_loc, CeedData ceed_data, Ceed ceed, CeedQFunctionContext ctx_phys, 242b730f8bSJeremy L Thompson CeedQFunctionContext ctx_phys_smoother, UserMult jacobian_ctx) { 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; 332b730f8bSJeremy L Thompson PetscCall(VecDuplicate(V_loc, &jacobian_ctx->Y_loc)); 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 512b730f8bSJeremy L Thompson PetscErrorCode SetupProlongRestrictCtx(MPI_Comm comm, AppCtx app_ctx, DM dm_c, DM dm_f, Vec V_f, Vec V_loc_c, Vec V_loc_f, CeedData ceed_data_c, 522b730f8bSJeremy L Thompson CeedData ceed_data_f, Ceed ceed, UserMultProlongRestr prolong_restr_ctx) { 53ccaff030SJeremy L Thompson PetscFunctionBeginUser; 54ccaff030SJeremy L Thompson 55ccaff030SJeremy L Thompson // PETSc objects 56d1d35e2fSjeremylt prolong_restr_ctx->comm = comm; 57d1d35e2fSjeremylt prolong_restr_ctx->dm_c = dm_c; 58d1d35e2fSjeremylt prolong_restr_ctx->dm_f = dm_f; 59ccaff030SJeremy L Thompson 60ccaff030SJeremy L Thompson // Work vectors 61d1d35e2fSjeremylt prolong_restr_ctx->loc_vec_c = V_loc_c; 62d1d35e2fSjeremylt prolong_restr_ctx->loc_vec_f = V_loc_f; 63d1d35e2fSjeremylt prolong_restr_ctx->ceed_vec_c = ceed_data_c->x_ceed; 64d1d35e2fSjeremylt prolong_restr_ctx->ceed_vec_f = ceed_data_f->x_ceed; 65ccaff030SJeremy L Thompson 66ccaff030SJeremy L Thompson // libCEED operators 67d1d35e2fSjeremylt prolong_restr_ctx->op_prolong = ceed_data_f->op_prolong; 68d1d35e2fSjeremylt prolong_restr_ctx->op_restrict = ceed_data_f->op_restrict; 69ccaff030SJeremy L Thompson 70ccaff030SJeremy L Thompson // Ceed 71d1d35e2fSjeremylt prolong_restr_ctx->ceed = ceed; 72ccaff030SJeremy L Thompson PetscFunctionReturn(0); 73ccaff030SJeremy L Thompson }; 74ccaff030SJeremy L Thompson 75ccaff030SJeremy L Thompson // ----------------------------------------------------------------------------- 76ccaff030SJeremy L Thompson // Jacobian setup 77ccaff030SJeremy L Thompson // ----------------------------------------------------------------------------- 78d1d35e2fSjeremylt PetscErrorCode FormJacobian(SNES snes, Vec U, Mat J, Mat J_pre, void *ctx) { 79ccaff030SJeremy L Thompson PetscFunctionBeginUser; 80ccaff030SJeremy L Thompson 81ccaff030SJeremy L Thompson // Context data 82d1d35e2fSjeremylt FormJacobCtx form_jacob_ctx = (FormJacobCtx)ctx; 83d1d35e2fSjeremylt PetscInt num_levels = form_jacob_ctx->num_levels; 84d1d35e2fSjeremylt Mat *jacob_mat = form_jacob_ctx->jacob_mat; 85ccaff030SJeremy L Thompson 86e3e3df41Sjeremylt // Update Jacobian on each level 87d1d35e2fSjeremylt for (PetscInt level = 0; level < num_levels; level++) { 882b730f8bSJeremy L Thompson PetscCall(MatAssemblyBegin(jacob_mat[level], MAT_FINAL_ASSEMBLY)); 892b730f8bSJeremy L Thompson PetscCall(MatAssemblyEnd(jacob_mat[level], MAT_FINAL_ASSEMBLY)); 90ccaff030SJeremy L Thompson } 91ccaff030SJeremy L Thompson 92ccaff030SJeremy L Thompson // Form coarse assembled matrix 932b730f8bSJeremy L Thompson CeedOperatorLinearAssemble(form_jacob_ctx->op_coarse, form_jacob_ctx->coo_values); 9417f0843fSJeremy L Thompson const CeedScalar *values; 9517f0843fSJeremy L Thompson CeedVectorGetArrayRead(form_jacob_ctx->coo_values, CEED_MEM_HOST, &values); 962b730f8bSJeremy L Thompson PetscCall(MatSetValuesCOO(form_jacob_ctx->jacob_mat_coarse, values, ADD_VALUES)); 9717f0843fSJeremy L Thompson CeedVectorRestoreArrayRead(form_jacob_ctx->coo_values, &values); 98ccaff030SJeremy L Thompson 99d1d35e2fSjeremylt // J_pre might be AIJ (e.g., when using coloring), so we need to assemble it 1002b730f8bSJeremy L Thompson PetscCall(MatAssemblyBegin(J_pre, MAT_FINAL_ASSEMBLY)); 1012b730f8bSJeremy L Thompson PetscCall(MatAssemblyEnd(J_pre, MAT_FINAL_ASSEMBLY)); 102d1d35e2fSjeremylt if (J != J_pre) { 1032b730f8bSJeremy L Thompson PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 1042b730f8bSJeremy L Thompson PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 1050e0d204cSJed Brown } 106ccaff030SJeremy L Thompson PetscFunctionReturn(0); 107ccaff030SJeremy L Thompson }; 108ccaff030SJeremy L Thompson 109ccaff030SJeremy L Thompson // ----------------------------------------------------------------------------- 110ccaff030SJeremy L Thompson // Output solution for visualization 111ccaff030SJeremy L Thompson // ----------------------------------------------------------------------------- 1122b730f8bSJeremy L Thompson PetscErrorCode ViewSolution(MPI_Comm comm, AppCtx app_ctx, Vec U, PetscInt increment, PetscScalar load_increment) { 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); 1222b730f8bSJeremy L Thompson if (!rank) { 1232b730f8bSJeremy L Thompson PetscCall(PetscMkdir(app_ctx->output_dir)); 1242b730f8bSJeremy L Thompson } 125d99129b9SLeila Ghaffari 126ccaff030SJeremy L Thompson // Build file name 1272b730f8bSJeremy L Thompson PetscCall(PetscSNPrintf(output_filename, sizeof output_filename, "%s/solution-%03" PetscInt_FMT ".vtu", app_ctx->output_dir, increment)); 128ccaff030SJeremy L Thompson 129050e48ebSJeremy L Thompson // Increment sequence 1302b730f8bSJeremy L Thompson PetscCall(VecGetDM(U, &dm)); 1312b730f8bSJeremy L Thompson PetscCall(DMSetOutputSequenceNumber(dm, increment, load_increment)); 132ccaff030SJeremy L Thompson 133ccaff030SJeremy L Thompson // Output solution vector 1342b730f8bSJeremy L Thompson PetscCall(PetscViewerVTKOpen(comm, output_filename, FILE_MODE_WRITE, &viewer)); 1352b730f8bSJeremy L Thompson PetscCall(VecView(U, viewer)); 1362b730f8bSJeremy L Thompson PetscCall(PetscViewerDestroy(&viewer)); 137ccaff030SJeremy L Thompson 138ccaff030SJeremy L Thompson PetscFunctionReturn(0); 139ccaff030SJeremy L Thompson }; 1405c25879aSJeremy L Thompson 1415c25879aSJeremy L Thompson // ----------------------------------------------------------------------------- 1425c25879aSJeremy L Thompson // Output diagnostic quantities for visualization 1435c25879aSJeremy L Thompson // ----------------------------------------------------------------------------- 1442b730f8bSJeremy L Thompson PetscErrorCode ViewDiagnosticQuantities(MPI_Comm comm, DM dmU, UserMult user, AppCtx app_ctx, Vec U, CeedElemRestriction elem_restr_diagnostic) { 145d1d35e2fSjeremylt Vec Diagnostic, Y_loc, mult_vec; 146d1d35e2fSjeremylt CeedVector y_ceed; 1475c25879aSJeremy L Thompson CeedScalar *x, *y; 148d1d35e2fSjeremylt PetscMemType x_mem_type, y_mem_type; 149d1d35e2fSjeremylt PetscInt loc_size; 1505c25879aSJeremy L Thompson PetscViewer viewer; 151d1d35e2fSjeremylt char output_filename[PETSC_MAX_PATH_LEN]; 1525c25879aSJeremy L Thompson 1535c25879aSJeremy L Thompson PetscFunctionBeginUser; 1545c25879aSJeremy L Thompson 1555c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 1565c25879aSJeremy L Thompson // PETSc and libCEED vectors 1575c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 1582b730f8bSJeremy L Thompson PetscCall(DMCreateGlobalVector(user->dm, &Diagnostic)); 1592b730f8bSJeremy L Thompson PetscCall(PetscObjectSetName((PetscObject)Diagnostic, "")); 1602b730f8bSJeremy L Thompson PetscCall(DMCreateLocalVector(user->dm, &Y_loc)); 1612b730f8bSJeremy L Thompson PetscCall(VecGetSize(Y_loc, &loc_size)); 162d1d35e2fSjeremylt CeedVectorCreate(user->ceed, loc_size, &y_ceed); 1635c25879aSJeremy L Thompson 1645c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 1655c25879aSJeremy L Thompson // Compute quantities 1665c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 1675c25879aSJeremy L Thompson // -- Global-to-local 1682b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(user->X_loc)); 1692b730f8bSJeremy L Thompson PetscCall(DMPlexInsertBoundaryValues(dmU, PETSC_TRUE, user->X_loc, user->load_increment, NULL, NULL, NULL)); 1702b730f8bSJeremy L Thompson PetscCall(DMGlobalToLocal(dmU, U, INSERT_VALUES, user->X_loc)); 1712b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(Y_loc)); 1725c25879aSJeremy L Thompson 1735c25879aSJeremy L Thompson // -- Setup CEED vectors 1742b730f8bSJeremy L Thompson PetscCall(VecGetArrayReadAndMemType(user->X_loc, (const PetscScalar **)&x, &x_mem_type)); 1752b730f8bSJeremy L Thompson PetscCall(VecGetArrayAndMemType(Y_loc, &y, &y_mem_type)); 176d1d35e2fSjeremylt CeedVectorSetArray(user->x_ceed, MemTypeP2C(x_mem_type), CEED_USE_POINTER, x); 177d1d35e2fSjeremylt CeedVectorSetArray(y_ceed, MemTypeP2C(y_mem_type), CEED_USE_POINTER, y); 1785c25879aSJeremy L Thompson 1795c25879aSJeremy L Thompson // -- Apply CEED operator 180d1d35e2fSjeremylt CeedOperatorApply(user->op, user->x_ceed, y_ceed, CEED_REQUEST_IMMEDIATE); 1815c25879aSJeremy L Thompson 182d1d35e2fSjeremylt // -- Restore PETSc vector; keep y_ceed viewing memory of Y_loc for use below 183d1d35e2fSjeremylt CeedVectorTakeArray(user->x_ceed, MemTypeP2C(x_mem_type), NULL); 1842b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayReadAndMemType(user->X_loc, (const PetscScalar **)&x)); 1855c25879aSJeremy L Thompson 1865c25879aSJeremy L Thompson // -- Local-to-global 1872b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(Diagnostic)); 1882b730f8bSJeremy L Thompson PetscCall(DMLocalToGlobal(user->dm, Y_loc, ADD_VALUES, Diagnostic)); 1895c25879aSJeremy L Thompson 1905c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 1915c25879aSJeremy L Thompson // Scale for multiplicity 1925c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 1935c25879aSJeremy L Thompson // -- Setup vectors 1942b730f8bSJeremy L Thompson PetscCall(VecDuplicate(Diagnostic, &mult_vec)); 1952b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(Y_loc)); 1965c25879aSJeremy L Thompson 1975c25879aSJeremy L Thompson // -- Compute multiplicity 198d1d35e2fSjeremylt CeedElemRestrictionGetMultiplicity(elem_restr_diagnostic, y_ceed); 1995c25879aSJeremy L Thompson 2005c25879aSJeremy L Thompson // -- Restore vectors 201d1d35e2fSjeremylt CeedVectorTakeArray(y_ceed, MemTypeP2C(y_mem_type), NULL); 2022b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayAndMemType(Y_loc, &y)); 2035c25879aSJeremy L Thompson 2045c25879aSJeremy L Thompson // -- Local-to-global 2052b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(mult_vec)); 2062b730f8bSJeremy L Thompson PetscCall(DMLocalToGlobal(user->dm, Y_loc, ADD_VALUES, mult_vec)); 2075c25879aSJeremy L Thompson 2085c25879aSJeremy L Thompson // -- Scale 2092b730f8bSJeremy L Thompson PetscCall(VecReciprocal(mult_vec)); 2102b730f8bSJeremy L Thompson PetscCall(VecPointwiseMult(Diagnostic, Diagnostic, mult_vec)); 2115c25879aSJeremy L Thompson 2125c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 2135c25879aSJeremy L Thompson // Output solution vector 2145c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 2152b730f8bSJeremy L Thompson PetscCall(PetscSNPrintf(output_filename, sizeof output_filename, "%s/diagnostic_quantities.vtu", app_ctx->output_dir)); 2162b730f8bSJeremy L Thompson PetscCall(PetscViewerVTKOpen(comm, output_filename, FILE_MODE_WRITE, &viewer)); 2172b730f8bSJeremy L Thompson PetscCall(VecView(Diagnostic, viewer)); 2182b730f8bSJeremy L Thompson PetscCall(PetscViewerDestroy(&viewer)); 2195c25879aSJeremy L Thompson 2205c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 2215c25879aSJeremy L Thompson // Cleanup 2225c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 2232b730f8bSJeremy L Thompson PetscCall(VecDestroy(&Diagnostic)); 2242b730f8bSJeremy L Thompson PetscCall(VecDestroy(&mult_vec)); 2252b730f8bSJeremy L Thompson PetscCall(VecDestroy(&Y_loc)); 226d1d35e2fSjeremylt CeedVectorDestroy(&y_ceed); 2275c25879aSJeremy L Thompson 2285c25879aSJeremy L Thompson PetscFunctionReturn(0); 2295c25879aSJeremy L Thompson }; 2305754ecacSJeremy L Thompson 2315754ecacSJeremy L Thompson // ----------------------------------------------------------------------------- 2325754ecacSJeremy L Thompson // Regression testing 2335754ecacSJeremy L Thompson // ----------------------------------------------------------------------------- 2345754ecacSJeremy L Thompson // test option change. could remove the loading step. Run only with one loading step and compare relatively to ref file 2352b730f8bSJeremy 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 2362b730f8bSJeremy L Thompson // energy 2375754ecacSJeremy L Thompson PetscErrorCode RegressionTests_solids(AppCtx app_ctx, PetscReal energy) { 2385754ecacSJeremy L Thompson PetscFunctionBegin; 2395754ecacSJeremy L Thompson 2405754ecacSJeremy L Thompson if (app_ctx->expect_final_strain >= 0.) { 2415754ecacSJeremy L Thompson PetscReal energy_ref = app_ctx->expect_final_strain; 2425754ecacSJeremy L Thompson PetscReal error = PetscAbsReal(energy - energy_ref) / energy_ref; 2435754ecacSJeremy L Thompson 2445754ecacSJeremy L Thompson if (error > app_ctx->test_tol) { 2452b730f8bSJeremy L Thompson PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Energy %e does not match expected energy %e: relative tolerance %e > %e\n", (double)energy, 2462b730f8bSJeremy L Thompson (double)energy_ref, (double)error, app_ctx->test_tol)); 2475754ecacSJeremy L Thompson } 2485754ecacSJeremy L Thompson } 2495754ecacSJeremy L Thompson PetscFunctionReturn(0); 2505754ecacSJeremy L Thompson }; 251