xref: /libCEED/examples/petsc/src/matops.c (revision 2b730f8b5a9c809740a0b3b302db43a719c636b1)
1e83e87a5Sjeremylt #include "../include/matops.h"
2*2b730f8bSJeremy L Thompson 
3e83e87a5Sjeremylt #include "../include/petscutils.h"
4e83e87a5Sjeremylt 
5e83e87a5Sjeremylt // -----------------------------------------------------------------------------
66c88e6a2Srezgarshakeri // Setup apply operator context data
76c88e6a2Srezgarshakeri // -----------------------------------------------------------------------------
8*2b730f8bSJeremy 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;
14*2b730f8bSJeremy 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;
19*2b730f8bSJeremy L Thompson 
206c88e6a2Srezgarshakeri   PetscFunctionReturn(0);
216c88e6a2Srezgarshakeri }
226c88e6a2Srezgarshakeri 
236c88e6a2Srezgarshakeri // -----------------------------------------------------------------------------
246c88e6a2Srezgarshakeri // Setup error operator context data
256c88e6a2Srezgarshakeri // -----------------------------------------------------------------------------
26*2b730f8bSJeremy 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;
33*2b730f8bSJeremy 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;
38*2b730f8bSJeremy L Thompson 
396c88e6a2Srezgarshakeri   PetscFunctionReturn(0);
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 
50*2b730f8bSJeremy 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
57*2b730f8bSJeremy L Thompson   PetscCall(VecGetArrayAndMemType(op_apply_ctx->Y_loc, &y, &mem_type));
58*2b730f8bSJeremy L Thompson   CeedVectorSetArray(op_apply_ctx->y_ceed, MemTypeP2C(mem_type), CEED_USE_POINTER, y);
59e83e87a5Sjeremylt 
60e83e87a5Sjeremylt   // -- Compute Diagonal
61*2b730f8bSJeremy 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);
65*2b730f8bSJeremy L Thompson   PetscCall(VecRestoreArrayAndMemType(op_apply_ctx->Y_loc, &y));
66*2b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(D));
67*2b730f8bSJeremy L Thompson   PetscCall(DMLocalToGlobal(op_apply_ctx->dm, op_apply_ctx->Y_loc, ADD_VALUES, D));
68e83e87a5Sjeremylt 
69e83e87a5Sjeremylt   PetscFunctionReturn(0);
70e83e87a5Sjeremylt };
71e83e87a5Sjeremylt 
72e83e87a5Sjeremylt // -----------------------------------------------------------------------------
73e83e87a5Sjeremylt // This function uses libCEED to compute the action of the Laplacian with
74e83e87a5Sjeremylt // Dirichlet boundary conditions
75e83e87a5Sjeremylt // -----------------------------------------------------------------------------
76*2b730f8bSJeremy L Thompson PetscErrorCode ApplyLocal_Ceed(Vec X, Vec Y, OperatorApplyContext op_apply_ctx) {
77e83e87a5Sjeremylt   PetscScalar *x, *y;
789b072555Sjeremylt   PetscMemType x_mem_type, y_mem_type;
79e83e87a5Sjeremylt 
80e83e87a5Sjeremylt   PetscFunctionBeginUser;
81e83e87a5Sjeremylt 
82e83e87a5Sjeremylt   // Global-to-local
83*2b730f8bSJeremy L Thompson   PetscCall(DMGlobalToLocal(op_apply_ctx->dm, X, INSERT_VALUES, op_apply_ctx->X_loc));
84e83e87a5Sjeremylt 
85e83e87a5Sjeremylt   // Setup libCEED vectors
86*2b730f8bSJeremy L Thompson   PetscCall(VecGetArrayReadAndMemType(op_apply_ctx->X_loc, (const PetscScalar **)&x, &x_mem_type));
87*2b730f8bSJeremy L Thompson   PetscCall(VecGetArrayAndMemType(op_apply_ctx->Y_loc, &y, &y_mem_type));
88*2b730f8bSJeremy L Thompson   CeedVectorSetArray(op_apply_ctx->x_ceed, MemTypeP2C(x_mem_type), CEED_USE_POINTER, x);
89*2b730f8bSJeremy L Thompson   CeedVectorSetArray(op_apply_ctx->y_ceed, MemTypeP2C(y_mem_type), CEED_USE_POINTER, y);
90e83e87a5Sjeremylt 
91e83e87a5Sjeremylt   // Apply libCEED operator
92*2b730f8bSJeremy L Thompson   CeedOperatorApply(op_apply_ctx->op, op_apply_ctx->x_ceed, op_apply_ctx->y_ceed, CEED_REQUEST_IMMEDIATE);
93e83e87a5Sjeremylt 
94e83e87a5Sjeremylt   // Restore PETSc vectors
95d4d45553Srezgarshakeri   CeedVectorTakeArray(op_apply_ctx->x_ceed, MemTypeP2C(x_mem_type), NULL);
96d4d45553Srezgarshakeri   CeedVectorTakeArray(op_apply_ctx->y_ceed, MemTypeP2C(y_mem_type), NULL);
97*2b730f8bSJeremy L Thompson   PetscCall(VecRestoreArrayReadAndMemType(op_apply_ctx->X_loc, (const PetscScalar **)&x));
98*2b730f8bSJeremy L Thompson   PetscCall(VecRestoreArrayAndMemType(op_apply_ctx->Y_loc, &y));
99e83e87a5Sjeremylt 
100e83e87a5Sjeremylt   // Local-to-global
101*2b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(Y));
102*2b730f8bSJeremy L Thompson   PetscCall(DMLocalToGlobal(op_apply_ctx->dm, op_apply_ctx->Y_loc, ADD_VALUES, Y));
103e83e87a5Sjeremylt 
104e83e87a5Sjeremylt   PetscFunctionReturn(0);
105e83e87a5Sjeremylt };
106e83e87a5Sjeremylt 
107e83e87a5Sjeremylt // -----------------------------------------------------------------------------
108e83e87a5Sjeremylt // This function wraps the libCEED operator for a MatShell
109e83e87a5Sjeremylt // -----------------------------------------------------------------------------
110e83e87a5Sjeremylt PetscErrorCode MatMult_Ceed(Mat A, Vec X, Vec Y) {
111d4d45553Srezgarshakeri   OperatorApplyContext op_apply_ctx;
112e83e87a5Sjeremylt 
113e83e87a5Sjeremylt   PetscFunctionBeginUser;
114e83e87a5Sjeremylt 
115*2b730f8bSJeremy L Thompson   PetscCall(MatShellGetContext(A, &op_apply_ctx));
116e83e87a5Sjeremylt 
117e83e87a5Sjeremylt   // libCEED for local action of residual evaluator
118*2b730f8bSJeremy L Thompson   PetscCall(ApplyLocal_Ceed(X, Y, op_apply_ctx));
119e83e87a5Sjeremylt 
120e83e87a5Sjeremylt   PetscFunctionReturn(0);
121e83e87a5Sjeremylt };
122e83e87a5Sjeremylt 
123e83e87a5Sjeremylt // -----------------------------------------------------------------------------
124e83e87a5Sjeremylt // This function uses libCEED to compute the action of the prolongation operator
125e83e87a5Sjeremylt // -----------------------------------------------------------------------------
126e83e87a5Sjeremylt PetscErrorCode MatMult_Prolong(Mat A, Vec X, Vec Y) {
127d4d45553Srezgarshakeri   ProlongRestrContext pr_restr_ctx;
128e83e87a5Sjeremylt   PetscScalar        *c, *f;
1299b072555Sjeremylt   PetscMemType        c_mem_type, f_mem_type;
130e83e87a5Sjeremylt 
131e83e87a5Sjeremylt   PetscFunctionBeginUser;
132e83e87a5Sjeremylt 
133*2b730f8bSJeremy L Thompson   PetscCall(MatShellGetContext(A, &pr_restr_ctx));
134e83e87a5Sjeremylt 
135e83e87a5Sjeremylt   // Global-to-local
136*2b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(pr_restr_ctx->loc_vec_c));
137*2b730f8bSJeremy L Thompson   PetscCall(DMGlobalToLocal(pr_restr_ctx->dmc, X, INSERT_VALUES, pr_restr_ctx->loc_vec_c));
138e83e87a5Sjeremylt 
139e83e87a5Sjeremylt   // Setup libCEED vectors
140*2b730f8bSJeremy L Thompson   PetscCall(VecGetArrayReadAndMemType(pr_restr_ctx->loc_vec_c, (const PetscScalar **)&c, &c_mem_type));
141*2b730f8bSJeremy L Thompson   PetscCall(VecGetArrayAndMemType(pr_restr_ctx->loc_vec_f, &f, &f_mem_type));
142*2b730f8bSJeremy L Thompson   CeedVectorSetArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), CEED_USE_POINTER, c);
143*2b730f8bSJeremy L Thompson   CeedVectorSetArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), CEED_USE_POINTER, f);
144e83e87a5Sjeremylt 
145e83e87a5Sjeremylt   // Apply libCEED operator
146*2b730f8bSJeremy L Thompson   CeedOperatorApply(pr_restr_ctx->op_prolong, pr_restr_ctx->ceed_vec_c, pr_restr_ctx->ceed_vec_f, CEED_REQUEST_IMMEDIATE);
147e83e87a5Sjeremylt 
148e83e87a5Sjeremylt   // Restore PETSc vectors
149d4d45553Srezgarshakeri   CeedVectorTakeArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), NULL);
150d4d45553Srezgarshakeri   CeedVectorTakeArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), NULL);
151*2b730f8bSJeremy L Thompson   PetscCall(VecRestoreArrayReadAndMemType(pr_restr_ctx->loc_vec_c, (const PetscScalar **)&c));
152*2b730f8bSJeremy L Thompson   PetscCall(VecRestoreArrayAndMemType(pr_restr_ctx->loc_vec_f, &f));
153e83e87a5Sjeremylt 
154e83e87a5Sjeremylt   // Multiplicity
155*2b730f8bSJeremy L Thompson   PetscCall(VecPointwiseMult(pr_restr_ctx->loc_vec_f, pr_restr_ctx->loc_vec_f, pr_restr_ctx->mult_vec));
156e83e87a5Sjeremylt 
157e83e87a5Sjeremylt   // Local-to-global
158*2b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(Y));
159*2b730f8bSJeremy L Thompson   PetscCall(DMLocalToGlobal(pr_restr_ctx->dmf, pr_restr_ctx->loc_vec_f, ADD_VALUES, Y));
160e83e87a5Sjeremylt 
161e83e87a5Sjeremylt   PetscFunctionReturn(0);
162e83e87a5Sjeremylt };
163e83e87a5Sjeremylt 
164e83e87a5Sjeremylt // -----------------------------------------------------------------------------
165e83e87a5Sjeremylt // This function uses libCEED to compute the action of the restriction operator
166e83e87a5Sjeremylt // -----------------------------------------------------------------------------
167e83e87a5Sjeremylt PetscErrorCode MatMult_Restrict(Mat A, Vec X, Vec Y) {
168d4d45553Srezgarshakeri   ProlongRestrContext pr_restr_ctx;
169e83e87a5Sjeremylt   PetscScalar        *c, *f;
1709b072555Sjeremylt   PetscMemType        c_mem_type, f_mem_type;
171e83e87a5Sjeremylt 
172e83e87a5Sjeremylt   PetscFunctionBeginUser;
173e83e87a5Sjeremylt 
174*2b730f8bSJeremy L Thompson   PetscCall(MatShellGetContext(A, &pr_restr_ctx));
175e83e87a5Sjeremylt 
176e83e87a5Sjeremylt   // Global-to-local
177*2b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(pr_restr_ctx->loc_vec_f));
178*2b730f8bSJeremy L Thompson   PetscCall(DMGlobalToLocal(pr_restr_ctx->dmf, X, INSERT_VALUES, pr_restr_ctx->loc_vec_f));
179e83e87a5Sjeremylt 
180e83e87a5Sjeremylt   // Multiplicity
181*2b730f8bSJeremy L Thompson   PetscCall(VecPointwiseMult(pr_restr_ctx->loc_vec_f, pr_restr_ctx->loc_vec_f, pr_restr_ctx->mult_vec));
182e83e87a5Sjeremylt 
183e83e87a5Sjeremylt   // Setup libCEED vectors
184*2b730f8bSJeremy L Thompson   PetscCall(VecGetArrayReadAndMemType(pr_restr_ctx->loc_vec_f, (const PetscScalar **)&f, &f_mem_type));
185*2b730f8bSJeremy L Thompson   PetscCall(VecGetArrayAndMemType(pr_restr_ctx->loc_vec_c, &c, &c_mem_type));
186*2b730f8bSJeremy L Thompson   CeedVectorSetArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), CEED_USE_POINTER, f);
187*2b730f8bSJeremy L Thompson   CeedVectorSetArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), CEED_USE_POINTER, c);
188e83e87a5Sjeremylt 
189e83e87a5Sjeremylt   // Apply CEED operator
190*2b730f8bSJeremy L Thompson   CeedOperatorApply(pr_restr_ctx->op_restrict, pr_restr_ctx->ceed_vec_f, pr_restr_ctx->ceed_vec_c, CEED_REQUEST_IMMEDIATE);
191e83e87a5Sjeremylt 
192e83e87a5Sjeremylt   // Restore PETSc vectors
193d4d45553Srezgarshakeri   CeedVectorTakeArray(pr_restr_ctx->ceed_vec_c, MemTypeP2C(c_mem_type), NULL);
194d4d45553Srezgarshakeri   CeedVectorTakeArray(pr_restr_ctx->ceed_vec_f, MemTypeP2C(f_mem_type), NULL);
195*2b730f8bSJeremy L Thompson   PetscCall(VecRestoreArrayReadAndMemType(pr_restr_ctx->loc_vec_f, (const PetscScalar **)&f));
196*2b730f8bSJeremy L Thompson   PetscCall(VecRestoreArrayAndMemType(pr_restr_ctx->loc_vec_c, &c));
197e83e87a5Sjeremylt 
198e83e87a5Sjeremylt   // Local-to-global
199*2b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(Y));
200*2b730f8bSJeremy L Thompson   PetscCall(DMLocalToGlobal(pr_restr_ctx->dmc, pr_restr_ctx->loc_vec_c, ADD_VALUES, Y));
201e83e87a5Sjeremylt 
202e83e87a5Sjeremylt   PetscFunctionReturn(0);
203e83e87a5Sjeremylt };
204e83e87a5Sjeremylt 
205e83e87a5Sjeremylt // -----------------------------------------------------------------------------
206e83e87a5Sjeremylt // This function calculates the error in the final solution
207e83e87a5Sjeremylt // -----------------------------------------------------------------------------
208*2b730f8bSJeremy L Thompson PetscErrorCode ComputeL2Error(Vec X, PetscScalar *l2_error, OperatorApplyContext op_error_ctx) {
20938f32c05Srezgarshakeri   Vec E;
210e83e87a5Sjeremylt   PetscFunctionBeginUser;
21138f32c05Srezgarshakeri   PetscCall(VecDuplicate(X, &E));
21238f32c05Srezgarshakeri   PetscCall(ApplyLocal_Ceed(X, E, op_error_ctx));
21338f32c05Srezgarshakeri   PetscScalar error_sq = 1.0;
21438f32c05Srezgarshakeri   PetscCall(VecSum(E, &error_sq));
21538f32c05Srezgarshakeri   *l2_error = sqrt(error_sq);
216e83e87a5Sjeremylt 
217e83e87a5Sjeremylt   PetscFunctionReturn(0);
218e83e87a5Sjeremylt };
219e83e87a5Sjeremylt 
220e83e87a5Sjeremylt // -----------------------------------------------------------------------------
221