xref: /libCEED/examples/petsc/src/matops.c (revision f63ecca4e342c87490318b4a937ccf05a8f235af)
1e83e87a5Sjeremylt #include "../include/matops.h"
22b730f8bSJeremy L Thompson 
3e83e87a5Sjeremylt #include "../include/petscutils.h"
4e83e87a5Sjeremylt 
5e83e87a5Sjeremylt // -----------------------------------------------------------------------------
66c88e6a2Srezgarshakeri // Setup apply operator context data
76c88e6a2Srezgarshakeri // -----------------------------------------------------------------------------
SetupApplyOperatorCtx(MPI_Comm comm,DM dm,Ceed ceed,CeedData ceed_data,Vec X_loc,OperatorApplyContext op_apply_ctx)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   op_apply_ctx->comm  = comm;
116c88e6a2Srezgarshakeri   op_apply_ctx->dm    = dm;
126c88e6a2Srezgarshakeri   op_apply_ctx->X_loc = X_loc;
132b730f8bSJeremy L Thompson   PetscCall(VecDuplicate(X_loc, &op_apply_ctx->Y_loc));
146c88e6a2Srezgarshakeri   op_apply_ctx->x_ceed = ceed_data->x_ceed;
156c88e6a2Srezgarshakeri   op_apply_ctx->y_ceed = ceed_data->y_ceed;
166c88e6a2Srezgarshakeri   op_apply_ctx->op     = ceed_data->op_apply;
176c88e6a2Srezgarshakeri   op_apply_ctx->ceed   = ceed;
18ee4ca9cbSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
196c88e6a2Srezgarshakeri }
206c88e6a2Srezgarshakeri 
216c88e6a2Srezgarshakeri // -----------------------------------------------------------------------------
226c88e6a2Srezgarshakeri // Setup error operator context data
236c88e6a2Srezgarshakeri // -----------------------------------------------------------------------------
SetupErrorOperatorCtx(MPI_Comm comm,DM dm,Ceed ceed,CeedData ceed_data,Vec X_loc,CeedOperator op_error,OperatorApplyContext op_error_ctx)242b730f8bSJeremy L Thompson PetscErrorCode SetupErrorOperatorCtx(MPI_Comm comm, DM dm, Ceed ceed, CeedData ceed_data, Vec X_loc, CeedOperator op_error,
256c88e6a2Srezgarshakeri                                      OperatorApplyContext op_error_ctx) {
266c88e6a2Srezgarshakeri   PetscFunctionBeginUser;
276c88e6a2Srezgarshakeri   op_error_ctx->comm  = comm;
286c88e6a2Srezgarshakeri   op_error_ctx->dm    = dm;
296c88e6a2Srezgarshakeri   op_error_ctx->X_loc = X_loc;
302b730f8bSJeremy L Thompson   PetscCall(VecDuplicate(X_loc, &op_error_ctx->Y_loc));
316c88e6a2Srezgarshakeri   op_error_ctx->x_ceed = ceed_data->x_ceed;
326c88e6a2Srezgarshakeri   op_error_ctx->y_ceed = ceed_data->y_ceed;
336c88e6a2Srezgarshakeri   op_error_ctx->op     = op_error;
346c88e6a2Srezgarshakeri   op_error_ctx->ceed   = ceed;
35ee4ca9cbSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
366c88e6a2Srezgarshakeri }
376c88e6a2Srezgarshakeri 
386c88e6a2Srezgarshakeri // -----------------------------------------------------------------------------
39e83e87a5Sjeremylt // This function returns the computed diagonal of the operator
40e83e87a5Sjeremylt // -----------------------------------------------------------------------------
MatGetDiag(Mat A,Vec D)41e83e87a5Sjeremylt PetscErrorCode MatGetDiag(Mat A, Vec D) {
42d4d45553Srezgarshakeri   OperatorApplyContext op_apply_ctx;
43e83e87a5Sjeremylt 
44e83e87a5Sjeremylt   PetscFunctionBeginUser;
452b730f8bSJeremy L Thompson   PetscCall(MatShellGetContext(A, &op_apply_ctx));
46e83e87a5Sjeremylt 
47e83e87a5Sjeremylt   // Compute Diagonal via libCEED
489b072555Sjeremylt   PetscMemType mem_type;
49e83e87a5Sjeremylt 
50179e5961SZach Atkins   // Place PETSc vector in libCEED vector
51179e5961SZach Atkins   PetscCall(VecP2C(op_apply_ctx->Y_loc, &mem_type, op_apply_ctx->y_ceed));
52e83e87a5Sjeremylt 
53179e5961SZach Atkins   // Compute Diagonal
542b730f8bSJeremy L Thompson   CeedOperatorLinearAssembleDiagonal(op_apply_ctx->op, op_apply_ctx->y_ceed, CEED_REQUEST_IMMEDIATE);
55e83e87a5Sjeremylt 
56179e5961SZach Atkins   // Local-to-Global
57179e5961SZach Atkins   PetscCall(VecC2P(op_apply_ctx->y_ceed, mem_type, op_apply_ctx->Y_loc));
582b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(D));
592b730f8bSJeremy L Thompson   PetscCall(DMLocalToGlobal(op_apply_ctx->dm, op_apply_ctx->Y_loc, ADD_VALUES, D));
60ee4ca9cbSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
61fd8f24faSSebastian Grimberg }
62e83e87a5Sjeremylt 
63e83e87a5Sjeremylt // -----------------------------------------------------------------------------
64ea61e9acSJeremy L Thompson // This function uses libCEED to compute the action of the Laplacian with Dirichlet boundary conditions
65e83e87a5Sjeremylt // -----------------------------------------------------------------------------
ApplyLocal_Ceed(Vec X,Vec Y,OperatorApplyContext op_apply_ctx)662b730f8bSJeremy L Thompson PetscErrorCode ApplyLocal_Ceed(Vec X, Vec Y, OperatorApplyContext op_apply_ctx) {
679b072555Sjeremylt   PetscMemType x_mem_type, y_mem_type;
68e83e87a5Sjeremylt 
69e83e87a5Sjeremylt   PetscFunctionBeginUser;
70e83e87a5Sjeremylt   // Global-to-local
712b730f8bSJeremy L Thompson   PetscCall(DMGlobalToLocal(op_apply_ctx->dm, X, INSERT_VALUES, op_apply_ctx->X_loc));
72e83e87a5Sjeremylt 
73e83e87a5Sjeremylt   // Setup libCEED vectors
74179e5961SZach Atkins   PetscCall(VecReadP2C(op_apply_ctx->X_loc, &x_mem_type, op_apply_ctx->x_ceed));
75179e5961SZach Atkins   PetscCall(VecP2C(op_apply_ctx->Y_loc, &y_mem_type, op_apply_ctx->y_ceed));
76e83e87a5Sjeremylt 
77e83e87a5Sjeremylt   // Apply libCEED operator
782b730f8bSJeremy L Thompson   CeedOperatorApply(op_apply_ctx->op, op_apply_ctx->x_ceed, op_apply_ctx->y_ceed, CEED_REQUEST_IMMEDIATE);
79e83e87a5Sjeremylt 
80e83e87a5Sjeremylt   // Restore PETSc vectors
81179e5961SZach Atkins   PetscCall(VecReadC2P(op_apply_ctx->x_ceed, x_mem_type, op_apply_ctx->X_loc));
82179e5961SZach Atkins   PetscCall(VecC2P(op_apply_ctx->y_ceed, y_mem_type, op_apply_ctx->Y_loc));
83e83e87a5Sjeremylt 
84e83e87a5Sjeremylt   // Local-to-global
852b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(Y));
862b730f8bSJeremy L Thompson   PetscCall(DMLocalToGlobal(op_apply_ctx->dm, op_apply_ctx->Y_loc, ADD_VALUES, Y));
87ee4ca9cbSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
88fd8f24faSSebastian Grimberg }
89e83e87a5Sjeremylt 
90e83e87a5Sjeremylt // -----------------------------------------------------------------------------
91e83e87a5Sjeremylt // This function wraps the libCEED operator for a MatShell
92e83e87a5Sjeremylt // -----------------------------------------------------------------------------
MatMult_Ceed(Mat A,Vec X,Vec Y)93e83e87a5Sjeremylt PetscErrorCode MatMult_Ceed(Mat A, Vec X, Vec Y) {
94d4d45553Srezgarshakeri   OperatorApplyContext op_apply_ctx;
95e83e87a5Sjeremylt 
96e83e87a5Sjeremylt   PetscFunctionBeginUser;
972b730f8bSJeremy L Thompson   PetscCall(MatShellGetContext(A, &op_apply_ctx));
98e83e87a5Sjeremylt 
99e83e87a5Sjeremylt   // libCEED for local action of residual evaluator
1002b730f8bSJeremy L Thompson   PetscCall(ApplyLocal_Ceed(X, Y, op_apply_ctx));
101ee4ca9cbSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
102fd8f24faSSebastian Grimberg }
103e83e87a5Sjeremylt 
104e83e87a5Sjeremylt // -----------------------------------------------------------------------------
105e83e87a5Sjeremylt // This function uses libCEED to compute the action of the prolongation operator
106e83e87a5Sjeremylt // -----------------------------------------------------------------------------
MatMult_Prolong(Mat A,Vec X,Vec Y)107e83e87a5Sjeremylt PetscErrorCode MatMult_Prolong(Mat A, Vec X, Vec Y) {
108d4d45553Srezgarshakeri   ProlongRestrContext pr_restr_ctx;
1099b072555Sjeremylt   PetscMemType        c_mem_type, f_mem_type;
110e83e87a5Sjeremylt 
111e83e87a5Sjeremylt   PetscFunctionBeginUser;
1122b730f8bSJeremy L Thompson   PetscCall(MatShellGetContext(A, &pr_restr_ctx));
113e83e87a5Sjeremylt 
114e83e87a5Sjeremylt   // Global-to-local
1152b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(pr_restr_ctx->loc_vec_c));
1162b730f8bSJeremy L Thompson   PetscCall(DMGlobalToLocal(pr_restr_ctx->dmc, X, INSERT_VALUES, pr_restr_ctx->loc_vec_c));
117e83e87a5Sjeremylt 
118e83e87a5Sjeremylt   // Setup libCEED vectors
119179e5961SZach Atkins   PetscCall(VecReadP2C(pr_restr_ctx->loc_vec_c, &c_mem_type, pr_restr_ctx->ceed_vec_c));
120179e5961SZach Atkins   PetscCall(VecP2C(pr_restr_ctx->loc_vec_f, &f_mem_type, pr_restr_ctx->ceed_vec_f));
121e83e87a5Sjeremylt 
122e83e87a5Sjeremylt   // Apply libCEED operator
1232b730f8bSJeremy L Thompson   CeedOperatorApply(pr_restr_ctx->op_prolong, pr_restr_ctx->ceed_vec_c, pr_restr_ctx->ceed_vec_f, CEED_REQUEST_IMMEDIATE);
124e83e87a5Sjeremylt 
125e83e87a5Sjeremylt   // Restore PETSc vectors
126179e5961SZach Atkins   PetscCall(VecReadC2P(pr_restr_ctx->ceed_vec_c, c_mem_type, pr_restr_ctx->loc_vec_c));
127179e5961SZach Atkins   PetscCall(VecC2P(pr_restr_ctx->ceed_vec_f, f_mem_type, pr_restr_ctx->loc_vec_f));
128e83e87a5Sjeremylt 
129e83e87a5Sjeremylt   // Multiplicity
1302b730f8bSJeremy L Thompson   PetscCall(VecPointwiseMult(pr_restr_ctx->loc_vec_f, pr_restr_ctx->loc_vec_f, pr_restr_ctx->mult_vec));
131e83e87a5Sjeremylt 
132e83e87a5Sjeremylt   // Local-to-global
1332b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(Y));
1342b730f8bSJeremy L Thompson   PetscCall(DMLocalToGlobal(pr_restr_ctx->dmf, pr_restr_ctx->loc_vec_f, ADD_VALUES, Y));
135ee4ca9cbSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
136fd8f24faSSebastian Grimberg }
137e83e87a5Sjeremylt 
138e83e87a5Sjeremylt // -----------------------------------------------------------------------------
139e83e87a5Sjeremylt // This function uses libCEED to compute the action of the restriction operator
140e83e87a5Sjeremylt // -----------------------------------------------------------------------------
MatMult_Restrict(Mat A,Vec X,Vec Y)141e83e87a5Sjeremylt PetscErrorCode MatMult_Restrict(Mat A, Vec X, Vec Y) {
142d4d45553Srezgarshakeri   ProlongRestrContext pr_restr_ctx;
1439b072555Sjeremylt   PetscMemType        c_mem_type, f_mem_type;
144e83e87a5Sjeremylt 
145e83e87a5Sjeremylt   PetscFunctionBeginUser;
1462b730f8bSJeremy L Thompson   PetscCall(MatShellGetContext(A, &pr_restr_ctx));
147e83e87a5Sjeremylt 
148e83e87a5Sjeremylt   // Global-to-local
1492b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(pr_restr_ctx->loc_vec_f));
1502b730f8bSJeremy L Thompson   PetscCall(DMGlobalToLocal(pr_restr_ctx->dmf, X, INSERT_VALUES, pr_restr_ctx->loc_vec_f));
151e83e87a5Sjeremylt 
152e83e87a5Sjeremylt   // Multiplicity
1532b730f8bSJeremy L Thompson   PetscCall(VecPointwiseMult(pr_restr_ctx->loc_vec_f, pr_restr_ctx->loc_vec_f, pr_restr_ctx->mult_vec));
154e83e87a5Sjeremylt 
155e83e87a5Sjeremylt   // Setup libCEED vectors
156179e5961SZach Atkins   PetscCall(VecReadP2C(pr_restr_ctx->loc_vec_f, &f_mem_type, pr_restr_ctx->ceed_vec_f));
157179e5961SZach Atkins   PetscCall(VecP2C(pr_restr_ctx->loc_vec_c, &c_mem_type, pr_restr_ctx->ceed_vec_c));
158e83e87a5Sjeremylt 
159e83e87a5Sjeremylt   // Apply CEED operator
1602b730f8bSJeremy L Thompson   CeedOperatorApply(pr_restr_ctx->op_restrict, pr_restr_ctx->ceed_vec_f, pr_restr_ctx->ceed_vec_c, CEED_REQUEST_IMMEDIATE);
161e83e87a5Sjeremylt 
162e83e87a5Sjeremylt   // Restore PETSc vectors
163179e5961SZach Atkins   PetscCall(VecReadC2P(pr_restr_ctx->ceed_vec_f, f_mem_type, pr_restr_ctx->loc_vec_f));
164179e5961SZach Atkins   PetscCall(VecC2P(pr_restr_ctx->ceed_vec_c, c_mem_type, pr_restr_ctx->loc_vec_c));
165e83e87a5Sjeremylt 
166e83e87a5Sjeremylt   // Local-to-global
1672b730f8bSJeremy L Thompson   PetscCall(VecZeroEntries(Y));
1682b730f8bSJeremy L Thompson   PetscCall(DMLocalToGlobal(pr_restr_ctx->dmc, pr_restr_ctx->loc_vec_c, ADD_VALUES, Y));
169ee4ca9cbSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
170fd8f24faSSebastian Grimberg }
171e83e87a5Sjeremylt 
172e83e87a5Sjeremylt // -----------------------------------------------------------------------------
173e83e87a5Sjeremylt // This function calculates the error in the final solution
174e83e87a5Sjeremylt // -----------------------------------------------------------------------------
ComputeL2Error(Vec X,PetscScalar * l2_error,OperatorApplyContext op_error_ctx)1752b730f8bSJeremy L Thompson PetscErrorCode ComputeL2Error(Vec X, PetscScalar *l2_error, OperatorApplyContext op_error_ctx) {
17638f32c05Srezgarshakeri   Vec E;
17798285ab4SZach Atkins 
178e83e87a5Sjeremylt   PetscFunctionBeginUser;
17938f32c05Srezgarshakeri   PetscCall(VecDuplicate(X, &E));
18038f32c05Srezgarshakeri   PetscCall(ApplyLocal_Ceed(X, E, op_error_ctx));
181*78f7fce3SZach Atkins   PetscCall(VecViewFromOptions(E, NULL, "-error_view"));
18238f32c05Srezgarshakeri   PetscScalar error_sq = 1.0;
18338f32c05Srezgarshakeri   PetscCall(VecSum(E, &error_sq));
18438f32c05Srezgarshakeri   *l2_error = sqrt(error_sq);
185*78f7fce3SZach Atkins   PetscCall(VecDestroy(&E));
186ee4ca9cbSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
187fd8f24faSSebastian Grimberg }
188e83e87a5Sjeremylt 
189e83e87a5Sjeremylt // -----------------------------------------------------------------------------
190