xref: /libCEED/examples/solids/src/setup-libceed.c (revision 7ed3e4cde27d28430628eaa24b22da48dc51cc32)
15754ecacSJeremy L Thompson /// @file
25754ecacSJeremy L Thompson /// libCEED setup for solid mechanics example using PETSc
35754ecacSJeremy L Thompson 
45754ecacSJeremy L Thompson #include "../include/setup-libceed.h"
55754ecacSJeremy L Thompson #include "../include/structs.h"
65754ecacSJeremy L Thompson #include "../include/utils.h"
75754ecacSJeremy L Thompson #include "../qfunctions/traction-boundary.h"  // Traction boundaries
85754ecacSJeremy L Thompson #include "../qfunctions/constant-force.h"     // Constant forcing function
95754ecacSJeremy L Thompson #include "../qfunctions/manufactured-force.h" // Manufactured solution forcing
105754ecacSJeremy L Thompson 
115754ecacSJeremy L Thompson #if PETSC_VERSION_LT(3,14,0)
125754ecacSJeremy L Thompson #  define DMPlexGetClosureIndices(a,b,c,d,e,f,g,h,i) DMPlexGetClosureIndices(a,b,c,d,f,g,i)
135754ecacSJeremy L Thompson #  define DMPlexRestoreClosureIndices(a,b,c,d,e,f,g,h,i) DMPlexRestoreClosureIndices(a,b,c,d,f,g,i)
145754ecacSJeremy L Thompson #endif
155754ecacSJeremy L Thompson 
165754ecacSJeremy L Thompson // -----------------------------------------------------------------------------
175754ecacSJeremy L Thompson // Problem options
185754ecacSJeremy L Thompson // -----------------------------------------------------------------------------
195754ecacSJeremy L Thompson // Forcing function data
205754ecacSJeremy L Thompson forcingData forcing_options[3] = {
215754ecacSJeremy L Thompson   [FORCE_NONE] = {
225754ecacSJeremy L Thompson     .setup_forcing = NULL,
235754ecacSJeremy L Thompson     .setup_forcing_loc = NULL
245754ecacSJeremy L Thompson   },
255754ecacSJeremy L Thompson   [FORCE_CONST] = {
265754ecacSJeremy L Thompson     .setup_forcing = SetupConstantForce,
275754ecacSJeremy L Thompson     .setup_forcing_loc = SetupConstantForce_loc
285754ecacSJeremy L Thompson   },
295754ecacSJeremy L Thompson   [FORCE_MMS] = {
305754ecacSJeremy L Thompson     .setup_forcing = SetupMMSForce,
315754ecacSJeremy L Thompson     .setup_forcing_loc = SetupMMSForce_loc
325754ecacSJeremy L Thompson   }
335754ecacSJeremy L Thompson };
345754ecacSJeremy L Thompson 
355754ecacSJeremy L Thompson // -----------------------------------------------------------------------------
365754ecacSJeremy L Thompson // libCEED Functions
375754ecacSJeremy L Thompson // -----------------------------------------------------------------------------
385754ecacSJeremy L Thompson // Destroy libCEED objects
395754ecacSJeremy L Thompson PetscErrorCode CeedDataDestroy(CeedInt level, CeedData data) {
405754ecacSJeremy L Thompson   PetscErrorCode ierr;
415754ecacSJeremy L Thompson 
425754ecacSJeremy L Thompson   PetscFunctionBegin;
435754ecacSJeremy L Thompson 
445754ecacSJeremy L Thompson   // Vectors
455754ecacSJeremy L Thompson   CeedVectorDestroy(&data->x_ceed);
465754ecacSJeremy L Thompson   CeedVectorDestroy(&data->y_ceed);
475754ecacSJeremy L Thompson   CeedVectorDestroy(&data->geo_data);
485754ecacSJeremy L Thompson   for (CeedInt i = 0; i < SOLIDS_MAX_NUMBER_FIELDS; i++)
495754ecacSJeremy L Thompson     CeedVectorDestroy(&data->stored_fields[i]);
505754ecacSJeremy L Thompson   CeedVectorDestroy(&data->geo_data_diagnostic);
515754ecacSJeremy L Thompson   CeedVectorDestroy(&data->true_soln);
525754ecacSJeremy L Thompson   // Restrictions
535754ecacSJeremy L Thompson   CeedElemRestrictionDestroy(&data->elem_restr_x);
545754ecacSJeremy L Thompson   CeedElemRestrictionDestroy(&data->elem_restr_u);
555754ecacSJeremy L Thompson   CeedElemRestrictionDestroy(&data->elem_restr_geo_data_i);
565754ecacSJeremy L Thompson   for (CeedInt i = 0; i < SOLIDS_MAX_NUMBER_FIELDS; i++)
575754ecacSJeremy L Thompson     CeedElemRestrictionDestroy(&data->elem_restr_stored_fields_i[i]);
585754ecacSJeremy L Thompson   CeedElemRestrictionDestroy(&data->elem_restr_energy);
595754ecacSJeremy L Thompson   CeedElemRestrictionDestroy(&data->elem_restr_diagnostic);
605754ecacSJeremy L Thompson   CeedElemRestrictionDestroy(&data->elem_restr_geo_data_diagnostic_i);
615754ecacSJeremy L Thompson   // Bases
625754ecacSJeremy L Thompson   CeedBasisDestroy(&data->basis_x);
635754ecacSJeremy L Thompson   CeedBasisDestroy(&data->basis_u);
645754ecacSJeremy L Thompson   CeedBasisDestroy(&data->basis_energy);
655754ecacSJeremy L Thompson   CeedBasisDestroy(&data->basis_diagnostic);
665754ecacSJeremy L Thompson   // QFunctions
675754ecacSJeremy L Thompson   CeedQFunctionDestroy(&data->qf_residual);
685754ecacSJeremy L Thompson   CeedQFunctionDestroy(&data->qf_jacobian);
695754ecacSJeremy L Thompson   CeedQFunctionDestroy(&data->qf_energy);
705754ecacSJeremy L Thompson   CeedQFunctionDestroy(&data->qf_diagnostic);
715754ecacSJeremy L Thompson   // Operators
725754ecacSJeremy L Thompson   CeedOperatorDestroy(&data->op_residual);
735754ecacSJeremy L Thompson   CeedOperatorDestroy(&data->op_jacobian);
745754ecacSJeremy L Thompson   CeedOperatorDestroy(&data->op_energy);
755754ecacSJeremy L Thompson   CeedOperatorDestroy(&data->op_diagnostic);
765754ecacSJeremy L Thompson   // Restriction and Prolongation data
775754ecacSJeremy L Thompson   CeedBasisDestroy(&data->basis_c_to_f);
785754ecacSJeremy L Thompson   CeedOperatorDestroy(&data->op_prolong);
795754ecacSJeremy L Thompson   CeedOperatorDestroy(&data->op_restrict);
805754ecacSJeremy L Thompson 
815754ecacSJeremy L Thompson   ierr = PetscFree(data); CHKERRQ(ierr);
825754ecacSJeremy L Thompson 
835754ecacSJeremy L Thompson   PetscFunctionReturn(0);
845754ecacSJeremy L Thompson };
855754ecacSJeremy L Thompson 
865754ecacSJeremy L Thompson // Utility function to create local CEED restriction from DMPlex
87*7ed3e4cdSJeremy L Thompson PetscErrorCode CreateRestrictionFromPlex(Ceed ceed, DM dm, CeedInt height,
88*7ed3e4cdSJeremy L Thompson     DMLabel domain_label, CeedInt value, CeedElemRestriction *elem_restr) {
89*7ed3e4cdSJeremy L Thompson   PetscInt num_elem, elem_size, num_dof, num_comp, *elem_restr_offsets;
905754ecacSJeremy L Thompson   PetscErrorCode ierr;
915754ecacSJeremy L Thompson 
925754ecacSJeremy L Thompson   PetscFunctionBeginUser;
93*7ed3e4cdSJeremy L Thompson   ierr = DMPlexGetLocalOffsets(dm, domain_label, value, height, 0, &num_elem,
94*7ed3e4cdSJeremy L Thompson                                &elem_size, &num_comp, &num_dof, &elem_restr_offsets);
95*7ed3e4cdSJeremy L Thompson   CHKERRQ(ierr);
965754ecacSJeremy L Thompson 
97*7ed3e4cdSJeremy L Thompson   CeedElemRestrictionCreate(ceed, num_elem, elem_size, num_comp,
98*7ed3e4cdSJeremy L Thompson                             1, num_dof, CEED_MEM_HOST, CEED_COPY_VALUES,
99*7ed3e4cdSJeremy L Thompson                             elem_restr_offsets, elem_restr);
100*7ed3e4cdSJeremy L Thompson   ierr = PetscFree(elem_restr_offsets); CHKERRQ(ierr);
1015754ecacSJeremy L Thompson 
1025754ecacSJeremy L Thompson   PetscFunctionReturn(0);
1035754ecacSJeremy L Thompson };
1045754ecacSJeremy L Thompson 
1055754ecacSJeremy L Thompson // Utility function to get Ceed Restriction for each domain
1065754ecacSJeremy L Thompson PetscErrorCode GetRestrictionForDomain(Ceed ceed, DM dm, CeedInt height,
1075754ecacSJeremy L Thompson                                        DMLabel domain_label, PetscInt value,
108*7ed3e4cdSJeremy L Thompson                                        CeedInt Q, CeedInt q_data_size,
1095754ecacSJeremy L Thompson                                        CeedElemRestriction *elem_restr_q,
1105754ecacSJeremy L Thompson                                        CeedElemRestriction *elem_restr_x,
1115754ecacSJeremy L Thompson                                        CeedElemRestriction *elem_restr_qd_i) {
1125754ecacSJeremy L Thompson 
1135754ecacSJeremy L Thompson   DM dm_coord;
1145754ecacSJeremy L Thompson   CeedInt dim, num_local_elem;
1155754ecacSJeremy L Thompson   CeedInt Q_dim;
1165754ecacSJeremy L Thompson   PetscErrorCode ierr;
1175754ecacSJeremy L Thompson 
1185754ecacSJeremy L Thompson   PetscFunctionBeginUser;
1195754ecacSJeremy L Thompson 
1205754ecacSJeremy L Thompson   ierr = DMGetDimension(dm, &dim); CHKERRQ(ierr);
1215754ecacSJeremy L Thompson   dim -= height;
1225754ecacSJeremy L Thompson   Q_dim = CeedIntPow(Q, dim);
1235754ecacSJeremy L Thompson   ierr = DMGetCoordinateDM(dm, &dm_coord); CHKERRQ(ierr);
1245754ecacSJeremy L Thompson   ierr = DMPlexSetClosurePermutationTensor(dm_coord, PETSC_DETERMINE, NULL);
1255754ecacSJeremy L Thompson   CHKERRQ(ierr);
1265754ecacSJeremy L Thompson   if (elem_restr_q) {
127*7ed3e4cdSJeremy L Thompson     ierr = CreateRestrictionFromPlex(ceed, dm, height, domain_label, value,
1285754ecacSJeremy L Thompson                                      elem_restr_q); CHKERRQ(ierr);
1295754ecacSJeremy L Thompson   }
1305754ecacSJeremy L Thompson   if (elem_restr_x) {
131*7ed3e4cdSJeremy L Thompson     ierr = CreateRestrictionFromPlex(ceed, dm_coord, height, domain_label,
1325754ecacSJeremy L Thompson                                      value, elem_restr_x); CHKERRQ(ierr);
1335754ecacSJeremy L Thompson   }
1345754ecacSJeremy L Thompson   if (elem_restr_qd_i) {
1355754ecacSJeremy L Thompson     CeedElemRestrictionGetNumElements(*elem_restr_q, &num_local_elem);
1365754ecacSJeremy L Thompson     CeedElemRestrictionCreateStrided(ceed, num_local_elem, Q_dim,
1375754ecacSJeremy L Thompson                                      q_data_size, q_data_size*num_local_elem*Q_dim,
1385754ecacSJeremy L Thompson                                      CEED_STRIDES_BACKEND, elem_restr_qd_i);
1395754ecacSJeremy L Thompson   }
1405754ecacSJeremy L Thompson 
1415754ecacSJeremy L Thompson   PetscFunctionReturn(0);
1425754ecacSJeremy L Thompson };
1435754ecacSJeremy L Thompson 
1445754ecacSJeremy L Thompson // Set up libCEED on the fine grid for a given degree
1455754ecacSJeremy L Thompson PetscErrorCode SetupLibceedFineLevel(DM dm, DM dm_energy, DM dm_diagnostic,
1465754ecacSJeremy L Thompson                                      Ceed ceed, AppCtx app_ctx,
1475754ecacSJeremy L Thompson                                      CeedQFunctionContext phys_ctx,
1485754ecacSJeremy L Thompson                                      ProblemData problem_data,
1495754ecacSJeremy L Thompson                                      PetscInt fine_level, PetscInt num_comp_u,
1505754ecacSJeremy L Thompson                                      PetscInt U_g_size, PetscInt U_loc_size,
1515754ecacSJeremy L Thompson                                      CeedVector force_ceed,
1525754ecacSJeremy L Thompson                                      CeedVector neumann_ceed, CeedData *data) {
1535754ecacSJeremy L Thompson   int           ierr;
1545754ecacSJeremy L Thompson   CeedInt       P = app_ctx->level_degrees[fine_level] + 1;
1555754ecacSJeremy L Thompson   CeedInt       Q = app_ctx->level_degrees[fine_level] + 1 + app_ctx->q_extra;
1565754ecacSJeremy L Thompson   CeedInt       dim, num_comp_x, num_comp_e = 1, num_comp_d = 5;
1575754ecacSJeremy L Thompson   CeedInt       num_qpts;
1585754ecacSJeremy L Thompson   CeedInt       geo_data_size = problem_data.geo_data_size;
1595754ecacSJeremy L Thompson   forcingType   forcing_choice = app_ctx->forcing_choice;
1605754ecacSJeremy L Thompson   DM            dm_coord;
1615754ecacSJeremy L Thompson   Vec           coords;
1625754ecacSJeremy L Thompson   PetscInt      c_start, c_end, num_elem;
1635754ecacSJeremy L Thompson   const PetscScalar *coordArray;
1645754ecacSJeremy L Thompson   CeedVector    x_coord;
1655754ecacSJeremy L Thompson   CeedQFunction qf_setup_geo, qf_residual, qf_jacobian, qf_energy, qf_diagnostic;
1665754ecacSJeremy L Thompson   CeedOperator  op_setup_geo, op_residual, op_jacobian, op_energy, op_diagnostic;
1675754ecacSJeremy L Thompson 
1685754ecacSJeremy L Thompson   PetscFunctionBeginUser;
1695754ecacSJeremy L Thompson 
1705754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
1715754ecacSJeremy L Thompson   // libCEED bases
1725754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
1735754ecacSJeremy L Thompson   ierr = DMGetDimension(dm, &dim); CHKERRQ(ierr);
1745754ecacSJeremy L Thompson   num_comp_x = dim;
1755754ecacSJeremy L Thompson   // -- Coordinate basis
1765754ecacSJeremy L Thompson   CeedBasisCreateTensorH1Lagrange(ceed, dim, num_comp_x, 2, Q,
1775754ecacSJeremy L Thompson                                   problem_data.quadrature_mode,
1785754ecacSJeremy L Thompson                                   &data[fine_level]->basis_x);
1795754ecacSJeremy L Thompson   // -- Solution basis
1805754ecacSJeremy L Thompson   CeedBasisCreateTensorH1Lagrange(ceed, dim, num_comp_u, P, Q,
1815754ecacSJeremy L Thompson                                   problem_data.quadrature_mode,
1825754ecacSJeremy L Thompson                                   &data[fine_level]->basis_u);
1835754ecacSJeremy L Thompson   // -- Energy basis
1845754ecacSJeremy L Thompson   CeedBasisCreateTensorH1Lagrange(ceed, dim, num_comp_e, P, Q,
1855754ecacSJeremy L Thompson                                   problem_data.quadrature_mode,
1865754ecacSJeremy L Thompson                                   &data[fine_level]->basis_energy);
1875754ecacSJeremy L Thompson   // -- Diagnostic output basis
1885754ecacSJeremy L Thompson   CeedBasisCreateTensorH1Lagrange(ceed, dim, num_comp_u, P, P, CEED_GAUSS_LOBATTO,
1895754ecacSJeremy L Thompson                                   &data[fine_level]->basis_diagnostic);
1905754ecacSJeremy L Thompson 
1915754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
1925754ecacSJeremy L Thompson   // libCEED restrictions
1935754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
1945754ecacSJeremy L Thompson   ierr = DMGetCoordinateDM(dm, &dm_coord); CHKERRQ(ierr);
1955754ecacSJeremy L Thompson   ierr = DMPlexSetClosurePermutationTensor(dm_coord, PETSC_DETERMINE, NULL);
1965754ecacSJeremy L Thompson   CHKERRQ(ierr);
1975754ecacSJeremy L Thompson 
1985754ecacSJeremy L Thompson   // -- Coordinate restriction
199*7ed3e4cdSJeremy L Thompson   ierr = CreateRestrictionFromPlex(ceed, dm_coord, 0, 0, 0,
2005754ecacSJeremy L Thompson                                    &(data[fine_level]->elem_restr_x));
2015754ecacSJeremy L Thompson   CHKERRQ(ierr);
2025754ecacSJeremy L Thompson   // -- Solution restriction
203*7ed3e4cdSJeremy L Thompson   ierr = CreateRestrictionFromPlex(ceed, dm, 0, 0, 0,
2045754ecacSJeremy L Thompson                                    &data[fine_level]->elem_restr_u);
2055754ecacSJeremy L Thompson   CHKERRQ(ierr);
2065754ecacSJeremy L Thompson   // -- Energy restriction
207*7ed3e4cdSJeremy L Thompson   ierr = CreateRestrictionFromPlex(ceed, dm_energy, 0, 0, 0,
2085754ecacSJeremy L Thompson                                    &data[fine_level]->elem_restr_energy);
2095754ecacSJeremy L Thompson   CHKERRQ(ierr);
2105754ecacSJeremy L Thompson   // -- Diagnostic data restriction
211*7ed3e4cdSJeremy L Thompson   ierr = CreateRestrictionFromPlex(ceed, dm_diagnostic, 0, 0, 0,
2125754ecacSJeremy L Thompson                                    &data[fine_level]->elem_restr_diagnostic);
2135754ecacSJeremy L Thompson   CHKERRQ(ierr);
2145754ecacSJeremy L Thompson 
2155754ecacSJeremy L Thompson   // -- Stored data at quadrature points
2165754ecacSJeremy L Thompson   ierr = DMPlexGetHeightStratum(dm, 0, &c_start, &c_end); CHKERRQ(ierr);
2175754ecacSJeremy L Thompson   num_elem = c_end - c_start;
2185754ecacSJeremy L Thompson   CeedBasisGetNumQuadraturePoints(data[fine_level]->basis_u, &num_qpts);
2195754ecacSJeremy L Thompson   // ---- Geometric data restriction, residual and Jacobian operators
2205754ecacSJeremy L Thompson   CeedElemRestrictionCreateStrided(ceed, num_elem, num_qpts, geo_data_size,
2215754ecacSJeremy L Thompson                                    num_elem*num_qpts*geo_data_size,
2225754ecacSJeremy L Thompson                                    CEED_STRIDES_BACKEND,
2235754ecacSJeremy L Thompson                                    &data[fine_level]->elem_restr_geo_data_i);
2245754ecacSJeremy L Thompson   // ---- Stored field restrictions
2255754ecacSJeremy L Thompson   for (CeedInt i = 0; i < problem_data.number_fields_stored; i++) {
2265754ecacSJeremy L Thompson     CeedElemRestrictionCreateStrided(ceed, num_elem, num_qpts,
2275754ecacSJeremy L Thompson                                      problem_data.field_sizes[i],
2285754ecacSJeremy L Thompson                                      num_elem*num_qpts*problem_data.field_sizes[i],
2295754ecacSJeremy L Thompson                                      CEED_STRIDES_BACKEND,
2305754ecacSJeremy L Thompson                                      &data[fine_level]->elem_restr_stored_fields_i[i]);
2315754ecacSJeremy L Thompson   }
2325754ecacSJeremy L Thompson   // ---- Geometric data restriction, diagnostic operator
2335754ecacSJeremy L Thompson   CeedElemRestrictionCreateStrided(ceed, num_elem, P*P*P, geo_data_size,
2345754ecacSJeremy L Thompson                                    num_elem*P*P*P*geo_data_size,
2355754ecacSJeremy L Thompson                                    CEED_STRIDES_BACKEND,
2365754ecacSJeremy L Thompson                                    &data[fine_level]->elem_restr_geo_data_diagnostic_i);
2375754ecacSJeremy L Thompson 
2385754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
2395754ecacSJeremy L Thompson   // Element coordinates
2405754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
2415754ecacSJeremy L Thompson   ierr = DMGetCoordinatesLocal(dm, &coords); CHKERRQ(ierr);
2425754ecacSJeremy L Thompson   ierr = VecGetArrayRead(coords, &coordArray); CHKERRQ(ierr);
2435754ecacSJeremy L Thompson 
2445754ecacSJeremy L Thompson   CeedElemRestrictionCreateVector(data[fine_level]->elem_restr_x, &x_coord, NULL);
2455754ecacSJeremy L Thompson   CeedVectorSetArray(x_coord, CEED_MEM_HOST, CEED_COPY_VALUES,
2465754ecacSJeremy L Thompson                      (PetscScalar *)coordArray);
2475754ecacSJeremy L Thompson   ierr = VecRestoreArrayRead(coords, &coordArray); CHKERRQ(ierr);
2485754ecacSJeremy L Thompson 
2495754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
2505754ecacSJeremy L Thompson   // Persistent libCEED vectors
2515754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
2525754ecacSJeremy L Thompson   // -- Operator action variables
2535754ecacSJeremy L Thompson   CeedVectorCreate(ceed, U_loc_size, &data[fine_level]->x_ceed);
2545754ecacSJeremy L Thompson   CeedVectorCreate(ceed, U_loc_size, &data[fine_level]->y_ceed);
2555754ecacSJeremy L Thompson   // -- Geometric data vector
2565754ecacSJeremy L Thompson   CeedVectorCreate(ceed, num_elem*num_qpts*geo_data_size,
2575754ecacSJeremy L Thompson                    &data[fine_level]->geo_data);
2585754ecacSJeremy L Thompson   // -- Stored field vectors
2595754ecacSJeremy L Thompson   for (CeedInt i = 0; i < problem_data.number_fields_stored; i++) {
2605754ecacSJeremy L Thompson     CeedVectorCreate(ceed, num_elem*num_qpts*problem_data.field_sizes[i],
2615754ecacSJeremy L Thompson                      &data[fine_level]->stored_fields[i]);
2625754ecacSJeremy L Thompson   }
2635754ecacSJeremy L Thompson   // -- Collocated geometric data vector
2645754ecacSJeremy L Thompson   CeedVectorCreate(ceed, num_elem*P*P*P*geo_data_size,
2655754ecacSJeremy L Thompson                    &data[fine_level]->geo_data_diagnostic);
2665754ecacSJeremy L Thompson 
2675754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
2685754ecacSJeremy L Thompson   // Geometric factor computation
2695754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
2705754ecacSJeremy L Thompson   // Create the QFunction and Operator that computes the quadrature data
2715754ecacSJeremy L Thompson   //   geo_data returns dXdx_i,j and w * det.
2725754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
2735754ecacSJeremy L Thompson   // -- QFunction
2745754ecacSJeremy L Thompson   CeedQFunctionCreateInterior(ceed, 1, problem_data.setup_geo,
2755754ecacSJeremy L Thompson                               problem_data.setup_geo_loc, &qf_setup_geo);
2765754ecacSJeremy L Thompson   CeedQFunctionAddInput(qf_setup_geo, "dx", num_comp_x*dim, CEED_EVAL_GRAD);
2775754ecacSJeremy L Thompson   CeedQFunctionAddInput(qf_setup_geo, "weight", 1, CEED_EVAL_WEIGHT);
2785754ecacSJeremy L Thompson   CeedQFunctionAddOutput(qf_setup_geo, "geo_data", geo_data_size, CEED_EVAL_NONE);
2795754ecacSJeremy L Thompson   // -- Operator
2805754ecacSJeremy L Thompson   CeedOperatorCreate(ceed, qf_setup_geo, CEED_QFUNCTION_NONE,
2815754ecacSJeremy L Thompson                      CEED_QFUNCTION_NONE, &op_setup_geo);
2825754ecacSJeremy L Thompson   CeedOperatorSetField(op_setup_geo, "dx", data[fine_level]->elem_restr_x,
2835754ecacSJeremy L Thompson                        data[fine_level]->basis_x, CEED_VECTOR_ACTIVE);
2845754ecacSJeremy L Thompson   CeedOperatorSetField(op_setup_geo, "weight", CEED_ELEMRESTRICTION_NONE,
2855754ecacSJeremy L Thompson                        data[fine_level]->basis_x, CEED_VECTOR_NONE);
2865754ecacSJeremy L Thompson   CeedOperatorSetField(op_setup_geo, "geo_data",
2875754ecacSJeremy L Thompson                        data[fine_level]->elem_restr_geo_data_i,
2885754ecacSJeremy L Thompson                        CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
2895754ecacSJeremy L Thompson   // -- Compute the quadrature data
2905754ecacSJeremy L Thompson   CeedOperatorApply(op_setup_geo, x_coord, data[fine_level]->geo_data,
2915754ecacSJeremy L Thompson                     CEED_REQUEST_IMMEDIATE);
2925754ecacSJeremy L Thompson   // -- Cleanup
2935754ecacSJeremy L Thompson   CeedQFunctionDestroy(&qf_setup_geo);
2945754ecacSJeremy L Thompson   CeedOperatorDestroy(&op_setup_geo);
2955754ecacSJeremy L Thompson 
2965754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
2975754ecacSJeremy L Thompson   // Local residual evaluator
2985754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
2995754ecacSJeremy L Thompson   // Create the QFunction and Operator that computes the residual of the
3005754ecacSJeremy L Thompson   //   non-linear PDE.
3015754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
3025754ecacSJeremy L Thompson   // -- QFunction
3035754ecacSJeremy L Thompson   CeedQFunctionCreateInterior(ceed, 1, problem_data.residual,
3045754ecacSJeremy L Thompson                               problem_data.residual_loc, &qf_residual);
3055754ecacSJeremy L Thompson   CeedQFunctionAddInput(qf_residual, "du", num_comp_u*dim, CEED_EVAL_GRAD);
3065754ecacSJeremy L Thompson   CeedQFunctionAddInput(qf_residual, "geo_data", geo_data_size, CEED_EVAL_NONE);
3075754ecacSJeremy L Thompson   CeedQFunctionAddOutput(qf_residual, "dv", num_comp_u*dim, CEED_EVAL_GRAD);
3085754ecacSJeremy L Thompson   for (CeedInt i = 0; i < problem_data.number_fields_stored; i++) {
3095754ecacSJeremy L Thompson     CeedQFunctionAddOutput(qf_residual, problem_data.field_names[i],
3105754ecacSJeremy L Thompson                            problem_data.field_sizes[i], CEED_EVAL_NONE);
3115754ecacSJeremy L Thompson   }
3125754ecacSJeremy L Thompson   CeedQFunctionSetContext(qf_residual, phys_ctx);
3135754ecacSJeremy L Thompson   // -- Operator
3145754ecacSJeremy L Thompson   CeedOperatorCreate(ceed, qf_residual, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
3155754ecacSJeremy L Thompson                      &op_residual);
3165754ecacSJeremy L Thompson   CeedOperatorSetField(op_residual, "du", data[fine_level]->elem_restr_u,
3175754ecacSJeremy L Thompson                        data[fine_level]->basis_u, CEED_VECTOR_ACTIVE);
3185754ecacSJeremy L Thompson   CeedOperatorSetField(op_residual, "geo_data",
3195754ecacSJeremy L Thompson                        data[fine_level]->elem_restr_geo_data_i,
3205754ecacSJeremy L Thompson                        CEED_BASIS_COLLOCATED, data[fine_level]->geo_data);
3215754ecacSJeremy L Thompson   CeedOperatorSetField(op_residual, "dv", data[fine_level]->elem_restr_u,
3225754ecacSJeremy L Thompson                        data[fine_level]->basis_u, CEED_VECTOR_ACTIVE);
3235754ecacSJeremy L Thompson   for (CeedInt i = 0; i < problem_data.number_fields_stored; i++) {
3245754ecacSJeremy L Thompson     CeedOperatorSetField(op_residual, problem_data.field_names[i],
3255754ecacSJeremy L Thompson                          data[fine_level]->elem_restr_stored_fields_i[i],
3265754ecacSJeremy L Thompson                          CEED_BASIS_COLLOCATED,
3275754ecacSJeremy L Thompson                          data[fine_level]->stored_fields[i]);
3285754ecacSJeremy L Thompson   }
3295754ecacSJeremy L Thompson   // -- Save libCEED data
3305754ecacSJeremy L Thompson   data[fine_level]->qf_residual = qf_residual;
3315754ecacSJeremy L Thompson   data[fine_level]->op_residual = op_residual;
3325754ecacSJeremy L Thompson 
3335754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
3345754ecacSJeremy L Thompson   // Jacobian evaluator
3355754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
3365754ecacSJeremy L Thompson   // Create the QFunction and Operator that computes the action of the
3375754ecacSJeremy L Thompson   //   Jacobian for each linear solve.
3385754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
3395754ecacSJeremy L Thompson   // -- QFunction
3405754ecacSJeremy L Thompson   CeedQFunctionCreateInterior(ceed, 1, problem_data.jacobian,
3415754ecacSJeremy L Thompson                               problem_data.jacobian_loc, &qf_jacobian);
3425754ecacSJeremy L Thompson   CeedQFunctionAddInput(qf_jacobian, "deltadu", num_comp_u*dim, CEED_EVAL_GRAD);
3435754ecacSJeremy L Thompson   CeedQFunctionAddInput(qf_jacobian, "geo_data", geo_data_size, CEED_EVAL_NONE);
3445754ecacSJeremy L Thompson   for (CeedInt i = 0; i < problem_data.number_fields_stored; i++) {
3455754ecacSJeremy L Thompson     CeedQFunctionAddInput(qf_jacobian, problem_data.field_names[i],
3465754ecacSJeremy L Thompson                           problem_data.field_sizes[i], CEED_EVAL_NONE);
3475754ecacSJeremy L Thompson   }
3485754ecacSJeremy L Thompson   CeedQFunctionAddOutput(qf_jacobian, "deltadv", num_comp_u*dim, CEED_EVAL_GRAD);
3495754ecacSJeremy L Thompson   CeedQFunctionSetContext(qf_jacobian, phys_ctx);
3505754ecacSJeremy L Thompson   // -- Operator
3515754ecacSJeremy L Thompson   CeedOperatorCreate(ceed, qf_jacobian, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
3525754ecacSJeremy L Thompson                      &op_jacobian);
3535754ecacSJeremy L Thompson   CeedOperatorSetField(op_jacobian, "deltadu", data[fine_level]->elem_restr_u,
3545754ecacSJeremy L Thompson                        data[fine_level]->basis_u, CEED_VECTOR_ACTIVE);
3555754ecacSJeremy L Thompson   CeedOperatorSetField(op_jacobian, "geo_data",
3565754ecacSJeremy L Thompson                        data[fine_level]->elem_restr_geo_data_i,
3575754ecacSJeremy L Thompson                        CEED_BASIS_COLLOCATED, data[fine_level]->geo_data);
3585754ecacSJeremy L Thompson   CeedOperatorSetField(op_jacobian, "deltadv", data[fine_level]->elem_restr_u,
3595754ecacSJeremy L Thompson                        data[fine_level]->basis_u, CEED_VECTOR_ACTIVE);
3605754ecacSJeremy L Thompson   for (CeedInt i = 0; i < problem_data.number_fields_stored; i++) {
3615754ecacSJeremy L Thompson     CeedOperatorSetField(op_jacobian, problem_data.field_names[i],
3625754ecacSJeremy L Thompson                          data[fine_level]->elem_restr_stored_fields_i[i],
3635754ecacSJeremy L Thompson                          CEED_BASIS_COLLOCATED,
3645754ecacSJeremy L Thompson                          data[fine_level]->stored_fields[i]);
3655754ecacSJeremy L Thompson   }
3665754ecacSJeremy L Thompson   // -- Save libCEED data
3675754ecacSJeremy L Thompson   data[fine_level]->qf_jacobian = qf_jacobian;
3685754ecacSJeremy L Thompson   data[fine_level]->op_jacobian = op_jacobian;
3695754ecacSJeremy L Thompson 
3705754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
3715754ecacSJeremy L Thompson   // Traction boundary conditions, if needed
3725754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
3735754ecacSJeremy L Thompson   if (app_ctx->bc_traction_count > 0) {
3745754ecacSJeremy L Thompson     // -- Setup
3755754ecacSJeremy L Thompson     DMLabel domain_label;
3765754ecacSJeremy L Thompson     ierr = DMGetLabel(dm, "Face Sets", &domain_label); CHKERRQ(ierr);
3775754ecacSJeremy L Thompson     ierr = DMGetDimension(dm, &dim); CHKERRQ(ierr);
3785754ecacSJeremy L Thompson 
3795754ecacSJeremy L Thompson     // -- Basis
3805754ecacSJeremy L Thompson     CeedInt height = 1;
3815754ecacSJeremy L Thompson     CeedBasis basis_x_face, basis_u_face;
3825754ecacSJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, dim - height, num_comp_x, 2, Q,
3835754ecacSJeremy L Thompson                                     problem_data.quadrature_mode, &basis_x_face);
3845754ecacSJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, dim - height, num_comp_u, P, Q,
3855754ecacSJeremy L Thompson                                     problem_data.quadrature_mode, &basis_u_face);
3865754ecacSJeremy L Thompson     // -- QFunction
3875754ecacSJeremy L Thompson     CeedQFunction qf_traction;
3885754ecacSJeremy L Thompson     CeedQFunctionContext traction_ctx;
3895754ecacSJeremy L Thompson     CeedQFunctionCreateInterior(ceed, 1, SetupTractionBCs, SetupTractionBCs_loc,
3905754ecacSJeremy L Thompson                                 &qf_traction);
3915754ecacSJeremy L Thompson     CeedQFunctionContextCreate(ceed, &traction_ctx);
3925754ecacSJeremy L Thompson     CeedQFunctionSetContext(qf_traction, traction_ctx);
3935754ecacSJeremy L Thompson     CeedQFunctionAddInput(qf_traction, "dx", num_comp_x*(num_comp_x - height),
3945754ecacSJeremy L Thompson                           CEED_EVAL_GRAD);
3955754ecacSJeremy L Thompson     CeedQFunctionAddInput(qf_traction, "weight", 1, CEED_EVAL_WEIGHT);
3965754ecacSJeremy L Thompson     CeedQFunctionAddOutput(qf_traction, "v", num_comp_u, CEED_EVAL_INTERP);
3975754ecacSJeremy L Thompson 
3985754ecacSJeremy L Thompson     // -- Compute contribution on each boundary face
3995754ecacSJeremy L Thompson     for (CeedInt i = 0; i < app_ctx->bc_traction_count; i++) {
4005754ecacSJeremy L Thompson       CeedElemRestriction elem_restr_x_face, elem_restr_u_face;
4015754ecacSJeremy L Thompson       CeedOperator op_traction;
4025754ecacSJeremy L Thompson       CeedQFunctionContextSetData(traction_ctx, CEED_MEM_HOST, CEED_USE_POINTER,
4035754ecacSJeremy L Thompson                                   3 * sizeof(CeedScalar),
4045754ecacSJeremy L Thompson                                   app_ctx->bc_traction_vector[i]);
4055754ecacSJeremy L Thompson       // Setup restriction
406*7ed3e4cdSJeremy L Thompson       ierr = GetRestrictionForDomain(ceed, dm, 1, domain_label,
407*7ed3e4cdSJeremy L Thompson                                      app_ctx->bc_traction_faces[i], Q,
4085754ecacSJeremy L Thompson                                      0, &elem_restr_u_face, &elem_restr_x_face, NULL);
4095754ecacSJeremy L Thompson       CHKERRQ(ierr);
4105754ecacSJeremy L Thompson       // ---- Create boundary Operator
4115754ecacSJeremy L Thompson       CeedOperatorCreate(ceed, qf_traction, NULL, NULL, &op_traction);
4125754ecacSJeremy L Thompson       CeedOperatorSetField(op_traction, "dx", elem_restr_x_face, basis_x_face,
4135754ecacSJeremy L Thompson                            CEED_VECTOR_ACTIVE);
4145754ecacSJeremy L Thompson       CeedOperatorSetField(op_traction, "weight", CEED_ELEMRESTRICTION_NONE,
4155754ecacSJeremy L Thompson                            basis_x_face, CEED_VECTOR_NONE);
4165754ecacSJeremy L Thompson       CeedOperatorSetField(op_traction, "v", elem_restr_u_face,
4175754ecacSJeremy L Thompson                            basis_u_face, CEED_VECTOR_ACTIVE);
4185754ecacSJeremy L Thompson       // ---- Compute traction on face
4195754ecacSJeremy L Thompson       CeedOperatorApplyAdd(op_traction, x_coord, neumann_ceed,
4205754ecacSJeremy L Thompson                            CEED_REQUEST_IMMEDIATE);
4215754ecacSJeremy L Thompson       // ---- Cleanup
4225754ecacSJeremy L Thompson       CeedElemRestrictionDestroy(&elem_restr_x_face);
4235754ecacSJeremy L Thompson       CeedElemRestrictionDestroy(&elem_restr_u_face);
4245754ecacSJeremy L Thompson       CeedOperatorDestroy(&op_traction);
4255754ecacSJeremy L Thompson     }
4265754ecacSJeremy L Thompson     // -- Cleanup
4275754ecacSJeremy L Thompson     CeedBasisDestroy(&basis_x_face);
4285754ecacSJeremy L Thompson     CeedBasisDestroy(&basis_u_face);
4295754ecacSJeremy L Thompson     CeedQFunctionDestroy(&qf_traction);
4305754ecacSJeremy L Thompson     CeedQFunctionContextDestroy(&traction_ctx);
4315754ecacSJeremy L Thompson   }
4325754ecacSJeremy L Thompson 
4335754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
4345754ecacSJeremy L Thompson   // Forcing term, if needed
4355754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
4365754ecacSJeremy L Thompson   // Create the QFunction and Operator that computes the forcing term (RHS)
4375754ecacSJeremy L Thompson   //   for the non-linear PDE.
4385754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
4395754ecacSJeremy L Thompson   if (forcing_choice != FORCE_NONE) {
4405754ecacSJeremy L Thompson     CeedQFunction qf_setup_force;
4415754ecacSJeremy L Thompson     CeedOperator op_setup_force;
4425754ecacSJeremy L Thompson 
4435754ecacSJeremy L Thompson     // -- QFunction
4445754ecacSJeremy L Thompson     CeedQFunctionCreateInterior(ceed, 1,
4455754ecacSJeremy L Thompson                                 forcing_options[forcing_choice].setup_forcing,
4465754ecacSJeremy L Thompson                                 forcing_options[forcing_choice].setup_forcing_loc,
4475754ecacSJeremy L Thompson                                 &qf_setup_force);
4485754ecacSJeremy L Thompson     CeedQFunctionAddInput(qf_setup_force, "x", num_comp_x, CEED_EVAL_INTERP);
4495754ecacSJeremy L Thompson     CeedQFunctionAddInput(qf_setup_force, "geo_data", geo_data_size,
4505754ecacSJeremy L Thompson                           CEED_EVAL_NONE);
4515754ecacSJeremy L Thompson     CeedQFunctionAddOutput(qf_setup_force, "force", num_comp_u, CEED_EVAL_INTERP);
4525754ecacSJeremy L Thompson     if (forcing_choice == FORCE_MMS) {
4535754ecacSJeremy L Thompson       CeedQFunctionSetContext(qf_setup_force, phys_ctx);
4545754ecacSJeremy L Thompson     } else {
4555754ecacSJeremy L Thompson       CeedQFunctionContext ctxForcing;
4565754ecacSJeremy L Thompson       CeedQFunctionContextCreate(ceed, &ctxForcing);
4575754ecacSJeremy L Thompson       CeedQFunctionContextSetData(ctxForcing, CEED_MEM_HOST, CEED_USE_POINTER,
4585754ecacSJeremy L Thompson                                   sizeof(*app_ctx->forcing_vector),
4595754ecacSJeremy L Thompson                                   app_ctx->forcing_vector);
4605754ecacSJeremy L Thompson       CeedQFunctionSetContext(qf_setup_force, ctxForcing);
4615754ecacSJeremy L Thompson       CeedQFunctionContextDestroy(&ctxForcing);
4625754ecacSJeremy L Thompson     }
4635754ecacSJeremy L Thompson     // -- Operator
4645754ecacSJeremy L Thompson     CeedOperatorCreate(ceed, qf_setup_force, CEED_QFUNCTION_NONE,
4655754ecacSJeremy L Thompson                        CEED_QFUNCTION_NONE, &op_setup_force);
4665754ecacSJeremy L Thompson     CeedOperatorSetField(op_setup_force, "x", data[fine_level]->elem_restr_x,
4675754ecacSJeremy L Thompson                          data[fine_level]->basis_x, CEED_VECTOR_ACTIVE);
4685754ecacSJeremy L Thompson     CeedOperatorSetField(op_setup_force, "geo_data",
4695754ecacSJeremy L Thompson                          data[fine_level]->elem_restr_geo_data_i,
4705754ecacSJeremy L Thompson                          CEED_BASIS_COLLOCATED, data[fine_level]->geo_data);
4715754ecacSJeremy L Thompson     CeedOperatorSetField(op_setup_force, "force", data[fine_level]->elem_restr_u,
4725754ecacSJeremy L Thompson                          data[fine_level]->basis_u, CEED_VECTOR_ACTIVE);
4735754ecacSJeremy L Thompson     // -- Compute forcing term
4745754ecacSJeremy L Thompson     CeedOperatorApply(op_setup_force, x_coord, force_ceed, CEED_REQUEST_IMMEDIATE);
4755754ecacSJeremy L Thompson     // -- Cleanup
4765754ecacSJeremy L Thompson     CeedQFunctionDestroy(&qf_setup_force);
4775754ecacSJeremy L Thompson     CeedOperatorDestroy(&op_setup_force);
4785754ecacSJeremy L Thompson   }
4795754ecacSJeremy L Thompson 
4805754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
4815754ecacSJeremy L Thompson   // True solution, for MMS
4825754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
4835754ecacSJeremy L Thompson   // Create the QFunction and Operator that computes the true solution at
4845754ecacSJeremy L Thompson   //   the mesh nodes for validation with the manufactured solution.
4855754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
4865754ecacSJeremy L Thompson   if (problem_data.true_soln) {
4875754ecacSJeremy L Thompson     CeedScalar *true_array;
4885754ecacSJeremy L Thompson     const CeedScalar *mult_array;
4895754ecacSJeremy L Thompson     CeedVector mult_vec;
4905754ecacSJeremy L Thompson     CeedBasis basis_x_true;
4915754ecacSJeremy L Thompson     CeedQFunction qf_true;
4925754ecacSJeremy L Thompson     CeedOperator op_true;
4935754ecacSJeremy L Thompson 
4945754ecacSJeremy L Thompson     // -- Solution vector
4955754ecacSJeremy L Thompson     CeedVectorCreate(ceed, U_loc_size, &(data[fine_level]->true_soln));
4965754ecacSJeremy L Thompson     // -- Basis
4975754ecacSJeremy L Thompson     CeedBasisCreateTensorH1Lagrange(ceed, dim, num_comp_x, 2, P, CEED_GAUSS_LOBATTO,
4985754ecacSJeremy L Thompson                                     &basis_x_true);
4995754ecacSJeremy L Thompson     // QFunction
5005754ecacSJeremy L Thompson     CeedQFunctionCreateInterior(ceed, 1, problem_data.true_soln,
5015754ecacSJeremy L Thompson                                 problem_data.true_soln_loc, &qf_true);
5025754ecacSJeremy L Thompson     CeedQFunctionAddInput(qf_true, "x", num_comp_x, CEED_EVAL_INTERP);
5035754ecacSJeremy L Thompson     CeedQFunctionAddOutput(qf_true, "true_soln", num_comp_u, CEED_EVAL_NONE);
5045754ecacSJeremy L Thompson     // Operator
5055754ecacSJeremy L Thompson     CeedOperatorCreate(ceed, qf_true, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
5065754ecacSJeremy L Thompson                        &op_true);
5075754ecacSJeremy L Thompson     CeedOperatorSetField(op_true, "x", data[fine_level]->elem_restr_x, basis_x_true,
5085754ecacSJeremy L Thompson                          CEED_VECTOR_ACTIVE);
5095754ecacSJeremy L Thompson     CeedOperatorSetField(op_true, "true_soln", data[fine_level]->elem_restr_u,
5105754ecacSJeremy L Thompson                          CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
5115754ecacSJeremy L Thompson     // -- Compute true solution
5125754ecacSJeremy L Thompson     CeedOperatorApply(op_true, x_coord, data[fine_level]->true_soln,
5135754ecacSJeremy L Thompson                       CEED_REQUEST_IMMEDIATE);
5145754ecacSJeremy L Thompson     // -- Multiplicity calculation
5155754ecacSJeremy L Thompson     CeedElemRestrictionCreateVector(data[fine_level]->elem_restr_u, &mult_vec,
5165754ecacSJeremy L Thompson                                     NULL);
5175754ecacSJeremy L Thompson     CeedVectorSetValue(mult_vec, 0.);
5185754ecacSJeremy L Thompson     CeedElemRestrictionGetMultiplicity(data[fine_level]->elem_restr_u, mult_vec);
5195754ecacSJeremy L Thompson     // -- Multiplicity correction
5205754ecacSJeremy L Thompson     CeedVectorGetArray(data[fine_level]->true_soln, CEED_MEM_HOST, &true_array);
5215754ecacSJeremy L Thompson     CeedVectorGetArrayRead(mult_vec, CEED_MEM_HOST, &mult_array);
5225754ecacSJeremy L Thompson     for (CeedInt i = 0; i < U_loc_size; i++)
5235754ecacSJeremy L Thompson       true_array[i] /= mult_array[i];
5245754ecacSJeremy L Thompson     CeedVectorRestoreArray(data[fine_level]->true_soln, &true_array);
5255754ecacSJeremy L Thompson     CeedVectorRestoreArrayRead(mult_vec, &mult_array);
5265754ecacSJeremy L Thompson     // -- Cleanup
5275754ecacSJeremy L Thompson     CeedVectorDestroy(&mult_vec);
5285754ecacSJeremy L Thompson     CeedBasisDestroy(&basis_x_true);
5295754ecacSJeremy L Thompson     CeedQFunctionDestroy(&qf_true);
5305754ecacSJeremy L Thompson     CeedOperatorDestroy(&op_true);
5315754ecacSJeremy L Thompson   }
5325754ecacSJeremy L Thompson 
5335754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
5345754ecacSJeremy L Thompson   // Local energy computation
5355754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
5365754ecacSJeremy L Thompson   // Create the QFunction and Operator that computes the strain energy
5375754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
5385754ecacSJeremy L Thompson   // -- QFunction
5395754ecacSJeremy L Thompson   CeedQFunctionCreateInterior(ceed, 1, problem_data.energy,
5405754ecacSJeremy L Thompson                               problem_data.energy_loc, &qf_energy);
5415754ecacSJeremy L Thompson   CeedQFunctionAddInput(qf_energy, "du", num_comp_u*dim, CEED_EVAL_GRAD);
5425754ecacSJeremy L Thompson   CeedQFunctionAddInput(qf_energy, "geo_data", geo_data_size, CEED_EVAL_NONE);
5435754ecacSJeremy L Thompson   CeedQFunctionAddOutput(qf_energy, "energy", num_comp_e, CEED_EVAL_INTERP);
5445754ecacSJeremy L Thompson   CeedQFunctionSetContext(qf_energy, phys_ctx);
5455754ecacSJeremy L Thompson   // -- Operator
5465754ecacSJeremy L Thompson   CeedOperatorCreate(ceed, qf_energy, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE,
5475754ecacSJeremy L Thompson                      &op_energy);
5485754ecacSJeremy L Thompson   CeedOperatorSetField(op_energy, "du", data[fine_level]->elem_restr_u,
5495754ecacSJeremy L Thompson                        data[fine_level]->basis_u, CEED_VECTOR_ACTIVE);
5505754ecacSJeremy L Thompson   CeedOperatorSetField(op_energy, "geo_data",
5515754ecacSJeremy L Thompson                        data[fine_level]->elem_restr_geo_data_i,
5525754ecacSJeremy L Thompson                        CEED_BASIS_COLLOCATED, data[fine_level]->geo_data);
5535754ecacSJeremy L Thompson   CeedOperatorSetField(op_energy, "energy", data[fine_level]->elem_restr_energy,
5545754ecacSJeremy L Thompson                        data[fine_level]->basis_energy, CEED_VECTOR_ACTIVE);
5555754ecacSJeremy L Thompson   // -- Save libCEED data
5565754ecacSJeremy L Thompson   data[fine_level]->qf_energy = qf_energy;
5575754ecacSJeremy L Thompson   data[fine_level]->op_energy = op_energy;
5585754ecacSJeremy L Thompson 
5595754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
5605754ecacSJeremy L Thompson   // Diagnostic value computation
5615754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
5625754ecacSJeremy L Thompson   // Create the QFunction and Operator that computes nodal diagnostic quantities
5635754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
5645754ecacSJeremy L Thompson   // Geometric factors
5655754ecacSJeremy L Thompson   // -- Coordinate basis
5665754ecacSJeremy L Thompson   CeedBasis basis_x;
5675754ecacSJeremy L Thompson   CeedBasisCreateTensorH1Lagrange(ceed, dim, num_comp_x, 2, Q, CEED_GAUSS_LOBATTO,
5685754ecacSJeremy L Thompson                                   &basis_x);
5695754ecacSJeremy L Thompson   // -- QFunction
5705754ecacSJeremy L Thompson   CeedQFunctionCreateInterior(ceed, 1, problem_data.setup_geo,
5715754ecacSJeremy L Thompson                               problem_data.setup_geo_loc, &qf_setup_geo);
5725754ecacSJeremy L Thompson   CeedQFunctionAddInput(qf_setup_geo, "dx", num_comp_x*dim, CEED_EVAL_GRAD);
5735754ecacSJeremy L Thompson   CeedQFunctionAddInput(qf_setup_geo, "weight", 1, CEED_EVAL_WEIGHT);
5745754ecacSJeremy L Thompson   CeedQFunctionAddOutput(qf_setup_geo, "geo_data", geo_data_size, CEED_EVAL_NONE);
5755754ecacSJeremy L Thompson   // -- Operator
5765754ecacSJeremy L Thompson   CeedOperatorCreate(ceed, qf_setup_geo, CEED_QFUNCTION_NONE,
5775754ecacSJeremy L Thompson                      CEED_QFUNCTION_NONE, &op_setup_geo);
5785754ecacSJeremy L Thompson   CeedOperatorSetField(op_setup_geo, "dx", data[fine_level]->elem_restr_x,
5795754ecacSJeremy L Thompson                        basis_x, CEED_VECTOR_ACTIVE);
5805754ecacSJeremy L Thompson   CeedOperatorSetField(op_setup_geo, "weight", CEED_ELEMRESTRICTION_NONE,
5815754ecacSJeremy L Thompson                        basis_x, CEED_VECTOR_NONE);
5825754ecacSJeremy L Thompson   CeedOperatorSetField(op_setup_geo, "geo_data",
5835754ecacSJeremy L Thompson                        data[fine_level]->elem_restr_geo_data_diagnostic_i,
5845754ecacSJeremy L Thompson                        CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
5855754ecacSJeremy L Thompson   // -- Compute the quadrature data
5865754ecacSJeremy L Thompson   CeedOperatorApply(op_setup_geo, x_coord, data[fine_level]->geo_data_diagnostic,
5875754ecacSJeremy L Thompson                     CEED_REQUEST_IMMEDIATE);
5885754ecacSJeremy L Thompson   // -- Cleanup
5895754ecacSJeremy L Thompson   CeedBasisDestroy(&basis_x);
5905754ecacSJeremy L Thompson   CeedQFunctionDestroy(&qf_setup_geo);
5915754ecacSJeremy L Thompson   CeedOperatorDestroy(&op_setup_geo);
5925754ecacSJeremy L Thompson 
5935754ecacSJeremy L Thompson   // Diagnostic quantities
5945754ecacSJeremy L Thompson   // -- QFunction
5955754ecacSJeremy L Thompson   CeedQFunctionCreateInterior(ceed, 1, problem_data.diagnostic,
5965754ecacSJeremy L Thompson                               problem_data.diagnostic_loc, &qf_diagnostic);
5975754ecacSJeremy L Thompson   CeedQFunctionAddInput(qf_diagnostic, "u", num_comp_u, CEED_EVAL_INTERP);
5985754ecacSJeremy L Thompson   CeedQFunctionAddInput(qf_diagnostic, "du", num_comp_u*dim, CEED_EVAL_GRAD);
5995754ecacSJeremy L Thompson   CeedQFunctionAddInput(qf_diagnostic, "geo_data", geo_data_size, CEED_EVAL_NONE);
6005754ecacSJeremy L Thompson   CeedQFunctionAddOutput(qf_diagnostic, "diagnostic", num_comp_u + num_comp_d,
6015754ecacSJeremy L Thompson                          CEED_EVAL_NONE);
6025754ecacSJeremy L Thompson   CeedQFunctionSetContext(qf_diagnostic, phys_ctx);
6035754ecacSJeremy L Thompson   // -- Operator
6045754ecacSJeremy L Thompson   CeedOperatorCreate(ceed, qf_diagnostic, CEED_QFUNCTION_NONE,
6055754ecacSJeremy L Thompson                      CEED_QFUNCTION_NONE, &op_diagnostic);
6065754ecacSJeremy L Thompson   CeedOperatorSetField(op_diagnostic, "u", data[fine_level]->elem_restr_u,
6075754ecacSJeremy L Thompson                        data[fine_level]->basis_diagnostic, CEED_VECTOR_ACTIVE);
6085754ecacSJeremy L Thompson   CeedOperatorSetField(op_diagnostic, "du", data[fine_level]->elem_restr_u,
6095754ecacSJeremy L Thompson                        data[fine_level]->basis_diagnostic, CEED_VECTOR_ACTIVE);
6105754ecacSJeremy L Thompson   CeedOperatorSetField(op_diagnostic, "geo_data",
6115754ecacSJeremy L Thompson                        data[fine_level]->elem_restr_geo_data_diagnostic_i,
6125754ecacSJeremy L Thompson                        CEED_BASIS_COLLOCATED, data[fine_level]->geo_data_diagnostic);
6135754ecacSJeremy L Thompson   CeedOperatorSetField(op_diagnostic, "diagnostic",
6145754ecacSJeremy L Thompson                        data[fine_level]->elem_restr_diagnostic,
6155754ecacSJeremy L Thompson                        CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
6165754ecacSJeremy L Thompson   // -- Save libCEED data
6175754ecacSJeremy L Thompson   data[fine_level]->qf_diagnostic = qf_diagnostic;
6185754ecacSJeremy L Thompson   data[fine_level]->op_diagnostic = op_diagnostic;
6195754ecacSJeremy L Thompson 
6205754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
6215754ecacSJeremy L Thompson   // Cleanup
6225754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
6235754ecacSJeremy L Thompson   CeedVectorDestroy(&x_coord);
6245754ecacSJeremy L Thompson 
6255754ecacSJeremy L Thompson   PetscFunctionReturn(0);
6265754ecacSJeremy L Thompson };
6275754ecacSJeremy L Thompson 
6285754ecacSJeremy L Thompson // Set up libCEED multigrid level for a given degree
6295754ecacSJeremy L Thompson //   Prolongation and Restriction are between level and level+1
6305754ecacSJeremy L Thompson PetscErrorCode SetupLibceedLevel(DM dm, Ceed ceed, AppCtx app_ctx,
6315754ecacSJeremy L Thompson                                  ProblemData problem_data, PetscInt level,
6325754ecacSJeremy L Thompson                                  PetscInt num_comp_u, PetscInt U_g_size,
6335754ecacSJeremy L Thompson                                  PetscInt U_loc_size, CeedVector fine_mult,
6345754ecacSJeremy L Thompson                                  CeedData *data) {
6355754ecacSJeremy L Thompson   PetscErrorCode ierr;
6365754ecacSJeremy L Thompson   CeedInt        fine_level = app_ctx->num_levels - 1;
6375754ecacSJeremy L Thompson   CeedInt        P = app_ctx->level_degrees[level] + 1;
6385754ecacSJeremy L Thompson   CeedInt        Q = app_ctx->level_degrees[fine_level] + 1 + app_ctx->q_extra;
6395754ecacSJeremy L Thompson   CeedInt        dim;
6405754ecacSJeremy L Thompson   CeedOperator   op_jacobian, op_prolong, op_restrict;
6415754ecacSJeremy L Thompson 
6425754ecacSJeremy L Thompson   PetscFunctionBeginUser;
6435754ecacSJeremy L Thompson 
6445754ecacSJeremy L Thompson   ierr = DMGetDimension(dm, &dim); CHKERRQ(ierr);
6455754ecacSJeremy L Thompson 
6465754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
6475754ecacSJeremy L Thompson   // libCEED restrictions
6485754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
6495754ecacSJeremy L Thompson   // -- Solution restriction
650*7ed3e4cdSJeremy L Thompson   ierr = CreateRestrictionFromPlex(ceed, dm, 0, 0, 0,
6515754ecacSJeremy L Thompson                                    &data[level]->elem_restr_u);
6525754ecacSJeremy L Thompson   CHKERRQ(ierr);
6535754ecacSJeremy L Thompson 
6545754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
6555754ecacSJeremy L Thompson   // libCEED bases
6565754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
6575754ecacSJeremy L Thompson   // -- Solution basis
6585754ecacSJeremy L Thompson   CeedBasisCreateTensorH1Lagrange(ceed, dim, num_comp_u, P, Q,
6595754ecacSJeremy L Thompson                                   problem_data.quadrature_mode,
6605754ecacSJeremy L Thompson                                   &data[level]->basis_u);
6615754ecacSJeremy L Thompson 
6625754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
6635754ecacSJeremy L Thompson   // Persistent libCEED vectors
6645754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
6655754ecacSJeremy L Thompson   CeedVectorCreate(ceed, U_loc_size, &data[level]->x_ceed);
6665754ecacSJeremy L Thompson   CeedVectorCreate(ceed, U_loc_size, &data[level]->y_ceed);
6675754ecacSJeremy L Thompson 
6685754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
6695754ecacSJeremy L Thompson   // Coarse Grid, Prolongation, and Restriction Operators
6705754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
6715754ecacSJeremy L Thompson   // Create the Operators that compute the prolongation and
6725754ecacSJeremy L Thompson   //   restriction between the p-multigrid levels and the coarse grid eval.
6735754ecacSJeremy L Thompson   // ---------------------------------------------------------------------------
6745754ecacSJeremy L Thompson   CeedOperatorMultigridLevelCreate(data[level+1]->op_jacobian, fine_mult,
6755754ecacSJeremy L Thompson                                    data[level]->elem_restr_u, data[level]->basis_u,
6765754ecacSJeremy L Thompson                                    &op_jacobian, &op_prolong, &op_restrict);
6775754ecacSJeremy L Thompson 
6785754ecacSJeremy L Thompson   // -- Save libCEED data
6795754ecacSJeremy L Thompson   data[level]->op_jacobian = op_jacobian;
6805754ecacSJeremy L Thompson   data[level+1]->op_prolong = op_prolong;
6815754ecacSJeremy L Thompson   data[level+1]->op_restrict = op_restrict;
6825754ecacSJeremy L Thompson 
6835754ecacSJeremy L Thompson   PetscFunctionReturn(0);
6845754ecacSJeremy L Thompson };
685