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" 12*2b730f8bSJeremy L Thompson 135754ecacSJeremy L Thompson #include "../include/utils.h" 14ccaff030SJeremy L Thompson 15ccaff030SJeremy L Thompson // ----------------------------------------------------------------------------- 16ccaff030SJeremy L Thompson // Create libCEED operator context 17ccaff030SJeremy L Thompson // ----------------------------------------------------------------------------- 18ccaff030SJeremy L Thompson // Setup context data for Jacobian evaluation 19*2b730f8bSJeremy 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, 20*2b730f8bSJeremy L Thompson CeedQFunctionContext ctx_phys_smoother, UserMult jacobian_ctx) { 21ccaff030SJeremy L Thompson PetscFunctionBeginUser; 22ccaff030SJeremy L Thompson 23ccaff030SJeremy L Thompson // PETSc objects 24d1d35e2fSjeremylt jacobian_ctx->comm = comm; 25d1d35e2fSjeremylt jacobian_ctx->dm = dm; 26ccaff030SJeremy L Thompson 27ccaff030SJeremy L Thompson // Work vectors 28d1d35e2fSjeremylt jacobian_ctx->X_loc = V_loc; 29*2b730f8bSJeremy L Thompson PetscCall(VecDuplicate(V_loc, &jacobian_ctx->Y_loc)); 30d1d35e2fSjeremylt jacobian_ctx->x_ceed = ceed_data->x_ceed; 31d1d35e2fSjeremylt jacobian_ctx->y_ceed = ceed_data->y_ceed; 32ccaff030SJeremy L Thompson 33ccaff030SJeremy L Thompson // libCEED operator 345754ecacSJeremy L Thompson jacobian_ctx->op = ceed_data->op_jacobian; 355754ecacSJeremy L Thompson jacobian_ctx->qf = ceed_data->qf_jacobian; 36ccaff030SJeremy L Thompson 37ccaff030SJeremy L Thompson // Ceed 38d1d35e2fSjeremylt jacobian_ctx->ceed = ceed; 39ccaff030SJeremy L Thompson 40f7b4142eSJeremy L Thompson // Physics 41d1d35e2fSjeremylt jacobian_ctx->ctx_phys = ctx_phys; 42d1d35e2fSjeremylt jacobian_ctx->ctx_phys_smoother = ctx_phys_smoother; 43ccaff030SJeremy L Thompson PetscFunctionReturn(0); 44ccaff030SJeremy L Thompson }; 45ccaff030SJeremy L Thompson 46ccaff030SJeremy L Thompson // Setup context data for prolongation and restriction operators 47*2b730f8bSJeremy 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, 48*2b730f8bSJeremy L Thompson CeedData ceed_data_f, Ceed ceed, UserMultProlongRestr prolong_restr_ctx) { 49ccaff030SJeremy L Thompson PetscFunctionBeginUser; 50ccaff030SJeremy L Thompson 51ccaff030SJeremy L Thompson // PETSc objects 52d1d35e2fSjeremylt prolong_restr_ctx->comm = comm; 53d1d35e2fSjeremylt prolong_restr_ctx->dm_c = dm_c; 54d1d35e2fSjeremylt prolong_restr_ctx->dm_f = dm_f; 55ccaff030SJeremy L Thompson 56ccaff030SJeremy L Thompson // Work vectors 57d1d35e2fSjeremylt prolong_restr_ctx->loc_vec_c = V_loc_c; 58d1d35e2fSjeremylt prolong_restr_ctx->loc_vec_f = V_loc_f; 59d1d35e2fSjeremylt prolong_restr_ctx->ceed_vec_c = ceed_data_c->x_ceed; 60d1d35e2fSjeremylt prolong_restr_ctx->ceed_vec_f = ceed_data_f->x_ceed; 61ccaff030SJeremy L Thompson 62ccaff030SJeremy L Thompson // libCEED operators 63d1d35e2fSjeremylt prolong_restr_ctx->op_prolong = ceed_data_f->op_prolong; 64d1d35e2fSjeremylt prolong_restr_ctx->op_restrict = ceed_data_f->op_restrict; 65ccaff030SJeremy L Thompson 66ccaff030SJeremy L Thompson // Ceed 67d1d35e2fSjeremylt prolong_restr_ctx->ceed = ceed; 68ccaff030SJeremy L Thompson PetscFunctionReturn(0); 69ccaff030SJeremy L Thompson }; 70ccaff030SJeremy L Thompson 71ccaff030SJeremy L Thompson // ----------------------------------------------------------------------------- 72ccaff030SJeremy L Thompson // Jacobian setup 73ccaff030SJeremy L Thompson // ----------------------------------------------------------------------------- 74d1d35e2fSjeremylt PetscErrorCode FormJacobian(SNES snes, Vec U, Mat J, Mat J_pre, void *ctx) { 75ccaff030SJeremy L Thompson PetscFunctionBeginUser; 76ccaff030SJeremy L Thompson 77ccaff030SJeremy L Thompson // Context data 78d1d35e2fSjeremylt FormJacobCtx form_jacob_ctx = (FormJacobCtx)ctx; 79d1d35e2fSjeremylt PetscInt num_levels = form_jacob_ctx->num_levels; 80d1d35e2fSjeremylt Mat *jacob_mat = form_jacob_ctx->jacob_mat; 81ccaff030SJeremy L Thompson 82e3e3df41Sjeremylt // Update Jacobian on each level 83d1d35e2fSjeremylt for (PetscInt level = 0; level < num_levels; level++) { 84*2b730f8bSJeremy L Thompson PetscCall(MatAssemblyBegin(jacob_mat[level], MAT_FINAL_ASSEMBLY)); 85*2b730f8bSJeremy L Thompson PetscCall(MatAssemblyEnd(jacob_mat[level], MAT_FINAL_ASSEMBLY)); 86ccaff030SJeremy L Thompson } 87ccaff030SJeremy L Thompson 88ccaff030SJeremy L Thompson // Form coarse assembled matrix 89*2b730f8bSJeremy L Thompson CeedOperatorLinearAssemble(form_jacob_ctx->op_coarse, form_jacob_ctx->coo_values); 9017f0843fSJeremy L Thompson const CeedScalar *values; 9117f0843fSJeremy L Thompson CeedVectorGetArrayRead(form_jacob_ctx->coo_values, CEED_MEM_HOST, &values); 92*2b730f8bSJeremy L Thompson PetscCall(MatSetValuesCOO(form_jacob_ctx->jacob_mat_coarse, values, ADD_VALUES)); 9317f0843fSJeremy L Thompson CeedVectorRestoreArrayRead(form_jacob_ctx->coo_values, &values); 94ccaff030SJeremy L Thompson 95d1d35e2fSjeremylt // J_pre might be AIJ (e.g., when using coloring), so we need to assemble it 96*2b730f8bSJeremy L Thompson PetscCall(MatAssemblyBegin(J_pre, MAT_FINAL_ASSEMBLY)); 97*2b730f8bSJeremy L Thompson PetscCall(MatAssemblyEnd(J_pre, MAT_FINAL_ASSEMBLY)); 98d1d35e2fSjeremylt if (J != J_pre) { 99*2b730f8bSJeremy L Thompson PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 100*2b730f8bSJeremy L Thompson PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 1010e0d204cSJed Brown } 102ccaff030SJeremy L Thompson PetscFunctionReturn(0); 103ccaff030SJeremy L Thompson }; 104ccaff030SJeremy L Thompson 105ccaff030SJeremy L Thompson // ----------------------------------------------------------------------------- 106ccaff030SJeremy L Thompson // Output solution for visualization 107ccaff030SJeremy L Thompson // ----------------------------------------------------------------------------- 108*2b730f8bSJeremy L Thompson PetscErrorCode ViewSolution(MPI_Comm comm, AppCtx app_ctx, Vec U, PetscInt increment, PetscScalar load_increment) { 109ccaff030SJeremy L Thompson DM dm; 110ccaff030SJeremy L Thompson PetscViewer viewer; 111d1d35e2fSjeremylt char output_filename[PETSC_MAX_PATH_LEN]; 112d99129b9SLeila Ghaffari PetscMPIInt rank; 113ccaff030SJeremy L Thompson 114ccaff030SJeremy L Thompson PetscFunctionBeginUser; 115ccaff030SJeremy L Thompson 116d99129b9SLeila Ghaffari // Create output directory 117d99129b9SLeila Ghaffari MPI_Comm_rank(comm, &rank); 118*2b730f8bSJeremy L Thompson if (!rank) { 119*2b730f8bSJeremy L Thompson PetscCall(PetscMkdir(app_ctx->output_dir)); 120*2b730f8bSJeremy L Thompson } 121d99129b9SLeila Ghaffari 122ccaff030SJeremy L Thompson // Build file name 123*2b730f8bSJeremy L Thompson PetscCall(PetscSNPrintf(output_filename, sizeof output_filename, "%s/solution-%03" PetscInt_FMT ".vtu", app_ctx->output_dir, increment)); 124ccaff030SJeremy L Thompson 125050e48ebSJeremy L Thompson // Increment sequence 126*2b730f8bSJeremy L Thompson PetscCall(VecGetDM(U, &dm)); 127*2b730f8bSJeremy L Thompson PetscCall(DMSetOutputSequenceNumber(dm, increment, load_increment)); 128ccaff030SJeremy L Thompson 129ccaff030SJeremy L Thompson // Output solution vector 130*2b730f8bSJeremy L Thompson PetscCall(PetscViewerVTKOpen(comm, output_filename, FILE_MODE_WRITE, &viewer)); 131*2b730f8bSJeremy L Thompson PetscCall(VecView(U, viewer)); 132*2b730f8bSJeremy L Thompson PetscCall(PetscViewerDestroy(&viewer)); 133ccaff030SJeremy L Thompson 134ccaff030SJeremy L Thompson PetscFunctionReturn(0); 135ccaff030SJeremy L Thompson }; 1365c25879aSJeremy L Thompson 1375c25879aSJeremy L Thompson // ----------------------------------------------------------------------------- 1385c25879aSJeremy L Thompson // Output diagnostic quantities for visualization 1395c25879aSJeremy L Thompson // ----------------------------------------------------------------------------- 140*2b730f8bSJeremy L Thompson PetscErrorCode ViewDiagnosticQuantities(MPI_Comm comm, DM dmU, UserMult user, AppCtx app_ctx, Vec U, CeedElemRestriction elem_restr_diagnostic) { 141d1d35e2fSjeremylt Vec Diagnostic, Y_loc, mult_vec; 142d1d35e2fSjeremylt CeedVector y_ceed; 1435c25879aSJeremy L Thompson CeedScalar *x, *y; 144d1d35e2fSjeremylt PetscMemType x_mem_type, y_mem_type; 145d1d35e2fSjeremylt PetscInt loc_size; 1465c25879aSJeremy L Thompson PetscViewer viewer; 147d1d35e2fSjeremylt char output_filename[PETSC_MAX_PATH_LEN]; 1485c25879aSJeremy L Thompson 1495c25879aSJeremy L Thompson PetscFunctionBeginUser; 1505c25879aSJeremy L Thompson 1515c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 1525c25879aSJeremy L Thompson // PETSc and libCEED vectors 1535c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 154*2b730f8bSJeremy L Thompson PetscCall(DMCreateGlobalVector(user->dm, &Diagnostic)); 155*2b730f8bSJeremy L Thompson PetscCall(PetscObjectSetName((PetscObject)Diagnostic, "")); 156*2b730f8bSJeremy L Thompson PetscCall(DMCreateLocalVector(user->dm, &Y_loc)); 157*2b730f8bSJeremy L Thompson PetscCall(VecGetSize(Y_loc, &loc_size)); 158d1d35e2fSjeremylt CeedVectorCreate(user->ceed, loc_size, &y_ceed); 1595c25879aSJeremy L Thompson 1605c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 1615c25879aSJeremy L Thompson // Compute quantities 1625c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 1635c25879aSJeremy L Thompson // -- Global-to-local 164*2b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(user->X_loc)); 165*2b730f8bSJeremy L Thompson PetscCall(DMPlexInsertBoundaryValues(dmU, PETSC_TRUE, user->X_loc, user->load_increment, NULL, NULL, NULL)); 166*2b730f8bSJeremy L Thompson PetscCall(DMGlobalToLocal(dmU, U, INSERT_VALUES, user->X_loc)); 167*2b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(Y_loc)); 1685c25879aSJeremy L Thompson 1695c25879aSJeremy L Thompson // -- Setup CEED vectors 170*2b730f8bSJeremy L Thompson PetscCall(VecGetArrayReadAndMemType(user->X_loc, (const PetscScalar **)&x, &x_mem_type)); 171*2b730f8bSJeremy L Thompson PetscCall(VecGetArrayAndMemType(Y_loc, &y, &y_mem_type)); 172d1d35e2fSjeremylt CeedVectorSetArray(user->x_ceed, MemTypeP2C(x_mem_type), CEED_USE_POINTER, x); 173d1d35e2fSjeremylt CeedVectorSetArray(y_ceed, MemTypeP2C(y_mem_type), CEED_USE_POINTER, y); 1745c25879aSJeremy L Thompson 1755c25879aSJeremy L Thompson // -- Apply CEED operator 176d1d35e2fSjeremylt CeedOperatorApply(user->op, user->x_ceed, y_ceed, CEED_REQUEST_IMMEDIATE); 1775c25879aSJeremy L Thompson 178d1d35e2fSjeremylt // -- Restore PETSc vector; keep y_ceed viewing memory of Y_loc for use below 179d1d35e2fSjeremylt CeedVectorTakeArray(user->x_ceed, MemTypeP2C(x_mem_type), NULL); 180*2b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayReadAndMemType(user->X_loc, (const PetscScalar **)&x)); 1815c25879aSJeremy L Thompson 1825c25879aSJeremy L Thompson // -- Local-to-global 183*2b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(Diagnostic)); 184*2b730f8bSJeremy L Thompson PetscCall(DMLocalToGlobal(user->dm, Y_loc, ADD_VALUES, Diagnostic)); 1855c25879aSJeremy L Thompson 1865c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 1875c25879aSJeremy L Thompson // Scale for multiplicity 1885c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 1895c25879aSJeremy L Thompson // -- Setup vectors 190*2b730f8bSJeremy L Thompson PetscCall(VecDuplicate(Diagnostic, &mult_vec)); 191*2b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(Y_loc)); 1925c25879aSJeremy L Thompson 1935c25879aSJeremy L Thompson // -- Compute multiplicity 194d1d35e2fSjeremylt CeedElemRestrictionGetMultiplicity(elem_restr_diagnostic, y_ceed); 1955c25879aSJeremy L Thompson 1965c25879aSJeremy L Thompson // -- Restore vectors 197d1d35e2fSjeremylt CeedVectorTakeArray(y_ceed, MemTypeP2C(y_mem_type), NULL); 198*2b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayAndMemType(Y_loc, &y)); 1995c25879aSJeremy L Thompson 2005c25879aSJeremy L Thompson // -- Local-to-global 201*2b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(mult_vec)); 202*2b730f8bSJeremy L Thompson PetscCall(DMLocalToGlobal(user->dm, Y_loc, ADD_VALUES, mult_vec)); 2035c25879aSJeremy L Thompson 2045c25879aSJeremy L Thompson // -- Scale 205*2b730f8bSJeremy L Thompson PetscCall(VecReciprocal(mult_vec)); 206*2b730f8bSJeremy L Thompson PetscCall(VecPointwiseMult(Diagnostic, Diagnostic, mult_vec)); 2075c25879aSJeremy L Thompson 2085c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 2095c25879aSJeremy L Thompson // Output solution vector 2105c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 211*2b730f8bSJeremy L Thompson PetscCall(PetscSNPrintf(output_filename, sizeof output_filename, "%s/diagnostic_quantities.vtu", app_ctx->output_dir)); 212*2b730f8bSJeremy L Thompson PetscCall(PetscViewerVTKOpen(comm, output_filename, FILE_MODE_WRITE, &viewer)); 213*2b730f8bSJeremy L Thompson PetscCall(VecView(Diagnostic, viewer)); 214*2b730f8bSJeremy L Thompson PetscCall(PetscViewerDestroy(&viewer)); 2155c25879aSJeremy L Thompson 2165c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 2175c25879aSJeremy L Thompson // Cleanup 2185c25879aSJeremy L Thompson // --------------------------------------------------------------------------- 219*2b730f8bSJeremy L Thompson PetscCall(VecDestroy(&Diagnostic)); 220*2b730f8bSJeremy L Thompson PetscCall(VecDestroy(&mult_vec)); 221*2b730f8bSJeremy L Thompson PetscCall(VecDestroy(&Y_loc)); 222d1d35e2fSjeremylt CeedVectorDestroy(&y_ceed); 2235c25879aSJeremy L Thompson 2245c25879aSJeremy L Thompson PetscFunctionReturn(0); 2255c25879aSJeremy L Thompson }; 2265754ecacSJeremy L Thompson 2275754ecacSJeremy L Thompson // ----------------------------------------------------------------------------- 2285754ecacSJeremy L Thompson // Regression testing 2295754ecacSJeremy L Thompson // ----------------------------------------------------------------------------- 2305754ecacSJeremy L Thompson // test option change. could remove the loading step. Run only with one loading step and compare relatively to ref file 231*2b730f8bSJeremy 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 232*2b730f8bSJeremy L Thompson // energy 2335754ecacSJeremy L Thompson PetscErrorCode RegressionTests_solids(AppCtx app_ctx, PetscReal energy) { 2345754ecacSJeremy L Thompson PetscFunctionBegin; 2355754ecacSJeremy L Thompson 2365754ecacSJeremy L Thompson if (app_ctx->expect_final_strain >= 0.) { 2375754ecacSJeremy L Thompson PetscReal energy_ref = app_ctx->expect_final_strain; 2385754ecacSJeremy L Thompson PetscReal error = PetscAbsReal(energy - energy_ref) / energy_ref; 2395754ecacSJeremy L Thompson 2405754ecacSJeremy L Thompson if (error > app_ctx->test_tol) { 241*2b730f8bSJeremy L Thompson PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Energy %e does not match expected energy %e: relative tolerance %e > %e\n", (double)energy, 242*2b730f8bSJeremy L Thompson (double)energy_ref, (double)error, app_ctx->test_tol)); 2435754ecacSJeremy L Thompson } 2445754ecacSJeremy L Thompson } 2455754ecacSJeremy L Thompson PetscFunctionReturn(0); 2465754ecacSJeremy L Thompson }; 247