xref: /libCEED/examples/petsc/src/libceedsetup.c (revision 1c9a79dbea105b3f95768697087571c12d59a016)
1636cccdbSjeremylt #include <stdio.h>
2e83e87a5Sjeremylt #include "../include/libceedsetup.h"
3e83e87a5Sjeremylt #include "../include/petscutils.h"
4e83e87a5Sjeremylt 
5e83e87a5Sjeremylt // -----------------------------------------------------------------------------
6e83e87a5Sjeremylt // Destroy libCEED operator objects
7e83e87a5Sjeremylt // -----------------------------------------------------------------------------
8e83e87a5Sjeremylt PetscErrorCode CeedDataDestroy(CeedInt i, CeedData data) {
9e83e87a5Sjeremylt   int ierr;
10e83e87a5Sjeremylt 
115dfaedb8SJed Brown   PetscFunctionBeginUser;
129b072555Sjeremylt   CeedVectorDestroy(&data->q_data);
139b072555Sjeremylt   CeedVectorDestroy(&data->x_ceed);
149b072555Sjeremylt   CeedVectorDestroy(&data->y_ceed);
159b072555Sjeremylt   CeedBasisDestroy(&data->basis_x);
169b072555Sjeremylt   CeedBasisDestroy(&data->basis_u);
179b072555Sjeremylt   CeedElemRestrictionDestroy(&data->elem_restr_u);
189b072555Sjeremylt   CeedElemRestrictionDestroy(&data->elem_restr_x);
199b072555Sjeremylt   CeedElemRestrictionDestroy(&data->elem_restr_u_i);
209b072555Sjeremylt   CeedElemRestrictionDestroy(&data->elem_restr_qd_i);
219b072555Sjeremylt   CeedQFunctionDestroy(&data->qf_apply);
229b072555Sjeremylt   CeedOperatorDestroy(&data->op_apply);
23e83e87a5Sjeremylt   if (i > 0) {
249b072555Sjeremylt     CeedOperatorDestroy(&data->op_prolong);
259b072555Sjeremylt     CeedOperatorDestroy(&data->op_restrict);
26e83e87a5Sjeremylt   }
27e83e87a5Sjeremylt   ierr = PetscFree(data); CHKERRQ(ierr);
28e83e87a5Sjeremylt 
29e83e87a5Sjeremylt   PetscFunctionReturn(0);
30e83e87a5Sjeremylt };
31e83e87a5Sjeremylt 
32e83e87a5Sjeremylt // -----------------------------------------------------------------------------
33e83e87a5Sjeremylt // Set up libCEED for a given degree
34e83e87a5Sjeremylt // -----------------------------------------------------------------------------
35e83e87a5Sjeremylt PetscErrorCode SetupLibceedByDegree(DM dm, Ceed ceed, CeedInt degree,
369b072555Sjeremylt                                     CeedInt topo_dim, CeedInt q_extra,
379b072555Sjeremylt                                     PetscInt num_comp_x, PetscInt num_comp_u,
389b072555Sjeremylt                                     PetscInt g_size, PetscInt xl_size,
399b072555Sjeremylt                                     BPData bp_data, CeedData data,
409b072555Sjeremylt                                     PetscBool setup_rhs, CeedVector rhs_ceed,
41e83e87a5Sjeremylt                                     CeedVector *target) {
42e83e87a5Sjeremylt   int ierr;
439b072555Sjeremylt   DM dm_coord;
44e83e87a5Sjeremylt   Vec coords;
459b072555Sjeremylt   const PetscScalar *coord_array;
469b072555Sjeremylt   CeedBasis basis_x, basis_u;
479b072555Sjeremylt   CeedElemRestriction elem_restr_x, elem_restr_u, elem_restr_u_i, elem_restr_qd_i;
489b072555Sjeremylt   CeedQFunction qf_setup_geo, qf_apply;
499b072555Sjeremylt   CeedOperator op_setup_geo, op_apply;
509b072555Sjeremylt   CeedVector x_coord, q_data, x_ceed, y_ceed;
51129d8736Srezgarshakeri   CeedInt num_qpts, c_start, c_end, num_elem,
529b072555Sjeremylt           q_data_size = bp_data.q_data_size;
53e83e87a5Sjeremylt   CeedScalar R = 1,                      // radius of the sphere
54e83e87a5Sjeremylt              l = 1.0/PetscSqrtReal(3.0); // half edge of the inscribed cube
55e83e87a5Sjeremylt 
56129d8736Srezgarshakeri <<<<<<< HEAD
57de1229c5Srezgarshakeri <<<<<<< HEAD
585dfaedb8SJed Brown   PetscFunctionBeginUser;
59e83e87a5Sjeremylt   // CEED bases
60e83e87a5Sjeremylt   P = degree + 1;
619b072555Sjeremylt   Q = P + q_extra;
629b072555Sjeremylt   CeedBasisCreateTensorH1Lagrange(ceed, topo_dim, num_comp_u, P, Q,
639b072555Sjeremylt                                   bp_data.q_mode,
649b072555Sjeremylt                                   &basis_u);
659b072555Sjeremylt   CeedBasisCreateTensorH1Lagrange(ceed, topo_dim, num_comp_x, 2, Q,
669b072555Sjeremylt                                   bp_data.q_mode,
679b072555Sjeremylt                                   &basis_x);
689b072555Sjeremylt   CeedBasisGetNumQuadraturePoints(basis_u, &num_qpts);
69e83e87a5Sjeremylt 
70e83e87a5Sjeremylt   // CEED restrictions
71129d8736Srezgarshakeri =======
72129d8736Srezgarshakeri >>>>>>> 158419b6 (example/petsc: added CreateBasisFromPlex and tested with tensor basis)
737ed3e4cdSJeremy L Thompson   ierr = DMSetCoordinateDim(dm, topo_dim); CHKERRQ(ierr);
74de1229c5Srezgarshakeri =======
75de1229c5Srezgarshakeri   //ierr = DMSetCoordinateDim(dm, topo_dim); CHKERRQ(ierr);
76de1229c5Srezgarshakeri >>>>>>> 0fa86f50 (example/petsc: Added CreateDistributedDM in petscutils.c and some cleanup)
779b072555Sjeremylt   ierr = DMGetCoordinateDM(dm, &dm_coord); CHKERRQ(ierr);
78129d8736Srezgarshakeri 
79129d8736Srezgarshakeri   // CEED bases
80129d8736Srezgarshakeri   ierr = CreateBasisFromPlex(ceed, dm_coord, 0, 0, 0, 0, &basis_x); CHKERRQ(ierr);
81129d8736Srezgarshakeri   ierr = CreateBasisFromPlex(ceed, dm, 0, 0, 0, 0, &basis_u); CHKERRQ(ierr);
82129d8736Srezgarshakeri 
83129d8736Srezgarshakeri   // CEED restrictions
849b072555Sjeremylt   ierr = DMPlexSetClosurePermutationTensor(dm_coord, PETSC_DETERMINE, NULL);
85e83e87a5Sjeremylt   CHKERRQ(ierr);
867ed3e4cdSJeremy L Thompson   ierr = CreateRestrictionFromPlex(ceed, dm_coord, 0, 0, 0, &elem_restr_x);
87e83e87a5Sjeremylt   CHKERRQ(ierr);
887ed3e4cdSJeremy L Thompson   ierr = CreateRestrictionFromPlex(ceed, dm, 0, 0, 0, &elem_restr_u);
89e83e87a5Sjeremylt   CHKERRQ(ierr);
90e83e87a5Sjeremylt 
919b072555Sjeremylt   ierr = DMPlexGetHeightStratum(dm, 0, &c_start, &c_end); CHKERRQ(ierr);
929b072555Sjeremylt   num_elem = c_end - c_start;
93129d8736Srezgarshakeri   CeedBasisGetNumQuadraturePoints(basis_u, &num_qpts);
94e83e87a5Sjeremylt 
959b072555Sjeremylt   CeedElemRestrictionCreateStrided(ceed, num_elem, num_qpts, num_comp_u,
969b072555Sjeremylt                                    num_comp_u*num_elem*num_qpts,
979b072555Sjeremylt                                    CEED_STRIDES_BACKEND, &elem_restr_u_i);
989b072555Sjeremylt   CeedElemRestrictionCreateStrided(ceed, num_elem, num_qpts, q_data_size,
999b072555Sjeremylt                                    q_data_size*num_elem*num_qpts,
1009b072555Sjeremylt                                    CEED_STRIDES_BACKEND, &elem_restr_qd_i);
101e83e87a5Sjeremylt 
102e83e87a5Sjeremylt   // Element coordinates
103e83e87a5Sjeremylt   ierr = DMGetCoordinatesLocal(dm, &coords); CHKERRQ(ierr);
1049b072555Sjeremylt   ierr = VecGetArrayRead(coords, &coord_array); CHKERRQ(ierr);
105e83e87a5Sjeremylt 
1069b072555Sjeremylt   CeedElemRestrictionCreateVector(elem_restr_x, &x_coord, NULL);
1079b072555Sjeremylt   CeedVectorSetArray(x_coord, CEED_MEM_HOST, CEED_COPY_VALUES,
1089b072555Sjeremylt                      (PetscScalar *)coord_array);
1099b072555Sjeremylt   ierr = VecRestoreArrayRead(coords, &coord_array);
110e83e87a5Sjeremylt 
111e83e87a5Sjeremylt   // Create the persistent vectors that will be needed in setup and apply
1129b072555Sjeremylt   CeedVectorCreate(ceed, q_data_size*num_elem*num_qpts, &q_data);
1139b072555Sjeremylt   CeedVectorCreate(ceed, xl_size, &x_ceed);
1149b072555Sjeremylt   CeedVectorCreate(ceed, xl_size, &y_ceed);
115e83e87a5Sjeremylt 
116e83e87a5Sjeremylt   // Create the QFunction that builds the context data
1179b072555Sjeremylt   CeedQFunctionCreateInterior(ceed, 1, bp_data.setup_geo, bp_data.setup_geo_loc,
1189b072555Sjeremylt                               &qf_setup_geo);
1199b072555Sjeremylt   CeedQFunctionAddInput(qf_setup_geo, "x", num_comp_x, CEED_EVAL_INTERP);
1209b072555Sjeremylt   CeedQFunctionAddInput(qf_setup_geo, "dx", num_comp_x*topo_dim, CEED_EVAL_GRAD);
1219b072555Sjeremylt   CeedQFunctionAddInput(qf_setup_geo, "weight", 1, CEED_EVAL_WEIGHT);
122a61c78d6SJeremy L Thompson   CeedQFunctionAddOutput(qf_setup_geo, "qdata", q_data_size, CEED_EVAL_NONE);
123e83e87a5Sjeremylt 
124e83e87a5Sjeremylt   // Create the operator that builds the quadrature data
1259b072555Sjeremylt   CeedOperatorCreate(ceed, qf_setup_geo, NULL, NULL, &op_setup_geo);
1269b072555Sjeremylt   CeedOperatorSetField(op_setup_geo, "x", elem_restr_x, basis_x,
1279b072555Sjeremylt                        CEED_VECTOR_ACTIVE);
1289b072555Sjeremylt   CeedOperatorSetField(op_setup_geo, "dx", elem_restr_x, basis_x,
1299b072555Sjeremylt                        CEED_VECTOR_ACTIVE);
1309b072555Sjeremylt   CeedOperatorSetField(op_setup_geo, "weight", CEED_ELEMRESTRICTION_NONE, basis_x,
131e83e87a5Sjeremylt                        CEED_VECTOR_NONE);
132a61c78d6SJeremy L Thompson   CeedOperatorSetField(op_setup_geo, "qdata", elem_restr_qd_i,
133e83e87a5Sjeremylt                        CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
134e83e87a5Sjeremylt 
1359b072555Sjeremylt   // Setup q_data
1369b072555Sjeremylt   CeedOperatorApply(op_setup_geo, x_coord, q_data, CEED_REQUEST_IMMEDIATE);
137e83e87a5Sjeremylt 
138e83e87a5Sjeremylt   // Set up PDE operator
1399b072555Sjeremylt   CeedInt in_scale = bp_data.in_mode == CEED_EVAL_GRAD ? topo_dim : 1;
1409b072555Sjeremylt   CeedInt out_scale = bp_data.out_mode == CEED_EVAL_GRAD ? topo_dim : 1;
1419b072555Sjeremylt   CeedQFunctionCreateInterior(ceed, 1, bp_data.apply, bp_data.apply_loc,
1429b072555Sjeremylt                               &qf_apply);
1439b072555Sjeremylt   CeedQFunctionAddInput(qf_apply, "u", num_comp_u*in_scale, bp_data.in_mode);
144a61c78d6SJeremy L Thompson   CeedQFunctionAddInput(qf_apply, "qdata", q_data_size, CEED_EVAL_NONE);
1459b072555Sjeremylt   CeedQFunctionAddOutput(qf_apply, "v", num_comp_u*out_scale, bp_data.out_mode);
146e83e87a5Sjeremylt 
147e83e87a5Sjeremylt   // Create the mass or diff operator
1489b072555Sjeremylt   CeedOperatorCreate(ceed, qf_apply, NULL, NULL, &op_apply);
1499b072555Sjeremylt   CeedOperatorSetField(op_apply, "u", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE);
150a61c78d6SJeremy L Thompson   CeedOperatorSetField(op_apply, "qdata", elem_restr_qd_i, CEED_BASIS_COLLOCATED,
1519b072555Sjeremylt                        q_data);
1529b072555Sjeremylt   CeedOperatorSetField(op_apply, "v", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE);
153e83e87a5Sjeremylt 
154e83e87a5Sjeremylt   // Set up RHS if needed
155e83e87a5Sjeremylt   if (setup_rhs) {
1569b072555Sjeremylt     CeedQFunction qf_setup_rhs;
1579b072555Sjeremylt     CeedOperator op_setup_rhs;
1589b072555Sjeremylt     CeedVectorCreate(ceed, num_elem*num_qpts*num_comp_u, target);
159e83e87a5Sjeremylt 
160e83e87a5Sjeremylt     // Create the q-function that sets up the RHS and true solution
1619b072555Sjeremylt     CeedQFunctionCreateInterior(ceed, 1, bp_data.setup_rhs, bp_data.setup_rhs_loc,
1629b072555Sjeremylt                                 &qf_setup_rhs);
1639b072555Sjeremylt     CeedQFunctionAddInput(qf_setup_rhs, "x", num_comp_x, CEED_EVAL_INTERP);
164a61c78d6SJeremy L Thompson     CeedQFunctionAddInput(qf_setup_rhs, "qdata", q_data_size, CEED_EVAL_NONE);
165a61c78d6SJeremy L Thompson     CeedQFunctionAddOutput(qf_setup_rhs, "true solution", num_comp_u,
166a61c78d6SJeremy L Thompson                            CEED_EVAL_NONE);
1679b072555Sjeremylt     CeedQFunctionAddOutput(qf_setup_rhs, "rhs", num_comp_u, CEED_EVAL_INTERP);
168e83e87a5Sjeremylt 
169e83e87a5Sjeremylt     // Create the operator that builds the RHS and true solution
1709b072555Sjeremylt     CeedOperatorCreate(ceed, qf_setup_rhs, NULL, NULL, &op_setup_rhs);
1719b072555Sjeremylt     CeedOperatorSetField(op_setup_rhs, "x", elem_restr_x, basis_x,
1729b072555Sjeremylt                          CEED_VECTOR_ACTIVE);
173a61c78d6SJeremy L Thompson     CeedOperatorSetField(op_setup_rhs, "qdata", elem_restr_qd_i,
174a61c78d6SJeremy L Thompson                          CEED_BASIS_COLLOCATED, q_data);
175a61c78d6SJeremy L Thompson     CeedOperatorSetField(op_setup_rhs, "true solution", elem_restr_u_i,
176e83e87a5Sjeremylt                          CEED_BASIS_COLLOCATED, *target);
1779b072555Sjeremylt     CeedOperatorSetField(op_setup_rhs, "rhs", elem_restr_u, basis_u,
178e83e87a5Sjeremylt                          CEED_VECTOR_ACTIVE);
179e83e87a5Sjeremylt 
180e83e87a5Sjeremylt     // Set up the libCEED context
1819b072555Sjeremylt     CeedQFunctionContext ctx_rhs_setup;
1829b072555Sjeremylt     CeedQFunctionContextCreate(ceed, &ctx_rhs_setup);
1839b072555Sjeremylt     CeedScalar rhs_setup_data[2] = {R, l};
1849b072555Sjeremylt     CeedQFunctionContextSetData(ctx_rhs_setup, CEED_MEM_HOST, CEED_COPY_VALUES,
1859b072555Sjeremylt                                 sizeof rhs_setup_data, &rhs_setup_data);
1869b072555Sjeremylt     CeedQFunctionSetContext(qf_setup_rhs, ctx_rhs_setup);
1879b072555Sjeremylt     CeedQFunctionContextDestroy(&ctx_rhs_setup);
188e83e87a5Sjeremylt 
189e83e87a5Sjeremylt     // Setup RHS and target
1909b072555Sjeremylt     CeedOperatorApply(op_setup_rhs, x_coord, rhs_ceed, CEED_REQUEST_IMMEDIATE);
191e83e87a5Sjeremylt 
192e83e87a5Sjeremylt     // Cleanup
1939b072555Sjeremylt     CeedQFunctionDestroy(&qf_setup_rhs);
1949b072555Sjeremylt     CeedOperatorDestroy(&op_setup_rhs);
195e83e87a5Sjeremylt   }
196e83e87a5Sjeremylt 
197e83e87a5Sjeremylt   // Cleanup
1989b072555Sjeremylt   CeedQFunctionDestroy(&qf_setup_geo);
1999b072555Sjeremylt   CeedOperatorDestroy(&op_setup_geo);
2009b072555Sjeremylt   CeedVectorDestroy(&x_coord);
201e83e87a5Sjeremylt 
202e83e87a5Sjeremylt   // Save libCEED data required for level
2039b072555Sjeremylt   data->basis_x = basis_x; data->basis_u = basis_u;
2049b072555Sjeremylt   data->elem_restr_x = elem_restr_x;
2059b072555Sjeremylt   data->elem_restr_u = elem_restr_u;
2069b072555Sjeremylt   data->elem_restr_u_i = elem_restr_u_i;
2079b072555Sjeremylt   data->elem_restr_qd_i = elem_restr_qd_i;
2089b072555Sjeremylt   data->qf_apply = qf_apply;
2099b072555Sjeremylt   data->op_apply = op_apply;
2109b072555Sjeremylt   data->q_data = q_data;
2119b072555Sjeremylt   data->x_ceed = x_ceed;
2129b072555Sjeremylt   data->y_ceed = y_ceed;
213e83e87a5Sjeremylt 
214e83e87a5Sjeremylt   PetscFunctionReturn(0);
215e83e87a5Sjeremylt };
216e83e87a5Sjeremylt 
217e83e87a5Sjeremylt // -----------------------------------------------------------------------------
218e83e87a5Sjeremylt // Setup libCEED level transfer operator objects
219e83e87a5Sjeremylt // -----------------------------------------------------------------------------
220*1c9a79dbSrezgarshakeri PetscErrorCode CeedLevelTransferSetup(DM dm, Ceed ceed, CeedInt level,
2219b072555Sjeremylt                                       CeedInt num_comp_u, CeedData *data,
222*1c9a79dbSrezgarshakeri <<<<<<< HEAD
2239b072555Sjeremylt                                       CeedInt *level_degrees,
2249b072555Sjeremylt                                       CeedQFunction qf_restrict, CeedQFunction qf_prolong) {
2255dfaedb8SJed Brown   PetscFunctionBeginUser;
2269b072555Sjeremylt   // Return early if num_levels=1
2279b072555Sjeremylt   if (num_levels == 1)
228e83e87a5Sjeremylt     PetscFunctionReturn(0);
229*1c9a79dbSrezgarshakeri =======
230*1c9a79dbSrezgarshakeri                                       Vec fine_mult) {
231*1c9a79dbSrezgarshakeri   int ierr;
232*1c9a79dbSrezgarshakeri >>>>>>> 2e9bde68 (Used "CeedOperatorMultigridLevelCreate" to create multigrid operators)
233e83e87a5Sjeremylt 
234e83e87a5Sjeremylt   // Restriction - Fine to corse
2359b072555Sjeremylt   CeedOperator op_restrict;
236e83e87a5Sjeremylt   // Interpolation - Corse to fine
2379b072555Sjeremylt   CeedOperator op_prolong;
238*1c9a79dbSrezgarshakeri   // Coarse grid operator
239*1c9a79dbSrezgarshakeri   CeedOperator op_apply;
240*1c9a79dbSrezgarshakeri   // Basis
241*1c9a79dbSrezgarshakeri   CeedBasis basis_u;
242*1c9a79dbSrezgarshakeri   ierr = CreateBasisFromPlex(ceed, dm, 0, 0, 0, 0, &basis_u);
243*1c9a79dbSrezgarshakeri   CHKERRQ(ierr);
244e83e87a5Sjeremylt 
245*1c9a79dbSrezgarshakeri   // ---------------------------------------------------------------------------
246*1c9a79dbSrezgarshakeri   // Coarse Grid, Prolongation, and Restriction Operators
247*1c9a79dbSrezgarshakeri   // ---------------------------------------------------------------------------
248*1c9a79dbSrezgarshakeri   // Create the Operators that compute the prolongation and
249*1c9a79dbSrezgarshakeri   //   restriction between the p-multigrid levels and the coarse grid eval.
250*1c9a79dbSrezgarshakeri   // ---------------------------------------------------------------------------
251*1c9a79dbSrezgarshakeri   // Place in libCEED array
252*1c9a79dbSrezgarshakeri   const PetscScalar *m;
253*1c9a79dbSrezgarshakeri   PetscMemType m_mem_type;
254*1c9a79dbSrezgarshakeri   ierr = VecGetArrayReadAndMemType(fine_mult, &m, &m_mem_type);
255*1c9a79dbSrezgarshakeri   CHKERRQ(ierr);
256*1c9a79dbSrezgarshakeri   CeedVectorSetArray(data[level]->x_ceed, MemTypeP2C(m_mem_type),
257*1c9a79dbSrezgarshakeri                      CEED_USE_POINTER, (CeedScalar *)m);
258e83e87a5Sjeremylt 
259*1c9a79dbSrezgarshakeri   CeedOperatorMultigridLevelCreate(data[level]->op_apply, data[level]->x_ceed,
260*1c9a79dbSrezgarshakeri                                    data[level-1]->elem_restr_u, basis_u,
261*1c9a79dbSrezgarshakeri                                    &op_apply, &op_prolong, &op_restrict);
262e83e87a5Sjeremylt 
263*1c9a79dbSrezgarshakeri   // Restore PETSc vector
264*1c9a79dbSrezgarshakeri   CeedVectorTakeArray(data[level]->x_ceed, MemTypeP2C(m_mem_type),
265*1c9a79dbSrezgarshakeri                       (CeedScalar **)&m);
266*1c9a79dbSrezgarshakeri   ierr = VecRestoreArrayReadAndMemType(fine_mult, &m); CHKERRQ(ierr);
267*1c9a79dbSrezgarshakeri   ierr = VecZeroEntries(fine_mult); CHKERRQ(ierr);
268*1c9a79dbSrezgarshakeri   // -- Save libCEED data
269*1c9a79dbSrezgarshakeri   data[level-1]->op_apply = op_apply;
270*1c9a79dbSrezgarshakeri   data[level]->op_prolong = op_prolong;
271*1c9a79dbSrezgarshakeri   data[level]->op_restrict = op_restrict;
272*1c9a79dbSrezgarshakeri 
273*1c9a79dbSrezgarshakeri   CeedBasisDestroy(&basis_u);
274e83e87a5Sjeremylt   PetscFunctionReturn(0);
275e83e87a5Sjeremylt };
276e83e87a5Sjeremylt 
277e83e87a5Sjeremylt // -----------------------------------------------------------------------------
278