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