1*e83e87a5Sjeremylt #include "../include/matops.h" 2*e83e87a5Sjeremylt #include "../include/petscutils.h" 3*e83e87a5Sjeremylt 4*e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 5*e83e87a5Sjeremylt // This function returns the computed diagonal of the operator 6*e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 7*e83e87a5Sjeremylt PetscErrorCode MatGetDiag(Mat A, Vec D) { 8*e83e87a5Sjeremylt PetscErrorCode ierr; 9*e83e87a5Sjeremylt UserO user; 10*e83e87a5Sjeremylt 11*e83e87a5Sjeremylt PetscFunctionBeginUser; 12*e83e87a5Sjeremylt 13*e83e87a5Sjeremylt ierr = MatShellGetContext(A, &user); CHKERRQ(ierr); 14*e83e87a5Sjeremylt 15*e83e87a5Sjeremylt // Compute Diagonal via libCEED 16*e83e87a5Sjeremylt PetscScalar *x; 17*e83e87a5Sjeremylt PetscMemType memtype; 18*e83e87a5Sjeremylt 19*e83e87a5Sjeremylt // -- Place PETSc vector in libCEED vector 20*e83e87a5Sjeremylt ierr = VecGetArrayAndMemType(user->Xloc, &x, &memtype); CHKERRQ(ierr); 21*e83e87a5Sjeremylt CeedVectorSetArray(user->Xceed, MemTypeP2C(memtype), CEED_USE_POINTER, x); 22*e83e87a5Sjeremylt 23*e83e87a5Sjeremylt // -- Compute Diagonal 24*e83e87a5Sjeremylt CeedOperatorLinearAssembleDiagonal(user->op, user->Xceed, 25*e83e87a5Sjeremylt CEED_REQUEST_IMMEDIATE); 26*e83e87a5Sjeremylt 27*e83e87a5Sjeremylt // -- Local-to-Global 28*e83e87a5Sjeremylt CeedVectorTakeArray(user->Xceed, MemTypeP2C(memtype), NULL); 29*e83e87a5Sjeremylt ierr = VecRestoreArrayAndMemType(user->Xloc, &x); CHKERRQ(ierr); 30*e83e87a5Sjeremylt ierr = VecZeroEntries(D); CHKERRQ(ierr); 31*e83e87a5Sjeremylt ierr = DMLocalToGlobal(user->dm, user->Xloc, ADD_VALUES, D); CHKERRQ(ierr); 32*e83e87a5Sjeremylt 33*e83e87a5Sjeremylt // Cleanup 34*e83e87a5Sjeremylt ierr = VecZeroEntries(user->Xloc); CHKERRQ(ierr); 35*e83e87a5Sjeremylt 36*e83e87a5Sjeremylt PetscFunctionReturn(0); 37*e83e87a5Sjeremylt }; 38*e83e87a5Sjeremylt 39*e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 40*e83e87a5Sjeremylt // This function uses libCEED to compute the action of the Laplacian with 41*e83e87a5Sjeremylt // Dirichlet boundary conditions 42*e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 43*e83e87a5Sjeremylt PetscErrorCode ApplyLocal_Ceed(Vec X, Vec Y, UserO user) { 44*e83e87a5Sjeremylt PetscErrorCode ierr; 45*e83e87a5Sjeremylt PetscScalar *x, *y; 46*e83e87a5Sjeremylt PetscMemType xmemtype, ymemtype; 47*e83e87a5Sjeremylt 48*e83e87a5Sjeremylt PetscFunctionBeginUser; 49*e83e87a5Sjeremylt 50*e83e87a5Sjeremylt // Global-to-local 51*e83e87a5Sjeremylt ierr = DMGlobalToLocal(user->dm, X, INSERT_VALUES, user->Xloc); CHKERRQ(ierr); 52*e83e87a5Sjeremylt 53*e83e87a5Sjeremylt // Setup libCEED vectors 54*e83e87a5Sjeremylt ierr = VecGetArrayReadAndMemType(user->Xloc, (const PetscScalar **)&x, 55*e83e87a5Sjeremylt &xmemtype); CHKERRQ(ierr); 56*e83e87a5Sjeremylt ierr = VecGetArrayAndMemType(user->Yloc, &y, &ymemtype); CHKERRQ(ierr); 57*e83e87a5Sjeremylt CeedVectorSetArray(user->Xceed, MemTypeP2C(xmemtype), CEED_USE_POINTER, x); 58*e83e87a5Sjeremylt CeedVectorSetArray(user->Yceed, MemTypeP2C(ymemtype), CEED_USE_POINTER, y); 59*e83e87a5Sjeremylt 60*e83e87a5Sjeremylt // Apply libCEED operator 61*e83e87a5Sjeremylt CeedOperatorApply(user->op, user->Xceed, user->Yceed, CEED_REQUEST_IMMEDIATE); 62*e83e87a5Sjeremylt 63*e83e87a5Sjeremylt // Restore PETSc vectors 64*e83e87a5Sjeremylt CeedVectorTakeArray(user->Xceed, MemTypeP2C(xmemtype), NULL); 65*e83e87a5Sjeremylt CeedVectorTakeArray(user->Yceed, MemTypeP2C(ymemtype), NULL); 66*e83e87a5Sjeremylt ierr = VecRestoreArrayReadAndMemType(user->Xloc, (const PetscScalar **)&x); 67*e83e87a5Sjeremylt CHKERRQ(ierr); 68*e83e87a5Sjeremylt ierr = VecRestoreArrayAndMemType(user->Yloc, &y); CHKERRQ(ierr); 69*e83e87a5Sjeremylt 70*e83e87a5Sjeremylt // Local-to-global 71*e83e87a5Sjeremylt ierr = VecZeroEntries(Y); CHKERRQ(ierr); 72*e83e87a5Sjeremylt ierr = DMLocalToGlobal(user->dm, user->Yloc, ADD_VALUES, Y); CHKERRQ(ierr); 73*e83e87a5Sjeremylt 74*e83e87a5Sjeremylt PetscFunctionReturn(0); 75*e83e87a5Sjeremylt }; 76*e83e87a5Sjeremylt 77*e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 78*e83e87a5Sjeremylt // This function wraps the libCEED operator for a MatShell 79*e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 80*e83e87a5Sjeremylt PetscErrorCode MatMult_Ceed(Mat A, Vec X, Vec Y) { 81*e83e87a5Sjeremylt PetscErrorCode ierr; 82*e83e87a5Sjeremylt UserO user; 83*e83e87a5Sjeremylt 84*e83e87a5Sjeremylt PetscFunctionBeginUser; 85*e83e87a5Sjeremylt 86*e83e87a5Sjeremylt ierr = MatShellGetContext(A, &user); CHKERRQ(ierr); 87*e83e87a5Sjeremylt 88*e83e87a5Sjeremylt // libCEED for local action of residual evaluator 89*e83e87a5Sjeremylt ierr = ApplyLocal_Ceed(X, Y, user); CHKERRQ(ierr); 90*e83e87a5Sjeremylt 91*e83e87a5Sjeremylt PetscFunctionReturn(0); 92*e83e87a5Sjeremylt }; 93*e83e87a5Sjeremylt 94*e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 95*e83e87a5Sjeremylt // This function wraps the libCEED operator for a SNES residual evaluation 96*e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 97*e83e87a5Sjeremylt PetscErrorCode FormResidual_Ceed(SNES snes, Vec X, Vec Y, void *ctx) { 98*e83e87a5Sjeremylt PetscErrorCode ierr; 99*e83e87a5Sjeremylt UserO user = (UserO)ctx; 100*e83e87a5Sjeremylt 101*e83e87a5Sjeremylt PetscFunctionBeginUser; 102*e83e87a5Sjeremylt 103*e83e87a5Sjeremylt // libCEED for local action of residual evaluator 104*e83e87a5Sjeremylt ierr = ApplyLocal_Ceed(X, Y, user); CHKERRQ(ierr); 105*e83e87a5Sjeremylt 106*e83e87a5Sjeremylt PetscFunctionReturn(0); 107*e83e87a5Sjeremylt }; 108*e83e87a5Sjeremylt 109*e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 110*e83e87a5Sjeremylt // This function uses libCEED to compute the action of the prolongation operator 111*e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 112*e83e87a5Sjeremylt PetscErrorCode MatMult_Prolong(Mat A, Vec X, Vec Y) { 113*e83e87a5Sjeremylt PetscErrorCode ierr; 114*e83e87a5Sjeremylt UserProlongRestr user; 115*e83e87a5Sjeremylt PetscScalar *c, *f; 116*e83e87a5Sjeremylt PetscMemType cmemtype, fmemtype; 117*e83e87a5Sjeremylt 118*e83e87a5Sjeremylt PetscFunctionBeginUser; 119*e83e87a5Sjeremylt 120*e83e87a5Sjeremylt ierr = MatShellGetContext(A, &user); CHKERRQ(ierr); 121*e83e87a5Sjeremylt 122*e83e87a5Sjeremylt // Global-to-local 123*e83e87a5Sjeremylt ierr = VecZeroEntries(user->locvecc); CHKERRQ(ierr); 124*e83e87a5Sjeremylt ierr = DMGlobalToLocal(user->dmc, X, INSERT_VALUES, user->locvecc); 125*e83e87a5Sjeremylt CHKERRQ(ierr); 126*e83e87a5Sjeremylt 127*e83e87a5Sjeremylt // Setup libCEED vectors 128*e83e87a5Sjeremylt ierr = VecGetArrayReadAndMemType(user->locvecc, (const PetscScalar **)&c, 129*e83e87a5Sjeremylt &cmemtype); CHKERRQ(ierr); 130*e83e87a5Sjeremylt ierr = VecGetArrayAndMemType(user->locvecf, &f, &fmemtype); CHKERRQ(ierr); 131*e83e87a5Sjeremylt CeedVectorSetArray(user->ceedvecc, MemTypeP2C(cmemtype), CEED_USE_POINTER, c); 132*e83e87a5Sjeremylt CeedVectorSetArray(user->ceedvecf, MemTypeP2C(fmemtype), CEED_USE_POINTER, f); 133*e83e87a5Sjeremylt 134*e83e87a5Sjeremylt // Apply libCEED operator 135*e83e87a5Sjeremylt CeedOperatorApply(user->opProlong, user->ceedvecc, user->ceedvecf, 136*e83e87a5Sjeremylt CEED_REQUEST_IMMEDIATE); 137*e83e87a5Sjeremylt 138*e83e87a5Sjeremylt // Restore PETSc vectors 139*e83e87a5Sjeremylt CeedVectorTakeArray(user->ceedvecc, MemTypeP2C(cmemtype), NULL); 140*e83e87a5Sjeremylt CeedVectorTakeArray(user->ceedvecf, MemTypeP2C(fmemtype), NULL); 141*e83e87a5Sjeremylt ierr = VecRestoreArrayReadAndMemType(user->locvecc, (const PetscScalar **)&c); 142*e83e87a5Sjeremylt CHKERRQ(ierr); 143*e83e87a5Sjeremylt ierr = VecRestoreArrayAndMemType(user->locvecf, &f); CHKERRQ(ierr); 144*e83e87a5Sjeremylt 145*e83e87a5Sjeremylt // Multiplicity 146*e83e87a5Sjeremylt ierr = VecPointwiseMult(user->locvecf, user->locvecf, user->multvec); 147*e83e87a5Sjeremylt 148*e83e87a5Sjeremylt // Local-to-global 149*e83e87a5Sjeremylt ierr = VecZeroEntries(Y); CHKERRQ(ierr); 150*e83e87a5Sjeremylt ierr = DMLocalToGlobal(user->dmf, user->locvecf, ADD_VALUES, Y); 151*e83e87a5Sjeremylt CHKERRQ(ierr); 152*e83e87a5Sjeremylt 153*e83e87a5Sjeremylt PetscFunctionReturn(0); 154*e83e87a5Sjeremylt }; 155*e83e87a5Sjeremylt 156*e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 157*e83e87a5Sjeremylt // This function uses libCEED to compute the action of the restriction operator 158*e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 159*e83e87a5Sjeremylt PetscErrorCode MatMult_Restrict(Mat A, Vec X, Vec Y) { 160*e83e87a5Sjeremylt PetscErrorCode ierr; 161*e83e87a5Sjeremylt UserProlongRestr user; 162*e83e87a5Sjeremylt PetscScalar *c, *f; 163*e83e87a5Sjeremylt PetscMemType cmemtype, fmemtype; 164*e83e87a5Sjeremylt 165*e83e87a5Sjeremylt PetscFunctionBeginUser; 166*e83e87a5Sjeremylt 167*e83e87a5Sjeremylt ierr = MatShellGetContext(A, &user); CHKERRQ(ierr); 168*e83e87a5Sjeremylt 169*e83e87a5Sjeremylt // Global-to-local 170*e83e87a5Sjeremylt ierr = VecZeroEntries(user->locvecf); CHKERRQ(ierr); 171*e83e87a5Sjeremylt ierr = DMGlobalToLocal(user->dmf, X, INSERT_VALUES, user->locvecf); 172*e83e87a5Sjeremylt CHKERRQ(ierr); 173*e83e87a5Sjeremylt 174*e83e87a5Sjeremylt // Multiplicity 175*e83e87a5Sjeremylt ierr = VecPointwiseMult(user->locvecf, user->locvecf, user->multvec); 176*e83e87a5Sjeremylt CHKERRQ(ierr); 177*e83e87a5Sjeremylt 178*e83e87a5Sjeremylt // Setup libCEED vectors 179*e83e87a5Sjeremylt ierr = VecGetArrayReadAndMemType(user->locvecf, (const PetscScalar **)&f, 180*e83e87a5Sjeremylt &fmemtype); CHKERRQ(ierr); 181*e83e87a5Sjeremylt ierr = VecGetArrayAndMemType(user->locvecc, &c, &cmemtype); CHKERRQ(ierr); 182*e83e87a5Sjeremylt CeedVectorSetArray(user->ceedvecf, MemTypeP2C(fmemtype), CEED_USE_POINTER, f); 183*e83e87a5Sjeremylt CeedVectorSetArray(user->ceedvecc, MemTypeP2C(cmemtype), CEED_USE_POINTER, c); 184*e83e87a5Sjeremylt 185*e83e87a5Sjeremylt // Apply CEED operator 186*e83e87a5Sjeremylt CeedOperatorApply(user->opRestrict, user->ceedvecf, user->ceedvecc, 187*e83e87a5Sjeremylt CEED_REQUEST_IMMEDIATE); 188*e83e87a5Sjeremylt 189*e83e87a5Sjeremylt // Restore PETSc vectors 190*e83e87a5Sjeremylt CeedVectorTakeArray(user->ceedvecc, MemTypeP2C(cmemtype), NULL); 191*e83e87a5Sjeremylt CeedVectorTakeArray(user->ceedvecf, MemTypeP2C(fmemtype), NULL); 192*e83e87a5Sjeremylt ierr = VecRestoreArrayReadAndMemType(user->locvecf, (const PetscScalar **)&f); 193*e83e87a5Sjeremylt CHKERRQ(ierr); 194*e83e87a5Sjeremylt ierr = VecRestoreArrayAndMemType(user->locvecc, &c); CHKERRQ(ierr); 195*e83e87a5Sjeremylt 196*e83e87a5Sjeremylt // Local-to-global 197*e83e87a5Sjeremylt ierr = VecZeroEntries(Y); CHKERRQ(ierr); 198*e83e87a5Sjeremylt ierr = DMLocalToGlobal(user->dmc, user->locvecc, ADD_VALUES, Y); 199*e83e87a5Sjeremylt CHKERRQ(ierr); 200*e83e87a5Sjeremylt 201*e83e87a5Sjeremylt PetscFunctionReturn(0); 202*e83e87a5Sjeremylt }; 203*e83e87a5Sjeremylt 204*e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 205*e83e87a5Sjeremylt // This function calculates the error in the final solution 206*e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 207*e83e87a5Sjeremylt PetscErrorCode ComputeErrorMax(UserO user, CeedOperator opError, 208*e83e87a5Sjeremylt Vec X, CeedVector target, 209*e83e87a5Sjeremylt PetscScalar *maxerror) { 210*e83e87a5Sjeremylt PetscErrorCode ierr; 211*e83e87a5Sjeremylt PetscScalar *x; 212*e83e87a5Sjeremylt PetscMemType memtype; 213*e83e87a5Sjeremylt CeedVector collocated_error; 214*e83e87a5Sjeremylt CeedInt length; 215*e83e87a5Sjeremylt 216*e83e87a5Sjeremylt PetscFunctionBeginUser; 217*e83e87a5Sjeremylt CeedVectorGetLength(target, &length); 218*e83e87a5Sjeremylt CeedVectorCreate(user->ceed, length, &collocated_error); 219*e83e87a5Sjeremylt 220*e83e87a5Sjeremylt // Global-to-local 221*e83e87a5Sjeremylt ierr = DMGlobalToLocal(user->dm, X, INSERT_VALUES, user->Xloc); CHKERRQ(ierr); 222*e83e87a5Sjeremylt 223*e83e87a5Sjeremylt // Setup CEED vector 224*e83e87a5Sjeremylt ierr = VecGetArrayAndMemType(user->Xloc, &x, &memtype); CHKERRQ(ierr); 225*e83e87a5Sjeremylt CeedVectorSetArray(user->Xceed, MemTypeP2C(memtype), CEED_USE_POINTER, x); 226*e83e87a5Sjeremylt 227*e83e87a5Sjeremylt // Apply CEED operator 228*e83e87a5Sjeremylt CeedOperatorApply(opError, user->Xceed, collocated_error, 229*e83e87a5Sjeremylt CEED_REQUEST_IMMEDIATE); 230*e83e87a5Sjeremylt 231*e83e87a5Sjeremylt // Restore PETSc vector 232*e83e87a5Sjeremylt CeedVectorTakeArray(user->Xceed, MemTypeP2C(memtype), NULL); 233*e83e87a5Sjeremylt ierr = VecRestoreArrayReadAndMemType(user->Xloc, (const PetscScalar **)&x); 234*e83e87a5Sjeremylt CHKERRQ(ierr); 235*e83e87a5Sjeremylt 236*e83e87a5Sjeremylt // Reduce max error 237*e83e87a5Sjeremylt *maxerror = 0; 238*e83e87a5Sjeremylt const CeedScalar *e; 239*e83e87a5Sjeremylt CeedVectorGetArrayRead(collocated_error, CEED_MEM_HOST, &e); 240*e83e87a5Sjeremylt for (CeedInt i=0; i<length; i++) { 241*e83e87a5Sjeremylt *maxerror = PetscMax(*maxerror, PetscAbsScalar(e[i])); 242*e83e87a5Sjeremylt } 243*e83e87a5Sjeremylt CeedVectorRestoreArrayRead(collocated_error, &e); 244*e83e87a5Sjeremylt ierr = MPI_Allreduce(MPI_IN_PLACE, maxerror, 1, MPIU_REAL, MPIU_MAX, 245*e83e87a5Sjeremylt user->comm); 246*e83e87a5Sjeremylt CHKERRQ(ierr); 247*e83e87a5Sjeremylt 248*e83e87a5Sjeremylt // Cleanup 249*e83e87a5Sjeremylt CeedVectorDestroy(&collocated_error); 250*e83e87a5Sjeremylt 251*e83e87a5Sjeremylt PetscFunctionReturn(0); 252*e83e87a5Sjeremylt }; 253*e83e87a5Sjeremylt 254*e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 255