xref: /libCEED/examples/petsc/src/matops.c (revision ee4ca9cbfe2be39196684117442f3ce8d00b6506)
1e83e87a5Sjeremylt #include "../include/matops.h"
22b730f8bSJeremy L Thompson 
3e83e87a5Sjeremylt #include "../include/petscutils.h"
4e83e87a5Sjeremylt 
5e83e87a5Sjeremylt // -----------------------------------------------------------------------------
66c88e6a2Srezgarshakeri // Setup apply operator context data
76c88e6a2Srezgarshakeri // -----------------------------------------------------------------------------
82b730f8bSJeremy L Thompson PetscErrorCode SetupApplyOperatorCtx(MPI_Comm comm, DM dm, Ceed ceed, CeedData ceed_data, Vec X_loc, OperatorApplyContext op_apply_ctx) {
96c88e6a2Srezgarshakeri   PetscFunctionBeginUser;
106c88e6a2Srezgarshakeri 
116c88e6a2Srezgarshakeri   op_apply_ctx->comm  = comm;
126c88e6a2Srezgarshakeri   op_apply_ctx->dm    = dm;
136c88e6a2Srezgarshakeri   op_apply_ctx->X_loc = X_loc;
142b730f8bSJeremy L Thompson   PetscCall(VecDuplicate(X_loc, &op_apply_ctx->Y_loc));
156c88e6a2Srezgarshakeri   op_apply_ctx->x_ceed = ceed_data->x_ceed;
166c88e6a2Srezgarshakeri   op_apply_ctx->y_ceed = ceed_data->y_ceed;
176c88e6a2Srezgarshakeri   op_apply_ctx->op     = ceed_data->op_apply;
186c88e6a2Srezgarshakeri   op_apply_ctx->ceed   = ceed;
192b730f8bSJeremy L Thompson 
20*ee4ca9cbSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
216c88e6a2Srezgarshakeri }
226c88e6a2Srezgarshakeri 
236c88e6a2Srezgarshakeri // -----------------------------------------------------------------------------
246c88e6a2Srezgarshakeri // Setup error operator context data
256c88e6a2Srezgarshakeri // -----------------------------------------------------------------------------
262b730f8bSJeremy L Thompson PetscErrorCode SetupErrorOperatorCtx(MPI_Comm comm, DM dm, Ceed ceed, CeedData ceed_data, Vec X_loc, CeedOperator op_error,
276c88e6a2Srezgarshakeri                                      OperatorApplyContext op_error_ctx) {
286c88e6a2Srezgarshakeri   PetscFunctionBeginUser;
296c88e6a2Srezgarshakeri 
306c88e6a2Srezgarshakeri   op_error_ctx->comm  = comm;
316c88e6a2Srezgarshakeri   op_error_ctx->dm    = dm;
326c88e6a2Srezgarshakeri   op_error_ctx->X_loc = X_loc;
332b730f8bSJeremy L Thompson   PetscCall(VecDuplicate(X_loc, &op_error_ctx->Y_loc));
346c88e6a2Srezgarshakeri   op_error_ctx->x_ceed = ceed_data->x_ceed;
356c88e6a2Srezgarshakeri   op_error_ctx->y_ceed = ceed_data->y_ceed;
366c88e6a2Srezgarshakeri   op_error_ctx->op     = op_error;
376c88e6a2Srezgarshakeri   op_error_ctx->ceed   = ceed;
382b730f8bSJeremy L Thompson 
39*ee4ca9cbSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
406c88e6a2Srezgarshakeri }
416c88e6a2Srezgarshakeri 
426c88e6a2Srezgarshakeri // -----------------------------------------------------------------------------
43e83e87a5Sjeremylt // This function returns the computed diagonal of the operator
44e83e87a5Sjeremylt // -----------------------------------------------------------------------------
45e83e87a5Sjeremylt PetscErrorCode MatGetDiag(Mat A, Vec D) {
46d4d45553Srezgarshakeri   OperatorApplyContext op_apply_ctx;
47e83e87a5Sjeremylt 
48e83e87a5Sjeremylt   PetscFunctionBeginUser;
49e83e87a5Sjeremylt 
502b730f8bSJeremy L Thompson   PetscCall(MatShellGetContext(A, &op_apply_ctx));
51e83e87a5Sjeremylt 
52e83e87a5Sjeremylt   // Compute Diagonal via libCEED
53f1c40530SJeremy L Thompson   PetscScalar *y;
549b072555Sjeremylt   PetscMemType mem_type;
55e83e87a5Sjeremylt 
56e83e87a5Sjeremylt   // -- Place PETSc vector in libCEED vector
572b730f8bSJeremy L Thompson   PetscCall(VecGetArrayAndMemType(op_apply_ctx->Y_loc, &y, &mem_type));
582b730f8bSJeremy L Thompson   CeedVectorSetArray(op_apply_ctx->y_ceed, MemTypeP2C(mem_type), CEED_USE_POINTER, y);
59e83e87a5Sjeremylt 
60e83e87a5Sjeremylt   // -- Compute Diagonal
612b730f8bSJeremy L Thompson   CeedOperatorLinearAssembleDiagonal(op_apply_ctx->op, op_apply_ctx->y_ceed, CEED_REQUEST_IMMEDIATE);
62e83e87a5Sjeremylt 
63e83e87a5Sjeremylt   // -- Local-to-Global
64d4d45553Srezgarshakeri   CeedVectorTakeArray(op_apply_ctx->y_ceed, MemTypeP2C(mem_type), NULL);
652b730f8bSJeremy L Thompson   PetscCall(VecRestoreArrayAndMemType(op_apply_ctx->Y_loc, &y));
662b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(D));
672b730f8bSJeremy L Thompson   PetscCall(DMLocalToGlobal(op_apply_ctx->dm, op_apply_ctx->Y_loc, ADD_VALUES, D));
68e83e87a5Sjeremylt 
69*ee4ca9cbSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
70e83e87a5Sjeremylt };
71e83e87a5Sjeremylt 
72e83e87a5Sjeremylt // -----------------------------------------------------------------------------
73ea61e9acSJeremy L Thompson // This function uses libCEED to compute the action of the Laplacian with Dirichlet boundary conditions
74e83e87a5Sjeremylt // -----------------------------------------------------------------------------
752b730f8bSJeremy L Thompson PetscErrorCode ApplyLocal_Ceed(Vec X, Vec Y, OperatorApplyContext op_apply_ctx) {
76e83e87a5Sjeremylt   PetscScalar *x, *y;
779b072555Sjeremylt   PetscMemType x_mem_type, y_mem_type;
78e83e87a5Sjeremylt 
79e83e87a5Sjeremylt   PetscFunctionBeginUser;
80e83e87a5Sjeremylt 
81e83e87a5Sjeremylt   // Global-to-local
822b730f8bSJeremy L Thompson   PetscCall(DMGlobalToLocal(op_apply_ctx->dm, X, INSERT_VALUES, op_apply_ctx->X_loc));
83e83e87a5Sjeremylt 
84e83e87a5Sjeremylt   // Setup libCEED vectors
852b730f8bSJeremy L Thompson   PetscCall(VecGetArrayReadAndMemType(op_apply_ctx->X_loc, (const PetscScalar **)&x, &x_mem_type));
862b730f8bSJeremy L Thompson   PetscCall(VecGetArrayAndMemType(op_apply_ctx->Y_loc, &y, &y_mem_type));
872b730f8bSJeremy L Thompson   CeedVectorSetArray(op_apply_ctx->x_ceed, MemTypeP2C(x_mem_type), CEED_USE_POINTER, x);
882b730f8bSJeremy L Thompson   CeedVectorSetArray(op_apply_ctx->y_ceed, MemTypeP2C(y_mem_type), CEED_USE_POINTER, y);
89e83e87a5Sjeremylt 
90e83e87a5Sjeremylt   // Apply libCEED operator
912b730f8bSJeremy L Thompson   CeedOperatorApply(op_apply_ctx->op, op_apply_ctx->x_ceed, op_apply_ctx->y_ceed, CEED_REQUEST_IMMEDIATE);
92e83e87a5Sjeremylt 
93e83e87a5Sjeremylt   // Restore PETSc vectors
94d4d45553Srezgarshakeri   CeedVectorTakeArray(op_apply_ctx->x_ceed, MemTypeP2C(x_mem_type), NULL);
95d4d45553Srezgarshakeri   CeedVectorTakeArray(op_apply_ctx->y_ceed, MemTypeP2C(y_mem_type), NULL);
962b730f8bSJeremy L Thompson   PetscCall(VecRestoreArrayReadAndMemType(op_apply_ctx->X_loc, (const PetscScalar **)&x));
972b730f8bSJeremy L Thompson   PetscCall(VecRestoreArrayAndMemType(op_apply_ctx->Y_loc, &y));
98e83e87a5Sjeremylt 
99e83e87a5Sjeremylt   // Local-to-global
1002b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(Y));
1012b730f8bSJeremy L Thompson   PetscCall(DMLocalToGlobal(op_apply_ctx->dm, op_apply_ctx->Y_loc, ADD_VALUES, Y));
102e83e87a5Sjeremylt 
103*ee4ca9cbSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
104e83e87a5Sjeremylt };
105e83e87a5Sjeremylt 
106e83e87a5Sjeremylt // -----------------------------------------------------------------------------
107e83e87a5Sjeremylt // This function wraps the libCEED operator for a MatShell
108e83e87a5Sjeremylt // -----------------------------------------------------------------------------
109e83e87a5Sjeremylt PetscErrorCode MatMult_Ceed(Mat A, Vec X, Vec Y) {
110d4d45553Srezgarshakeri   OperatorApplyContext op_apply_ctx;
111e83e87a5Sjeremylt 
112e83e87a5Sjeremylt   PetscFunctionBeginUser;
113e83e87a5Sjeremylt 
1142b730f8bSJeremy L Thompson   PetscCall(MatShellGetContext(A, &op_apply_ctx));
115e83e87a5Sjeremylt 
116e83e87a5Sjeremylt   // libCEED for local action of residual evaluator
1172b730f8bSJeremy L Thompson   PetscCall(ApplyLocal_Ceed(X, Y, op_apply_ctx));
118e83e87a5Sjeremylt 
119*ee4ca9cbSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
120e83e87a5Sjeremylt };
121e83e87a5Sjeremylt 
122e83e87a5Sjeremylt // -----------------------------------------------------------------------------
123e83e87a5Sjeremylt // This function uses libCEED to compute the action of the prolongation operator
124e83e87a5Sjeremylt // -----------------------------------------------------------------------------
125e83e87a5Sjeremylt PetscErrorCode MatMult_Prolong(Mat A, Vec X, Vec Y) {
126d4d45553Srezgarshakeri   ProlongRestrContext pr_restr_ctx;
127e83e87a5Sjeremylt   PetscScalar        *c, *f;
1289b072555Sjeremylt   PetscMemType        c_mem_type, f_mem_type;
129e83e87a5Sjeremylt 
130e83e87a5Sjeremylt   PetscFunctionBeginUser;
131e83e87a5Sjeremylt 
1322b730f8bSJeremy L Thompson   PetscCall(MatShellGetContext(A, &pr_restr_ctx));
133e83e87a5Sjeremylt 
134e83e87a5Sjeremylt   // Global-to-local
1352b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(pr_restr_ctx->loc_vec_c));
1362b730f8bSJeremy L Thompson   PetscCall(DMGlobalToLocal(pr_restr_ctx->dmc, X, INSERT_VALUES, pr_restr_ctx->loc_vec_c));
137e83e87a5Sjeremylt 
138e83e87a5Sjeremylt   // Setup libCEED vectors
1392b730f8bSJeremy L Thompson   PetscCall(VecGetArrayReadAndMemType(pr_restr_ctx->loc_vec_c, (const PetscScalar **)&c, &c_mem_type));
1402b730f8bSJeremy L Thompson   PetscCall(VecGetArrayAndMemType(pr_restr_ctx->loc_vec_f, &f, &f_mem_type));
1412b730f8bSJeremy L Thompson   CeedVectorSetArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), CEED_USE_POINTER, c);
1422b730f8bSJeremy L Thompson   CeedVectorSetArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), CEED_USE_POINTER, f);
143e83e87a5Sjeremylt 
144e83e87a5Sjeremylt   // Apply libCEED operator
1452b730f8bSJeremy L Thompson   CeedOperatorApply(pr_restr_ctx->op_prolong, pr_restr_ctx->ceed_vec_c, pr_restr_ctx->ceed_vec_f, CEED_REQUEST_IMMEDIATE);
146e83e87a5Sjeremylt 
147e83e87a5Sjeremylt   // Restore PETSc vectors
148d4d45553Srezgarshakeri   CeedVectorTakeArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), NULL);
149d4d45553Srezgarshakeri   CeedVectorTakeArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), NULL);
1502b730f8bSJeremy L Thompson   PetscCall(VecRestoreArrayReadAndMemType(pr_restr_ctx->loc_vec_c, (const PetscScalar **)&c));
1512b730f8bSJeremy L Thompson   PetscCall(VecRestoreArrayAndMemType(pr_restr_ctx->loc_vec_f, &f));
152e83e87a5Sjeremylt 
153e83e87a5Sjeremylt   // Multiplicity
1542b730f8bSJeremy L Thompson   PetscCall(VecPointwiseMult(pr_restr_ctx->loc_vec_f, pr_restr_ctx->loc_vec_f, pr_restr_ctx->mult_vec));
155e83e87a5Sjeremylt 
156e83e87a5Sjeremylt   // Local-to-global
1572b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(Y));
1582b730f8bSJeremy L Thompson   PetscCall(DMLocalToGlobal(pr_restr_ctx->dmf, pr_restr_ctx->loc_vec_f, ADD_VALUES, Y));
159e83e87a5Sjeremylt 
160*ee4ca9cbSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
161e83e87a5Sjeremylt };
162e83e87a5Sjeremylt 
163e83e87a5Sjeremylt // -----------------------------------------------------------------------------
164e83e87a5Sjeremylt // This function uses libCEED to compute the action of the restriction operator
165e83e87a5Sjeremylt // -----------------------------------------------------------------------------
166e83e87a5Sjeremylt PetscErrorCode MatMult_Restrict(Mat A, Vec X, Vec Y) {
167d4d45553Srezgarshakeri   ProlongRestrContext pr_restr_ctx;
168e83e87a5Sjeremylt   PetscScalar        *c, *f;
1699b072555Sjeremylt   PetscMemType        c_mem_type, f_mem_type;
170e83e87a5Sjeremylt 
171e83e87a5Sjeremylt   PetscFunctionBeginUser;
172e83e87a5Sjeremylt 
1732b730f8bSJeremy L Thompson   PetscCall(MatShellGetContext(A, &pr_restr_ctx));
174e83e87a5Sjeremylt 
175e83e87a5Sjeremylt   // Global-to-local
1762b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(pr_restr_ctx->loc_vec_f));
1772b730f8bSJeremy L Thompson   PetscCall(DMGlobalToLocal(pr_restr_ctx->dmf, X, INSERT_VALUES, pr_restr_ctx->loc_vec_f));
178e83e87a5Sjeremylt 
179e83e87a5Sjeremylt   // Multiplicity
1802b730f8bSJeremy L Thompson   PetscCall(VecPointwiseMult(pr_restr_ctx->loc_vec_f, pr_restr_ctx->loc_vec_f, pr_restr_ctx->mult_vec));
181e83e87a5Sjeremylt 
182e83e87a5Sjeremylt   // Setup libCEED vectors
1832b730f8bSJeremy L Thompson   PetscCall(VecGetArrayReadAndMemType(pr_restr_ctx->loc_vec_f, (const PetscScalar **)&f, &f_mem_type));
1842b730f8bSJeremy L Thompson   PetscCall(VecGetArrayAndMemType(pr_restr_ctx->loc_vec_c, &c, &c_mem_type));
1852b730f8bSJeremy L Thompson   CeedVectorSetArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), CEED_USE_POINTER, f);
1862b730f8bSJeremy L Thompson   CeedVectorSetArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), CEED_USE_POINTER, c);
187e83e87a5Sjeremylt 
188e83e87a5Sjeremylt   // Apply CEED operator
1892b730f8bSJeremy L Thompson   CeedOperatorApply(pr_restr_ctx->op_restrict, pr_restr_ctx->ceed_vec_f, pr_restr_ctx->ceed_vec_c, CEED_REQUEST_IMMEDIATE);
190e83e87a5Sjeremylt 
191e83e87a5Sjeremylt   // Restore PETSc vectors
192d4d45553Srezgarshakeri   CeedVectorTakeArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), NULL);
193d4d45553Srezgarshakeri   CeedVectorTakeArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), NULL);
1942b730f8bSJeremy L Thompson   PetscCall(VecRestoreArrayReadAndMemType(pr_restr_ctx->loc_vec_f, (const PetscScalar **)&f));
1952b730f8bSJeremy L Thompson   PetscCall(VecRestoreArrayAndMemType(pr_restr_ctx->loc_vec_c, &c));
196e83e87a5Sjeremylt 
197e83e87a5Sjeremylt   // Local-to-global
1982b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(Y));
1992b730f8bSJeremy L Thompson   PetscCall(DMLocalToGlobal(pr_restr_ctx->dmc, pr_restr_ctx->loc_vec_c, ADD_VALUES, Y));
200e83e87a5Sjeremylt 
201*ee4ca9cbSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
202e83e87a5Sjeremylt };
203e83e87a5Sjeremylt 
204e83e87a5Sjeremylt // -----------------------------------------------------------------------------
205e83e87a5Sjeremylt // This function calculates the error in the final solution
206e83e87a5Sjeremylt // -----------------------------------------------------------------------------
2072b730f8bSJeremy L Thompson PetscErrorCode ComputeL2Error(Vec X, PetscScalar *l2_error, OperatorApplyContext op_error_ctx) {
20838f32c05Srezgarshakeri   Vec E;
209e83e87a5Sjeremylt   PetscFunctionBeginUser;
21038f32c05Srezgarshakeri   PetscCall(VecDuplicate(X, &E));
21138f32c05Srezgarshakeri   PetscCall(ApplyLocal_Ceed(X, E, op_error_ctx));
21238f32c05Srezgarshakeri   PetscScalar error_sq = 1.0;
21338f32c05Srezgarshakeri   PetscCall(VecSum(E, &error_sq));
21438f32c05Srezgarshakeri   *l2_error = sqrt(error_sq);
215e83e87a5Sjeremylt 
216*ee4ca9cbSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
217e83e87a5Sjeremylt };
218e83e87a5Sjeremylt 
219e83e87a5Sjeremylt // -----------------------------------------------------------------------------
220