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