1e83e87a5Sjeremylt #include "../include/matops.h" 2e83e87a5Sjeremylt #include "../include/petscutils.h" 3e83e87a5Sjeremylt 4e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 5e83e87a5Sjeremylt // This function returns the computed diagonal of the operator 6e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 7e83e87a5Sjeremylt PetscErrorCode MatGetDiag(Mat A, Vec D) { 8e83e87a5Sjeremylt PetscErrorCode ierr; 9e83e87a5Sjeremylt UserO user; 10e83e87a5Sjeremylt 11e83e87a5Sjeremylt PetscFunctionBeginUser; 12e83e87a5Sjeremylt 13e83e87a5Sjeremylt ierr = MatShellGetContext(A, &user); CHKERRQ(ierr); 14e83e87a5Sjeremylt 15e83e87a5Sjeremylt // Compute Diagonal via libCEED 16e83e87a5Sjeremylt PetscScalar *x; 179b072555Sjeremylt PetscMemType mem_type; 18e83e87a5Sjeremylt 19e83e87a5Sjeremylt // -- Place PETSc vector in libCEED vector 209b072555Sjeremylt ierr = VecGetArrayAndMemType(user->X_loc, &x, &mem_type); CHKERRQ(ierr); 219b072555Sjeremylt CeedVectorSetArray(user->x_ceed, MemTypeP2C(mem_type), CEED_USE_POINTER, x); 22e83e87a5Sjeremylt 23e83e87a5Sjeremylt // -- Compute Diagonal 249b072555Sjeremylt CeedOperatorLinearAssembleDiagonal(user->op, user->x_ceed, 25e83e87a5Sjeremylt CEED_REQUEST_IMMEDIATE); 26e83e87a5Sjeremylt 27e83e87a5Sjeremylt // -- Local-to-Global 289b072555Sjeremylt CeedVectorTakeArray(user->x_ceed, MemTypeP2C(mem_type), NULL); 299b072555Sjeremylt ierr = VecRestoreArrayAndMemType(user->X_loc, &x); CHKERRQ(ierr); 30e83e87a5Sjeremylt ierr = VecZeroEntries(D); CHKERRQ(ierr); 319b072555Sjeremylt ierr = DMLocalToGlobal(user->dm, user->X_loc, ADD_VALUES, D); CHKERRQ(ierr); 32e83e87a5Sjeremylt 33e83e87a5Sjeremylt // Cleanup 349b072555Sjeremylt ierr = VecZeroEntries(user->X_loc); CHKERRQ(ierr); 35e83e87a5Sjeremylt 36e83e87a5Sjeremylt PetscFunctionReturn(0); 37e83e87a5Sjeremylt }; 38e83e87a5Sjeremylt 39e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 40e83e87a5Sjeremylt // This function uses libCEED to compute the action of the Laplacian with 41e83e87a5Sjeremylt // Dirichlet boundary conditions 42e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 43e83e87a5Sjeremylt PetscErrorCode ApplyLocal_Ceed(Vec X, Vec Y, UserO user) { 44e83e87a5Sjeremylt PetscErrorCode ierr; 45e83e87a5Sjeremylt PetscScalar *x, *y; 469b072555Sjeremylt PetscMemType x_mem_type, y_mem_type; 47e83e87a5Sjeremylt 48e83e87a5Sjeremylt PetscFunctionBeginUser; 49e83e87a5Sjeremylt 50e83e87a5Sjeremylt // Global-to-local 519b072555Sjeremylt ierr = DMGlobalToLocal(user->dm, X, INSERT_VALUES, user->X_loc); CHKERRQ(ierr); 52e83e87a5Sjeremylt 53e83e87a5Sjeremylt // Setup libCEED vectors 549b072555Sjeremylt ierr = VecGetArrayReadAndMemType(user->X_loc, (const PetscScalar **)&x, 559b072555Sjeremylt &x_mem_type); CHKERRQ(ierr); 569b072555Sjeremylt ierr = VecGetArrayAndMemType(user->Y_loc, &y, &y_mem_type); CHKERRQ(ierr); 579b072555Sjeremylt CeedVectorSetArray(user->x_ceed, MemTypeP2C(x_mem_type), CEED_USE_POINTER, x); 589b072555Sjeremylt CeedVectorSetArray(user->y_ceed, MemTypeP2C(y_mem_type), CEED_USE_POINTER, y); 59e83e87a5Sjeremylt 60e83e87a5Sjeremylt // Apply libCEED operator 619b072555Sjeremylt CeedOperatorApply(user->op, user->x_ceed, user->y_ceed, CEED_REQUEST_IMMEDIATE); 62e83e87a5Sjeremylt 63e83e87a5Sjeremylt // Restore PETSc vectors 649b072555Sjeremylt CeedVectorTakeArray(user->x_ceed, MemTypeP2C(x_mem_type), NULL); 659b072555Sjeremylt CeedVectorTakeArray(user->y_ceed, MemTypeP2C(y_mem_type), NULL); 669b072555Sjeremylt ierr = VecRestoreArrayReadAndMemType(user->X_loc, (const PetscScalar **)&x); 67e83e87a5Sjeremylt CHKERRQ(ierr); 689b072555Sjeremylt ierr = VecRestoreArrayAndMemType(user->Y_loc, &y); CHKERRQ(ierr); 69e83e87a5Sjeremylt 70e83e87a5Sjeremylt // Local-to-global 71e83e87a5Sjeremylt ierr = VecZeroEntries(Y); CHKERRQ(ierr); 729b072555Sjeremylt ierr = DMLocalToGlobal(user->dm, user->Y_loc, ADD_VALUES, Y); CHKERRQ(ierr); 73e83e87a5Sjeremylt 74e83e87a5Sjeremylt PetscFunctionReturn(0); 75e83e87a5Sjeremylt }; 76e83e87a5Sjeremylt 77e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 78e83e87a5Sjeremylt // This function wraps the libCEED operator for a MatShell 79e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 80e83e87a5Sjeremylt PetscErrorCode MatMult_Ceed(Mat A, Vec X, Vec Y) { 81e83e87a5Sjeremylt PetscErrorCode ierr; 82e83e87a5Sjeremylt UserO user; 83e83e87a5Sjeremylt 84e83e87a5Sjeremylt PetscFunctionBeginUser; 85e83e87a5Sjeremylt 86e83e87a5Sjeremylt ierr = MatShellGetContext(A, &user); CHKERRQ(ierr); 87e83e87a5Sjeremylt 88e83e87a5Sjeremylt // libCEED for local action of residual evaluator 89e83e87a5Sjeremylt ierr = ApplyLocal_Ceed(X, Y, user); CHKERRQ(ierr); 90e83e87a5Sjeremylt 91e83e87a5Sjeremylt PetscFunctionReturn(0); 92e83e87a5Sjeremylt }; 93e83e87a5Sjeremylt 94e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 95e83e87a5Sjeremylt // This function wraps the libCEED operator for a SNES residual evaluation 96e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 97e83e87a5Sjeremylt PetscErrorCode FormResidual_Ceed(SNES snes, Vec X, Vec Y, void *ctx) { 98e83e87a5Sjeremylt PetscErrorCode ierr; 99e83e87a5Sjeremylt UserO user = (UserO)ctx; 100e83e87a5Sjeremylt 101e83e87a5Sjeremylt PetscFunctionBeginUser; 102e83e87a5Sjeremylt 103e83e87a5Sjeremylt // libCEED for local action of residual evaluator 104e83e87a5Sjeremylt ierr = ApplyLocal_Ceed(X, Y, user); CHKERRQ(ierr); 105e83e87a5Sjeremylt 106e83e87a5Sjeremylt PetscFunctionReturn(0); 107e83e87a5Sjeremylt }; 108e83e87a5Sjeremylt 109e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 110e83e87a5Sjeremylt // This function uses libCEED to compute the action of the prolongation operator 111e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 112e83e87a5Sjeremylt PetscErrorCode MatMult_Prolong(Mat A, Vec X, Vec Y) { 113e83e87a5Sjeremylt PetscErrorCode ierr; 114e83e87a5Sjeremylt UserProlongRestr user; 115e83e87a5Sjeremylt PetscScalar *c, *f; 1169b072555Sjeremylt PetscMemType c_mem_type, f_mem_type; 117e83e87a5Sjeremylt 118e83e87a5Sjeremylt PetscFunctionBeginUser; 119e83e87a5Sjeremylt 120e83e87a5Sjeremylt ierr = MatShellGetContext(A, &user); CHKERRQ(ierr); 121e83e87a5Sjeremylt 122e83e87a5Sjeremylt // Global-to-local 1239b072555Sjeremylt ierr = VecZeroEntries(user->loc_vec_c); CHKERRQ(ierr); 1249b072555Sjeremylt ierr = DMGlobalToLocal(user->dmc, X, INSERT_VALUES, user->loc_vec_c); 125e83e87a5Sjeremylt CHKERRQ(ierr); 126e83e87a5Sjeremylt 127e83e87a5Sjeremylt // Setup libCEED vectors 1289b072555Sjeremylt ierr = VecGetArrayReadAndMemType(user->loc_vec_c, (const PetscScalar **)&c, 1299b072555Sjeremylt &c_mem_type); CHKERRQ(ierr); 1309b072555Sjeremylt ierr = VecGetArrayAndMemType(user->loc_vec_f, &f, &f_mem_type); CHKERRQ(ierr); 1319b072555Sjeremylt CeedVectorSetArray(user->ceed_vec_c, MemTypeP2C(c_mem_type), CEED_USE_POINTER, 1329b072555Sjeremylt c); 1339b072555Sjeremylt CeedVectorSetArray(user->ceed_vec_f, MemTypeP2C(f_mem_type), CEED_USE_POINTER, 1349b072555Sjeremylt f); 135e83e87a5Sjeremylt 136e83e87a5Sjeremylt // Apply libCEED operator 1379b072555Sjeremylt CeedOperatorApply(user->op_prolong, user->ceed_vec_c, user->ceed_vec_f, 138e83e87a5Sjeremylt CEED_REQUEST_IMMEDIATE); 139e83e87a5Sjeremylt 140e83e87a5Sjeremylt // Restore PETSc vectors 1419b072555Sjeremylt CeedVectorTakeArray(user->ceed_vec_c, MemTypeP2C(c_mem_type), NULL); 1429b072555Sjeremylt CeedVectorTakeArray(user->ceed_vec_f, MemTypeP2C(f_mem_type), NULL); 1439b072555Sjeremylt ierr = VecRestoreArrayReadAndMemType(user->loc_vec_c, (const PetscScalar **)&c); 144e83e87a5Sjeremylt CHKERRQ(ierr); 1459b072555Sjeremylt ierr = VecRestoreArrayAndMemType(user->loc_vec_f, &f); CHKERRQ(ierr); 146e83e87a5Sjeremylt 147e83e87a5Sjeremylt // Multiplicity 1489b072555Sjeremylt ierr = VecPointwiseMult(user->loc_vec_f, user->loc_vec_f, user->mult_vec); 149e83e87a5Sjeremylt 150e83e87a5Sjeremylt // Local-to-global 151e83e87a5Sjeremylt ierr = VecZeroEntries(Y); CHKERRQ(ierr); 1529b072555Sjeremylt ierr = DMLocalToGlobal(user->dmf, user->loc_vec_f, ADD_VALUES, Y); 153e83e87a5Sjeremylt CHKERRQ(ierr); 154e83e87a5Sjeremylt 155e83e87a5Sjeremylt PetscFunctionReturn(0); 156e83e87a5Sjeremylt }; 157e83e87a5Sjeremylt 158e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 159e83e87a5Sjeremylt // This function uses libCEED to compute the action of the restriction operator 160e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 161e83e87a5Sjeremylt PetscErrorCode MatMult_Restrict(Mat A, Vec X, Vec Y) { 162e83e87a5Sjeremylt PetscErrorCode ierr; 163e83e87a5Sjeremylt UserProlongRestr user; 164e83e87a5Sjeremylt PetscScalar *c, *f; 1659b072555Sjeremylt PetscMemType c_mem_type, f_mem_type; 166e83e87a5Sjeremylt 167e83e87a5Sjeremylt PetscFunctionBeginUser; 168e83e87a5Sjeremylt 169e83e87a5Sjeremylt ierr = MatShellGetContext(A, &user); CHKERRQ(ierr); 170e83e87a5Sjeremylt 171e83e87a5Sjeremylt // Global-to-local 1729b072555Sjeremylt ierr = VecZeroEntries(user->loc_vec_f); CHKERRQ(ierr); 1739b072555Sjeremylt ierr = DMGlobalToLocal(user->dmf, X, INSERT_VALUES, user->loc_vec_f); 174e83e87a5Sjeremylt CHKERRQ(ierr); 175e83e87a5Sjeremylt 176e83e87a5Sjeremylt // Multiplicity 1779b072555Sjeremylt ierr = VecPointwiseMult(user->loc_vec_f, user->loc_vec_f, user->mult_vec); 178e83e87a5Sjeremylt CHKERRQ(ierr); 179e83e87a5Sjeremylt 180e83e87a5Sjeremylt // Setup libCEED vectors 1819b072555Sjeremylt ierr = VecGetArrayReadAndMemType(user->loc_vec_f, (const PetscScalar **)&f, 1829b072555Sjeremylt &f_mem_type); CHKERRQ(ierr); 1839b072555Sjeremylt ierr = VecGetArrayAndMemType(user->loc_vec_c, &c, &c_mem_type); CHKERRQ(ierr); 1849b072555Sjeremylt CeedVectorSetArray(user->ceed_vec_f, MemTypeP2C(f_mem_type), CEED_USE_POINTER, 1859b072555Sjeremylt f); 1869b072555Sjeremylt CeedVectorSetArray(user->ceed_vec_c, MemTypeP2C(c_mem_type), CEED_USE_POINTER, 1879b072555Sjeremylt c); 188e83e87a5Sjeremylt 189e83e87a5Sjeremylt // Apply CEED operator 1909b072555Sjeremylt CeedOperatorApply(user->op_restrict, user->ceed_vec_f, user->ceed_vec_c, 191e83e87a5Sjeremylt CEED_REQUEST_IMMEDIATE); 192e83e87a5Sjeremylt 193e83e87a5Sjeremylt // Restore PETSc vectors 1949b072555Sjeremylt CeedVectorTakeArray(user->ceed_vec_c, MemTypeP2C(c_mem_type), NULL); 1959b072555Sjeremylt CeedVectorTakeArray(user->ceed_vec_f, MemTypeP2C(f_mem_type), NULL); 1969b072555Sjeremylt ierr = VecRestoreArrayReadAndMemType(user->loc_vec_f, (const PetscScalar **)&f); 197e83e87a5Sjeremylt CHKERRQ(ierr); 1989b072555Sjeremylt ierr = VecRestoreArrayAndMemType(user->loc_vec_c, &c); CHKERRQ(ierr); 199e83e87a5Sjeremylt 200e83e87a5Sjeremylt // Local-to-global 201e83e87a5Sjeremylt ierr = VecZeroEntries(Y); CHKERRQ(ierr); 2029b072555Sjeremylt ierr = DMLocalToGlobal(user->dmc, user->loc_vec_c, ADD_VALUES, Y); 203e83e87a5Sjeremylt CHKERRQ(ierr); 204e83e87a5Sjeremylt 205e83e87a5Sjeremylt PetscFunctionReturn(0); 206e83e87a5Sjeremylt }; 207e83e87a5Sjeremylt 208e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 209e83e87a5Sjeremylt // This function calculates the error in the final solution 210e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 2119b072555Sjeremylt PetscErrorCode ComputeErrorMax(UserO user, CeedOperator op_error, 212e83e87a5Sjeremylt Vec X, CeedVector target, 2139b072555Sjeremylt PetscScalar *max_error) { 214e83e87a5Sjeremylt PetscErrorCode ierr; 215e83e87a5Sjeremylt PetscScalar *x; 2169b072555Sjeremylt PetscMemType mem_type; 217e83e87a5Sjeremylt CeedVector collocated_error; 218*1f9221feSJeremy L Thompson CeedSize length; 219e83e87a5Sjeremylt 220e83e87a5Sjeremylt PetscFunctionBeginUser; 221e83e87a5Sjeremylt CeedVectorGetLength(target, &length); 222e83e87a5Sjeremylt CeedVectorCreate(user->ceed, length, &collocated_error); 223e83e87a5Sjeremylt 224e83e87a5Sjeremylt // Global-to-local 2259b072555Sjeremylt ierr = DMGlobalToLocal(user->dm, X, INSERT_VALUES, user->X_loc); CHKERRQ(ierr); 226e83e87a5Sjeremylt 227e83e87a5Sjeremylt // Setup CEED vector 2289b072555Sjeremylt ierr = VecGetArrayAndMemType(user->X_loc, &x, &mem_type); CHKERRQ(ierr); 2299b072555Sjeremylt CeedVectorSetArray(user->x_ceed, MemTypeP2C(mem_type), CEED_USE_POINTER, x); 230e83e87a5Sjeremylt 231e83e87a5Sjeremylt // Apply CEED operator 2329b072555Sjeremylt CeedOperatorApply(op_error, user->x_ceed, collocated_error, 233e83e87a5Sjeremylt CEED_REQUEST_IMMEDIATE); 234e83e87a5Sjeremylt 235e83e87a5Sjeremylt // Restore PETSc vector 2369b072555Sjeremylt CeedVectorTakeArray(user->x_ceed, MemTypeP2C(mem_type), NULL); 2379b072555Sjeremylt ierr = VecRestoreArrayReadAndMemType(user->X_loc, (const PetscScalar **)&x); 238e83e87a5Sjeremylt CHKERRQ(ierr); 239e83e87a5Sjeremylt 240e83e87a5Sjeremylt // Reduce max error 2419b072555Sjeremylt *max_error = 0; 242e83e87a5Sjeremylt const CeedScalar *e; 243e83e87a5Sjeremylt CeedVectorGetArrayRead(collocated_error, CEED_MEM_HOST, &e); 244e83e87a5Sjeremylt for (CeedInt i=0; i<length; i++) { 2459b072555Sjeremylt *max_error = PetscMax(*max_error, PetscAbsScalar(e[i])); 246e83e87a5Sjeremylt } 247e83e87a5Sjeremylt CeedVectorRestoreArrayRead(collocated_error, &e); 2489b072555Sjeremylt ierr = MPI_Allreduce(MPI_IN_PLACE, max_error, 1, MPIU_REAL, MPIU_MAX, 249e83e87a5Sjeremylt user->comm); 250e83e87a5Sjeremylt CHKERRQ(ierr); 251e83e87a5Sjeremylt 252e83e87a5Sjeremylt // Cleanup 253e83e87a5Sjeremylt CeedVectorDestroy(&collocated_error); 254e83e87a5Sjeremylt 255e83e87a5Sjeremylt PetscFunctionReturn(0); 256e83e87a5Sjeremylt }; 257e83e87a5Sjeremylt 258e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 259