1d275d636SJeremy L Thompson // Copyright (c) 2017-2025, Lawrence Livermore National Security, LLC and other CEED contributors. 298285ab4SZach Atkins // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 398285ab4SZach Atkins // 498285ab4SZach Atkins // SPDX-License-Identifier: BSD-2-Clause 598285ab4SZach Atkins // 698285ab4SZach Atkins // This file is part of CEED: http://github.com/ceed 798285ab4SZach Atkins 8e83e87a5Sjeremylt #include "../include/libceedsetup.h" 92b730f8bSJeremy L Thompson 102b730f8bSJeremy L Thompson #include <stdio.h> 112b730f8bSJeremy L Thompson 1278f7fce3SZach Atkins #include "../include/libceedsetup.h" 13e83e87a5Sjeremylt #include "../include/petscutils.h" 14e83e87a5Sjeremylt 15e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 16e83e87a5Sjeremylt // Destroy libCEED operator objects 17e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 18e83e87a5Sjeremylt PetscErrorCode CeedDataDestroy(CeedInt i, CeedData data) { 195dfaedb8SJed Brown PetscFunctionBeginUser; 209b072555Sjeremylt CeedVectorDestroy(&data->q_data); 219b072555Sjeremylt CeedVectorDestroy(&data->x_ceed); 229b072555Sjeremylt CeedVectorDestroy(&data->y_ceed); 239b072555Sjeremylt CeedBasisDestroy(&data->basis_x); 249b072555Sjeremylt CeedBasisDestroy(&data->basis_u); 259b072555Sjeremylt CeedElemRestrictionDestroy(&data->elem_restr_u); 269b072555Sjeremylt CeedElemRestrictionDestroy(&data->elem_restr_x); 279b072555Sjeremylt CeedElemRestrictionDestroy(&data->elem_restr_u_i); 289b072555Sjeremylt CeedElemRestrictionDestroy(&data->elem_restr_qd_i); 299b072555Sjeremylt CeedQFunctionDestroy(&data->qf_apply); 309b072555Sjeremylt CeedOperatorDestroy(&data->op_apply); 31e83e87a5Sjeremylt if (i > 0) { 329b072555Sjeremylt CeedOperatorDestroy(&data->op_prolong); 339b072555Sjeremylt CeedOperatorDestroy(&data->op_restrict); 34e83e87a5Sjeremylt } 352b730f8bSJeremy L Thompson PetscCall(PetscFree(data)); 36ee4ca9cbSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 37e83e87a5Sjeremylt }; 38e83e87a5Sjeremylt 39e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 40e83e87a5Sjeremylt // Set up libCEED for a given degree 41e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 422b730f8bSJeremy L Thompson PetscErrorCode SetupLibceedByDegree(DM dm, Ceed ceed, CeedInt degree, CeedInt topo_dim, CeedInt q_extra, PetscInt num_comp_x, PetscInt num_comp_u, 434dbe2ad5SJeremy L Thompson PetscInt g_size, PetscInt xl_size, BPData bp_data, CeedData data, PetscBool setup_rhs, PetscBool is_fine_level, 444dbe2ad5SJeremy L Thompson CeedVector rhs_ceed, CeedVector *target) { 459b072555Sjeremylt DM dm_coord; 46e83e87a5Sjeremylt Vec coords; 479b072555Sjeremylt const PetscScalar *coord_array; 489b072555Sjeremylt CeedBasis basis_x, basis_u; 499b072555Sjeremylt CeedElemRestriction elem_restr_x, elem_restr_u, elem_restr_u_i, elem_restr_qd_i; 504dbe2ad5SJeremy L Thompson CeedQFunction qf_setup_geo = NULL, qf_apply = NULL; 519b072555Sjeremylt CeedOperator op_setup_geo, op_apply; 529b072555Sjeremylt CeedVector x_coord, q_data, x_ceed, y_ceed; 534d00b080SJeremy L Thompson PetscInt c_start, c_end, num_elem; 544d00b080SJeremy L Thompson CeedInt num_qpts, q_data_size = bp_data.q_data_size; 552b730f8bSJeremy L Thompson CeedScalar R = 1; // radius of the sphere 562b730f8bSJeremy L Thompson CeedScalar l = 1.0 / PetscSqrtReal(3.0); // half edge of the inscribed cube 57e83e87a5Sjeremylt 585dfaedb8SJed Brown PetscFunctionBeginUser; 592b730f8bSJeremy L Thompson PetscCall(DMGetCoordinateDM(dm, &dm_coord)); 60129d8736Srezgarshakeri 61129d8736Srezgarshakeri // CEED bases 622b730f8bSJeremy L Thompson PetscCall(CreateBasisFromPlex(ceed, dm_coord, 0, 0, 0, 0, bp_data, &basis_x)); 632b730f8bSJeremy L Thompson PetscCall(CreateBasisFromPlex(ceed, dm, 0, 0, 0, 0, bp_data, &basis_u)); 64129d8736Srezgarshakeri 65129d8736Srezgarshakeri // CEED restrictions 662b730f8bSJeremy L Thompson PetscCall(CreateRestrictionFromPlex(ceed, dm_coord, 0, 0, 0, &elem_restr_x)); 672b730f8bSJeremy L Thompson PetscCall(CreateRestrictionFromPlex(ceed, dm, 0, 0, 0, &elem_restr_u)); 68e83e87a5Sjeremylt 692b730f8bSJeremy L Thompson PetscCall(DMPlexGetHeightStratum(dm, 0, &c_start, &c_end)); 709b072555Sjeremylt num_elem = c_end - c_start; 71129d8736Srezgarshakeri CeedBasisGetNumQuadraturePoints(basis_u, &num_qpts); 72e83e87a5Sjeremylt 732b730f8bSJeremy L Thompson CeedElemRestrictionCreateStrided(ceed, num_elem, num_qpts, num_comp_u, num_comp_u * num_elem * num_qpts, CEED_STRIDES_BACKEND, &elem_restr_u_i); 742b730f8bSJeremy L Thompson CeedElemRestrictionCreateStrided(ceed, num_elem, num_qpts, q_data_size, q_data_size * num_elem * num_qpts, CEED_STRIDES_BACKEND, &elem_restr_qd_i); 75e83e87a5Sjeremylt 76e83e87a5Sjeremylt // Element coordinates 772b730f8bSJeremy L Thompson PetscCall(DMGetCoordinatesLocal(dm, &coords)); 782b730f8bSJeremy L Thompson PetscCall(VecGetArrayRead(coords, &coord_array)); 79e83e87a5Sjeremylt 809b072555Sjeremylt CeedElemRestrictionCreateVector(elem_restr_x, &x_coord, NULL); 812b730f8bSJeremy L Thompson CeedVectorSetArray(x_coord, CEED_MEM_HOST, CEED_COPY_VALUES, (PetscScalar *)coord_array); 822b730f8bSJeremy L Thompson PetscCall(VecRestoreArrayRead(coords, &coord_array)); 83e83e87a5Sjeremylt 84e83e87a5Sjeremylt // Create the persistent vectors that will be needed in setup and apply 859b072555Sjeremylt CeedVectorCreate(ceed, q_data_size * num_elem * num_qpts, &q_data); 869b072555Sjeremylt CeedVectorCreate(ceed, xl_size, &x_ceed); 879b072555Sjeremylt CeedVectorCreate(ceed, xl_size, &y_ceed); 88e83e87a5Sjeremylt 894dbe2ad5SJeremy L Thompson if (is_fine_level) { 90e83e87a5Sjeremylt // Create the QFunction that builds the context data 912b730f8bSJeremy L Thompson CeedQFunctionCreateInterior(ceed, 1, bp_data.setup_geo, bp_data.setup_geo_loc, &qf_setup_geo); 929b072555Sjeremylt CeedQFunctionAddInput(qf_setup_geo, "x", num_comp_x, CEED_EVAL_INTERP); 939b072555Sjeremylt CeedQFunctionAddInput(qf_setup_geo, "dx", num_comp_x * topo_dim, CEED_EVAL_GRAD); 949b072555Sjeremylt CeedQFunctionAddInput(qf_setup_geo, "weight", 1, CEED_EVAL_WEIGHT); 95a61c78d6SJeremy L Thompson CeedQFunctionAddOutput(qf_setup_geo, "qdata", q_data_size, CEED_EVAL_NONE); 96e83e87a5Sjeremylt 97e83e87a5Sjeremylt // Create the operator that builds the quadrature data 989b072555Sjeremylt CeedOperatorCreate(ceed, qf_setup_geo, NULL, NULL, &op_setup_geo); 992b730f8bSJeremy L Thompson CeedOperatorSetField(op_setup_geo, "x", elem_restr_x, basis_x, CEED_VECTOR_ACTIVE); 1002b730f8bSJeremy L Thompson CeedOperatorSetField(op_setup_geo, "dx", elem_restr_x, basis_x, CEED_VECTOR_ACTIVE); 1012b730f8bSJeremy L Thompson CeedOperatorSetField(op_setup_geo, "weight", CEED_ELEMRESTRICTION_NONE, basis_x, CEED_VECTOR_NONE); 102356036faSJeremy L Thompson CeedOperatorSetField(op_setup_geo, "qdata", elem_restr_qd_i, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE); 103e83e87a5Sjeremylt 1049b072555Sjeremylt // Setup q_data 1059b072555Sjeremylt CeedOperatorApply(op_setup_geo, x_coord, q_data, CEED_REQUEST_IMMEDIATE); 106e83e87a5Sjeremylt 107e83e87a5Sjeremylt // Set up PDE operator 108*3c11f1fcSJeremy L Thompson PetscBool is_interp = bp_data.in_mode == CEED_EVAL_INTERP; 1099b072555Sjeremylt CeedInt in_scale = bp_data.in_mode == CEED_EVAL_GRAD ? topo_dim : 1; 1109b072555Sjeremylt CeedInt out_scale = bp_data.out_mode == CEED_EVAL_GRAD ? topo_dim : 1; 111*3c11f1fcSJeremy L Thompson 1122b730f8bSJeremy L Thompson CeedQFunctionCreateInterior(ceed, 1, bp_data.apply, bp_data.apply_loc, &qf_apply); 113*3c11f1fcSJeremy L Thompson if (bp_data.in_mode == CEED_EVAL_INTERP + CEED_EVAL_GRAD) { 114*3c11f1fcSJeremy L Thompson CeedQFunctionAddInput(qf_apply, "u", num_comp_u, CEED_EVAL_INTERP); 115*3c11f1fcSJeremy L Thompson CeedQFunctionAddInput(qf_apply, "du", num_comp_u * topo_dim, CEED_EVAL_GRAD); 116*3c11f1fcSJeremy L Thompson } else { 117*3c11f1fcSJeremy L Thompson CeedQFunctionAddInput(qf_apply, is_interp ? "u" : "du", num_comp_u * in_scale, bp_data.in_mode); 118*3c11f1fcSJeremy L Thompson } 119a61c78d6SJeremy L Thompson CeedQFunctionAddInput(qf_apply, "qdata", q_data_size, CEED_EVAL_NONE); 120*3c11f1fcSJeremy L Thompson if (bp_data.out_mode == CEED_EVAL_INTERP + CEED_EVAL_GRAD) { 121*3c11f1fcSJeremy L Thompson CeedQFunctionAddOutput(qf_apply, "v", num_comp_u, CEED_EVAL_INTERP); 122*3c11f1fcSJeremy L Thompson CeedQFunctionAddOutput(qf_apply, "dv", num_comp_u * topo_dim, CEED_EVAL_GRAD); 123*3c11f1fcSJeremy L Thompson } else { 124*3c11f1fcSJeremy L Thompson CeedQFunctionAddOutput(qf_apply, is_interp ? "v" : "dv", num_comp_u * out_scale, bp_data.out_mode); 125*3c11f1fcSJeremy L Thompson } 126e83e87a5Sjeremylt 127e83e87a5Sjeremylt // Create the mass or diff operator 1289b072555Sjeremylt CeedOperatorCreate(ceed, qf_apply, NULL, NULL, &op_apply); 129*3c11f1fcSJeremy L Thompson if (bp_data.in_mode == CEED_EVAL_INTERP + CEED_EVAL_GRAD) { 1309b072555Sjeremylt CeedOperatorSetField(op_apply, "u", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE); 131*3c11f1fcSJeremy L Thompson CeedOperatorSetField(op_apply, "du", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE); 132*3c11f1fcSJeremy L Thompson } else { 133*3c11f1fcSJeremy L Thompson CeedOperatorSetField(op_apply, is_interp ? "u" : "du", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE); 134*3c11f1fcSJeremy L Thompson } 135356036faSJeremy L Thompson CeedOperatorSetField(op_apply, "qdata", elem_restr_qd_i, CEED_BASIS_NONE, q_data); 136*3c11f1fcSJeremy L Thompson if (bp_data.out_mode == CEED_EVAL_INTERP + CEED_EVAL_GRAD) { 1379b072555Sjeremylt CeedOperatorSetField(op_apply, "v", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE); 138*3c11f1fcSJeremy L Thompson CeedOperatorSetField(op_apply, "dv", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE); 139*3c11f1fcSJeremy L Thompson } else { 140*3c11f1fcSJeremy L Thompson CeedOperatorSetField(op_apply, is_interp ? "v" : "dv", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE); 141*3c11f1fcSJeremy L Thompson } 142e83e87a5Sjeremylt 1434dbe2ad5SJeremy L Thompson // Cleanup 1444dbe2ad5SJeremy L Thompson CeedQFunctionDestroy(&qf_setup_geo); 1454dbe2ad5SJeremy L Thompson CeedOperatorDestroy(&op_setup_geo); 1464dbe2ad5SJeremy L Thompson } 1474dbe2ad5SJeremy L Thompson 148e83e87a5Sjeremylt // Set up RHS if needed 149e83e87a5Sjeremylt if (setup_rhs) { 1509b072555Sjeremylt CeedQFunction qf_setup_rhs; 1519b072555Sjeremylt CeedOperator op_setup_rhs; 1529b072555Sjeremylt CeedVectorCreate(ceed, num_elem * num_qpts * num_comp_u, target); 153e83e87a5Sjeremylt // Create the q-function that sets up the RHS and true solution 1542b730f8bSJeremy L Thompson CeedQFunctionCreateInterior(ceed, 1, bp_data.setup_rhs, bp_data.setup_rhs_loc, &qf_setup_rhs); 1559b072555Sjeremylt CeedQFunctionAddInput(qf_setup_rhs, "x", num_comp_x, CEED_EVAL_INTERP); 156a61c78d6SJeremy L Thompson CeedQFunctionAddInput(qf_setup_rhs, "qdata", q_data_size, CEED_EVAL_NONE); 1572b730f8bSJeremy L Thompson CeedQFunctionAddOutput(qf_setup_rhs, "true solution", num_comp_u, CEED_EVAL_NONE); 1589b072555Sjeremylt CeedQFunctionAddOutput(qf_setup_rhs, "rhs", num_comp_u, CEED_EVAL_INTERP); 159e83e87a5Sjeremylt 160e83e87a5Sjeremylt // Create the operator that builds the RHS and true solution 1619b072555Sjeremylt CeedOperatorCreate(ceed, qf_setup_rhs, NULL, NULL, &op_setup_rhs); 1622b730f8bSJeremy L Thompson CeedOperatorSetField(op_setup_rhs, "x", elem_restr_x, basis_x, CEED_VECTOR_ACTIVE); 163356036faSJeremy L Thompson CeedOperatorSetField(op_setup_rhs, "qdata", elem_restr_qd_i, CEED_BASIS_NONE, q_data); 164356036faSJeremy L Thompson CeedOperatorSetField(op_setup_rhs, "true solution", elem_restr_u_i, CEED_BASIS_NONE, *target); 1652b730f8bSJeremy L Thompson CeedOperatorSetField(op_setup_rhs, "rhs", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE); 166e83e87a5Sjeremylt 167e83e87a5Sjeremylt // Set up the libCEED context 1689b072555Sjeremylt CeedQFunctionContext ctx_rhs_setup; 1699b072555Sjeremylt CeedQFunctionContextCreate(ceed, &ctx_rhs_setup); 1709b072555Sjeremylt CeedScalar rhs_setup_data[2] = {R, l}; 1712b730f8bSJeremy L Thompson CeedQFunctionContextSetData(ctx_rhs_setup, CEED_MEM_HOST, CEED_COPY_VALUES, sizeof rhs_setup_data, &rhs_setup_data); 1729b072555Sjeremylt CeedQFunctionSetContext(qf_setup_rhs, ctx_rhs_setup); 1739b072555Sjeremylt CeedQFunctionContextDestroy(&ctx_rhs_setup); 174e83e87a5Sjeremylt 175e83e87a5Sjeremylt // Setup RHS and target 1769b072555Sjeremylt CeedOperatorApply(op_setup_rhs, x_coord, rhs_ceed, CEED_REQUEST_IMMEDIATE); 177e83e87a5Sjeremylt 178e83e87a5Sjeremylt // Cleanup 1799b072555Sjeremylt CeedQFunctionDestroy(&qf_setup_rhs); 1809b072555Sjeremylt CeedOperatorDestroy(&op_setup_rhs); 181e83e87a5Sjeremylt } 182e83e87a5Sjeremylt // Cleanup 1839b072555Sjeremylt CeedVectorDestroy(&x_coord); 184e83e87a5Sjeremylt 185e83e87a5Sjeremylt // Save libCEED data required for level 1862b730f8bSJeremy L Thompson data->basis_x = basis_x; 1872b730f8bSJeremy L Thompson data->basis_u = basis_u; 1889b072555Sjeremylt data->elem_restr_x = elem_restr_x; 1899b072555Sjeremylt data->elem_restr_u = elem_restr_u; 1909b072555Sjeremylt data->elem_restr_u_i = elem_restr_u_i; 1919b072555Sjeremylt data->elem_restr_qd_i = elem_restr_qd_i; 1929b072555Sjeremylt data->qf_apply = qf_apply; 1939b072555Sjeremylt data->op_apply = op_apply; 1949b072555Sjeremylt data->q_data = q_data; 1959b072555Sjeremylt data->x_ceed = x_ceed; 1969b072555Sjeremylt data->y_ceed = y_ceed; 197d4d45553Srezgarshakeri data->q_data_size = q_data_size; 198ee4ca9cbSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 199e83e87a5Sjeremylt }; 200e83e87a5Sjeremylt 201e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 202e83e87a5Sjeremylt // Setup libCEED level transfer operator objects 203e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 2042b730f8bSJeremy L Thompson PetscErrorCode CeedLevelTransferSetup(DM dm, Ceed ceed, CeedInt level, CeedInt num_comp_u, CeedData *data, BPData bp_data, Vec fine_mult) { 205751eb813Srezgarshakeri PetscFunctionBeginUser; 206e83e87a5Sjeremylt // Restriction - Fine to corse 2079b072555Sjeremylt CeedOperator op_restrict; 208e83e87a5Sjeremylt // Interpolation - Corse to fine 2099b072555Sjeremylt CeedOperator op_prolong; 2101c9a79dbSrezgarshakeri // Coarse grid operator 2111c9a79dbSrezgarshakeri CeedOperator op_apply; 2121c9a79dbSrezgarshakeri // Basis 2131c9a79dbSrezgarshakeri CeedBasis basis_u; 2142b730f8bSJeremy L Thompson PetscCall(CreateBasisFromPlex(ceed, dm, 0, 0, 0, 0, bp_data, &basis_u)); 215e83e87a5Sjeremylt 2161c9a79dbSrezgarshakeri // --------------------------------------------------------------------------- 2171c9a79dbSrezgarshakeri // Coarse Grid, Prolongation, and Restriction Operators 2181c9a79dbSrezgarshakeri // --------------------------------------------------------------------------- 2191c9a79dbSrezgarshakeri // Create the Operators that compute the prolongation and 2201c9a79dbSrezgarshakeri // restriction between the p-multigrid levels and the coarse grid eval. 2211c9a79dbSrezgarshakeri // --------------------------------------------------------------------------- 2221c9a79dbSrezgarshakeri // Place in libCEED array 2231c9a79dbSrezgarshakeri PetscMemType m_mem_type; 224179e5961SZach Atkins PetscCall(VecReadP2C(fine_mult, &m_mem_type, data[level]->x_ceed)); 225e83e87a5Sjeremylt 2262b730f8bSJeremy L Thompson CeedOperatorMultigridLevelCreate(data[level]->op_apply, data[level]->x_ceed, data[level - 1]->elem_restr_u, basis_u, &op_apply, &op_prolong, 2272b730f8bSJeremy L Thompson &op_restrict); 228e83e87a5Sjeremylt 2291c9a79dbSrezgarshakeri // Restore PETSc vector 230179e5961SZach Atkins PetscCall(VecReadC2P(data[level]->x_ceed, m_mem_type, fine_mult)); 2312b730f8bSJeremy L Thompson PetscCall(VecZeroEntries(fine_mult)); 2321c9a79dbSrezgarshakeri // -- Save libCEED data 2331c9a79dbSrezgarshakeri data[level - 1]->op_apply = op_apply; 2341c9a79dbSrezgarshakeri data[level]->op_prolong = op_prolong; 2351c9a79dbSrezgarshakeri data[level]->op_restrict = op_restrict; 2361c9a79dbSrezgarshakeri 2371c9a79dbSrezgarshakeri CeedBasisDestroy(&basis_u); 238ee4ca9cbSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 239e83e87a5Sjeremylt }; 240e83e87a5Sjeremylt 24178f7fce3SZach Atkins PetscErrorCode SetupErrorOperator(DM dm, Ceed ceed, BPData bp_data, CeedInt topo_dim, PetscInt num_comp_x, PetscInt num_comp_u, 24278f7fce3SZach Atkins CeedOperator *op_error) { 24378f7fce3SZach Atkins DM dm_coord; 24478f7fce3SZach Atkins Vec coords; 24578f7fce3SZach Atkins const PetscScalar *coord_array; 24678f7fce3SZach Atkins CeedBasis basis_x, basis_u; 24778f7fce3SZach Atkins CeedElemRestriction elem_restr_x, elem_restr_u, elem_restr_u_i, elem_restr_qd_i; 24878f7fce3SZach Atkins CeedQFunction qf_setup_geo, qf_setup_rhs, qf_error; 24978f7fce3SZach Atkins CeedOperator op_setup_geo, op_setup_rhs; 25078f7fce3SZach Atkins CeedVector x_coord, q_data, target, rhs; 2514d00b080SJeremy L Thompson PetscInt c_start, c_end, num_elem; 2524d00b080SJeremy L Thompson CeedInt num_qpts, q_data_size = bp_data.q_data_size; 25378f7fce3SZach Atkins CeedScalar R = 1; // radius of the sphere 25478f7fce3SZach Atkins CeedScalar l = 1.0 / PetscSqrtReal(3.0); // half edge of the inscribed cube 25578f7fce3SZach Atkins 25678f7fce3SZach Atkins PetscFunctionBeginUser; 25778f7fce3SZach Atkins PetscCall(DMGetCoordinateDM(dm, &dm_coord)); 25878f7fce3SZach Atkins 25978f7fce3SZach Atkins // CEED bases 26078f7fce3SZach Atkins PetscCall(CreateBasisFromPlex(ceed, dm_coord, 0, 0, 0, 0, bp_data, &basis_x)); 26178f7fce3SZach Atkins PetscCall(CreateBasisFromPlex(ceed, dm, 0, 0, 0, 0, bp_data, &basis_u)); 26278f7fce3SZach Atkins 26378f7fce3SZach Atkins // CEED restrictions 26478f7fce3SZach Atkins PetscCall(CreateRestrictionFromPlex(ceed, dm_coord, 0, 0, 0, &elem_restr_x)); 26578f7fce3SZach Atkins PetscCall(CreateRestrictionFromPlex(ceed, dm, 0, 0, 0, &elem_restr_u)); 26678f7fce3SZach Atkins 26778f7fce3SZach Atkins PetscCall(DMPlexGetHeightStratum(dm, 0, &c_start, &c_end)); 26878f7fce3SZach Atkins num_elem = c_end - c_start; 26978f7fce3SZach Atkins CeedBasisGetNumQuadraturePoints(basis_u, &num_qpts); 27078f7fce3SZach Atkins 27178f7fce3SZach Atkins CeedElemRestrictionCreateStrided(ceed, num_elem, num_qpts, num_comp_u, num_comp_u * num_elem * num_qpts, CEED_STRIDES_BACKEND, &elem_restr_u_i); 27278f7fce3SZach Atkins CeedElemRestrictionCreateStrided(ceed, num_elem, num_qpts, q_data_size, q_data_size * num_elem * num_qpts, CEED_STRIDES_BACKEND, &elem_restr_qd_i); 27378f7fce3SZach Atkins 27478f7fce3SZach Atkins // Element coordinates 27578f7fce3SZach Atkins PetscCall(DMGetCoordinatesLocal(dm, &coords)); 27678f7fce3SZach Atkins PetscCall(VecGetArrayRead(coords, &coord_array)); 27778f7fce3SZach Atkins 27878f7fce3SZach Atkins CeedElemRestrictionCreateVector(elem_restr_x, &x_coord, NULL); 27978f7fce3SZach Atkins CeedVectorSetArray(x_coord, CEED_MEM_HOST, CEED_COPY_VALUES, (PetscScalar *)coord_array); 28078f7fce3SZach Atkins PetscCall(VecRestoreArrayRead(coords, &coord_array)); 28178f7fce3SZach Atkins 28278f7fce3SZach Atkins // Create the persistent vectors that will be needed in setup and apply 28378f7fce3SZach Atkins CeedVectorCreate(ceed, q_data_size * num_elem * num_qpts, &q_data); 28478f7fce3SZach Atkins 28578f7fce3SZach Atkins // Create the QFunction that builds the context data 28678f7fce3SZach Atkins CeedQFunctionCreateInterior(ceed, 1, bp_data.setup_geo, bp_data.setup_geo_loc, &qf_setup_geo); 28778f7fce3SZach Atkins CeedQFunctionAddInput(qf_setup_geo, "x", num_comp_x, CEED_EVAL_INTERP); 28878f7fce3SZach Atkins CeedQFunctionAddInput(qf_setup_geo, "dx", num_comp_x * topo_dim, CEED_EVAL_GRAD); 28978f7fce3SZach Atkins CeedQFunctionAddInput(qf_setup_geo, "weight", 1, CEED_EVAL_WEIGHT); 29078f7fce3SZach Atkins CeedQFunctionAddOutput(qf_setup_geo, "qdata", q_data_size, CEED_EVAL_NONE); 29178f7fce3SZach Atkins 29278f7fce3SZach Atkins // Create the operator that builds the quadrature data 29378f7fce3SZach Atkins CeedOperatorCreate(ceed, qf_setup_geo, NULL, NULL, &op_setup_geo); 29478f7fce3SZach Atkins CeedOperatorSetField(op_setup_geo, "x", elem_restr_x, basis_x, CEED_VECTOR_ACTIVE); 29578f7fce3SZach Atkins CeedOperatorSetField(op_setup_geo, "dx", elem_restr_x, basis_x, CEED_VECTOR_ACTIVE); 29678f7fce3SZach Atkins CeedOperatorSetField(op_setup_geo, "weight", CEED_ELEMRESTRICTION_NONE, basis_x, CEED_VECTOR_NONE); 29778f7fce3SZach Atkins CeedOperatorSetField(op_setup_geo, "qdata", elem_restr_qd_i, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE); 29878f7fce3SZach Atkins 29978f7fce3SZach Atkins // Setup q_data 30078f7fce3SZach Atkins CeedOperatorApply(op_setup_geo, x_coord, q_data, CEED_REQUEST_IMMEDIATE); 30178f7fce3SZach Atkins 30278f7fce3SZach Atkins // Set up target vector 30378f7fce3SZach Atkins CeedElemRestrictionCreateVector(elem_restr_u, &rhs, NULL); 30478f7fce3SZach Atkins CeedVectorCreate(ceed, num_elem * num_qpts * num_comp_u, &target); 30578f7fce3SZach Atkins // Create the q-function that sets up the RHS and true solution 30678f7fce3SZach Atkins CeedQFunctionCreateInterior(ceed, 1, bp_data.setup_rhs, bp_data.setup_rhs_loc, &qf_setup_rhs); 30778f7fce3SZach Atkins CeedQFunctionAddInput(qf_setup_rhs, "x", num_comp_x, CEED_EVAL_INTERP); 30878f7fce3SZach Atkins CeedQFunctionAddInput(qf_setup_rhs, "qdata", q_data_size, CEED_EVAL_NONE); 30978f7fce3SZach Atkins CeedQFunctionAddOutput(qf_setup_rhs, "true solution", num_comp_u, CEED_EVAL_NONE); 31078f7fce3SZach Atkins CeedQFunctionAddOutput(qf_setup_rhs, "rhs", num_comp_u, CEED_EVAL_INTERP); 31178f7fce3SZach Atkins 31278f7fce3SZach Atkins // Create the operator that builds the RHS and true solution 31378f7fce3SZach Atkins CeedOperatorCreate(ceed, qf_setup_rhs, NULL, NULL, &op_setup_rhs); 31478f7fce3SZach Atkins CeedOperatorSetField(op_setup_rhs, "x", elem_restr_x, basis_x, CEED_VECTOR_ACTIVE); 31578f7fce3SZach Atkins CeedOperatorSetField(op_setup_rhs, "qdata", elem_restr_qd_i, CEED_BASIS_NONE, q_data); 31678f7fce3SZach Atkins CeedOperatorSetField(op_setup_rhs, "true solution", elem_restr_u_i, CEED_BASIS_NONE, target); 31778f7fce3SZach Atkins CeedOperatorSetField(op_setup_rhs, "rhs", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE); 31878f7fce3SZach Atkins 31978f7fce3SZach Atkins // Set up the libCEED context 32078f7fce3SZach Atkins CeedQFunctionContext ctx_rhs_setup; 32178f7fce3SZach Atkins CeedQFunctionContextCreate(ceed, &ctx_rhs_setup); 32278f7fce3SZach Atkins CeedScalar rhs_setup_data[2] = {R, l}; 32378f7fce3SZach Atkins CeedQFunctionContextSetData(ctx_rhs_setup, CEED_MEM_HOST, CEED_COPY_VALUES, sizeof rhs_setup_data, &rhs_setup_data); 32478f7fce3SZach Atkins CeedQFunctionSetContext(qf_setup_rhs, ctx_rhs_setup); 32578f7fce3SZach Atkins CeedQFunctionContextDestroy(&ctx_rhs_setup); 32678f7fce3SZach Atkins 32778f7fce3SZach Atkins // Setup RHS and target 32878f7fce3SZach Atkins CeedOperatorApply(op_setup_rhs, x_coord, rhs, CEED_REQUEST_IMMEDIATE); 32978f7fce3SZach Atkins 33078f7fce3SZach Atkins // Set up error operator 33178f7fce3SZach Atkins // Create the error QFunction 33278f7fce3SZach Atkins CeedQFunctionCreateInterior(ceed, 1, bp_data.error, bp_data.error_loc, &qf_error); 33378f7fce3SZach Atkins CeedQFunctionAddInput(qf_error, "u", num_comp_u, CEED_EVAL_INTERP); 33478f7fce3SZach Atkins CeedQFunctionAddInput(qf_error, "true_soln", num_comp_u, CEED_EVAL_NONE); 33578f7fce3SZach Atkins CeedQFunctionAddInput(qf_error, "qdata", q_data_size, CEED_EVAL_NONE); 33678f7fce3SZach Atkins CeedQFunctionAddOutput(qf_error, "error", num_comp_u, CEED_EVAL_INTERP); 33778f7fce3SZach Atkins 33878f7fce3SZach Atkins // Create the error operator 33978f7fce3SZach Atkins CeedOperatorCreate(ceed, qf_error, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, op_error); 34078f7fce3SZach Atkins CeedOperatorSetField(*op_error, "u", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE); 34178f7fce3SZach Atkins CeedOperatorSetField(*op_error, "true_soln", elem_restr_u_i, CEED_BASIS_NONE, target); 34278f7fce3SZach Atkins CeedOperatorSetField(*op_error, "qdata", elem_restr_qd_i, CEED_BASIS_NONE, q_data); 34378f7fce3SZach Atkins CeedOperatorSetField(*op_error, "error", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE); 34478f7fce3SZach Atkins 34578f7fce3SZach Atkins // Cleanup 34678f7fce3SZach Atkins CeedQFunctionDestroy(&qf_setup_rhs); 34778f7fce3SZach Atkins CeedOperatorDestroy(&op_setup_rhs); 34878f7fce3SZach Atkins CeedQFunctionDestroy(&qf_setup_geo); 34978f7fce3SZach Atkins CeedOperatorDestroy(&op_setup_geo); 35078f7fce3SZach Atkins CeedQFunctionDestroy(&qf_error); 35178f7fce3SZach Atkins CeedVectorDestroy(&x_coord); 35278f7fce3SZach Atkins CeedVectorDestroy(&rhs); 35378f7fce3SZach Atkins CeedVectorDestroy(&target); 35478f7fce3SZach Atkins CeedVectorDestroy(&q_data); 35578f7fce3SZach Atkins CeedElemRestrictionDestroy(&elem_restr_u_i); 35678f7fce3SZach Atkins CeedElemRestrictionDestroy(&elem_restr_qd_i); 35778f7fce3SZach Atkins CeedElemRestrictionDestroy(&elem_restr_x); 35878f7fce3SZach Atkins CeedElemRestrictionDestroy(&elem_restr_u); 35978f7fce3SZach Atkins CeedBasisDestroy(&basis_x); 36078f7fce3SZach Atkins CeedBasisDestroy(&basis_u); 36178f7fce3SZach Atkins 36278f7fce3SZach Atkins PetscFunctionReturn(PETSC_SUCCESS); 36378f7fce3SZach Atkins } 364