1ccaff030SJeremy L Thompson // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2ccaff030SJeremy L Thompson // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3ccaff030SJeremy L Thompson // reserved. See files LICENSE and NOTICE for details. 4ccaff030SJeremy L Thompson // 5ccaff030SJeremy L Thompson // This file is part of CEED, a collection of benchmarks, miniapps, software 6ccaff030SJeremy L Thompson // libraries and APIs for efficient high-order finite element and spectral 7ccaff030SJeremy L Thompson // element discretizations for exascale applications. For more information and 8ccaff030SJeremy L Thompson // source code availability see http://github.com/ceed. 9ccaff030SJeremy L Thompson // 10ccaff030SJeremy L Thompson // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11ccaff030SJeremy L Thompson // a collaborative effort of two U.S. Department of Energy organizations (Office 12ccaff030SJeremy L Thompson // of Science and the National Nuclear Security Administration) responsible for 13ccaff030SJeremy L Thompson // the planning and preparation of a capable exascale ecosystem, including 14ccaff030SJeremy L Thompson // software, applications, hardware, advanced system engineering and early 15ccaff030SJeremy L Thompson // testbed platforms, in support of the nation's exascale computing imperative. 16ccaff030SJeremy L Thompson 17ccaff030SJeremy L Thompson /// @file 18ccaff030SJeremy L Thompson /// Matrix shell operations for solid mechanics example using PETSc 19ccaff030SJeremy L Thompson 20ccaff030SJeremy L Thompson #include "../elasticity.h" 21ccaff030SJeremy L Thompson 22ccaff030SJeremy L Thompson // ----------------------------------------------------------------------------- 23ccaff030SJeremy L Thompson // libCEED Operators for MatShell 24ccaff030SJeremy L Thompson // ----------------------------------------------------------------------------- 25ccaff030SJeremy L Thompson // This function uses libCEED to compute the local action of an operator 26ccaff030SJeremy L Thompson PetscErrorCode ApplyLocalCeedOp(Vec X, Vec Y, UserMult user) { 27ccaff030SJeremy L Thompson PetscErrorCode ierr; 28ccaff030SJeremy L Thompson PetscScalar *x, *y; 29ccaff030SJeremy L Thompson 30ccaff030SJeremy L Thompson PetscFunctionBeginUser; 31ccaff030SJeremy L Thompson 32ccaff030SJeremy L Thompson // Global-to-local 33ccaff030SJeremy L Thompson ierr = DMGlobalToLocal(user->dm, X, INSERT_VALUES, user->Xloc); CHKERRQ(ierr); 34ccaff030SJeremy L Thompson ierr = VecZeroEntries(user->Yloc); CHKERRQ(ierr); 35ccaff030SJeremy L Thompson 36ccaff030SJeremy L Thompson // Setup CEED vectors 3762e9c006SJeremy L Thompson ierr = user->VecGetArrayRead(user->Xloc, (const PetscScalar **)&x); 3862e9c006SJeremy L Thompson CHKERRQ(ierr); 3962e9c006SJeremy L Thompson ierr = user->VecGetArray(user->Yloc, &y); CHKERRQ(ierr); 4062e9c006SJeremy L Thompson CeedVectorSetArray(user->Xceed, user->memType, CEED_USE_POINTER, x); 4162e9c006SJeremy L Thompson CeedVectorSetArray(user->Yceed, user->memType, CEED_USE_POINTER, y); 42ccaff030SJeremy L Thompson 43ccaff030SJeremy L Thompson // Apply CEED operator 44*6a6c615bSJeremy L Thompson // Note: We could use VecGetArrayInPlace. Instead, we use SetArray/TakeArray 45*6a6c615bSJeremy L Thompson // so we can request host memory for easier debugging. 46ccaff030SJeremy L Thompson CeedOperatorApply(user->op, user->Xceed, user->Yceed, CEED_REQUEST_IMMEDIATE); 47ccaff030SJeremy L Thompson 48ccaff030SJeremy L Thompson // Restore PETSc vectors 49*6a6c615bSJeremy L Thompson CeedVectorTakeArray(user->Xceed, user->memType, NULL); 50*6a6c615bSJeremy L Thompson CeedVectorTakeArray(user->Yceed, user->memType, NULL); 5162e9c006SJeremy L Thompson ierr = user->VecRestoreArrayRead(user->Xloc, (const PetscScalar **)&x); 52ccaff030SJeremy L Thompson CHKERRQ(ierr); 5362e9c006SJeremy L Thompson ierr = user->VecRestoreArray(user->Yloc, &y); CHKERRQ(ierr); 54ccaff030SJeremy L Thompson 55ccaff030SJeremy L Thompson // Local-to-global 56ccaff030SJeremy L Thompson ierr = VecZeroEntries(Y); CHKERRQ(ierr); 57ccaff030SJeremy L Thompson ierr = DMLocalToGlobal(user->dm, user->Yloc, ADD_VALUES, Y); CHKERRQ(ierr); 58ccaff030SJeremy L Thompson 59ccaff030SJeremy L Thompson PetscFunctionReturn(0); 60ccaff030SJeremy L Thompson }; 61ccaff030SJeremy L Thompson 62ccaff030SJeremy L Thompson // This function uses libCEED to compute the non-linear residual 63ccaff030SJeremy L Thompson PetscErrorCode FormResidual_Ceed(SNES snes, Vec X, Vec Y, void *ctx) { 64ccaff030SJeremy L Thompson PetscErrorCode ierr; 65ccaff030SJeremy L Thompson UserMult user = (UserMult)ctx; 66ccaff030SJeremy L Thompson 67ccaff030SJeremy L Thompson PetscFunctionBeginUser; 68ccaff030SJeremy L Thompson 69ccaff030SJeremy L Thompson // Use computed BCs 70ccaff030SJeremy L Thompson ierr = VecZeroEntries(user->Xloc); CHKERRQ(ierr); 71ccaff030SJeremy L Thompson ierr = DMPlexInsertBoundaryValues(user->dm, PETSC_TRUE, user->Xloc, 72ccaff030SJeremy L Thompson user->loadIncrement, NULL, NULL, NULL); 73ccaff030SJeremy L Thompson CHKERRQ(ierr); 74ccaff030SJeremy L Thompson 75ccaff030SJeremy L Thompson // libCEED for local action of residual evaluator 76ccaff030SJeremy L Thompson ierr = ApplyLocalCeedOp(X, Y, user); CHKERRQ(ierr); 77ccaff030SJeremy L Thompson 78ccaff030SJeremy L Thompson PetscFunctionReturn(0); 79ccaff030SJeremy L Thompson }; 80ccaff030SJeremy L Thompson 81ccaff030SJeremy L Thompson // This function uses libCEED to apply the Jacobian for assembly via a SNES 82ccaff030SJeremy L Thompson PetscErrorCode ApplyJacobianCoarse_Ceed(SNES snes, Vec X, Vec Y, void *ctx) { 83ccaff030SJeremy L Thompson PetscErrorCode ierr; 84ccaff030SJeremy L Thompson UserMult user = (UserMult)ctx; 85ccaff030SJeremy L Thompson 86ccaff030SJeremy L Thompson PetscFunctionBeginUser; 87ccaff030SJeremy L Thompson 8862e9c006SJeremy L Thompson // Zero boundary values 89ccaff030SJeremy L Thompson ierr = VecZeroEntries(user->Xloc); CHKERRQ(ierr); 90ccaff030SJeremy L Thompson 91ccaff030SJeremy L Thompson // libCEED for local action of residual evaluator 92ccaff030SJeremy L Thompson ierr = ApplyLocalCeedOp(X, Y, user); CHKERRQ(ierr); 93ccaff030SJeremy L Thompson 94ccaff030SJeremy L Thompson PetscFunctionReturn(0); 95ccaff030SJeremy L Thompson }; 96ccaff030SJeremy L Thompson 97ccaff030SJeremy L Thompson // This function uses libCEED to compute the action of the Jacobian 98ccaff030SJeremy L Thompson PetscErrorCode ApplyJacobian_Ceed(Mat A, Vec X, Vec Y) { 99ccaff030SJeremy L Thompson PetscErrorCode ierr; 100ccaff030SJeremy L Thompson UserMult user; 101ccaff030SJeremy L Thompson 102ccaff030SJeremy L Thompson PetscFunctionBeginUser; 103ccaff030SJeremy L Thompson 104ccaff030SJeremy L Thompson // Zero boundary values 105ccaff030SJeremy L Thompson ierr = MatShellGetContext(A, &user); CHKERRQ(ierr); 106ccaff030SJeremy L Thompson ierr = VecZeroEntries(user->Xloc); CHKERRQ(ierr); 107ccaff030SJeremy L Thompson 108ccaff030SJeremy L Thompson // libCEED for local action of Jacobian 109ccaff030SJeremy L Thompson ierr = ApplyLocalCeedOp(X, Y, user); CHKERRQ(ierr); 110ccaff030SJeremy L Thompson 111ccaff030SJeremy L Thompson PetscFunctionReturn(0); 112ccaff030SJeremy L Thompson }; 113ccaff030SJeremy L Thompson 114ccaff030SJeremy L Thompson // This function uses libCEED to compute the action of the prolongation operator 115ccaff030SJeremy L Thompson PetscErrorCode Prolong_Ceed(Mat A, Vec X, Vec Y) { 116ccaff030SJeremy L Thompson PetscErrorCode ierr; 117ccaff030SJeremy L Thompson UserMultProlongRestr user; 118ccaff030SJeremy L Thompson PetscScalar *c, *f; 119ccaff030SJeremy L Thompson 120ccaff030SJeremy L Thompson PetscFunctionBeginUser; 121ccaff030SJeremy L Thompson 122ccaff030SJeremy L Thompson ierr = MatShellGetContext(A, &user); CHKERRQ(ierr); 123ccaff030SJeremy L Thompson 124ccaff030SJeremy L Thompson // Global-to-local 125ccaff030SJeremy L Thompson ierr = VecZeroEntries(user->locVecC); CHKERRQ(ierr); 126ccaff030SJeremy L Thompson ierr = DMGlobalToLocal(user->dmC, X, INSERT_VALUES, user->locVecC); 127ccaff030SJeremy L Thompson CHKERRQ(ierr); 128ccaff030SJeremy L Thompson ierr = VecZeroEntries(user->locVecF); CHKERRQ(ierr); 129ccaff030SJeremy L Thompson 130ccaff030SJeremy L Thompson // Setup CEED vectors 13162e9c006SJeremy L Thompson ierr = user->VecGetArrayRead(user->locVecC, (const PetscScalar **)&c); 132ccaff030SJeremy L Thompson CHKERRQ(ierr); 13362e9c006SJeremy L Thompson ierr = user->VecGetArray(user->locVecF, &f); CHKERRQ(ierr); 13462e9c006SJeremy L Thompson CeedVectorSetArray(user->ceedVecC, user->memType, CEED_USE_POINTER, c); 13562e9c006SJeremy L Thompson CeedVectorSetArray(user->ceedVecF, user->memType, CEED_USE_POINTER, f); 136ccaff030SJeremy L Thompson 137ccaff030SJeremy L Thompson // Apply CEED operator 138ccaff030SJeremy L Thompson CeedOperatorApply(user->opProlong, user->ceedVecC, user->ceedVecF, 139ccaff030SJeremy L Thompson CEED_REQUEST_IMMEDIATE); 140ccaff030SJeremy L Thompson 141ccaff030SJeremy L Thompson // Restore PETSc vectors 142*6a6c615bSJeremy L Thompson CeedVectorTakeArray(user->ceedVecC, user->memType, NULL); 143*6a6c615bSJeremy L Thompson CeedVectorTakeArray(user->ceedVecF, user->memType, NULL); 144cd11335eSJeremy L Thompson ierr = user->VecRestoreArrayRead(user->locVecC, (const PetscScalar **)&c); 145ccaff030SJeremy L Thompson CHKERRQ(ierr); 14662e9c006SJeremy L Thompson ierr = user->VecRestoreArray(user->locVecF, &f); CHKERRQ(ierr); 147ccaff030SJeremy L Thompson 148ccaff030SJeremy L Thompson // Multiplicity 149ccaff030SJeremy L Thompson ierr = VecPointwiseMult(user->locVecF, user->locVecF, user->multVec); 150ccaff030SJeremy L Thompson 151ccaff030SJeremy L Thompson // Local-to-global 152ccaff030SJeremy L Thompson ierr = VecZeroEntries(Y); CHKERRQ(ierr); 153ccaff030SJeremy L Thompson ierr = DMLocalToGlobal(user->dmF, user->locVecF, ADD_VALUES, Y); 154ccaff030SJeremy L Thompson CHKERRQ(ierr); 155ccaff030SJeremy L Thompson 156ccaff030SJeremy L Thompson PetscFunctionReturn(0); 157ccaff030SJeremy L Thompson } 158ccaff030SJeremy L Thompson 159ccaff030SJeremy L Thompson // This function uses libCEED to compute the action of the restriction operator 160ccaff030SJeremy L Thompson PetscErrorCode Restrict_Ceed(Mat A, Vec X, Vec Y) { 161ccaff030SJeremy L Thompson PetscErrorCode ierr; 162ccaff030SJeremy L Thompson UserMultProlongRestr user; 163ccaff030SJeremy L Thompson PetscScalar *c, *f; 164ccaff030SJeremy L Thompson 165ccaff030SJeremy L Thompson PetscFunctionBeginUser; 166ccaff030SJeremy L Thompson 167ccaff030SJeremy L Thompson ierr = MatShellGetContext(A, &user); CHKERRQ(ierr); 168ccaff030SJeremy L Thompson 169ccaff030SJeremy L Thompson // Global-to-local 170ccaff030SJeremy L Thompson ierr = VecZeroEntries(user->locVecF); CHKERRQ(ierr); 171ccaff030SJeremy L Thompson ierr = DMGlobalToLocal(user->dmF, X, INSERT_VALUES, user->locVecF); 172ccaff030SJeremy L Thompson CHKERRQ(ierr); 173ccaff030SJeremy L Thompson ierr = VecZeroEntries(user->locVecC); CHKERRQ(ierr); 174ccaff030SJeremy L Thompson 175ccaff030SJeremy L Thompson // Multiplicity 176ccaff030SJeremy L Thompson ierr = VecPointwiseMult(user->locVecF, user->locVecF, user->multVec); 177ccaff030SJeremy L Thompson CHKERRQ(ierr); 178ccaff030SJeremy L Thompson 179ccaff030SJeremy L Thompson // Setup CEED vectors 18062e9c006SJeremy L Thompson ierr = user->VecGetArrayRead(user->locVecF, (const PetscScalar **)&f); 18162e9c006SJeremy L Thompson CHKERRQ(ierr); 18262e9c006SJeremy L Thompson ierr = user->VecGetArray(user->locVecC, &c); CHKERRQ(ierr); 18362e9c006SJeremy L Thompson CeedVectorSetArray(user->ceedVecF, user->memType, CEED_USE_POINTER, f); 18462e9c006SJeremy L Thompson CeedVectorSetArray(user->ceedVecC, user->memType, CEED_USE_POINTER, c); 185ccaff030SJeremy L Thompson 186ccaff030SJeremy L Thompson // Apply CEED operator 187ccaff030SJeremy L Thompson CeedOperatorApply(user->opRestrict, user->ceedVecF, user->ceedVecC, 188ccaff030SJeremy L Thompson CEED_REQUEST_IMMEDIATE); 189ccaff030SJeremy L Thompson 190ccaff030SJeremy L Thompson // Restore PETSc vectors 191*6a6c615bSJeremy L Thompson CeedVectorTakeArray(user->ceedVecF, user->memType, NULL); 192*6a6c615bSJeremy L Thompson CeedVectorTakeArray(user->ceedVecC, user->memType, NULL); 19362e9c006SJeremy L Thompson ierr = user->VecRestoreArrayRead(user->locVecF, (const PetscScalar **)&f); 194ccaff030SJeremy L Thompson CHKERRQ(ierr); 19562e9c006SJeremy L Thompson ierr = user->VecRestoreArray(user->locVecC, &c); CHKERRQ(ierr); 196ccaff030SJeremy L Thompson 197ccaff030SJeremy L Thompson // Local-to-global 198ccaff030SJeremy L Thompson ierr = VecZeroEntries(Y); CHKERRQ(ierr); 199ccaff030SJeremy L Thompson ierr = DMLocalToGlobal(user->dmC, user->locVecC, ADD_VALUES, Y); 200ccaff030SJeremy L Thompson CHKERRQ(ierr); 201ccaff030SJeremy L Thompson 202ccaff030SJeremy L Thompson PetscFunctionReturn(0); 203ccaff030SJeremy L Thompson }; 2042d93065eSjeremylt 205ccaff030SJeremy L Thompson // This function returns the computed diagonal of the operator 206ccaff030SJeremy L Thompson PetscErrorCode GetDiag_Ceed(Mat A, Vec D) { 207ccaff030SJeremy L Thompson PetscErrorCode ierr; 208ccaff030SJeremy L Thompson UserMult user; 209ccaff030SJeremy L Thompson 210ccaff030SJeremy L Thompson PetscFunctionBeginUser; 211ccaff030SJeremy L Thompson 212ccaff030SJeremy L Thompson ierr = MatShellGetContext(A, &user); CHKERRQ(ierr); 213ccaff030SJeremy L Thompson 214f7b4142eSJeremy L Thompson // -- Set physics context 215f7b4142eSJeremy L Thompson if (user->physSmoother) 216f7b4142eSJeremy L Thompson CeedQFunctionSetContext(user->qf, user->physSmoother, 217f7b4142eSJeremy L Thompson sizeof(*user->physSmoother)); 218f7b4142eSJeremy L Thompson 2192bba3ffaSJeremy L Thompson // Compute Diagonal via libCEED 2202bba3ffaSJeremy L Thompson PetscScalar *x; 2212bba3ffaSJeremy L Thompson 2222bba3ffaSJeremy L Thompson // -- Place PETSc vector in libCEED vector 22362e9c006SJeremy L Thompson ierr = user->VecGetArray(user->Xloc, &x); CHKERRQ(ierr); 22462e9c006SJeremy L Thompson CeedVectorSetArray(user->Xceed, user->memType, CEED_USE_POINTER, x); 2252bba3ffaSJeremy L Thompson 2262bba3ffaSJeremy L Thompson // -- Compute Diagonal 2272bba3ffaSJeremy L Thompson CeedOperatorLinearAssembleDiagonal(user->op, user->Xceed, 228ccaff030SJeremy L Thompson CEED_REQUEST_IMMEDIATE); 229ccaff030SJeremy L Thompson 230f7b4142eSJeremy L Thompson // -- Reset physics context 231f7b4142eSJeremy L Thompson if (user->physSmoother) 232f7b4142eSJeremy L Thompson CeedQFunctionSetContext(user->qf, user->phys, sizeof(*user->phys)); 233f7b4142eSJeremy L Thompson 234ccaff030SJeremy L Thompson // -- Local-to-Global 235*6a6c615bSJeremy L Thompson CeedVectorTakeArray(user->Xceed, user->memType, NULL); 23662e9c006SJeremy L Thompson ierr = user->VecRestoreArray(user->Xloc, &x); CHKERRQ(ierr); 237ccaff030SJeremy L Thompson ierr = VecZeroEntries(D); CHKERRQ(ierr); 238ccaff030SJeremy L Thompson ierr = DMLocalToGlobal(user->dm, user->Xloc, ADD_VALUES, D); CHKERRQ(ierr); 239ccaff030SJeremy L Thompson 2402bba3ffaSJeremy L Thompson // Cleanup 2412bba3ffaSJeremy L Thompson ierr = VecZeroEntries(user->Xloc); CHKERRQ(ierr); 242ccaff030SJeremy L Thompson 243ccaff030SJeremy L Thompson PetscFunctionReturn(0); 244ccaff030SJeremy L Thompson }; 2452d93065eSjeremylt 2462d93065eSjeremylt // This function calculates the strain energy in the final solution 247a3c02c40SJeremy L Thompson PetscErrorCode ComputeStrainEnergy(DM dmEnergy, UserMult user, 248a3c02c40SJeremy L Thompson CeedOperator opEnergy, Vec X, 249a3c02c40SJeremy L Thompson PetscReal *energy) { 2502d93065eSjeremylt PetscErrorCode ierr; 2512d93065eSjeremylt PetscScalar *x; 2522d93065eSjeremylt CeedInt length; 2532d93065eSjeremylt 2542d93065eSjeremylt PetscFunctionBeginUser; 2552d93065eSjeremylt 2562d93065eSjeremylt // Global-to-local 2572d93065eSjeremylt ierr = VecZeroEntries(user->Xloc); CHKERRQ(ierr); 2582d93065eSjeremylt ierr = DMGlobalToLocal(user->dm, X, INSERT_VALUES, user->Xloc); CHKERRQ(ierr); 2592d93065eSjeremylt ierr = DMPlexInsertBoundaryValues(user->dm, PETSC_TRUE, user->Xloc, 2602d93065eSjeremylt user->loadIncrement, NULL, NULL, NULL); 2615c25879aSJeremy L Thompson CHKERRQ(ierr); 2622d93065eSjeremylt 263a3c02c40SJeremy L Thompson // Setup libCEED input vector 26462e9c006SJeremy L Thompson ierr = user->VecGetArrayRead(user->Xloc, (const PetscScalar **)&x); 2652d93065eSjeremylt CHKERRQ(ierr); 26662e9c006SJeremy L Thompson CeedVectorSetArray(user->Xceed, user->memType, CEED_USE_POINTER, x); 2672d93065eSjeremylt 268a3c02c40SJeremy L Thompson // Setup libCEED output vector 269a3c02c40SJeremy L Thompson Vec Eloc; 270a3c02c40SJeremy L Thompson CeedVector eloc; 271a3c02c40SJeremy L Thompson ierr = DMCreateLocalVector(dmEnergy, &Eloc); CHKERRQ(ierr); 272a3c02c40SJeremy L Thompson ierr = VecGetSize(Eloc, &length); CHKERRQ(ierr); 273a3c02c40SJeremy L Thompson ierr = VecDestroy(&Eloc); CHKERRQ(ierr); 274a3c02c40SJeremy L Thompson CeedVectorCreate(user->ceed, length, &eloc); 275a3c02c40SJeremy L Thompson 2762d93065eSjeremylt // Apply libCEED operator 277a3c02c40SJeremy L Thompson CeedOperatorApply(opEnergy, user->Xceed, eloc, CEED_REQUEST_IMMEDIATE); 2782d93065eSjeremylt 2792d93065eSjeremylt // Restore PETSc vector 28062e9c006SJeremy L Thompson ierr = user->VecRestoreArrayRead(user->Xloc, (const PetscScalar **)&x); 2812d93065eSjeremylt CHKERRQ(ierr); 2822d93065eSjeremylt 2832d93065eSjeremylt // Reduce max error 2842d93065eSjeremylt const CeedScalar *e; 285a3c02c40SJeremy L Thompson CeedVectorGetArrayRead(eloc, CEED_MEM_HOST, &e); 2862d93065eSjeremylt (*energy) = 0; 2872d93065eSjeremylt for (CeedInt i=0; i<length; i++) 2882d93065eSjeremylt (*energy) += e[i]; 289a3c02c40SJeremy L Thompson CeedVectorRestoreArrayRead(eloc, &e); 290a3c02c40SJeremy L Thompson CeedVectorDestroy(&eloc); 2912d93065eSjeremylt 2922d93065eSjeremylt ierr = MPI_Allreduce(MPI_IN_PLACE, energy, 1, MPIU_REAL, MPIU_SUM, 2932d93065eSjeremylt user->comm); CHKERRQ(ierr); 2942d93065eSjeremylt 2952d93065eSjeremylt PetscFunctionReturn(0); 2962d93065eSjeremylt }; 297