xref: /libCEED/examples/fluids/src/setuplibceed.c (revision e6225c4737d2b5358b9c1c5b7c13d86915d842f6)
177841947SLeila Ghaffari // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
277841947SLeila Ghaffari // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
377841947SLeila Ghaffari // reserved. See files LICENSE and NOTICE for details.
477841947SLeila Ghaffari //
577841947SLeila Ghaffari // This file is part of CEED, a collection of benchmarks, miniapps, software
677841947SLeila Ghaffari // libraries and APIs for efficient high-order finite element and spectral
777841947SLeila Ghaffari // element discretizations for exascale applications. For more information and
877841947SLeila Ghaffari // source code availability see http://github.com/ceed.
977841947SLeila Ghaffari //
1077841947SLeila Ghaffari // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
1177841947SLeila Ghaffari // a collaborative effort of two U.S. Department of Energy organizations (Office
1277841947SLeila Ghaffari // of Science and the National Nuclear Security Administration) responsible for
1377841947SLeila Ghaffari // the planning and preparation of a capable exascale ecosystem, including
1477841947SLeila Ghaffari // software, applications, hardware, advanced system engineering and early
1577841947SLeila Ghaffari // testbed platforms, in support of the nation's exascale computing imperative.
1677841947SLeila Ghaffari 
1777841947SLeila Ghaffari /// @file
1877841947SLeila Ghaffari /// Setup libCEED for Navier-Stokes example using PETSc
1977841947SLeila Ghaffari 
2077841947SLeila Ghaffari #include "../navierstokes.h"
2177841947SLeila Ghaffari 
2277841947SLeila Ghaffari // Utility function - essential BC dofs are encoded in closure indices as -(i+1).
2377841947SLeila Ghaffari PetscInt Involute(PetscInt i) {
2477841947SLeila Ghaffari   return i >= 0 ? i : -(i+1);
2577841947SLeila Ghaffari }
2677841947SLeila Ghaffari 
2777841947SLeila Ghaffari // Utility function to create local CEED restriction
2877841947SLeila Ghaffari PetscErrorCode CreateRestrictionFromPlex(Ceed ceed, DM dm, CeedInt P,
2977841947SLeila Ghaffari     CeedInt height, DMLabel domain_label,
3077841947SLeila Ghaffari     CeedInt value, CeedElemRestriction *elem_restr) {
3177841947SLeila Ghaffari   PetscSection   section;
3277841947SLeila Ghaffari   PetscInt       p, num_elem, num_dofs, *elem_restrict, elem_offset, num_fields,
3377841947SLeila Ghaffari                  dim, depth;
3477841947SLeila Ghaffari   DMLabel        depth_label;
3577841947SLeila Ghaffari   IS             depth_IS, iter_IS;
3677841947SLeila Ghaffari   Vec            U_loc;
3777841947SLeila Ghaffari   const PetscInt *iter_indices;
3877841947SLeila Ghaffari   PetscErrorCode ierr;
3977841947SLeila Ghaffari   PetscFunctionBeginUser;
4077841947SLeila Ghaffari 
4177841947SLeila Ghaffari   ierr = DMGetDimension(dm, &dim); CHKERRQ(ierr);
4277841947SLeila Ghaffari   dim -= height;
4377841947SLeila Ghaffari   ierr = DMGetLocalSection(dm, &section); CHKERRQ(ierr);
4477841947SLeila Ghaffari   ierr = PetscSectionGetNumFields(section, &num_fields); CHKERRQ(ierr);
4577841947SLeila Ghaffari   PetscInt num_comp[num_fields], field_off[num_fields+1];
4677841947SLeila Ghaffari   field_off[0] = 0;
4777841947SLeila Ghaffari   for (PetscInt f=0; f<num_fields; f++) {
4877841947SLeila Ghaffari     ierr = PetscSectionGetFieldComponents(section, f, &num_comp[f]); CHKERRQ(ierr);
4977841947SLeila Ghaffari     field_off[f+1] = field_off[f] + num_comp[f];
5077841947SLeila Ghaffari   }
5177841947SLeila Ghaffari 
5277841947SLeila Ghaffari   ierr = DMPlexGetDepth(dm, &depth); CHKERRQ(ierr);
5377841947SLeila Ghaffari   ierr = DMPlexGetDepthLabel(dm, &depth_label); CHKERRQ(ierr);
5477841947SLeila Ghaffari   ierr = DMLabelGetStratumIS(depth_label, depth - height, &depth_IS);
5577841947SLeila Ghaffari   CHKERRQ(ierr);
5677841947SLeila Ghaffari   if (domain_label) {
5777841947SLeila Ghaffari     IS domain_IS;
5877841947SLeila Ghaffari     ierr = DMLabelGetStratumIS(domain_label, value, &domain_IS); CHKERRQ(ierr);
5977841947SLeila Ghaffari     if (domain_IS) { // domain_IS is non-empty
6077841947SLeila Ghaffari       ierr = ISIntersect(depth_IS, domain_IS, &iter_IS); CHKERRQ(ierr);
6177841947SLeila Ghaffari       ierr = ISDestroy(&domain_IS); CHKERRQ(ierr);
6277841947SLeila Ghaffari     } else { // domain_IS is NULL (empty)
6377841947SLeila Ghaffari       iter_IS = NULL;
6477841947SLeila Ghaffari     }
6577841947SLeila Ghaffari     ierr = ISDestroy(&depth_IS); CHKERRQ(ierr);
6677841947SLeila Ghaffari   } else {
6777841947SLeila Ghaffari     iter_IS = depth_IS;
6877841947SLeila Ghaffari   }
6977841947SLeila Ghaffari   if (iter_IS) {
7077841947SLeila Ghaffari     ierr = ISGetLocalSize(iter_IS, &num_elem); CHKERRQ(ierr);
7177841947SLeila Ghaffari     ierr = ISGetIndices(iter_IS, &iter_indices); CHKERRQ(ierr);
7277841947SLeila Ghaffari   } else {
7377841947SLeila Ghaffari     num_elem = 0;
7477841947SLeila Ghaffari     iter_indices = NULL;
7577841947SLeila Ghaffari   }
7677841947SLeila Ghaffari   ierr = PetscMalloc1(num_elem*PetscPowInt(P, dim), &elem_restrict);
7777841947SLeila Ghaffari   CHKERRQ(ierr);
7877841947SLeila Ghaffari   for (p=0, elem_offset=0; p<num_elem; p++) {
7977841947SLeila Ghaffari     PetscInt c = iter_indices[p];
8077841947SLeila Ghaffari     PetscInt num_indices, *indices, num_nodes;
8177841947SLeila Ghaffari     ierr = DMPlexGetClosureIndices(dm, section, section, c, PETSC_TRUE,
8277841947SLeila Ghaffari                                    &num_indices, &indices, NULL, NULL);
8377841947SLeila Ghaffari     CHKERRQ(ierr);
8477841947SLeila Ghaffari     bool flip = false;
8577841947SLeila Ghaffari     if (height > 0) {
8677841947SLeila Ghaffari       PetscInt num_cells, num_faces, start = -1;
8777841947SLeila Ghaffari       const PetscInt *orients, *faces, *cells;
8877841947SLeila Ghaffari       ierr = DMPlexGetSupport(dm, c, &cells); CHKERRQ(ierr);
8977841947SLeila Ghaffari       ierr = DMPlexGetSupportSize(dm, c, &num_cells); CHKERRQ(ierr);
9077841947SLeila Ghaffari       if (num_cells != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
9177841947SLeila Ghaffari                                      "Expected one cell in support of exterior face, but got %D cells",
9277841947SLeila Ghaffari                                      num_cells);
9377841947SLeila Ghaffari       ierr = DMPlexGetCone(dm, cells[0], &faces); CHKERRQ(ierr);
9477841947SLeila Ghaffari       ierr = DMPlexGetConeSize(dm, cells[0], &num_faces); CHKERRQ(ierr);
9577841947SLeila Ghaffari       for (PetscInt i=0; i<num_faces; i++) {if (faces[i] == c) start = i;}
9677841947SLeila Ghaffari       if (start < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT,
9777841947SLeila Ghaffari                                 "Could not find face %D in cone of its support",
9877841947SLeila Ghaffari                                 c);
9977841947SLeila Ghaffari       ierr = DMPlexGetConeOrientation(dm, cells[0], &orients); CHKERRQ(ierr);
10077841947SLeila Ghaffari       if (orients[start] < 0) flip = true;
10177841947SLeila Ghaffari     }
10277841947SLeila Ghaffari     if (num_indices % field_off[num_fields]) SETERRQ1(PETSC_COMM_SELF,
10377841947SLeila Ghaffari           PETSC_ERR_ARG_INCOMP, "Number of closure indices not compatible with Cell %D",
10477841947SLeila Ghaffari           c);
10577841947SLeila Ghaffari     num_nodes = num_indices / field_off[num_fields];
10677841947SLeila Ghaffari     for (PetscInt i=0; i<num_nodes; i++) {
10777841947SLeila Ghaffari       PetscInt ii = i;
10877841947SLeila Ghaffari       if (flip) {
10977841947SLeila Ghaffari         if (P == num_nodes) ii = num_nodes - 1 - i;
11077841947SLeila Ghaffari         else if (P*P == num_nodes) {
11177841947SLeila Ghaffari           PetscInt row = i / P, col = i % P;
11277841947SLeila Ghaffari           ii = row + col * P;
11377841947SLeila Ghaffari         } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP,
11477841947SLeila Ghaffari                           "No support for flipping point with %D nodes != P (%D) or P^2",
11577841947SLeila Ghaffari                           num_nodes, P);
11677841947SLeila Ghaffari       }
11777841947SLeila Ghaffari       // Check that indices are blocked by node and thus can be coalesced as a single field with
11877841947SLeila Ghaffari       // field_off[num_fields] = sum(num_comp) components.
11977841947SLeila Ghaffari       for (PetscInt f=0; f<num_fields; f++) {
12077841947SLeila Ghaffari         for (PetscInt j=0; j<num_comp[f]; j++) {
12177841947SLeila Ghaffari           if (Involute(indices[field_off[f]*num_nodes + ii*num_comp[f] + j])
12277841947SLeila Ghaffari               != Involute(indices[ii*num_comp[0]]) + field_off[f] + j)
12377841947SLeila Ghaffari             SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
12477841947SLeila Ghaffari                      "Cell %D closure indices not interlaced for node %D field %D component %D",
12577841947SLeila Ghaffari                      c, ii, f, j);
12677841947SLeila Ghaffari         }
12777841947SLeila Ghaffari       }
12877841947SLeila Ghaffari       // Essential boundary conditions are encoded as -(loc+1), but we don't care so we decode.
12977841947SLeila Ghaffari       PetscInt loc = Involute(indices[ii*num_comp[0]]);
13077841947SLeila Ghaffari       elem_restrict[elem_offset++] = loc;
13177841947SLeila Ghaffari     }
13277841947SLeila Ghaffari     ierr = DMPlexRestoreClosureIndices(dm, section, section, c, PETSC_TRUE,
13377841947SLeila Ghaffari                                        &num_indices, &indices, NULL, NULL);
13477841947SLeila Ghaffari     CHKERRQ(ierr);
13577841947SLeila Ghaffari   }
13677841947SLeila Ghaffari   if (elem_offset != num_elem*PetscPowInt(P, dim))
13777841947SLeila Ghaffari     SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB,
13877841947SLeila Ghaffari              "ElemRestriction of size (%D,%D) initialized %D nodes", num_elem,
13977841947SLeila Ghaffari              PetscPowInt(P, dim),elem_offset);
14077841947SLeila Ghaffari   if (iter_IS) {
14177841947SLeila Ghaffari     ierr = ISRestoreIndices(iter_IS, &iter_indices); CHKERRQ(ierr);
14277841947SLeila Ghaffari   }
14377841947SLeila Ghaffari   ierr = ISDestroy(&iter_IS); CHKERRQ(ierr);
14477841947SLeila Ghaffari 
14577841947SLeila Ghaffari   ierr = DMGetLocalVector(dm, &U_loc); CHKERRQ(ierr);
14677841947SLeila Ghaffari   ierr = VecGetLocalSize(U_loc, &num_dofs); CHKERRQ(ierr);
14777841947SLeila Ghaffari   ierr = DMRestoreLocalVector(dm, &U_loc); CHKERRQ(ierr);
14877841947SLeila Ghaffari   CeedElemRestrictionCreate(ceed, num_elem, PetscPowInt(P, dim),
14977841947SLeila Ghaffari                             field_off[num_fields],
15077841947SLeila Ghaffari                             1, num_dofs, CEED_MEM_HOST, CEED_COPY_VALUES, elem_restrict,
15177841947SLeila Ghaffari                             elem_restr);
15277841947SLeila Ghaffari   ierr = PetscFree(elem_restrict); CHKERRQ(ierr);
15377841947SLeila Ghaffari   PetscFunctionReturn(0);
15477841947SLeila Ghaffari }
15577841947SLeila Ghaffari 
15677841947SLeila Ghaffari // Utility function to get Ceed Restriction for each domain
15777841947SLeila Ghaffari PetscErrorCode GetRestrictionForDomain(Ceed ceed, DM dm, CeedInt height,
15877841947SLeila Ghaffari                                        DMLabel domain_label, PetscInt value,
15977841947SLeila Ghaffari                                        CeedInt P, CeedInt Q, CeedInt q_data_size,
16077841947SLeila Ghaffari                                        CeedElemRestriction *elem_restr_q,
16177841947SLeila Ghaffari                                        CeedElemRestriction *elem_restr_x,
16277841947SLeila Ghaffari                                        CeedElemRestriction *elem_restr_qd_i) {
16377841947SLeila Ghaffari   DM             dm_coord;
16477841947SLeila Ghaffari   CeedInt        dim, loc_num_elem;
16577841947SLeila Ghaffari   CeedInt        Q_dim;
16677841947SLeila Ghaffari   PetscErrorCode ierr;
16777841947SLeila Ghaffari   PetscFunctionBeginUser;
16877841947SLeila Ghaffari 
16977841947SLeila Ghaffari   ierr = DMGetDimension(dm, &dim); CHKERRQ(ierr);
17077841947SLeila Ghaffari   dim -= height;
17177841947SLeila Ghaffari   Q_dim = CeedIntPow(Q, dim);
17277841947SLeila Ghaffari   ierr = DMGetCoordinateDM(dm, &dm_coord); CHKERRQ(ierr);
17377841947SLeila Ghaffari   ierr = DMPlexSetClosurePermutationTensor(dm_coord, PETSC_DETERMINE, NULL);
17477841947SLeila Ghaffari   CHKERRQ(ierr);
17577841947SLeila Ghaffari   ierr = CreateRestrictionFromPlex(ceed, dm, P, height, domain_label, value,
176*e6225c47SLeila Ghaffari                                    elem_restr_q); CHKERRQ(ierr);
17777841947SLeila Ghaffari   ierr = CreateRestrictionFromPlex(ceed, dm_coord, 2, height, domain_label, value,
178*e6225c47SLeila Ghaffari                                    elem_restr_x); CHKERRQ(ierr);
17977841947SLeila Ghaffari   CeedElemRestrictionGetNumElements(*elem_restr_q, &loc_num_elem);
18077841947SLeila Ghaffari   CeedElemRestrictionCreateStrided(ceed, loc_num_elem, Q_dim,
18177841947SLeila Ghaffari                                    q_data_size, q_data_size*loc_num_elem*Q_dim,
18277841947SLeila Ghaffari                                    CEED_STRIDES_BACKEND, elem_restr_qd_i);
18377841947SLeila Ghaffari   PetscFunctionReturn(0);
18477841947SLeila Ghaffari }
18577841947SLeila Ghaffari 
18677841947SLeila Ghaffari // Utility function to create CEED Composite Operator for the entire domain
18777841947SLeila Ghaffari PetscErrorCode CreateOperatorForDomain(Ceed ceed, DM dm, SimpleBC bc,
18877841947SLeila Ghaffari                                        CeedData ceed_data, Physics phys,
18977841947SLeila Ghaffari                                        CeedOperator op_apply_vol, CeedInt height,
19077841947SLeila Ghaffari                                        CeedInt P_sur, CeedInt Q_sur, CeedInt q_data_size_sur,
19177841947SLeila Ghaffari                                        CeedOperator *op_apply) {
19277841947SLeila Ghaffari   CeedInt        dim, num_face;
19377841947SLeila Ghaffari   DMLabel        domain_label;
19477841947SLeila Ghaffari   PetscErrorCode ierr;
19577841947SLeila Ghaffari   PetscFunctionBeginUser;
19677841947SLeila Ghaffari 
19777841947SLeila Ghaffari   // Create Composite Operaters
19877841947SLeila Ghaffari   CeedCompositeOperatorCreate(ceed, op_apply);
19977841947SLeila Ghaffari 
20077841947SLeila Ghaffari   // --Apply Sub-Operator for the volume
20177841947SLeila Ghaffari   CeedCompositeOperatorAddSub(*op_apply, op_apply_vol);
20277841947SLeila Ghaffari 
20377841947SLeila Ghaffari   // -- Create Sub-Operator for in/outflow BCs
204*e6225c47SLeila Ghaffari   if (phys->has_neumann) {
20577841947SLeila Ghaffari     // --- Setup
20677841947SLeila Ghaffari     ierr = DMGetLabel(dm, "Face Sets", &domain_label); CHKERRQ(ierr);
20777841947SLeila Ghaffari     ierr = DMGetDimension(dm, &dim); CHKERRQ(ierr);
20877841947SLeila Ghaffari     if (dim == 2) num_face = 4;
20977841947SLeila Ghaffari     if (dim == 3) num_face = 6;
21077841947SLeila Ghaffari 
21177841947SLeila Ghaffari     // --- Get number of quadrature points for the boundaries
21277841947SLeila Ghaffari     CeedInt num_qpts_sur;
21377841947SLeila Ghaffari     CeedBasisGetNumQuadraturePoints(ceed_data->basis_q_sur, &num_qpts_sur);
21477841947SLeila Ghaffari 
21577841947SLeila Ghaffari     // --- Create Sub-Operator for each face
21677841947SLeila Ghaffari     for (CeedInt i=0; i<num_face; i++) {
21777841947SLeila Ghaffari       CeedVector          q_data_sur;
21877841947SLeila Ghaffari       CeedOperator        op_setup_sur, op_apply_sur;
21977841947SLeila Ghaffari       CeedElemRestriction elem_restr_x_sur, elem_restr_q_sur,
22077841947SLeila Ghaffari                           elem_restr_qd_i_sur;
22177841947SLeila Ghaffari 
22277841947SLeila Ghaffari       // ---- CEED Restriction
22377841947SLeila Ghaffari       ierr = GetRestrictionForDomain(ceed, dm, height, domain_label, i+1, P_sur,
22477841947SLeila Ghaffari                                      Q_sur, q_data_size_sur, &elem_restr_q_sur,
22577841947SLeila Ghaffari                                      &elem_restr_x_sur, &elem_restr_qd_i_sur);
22677841947SLeila Ghaffari       CHKERRQ(ierr);
22777841947SLeila Ghaffari 
22877841947SLeila Ghaffari       // ---- CEED Vector
22977841947SLeila Ghaffari       PetscInt loc_num_elem_sur;
23077841947SLeila Ghaffari       CeedElemRestrictionGetNumElements(elem_restr_q_sur, &loc_num_elem_sur);
23177841947SLeila Ghaffari       CeedVectorCreate(ceed, q_data_size_sur*loc_num_elem_sur*num_qpts_sur,
23277841947SLeila Ghaffari                        &q_data_sur);
23377841947SLeila Ghaffari 
23477841947SLeila Ghaffari       // ---- CEED Operator
23577841947SLeila Ghaffari       // ----- CEED Operator for Setup (geometric factors)
23677841947SLeila Ghaffari       CeedOperatorCreate(ceed, ceed_data->qf_setup_sur, NULL, NULL, &op_setup_sur);
23777841947SLeila Ghaffari       CeedOperatorSetField(op_setup_sur, "dx", elem_restr_x_sur,
238*e6225c47SLeila Ghaffari                            ceed_data->basis_x_sur, CEED_VECTOR_ACTIVE);
23977841947SLeila Ghaffari       CeedOperatorSetField(op_setup_sur, "weight", CEED_ELEMRESTRICTION_NONE,
24077841947SLeila Ghaffari                            ceed_data->basis_x_sur, CEED_VECTOR_NONE);
24177841947SLeila Ghaffari       CeedOperatorSetField(op_setup_sur, "q_data_sur", elem_restr_qd_i_sur,
24277841947SLeila Ghaffari                            CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
24377841947SLeila Ghaffari 
24477841947SLeila Ghaffari       // ----- CEED Operator for Physics
24577841947SLeila Ghaffari       CeedOperatorCreate(ceed, ceed_data->qf_apply_sur, NULL, NULL, &op_apply_sur);
24677841947SLeila Ghaffari       CeedOperatorSetField(op_apply_sur, "q", elem_restr_q_sur,
24777841947SLeila Ghaffari                            ceed_data->basis_q_sur, CEED_VECTOR_ACTIVE);
24877841947SLeila Ghaffari       CeedOperatorSetField(op_apply_sur, "q_data_sur", elem_restr_qd_i_sur,
24977841947SLeila Ghaffari                            CEED_BASIS_COLLOCATED, q_data_sur);
25077841947SLeila Ghaffari       CeedOperatorSetField(op_apply_sur, "x", elem_restr_x_sur,
25177841947SLeila Ghaffari                            ceed_data->basis_x_sur, ceed_data->x_coord);
25277841947SLeila Ghaffari       CeedOperatorSetField(op_apply_sur, "v", elem_restr_q_sur,
25377841947SLeila Ghaffari                            ceed_data->basis_q_sur, CEED_VECTOR_ACTIVE);
25477841947SLeila Ghaffari 
25577841947SLeila Ghaffari       // ----- Apply CEED operator for Setup
25677841947SLeila Ghaffari       CeedOperatorApply(op_setup_sur, ceed_data->x_coord, q_data_sur,
25777841947SLeila Ghaffari                         CEED_REQUEST_IMMEDIATE);
25877841947SLeila Ghaffari 
25977841947SLeila Ghaffari       // ----- Apply Sub-Operator for the Boundary
26077841947SLeila Ghaffari       CeedCompositeOperatorAddSub(*op_apply, op_apply_sur);
26177841947SLeila Ghaffari 
26277841947SLeila Ghaffari       // ----- Cleanup
26377841947SLeila Ghaffari       CeedVectorDestroy(&q_data_sur);
26477841947SLeila Ghaffari       CeedElemRestrictionDestroy(&elem_restr_q_sur);
26577841947SLeila Ghaffari       CeedElemRestrictionDestroy(&elem_restr_x_sur);
26677841947SLeila Ghaffari       CeedElemRestrictionDestroy(&elem_restr_qd_i_sur);
26777841947SLeila Ghaffari       CeedOperatorDestroy(&op_setup_sur);
26877841947SLeila Ghaffari       CeedOperatorDestroy(&op_apply_sur);
26977841947SLeila Ghaffari     }
27077841947SLeila Ghaffari   }
27177841947SLeila Ghaffari 
27277841947SLeila Ghaffari   PetscFunctionReturn(0);
27377841947SLeila Ghaffari }
27477841947SLeila Ghaffari 
27577841947SLeila Ghaffari PetscErrorCode SetupLibceed(Ceed ceed, CeedData ceed_data, DM dm, User user,
27677841947SLeila Ghaffari                             AppCtx app_ctx, ProblemData *problem, SimpleBC bc) {
27777841947SLeila Ghaffari   PetscErrorCode ierr;
27877841947SLeila Ghaffari   PetscFunctionBeginUser;
27977841947SLeila Ghaffari 
28077841947SLeila Ghaffari   // *****************************************************************************
28177841947SLeila Ghaffari   // Set up CEED objects for the interior domain (volume)
28277841947SLeila Ghaffari   // *****************************************************************************
28377841947SLeila Ghaffari   const PetscInt num_comp_q      = 5;
28477841947SLeila Ghaffari   const CeedInt  dim             = problem->dim,
28577841947SLeila Ghaffari                  num_comp_x      = problem->dim,
28677841947SLeila Ghaffari                  q_data_size_vol = problem->q_data_size_vol,
28777841947SLeila Ghaffari                  P               = app_ctx->degree + 1,
28877841947SLeila Ghaffari                  Q               = P + app_ctx->q_extra;
28977841947SLeila Ghaffari 
29077841947SLeila Ghaffari   // -----------------------------------------------------------------------------
29177841947SLeila Ghaffari   // CEED Bases
29277841947SLeila Ghaffari   // -----------------------------------------------------------------------------
29377841947SLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dim, num_comp_q, P, Q, CEED_GAUSS,
29477841947SLeila Ghaffari                                   &ceed_data->basis_q);
29577841947SLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dim, num_comp_x, 2, Q, CEED_GAUSS,
29677841947SLeila Ghaffari                                   &ceed_data->basis_x);
29777841947SLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dim, num_comp_x, 2, P,
29877841947SLeila Ghaffari                                   CEED_GAUSS_LOBATTO, &ceed_data->basis_xc);
29977841947SLeila Ghaffari 
30077841947SLeila Ghaffari   // -----------------------------------------------------------------------------
30177841947SLeila Ghaffari   // CEED Restrictions
30277841947SLeila Ghaffari   // -----------------------------------------------------------------------------
30377841947SLeila Ghaffari   // -- Create restriction
30477841947SLeila Ghaffari   ierr = GetRestrictionForDomain(ceed, dm, 0, 0, 0, P, Q,
30577841947SLeila Ghaffari                                  q_data_size_vol, &ceed_data->elem_restr_q, &ceed_data->elem_restr_x,
30677841947SLeila Ghaffari                                  &ceed_data->elem_restr_qd_i); CHKERRQ(ierr);
30777841947SLeila Ghaffari   // -- Create E vectors
30877841947SLeila Ghaffari   CeedElemRestrictionCreateVector(ceed_data->elem_restr_q, &user->q_ceed, NULL);
30977841947SLeila Ghaffari   CeedElemRestrictionCreateVector(ceed_data->elem_restr_q, &user->q_dot_ceed,
31077841947SLeila Ghaffari                                   NULL);
31177841947SLeila Ghaffari   CeedElemRestrictionCreateVector(ceed_data->elem_restr_q, &user->g_ceed, NULL);
31277841947SLeila Ghaffari 
31377841947SLeila Ghaffari   // -----------------------------------------------------------------------------
31477841947SLeila Ghaffari   // CEED QFunctions
31577841947SLeila Ghaffari   // -----------------------------------------------------------------------------
31677841947SLeila Ghaffari   // -- Create QFunction for quadrature data
31777841947SLeila Ghaffari   CeedQFunctionCreateInterior(ceed, 1, problem->setup_vol, problem->setup_vol_loc,
31877841947SLeila Ghaffari                               &ceed_data->qf_setup_vol);
31977841947SLeila Ghaffari   CeedQFunctionAddInput(ceed_data->qf_setup_vol, "dx", num_comp_x*dim,
32077841947SLeila Ghaffari                         CEED_EVAL_GRAD);
32177841947SLeila Ghaffari   CeedQFunctionAddInput(ceed_data->qf_setup_vol, "weight", 1, CEED_EVAL_WEIGHT);
32277841947SLeila Ghaffari   CeedQFunctionAddOutput(ceed_data->qf_setup_vol, "q_data", q_data_size_vol,
32377841947SLeila Ghaffari                          CEED_EVAL_NONE);
32477841947SLeila Ghaffari 
32577841947SLeila Ghaffari   // -- Create QFunction for ICs
32677841947SLeila Ghaffari   CeedQFunctionCreateInterior(ceed, 1, problem->ics, problem->ics_loc,
32777841947SLeila Ghaffari                               &ceed_data->qf_ics);
32877841947SLeila Ghaffari   CeedQFunctionAddInput(ceed_data->qf_ics, "x", num_comp_x, CEED_EVAL_INTERP);
32977841947SLeila Ghaffari   CeedQFunctionAddOutput(ceed_data->qf_ics, "q0", num_comp_q, CEED_EVAL_NONE);
33077841947SLeila Ghaffari 
33177841947SLeila Ghaffari   // -- Create QFunction for RHS
33277841947SLeila Ghaffari   if (problem->apply_vol_rhs) {
33377841947SLeila Ghaffari     CeedQFunctionCreateInterior(ceed, 1, problem->apply_vol_rhs,
33477841947SLeila Ghaffari                                 problem->apply_vol_rhs_loc, &ceed_data->qf_rhs_vol);
33577841947SLeila Ghaffari     CeedQFunctionAddInput(ceed_data->qf_rhs_vol, "q", num_comp_q, CEED_EVAL_INTERP);
33677841947SLeila Ghaffari     CeedQFunctionAddInput(ceed_data->qf_rhs_vol, "dq", num_comp_q*dim,
33777841947SLeila Ghaffari                           CEED_EVAL_GRAD);
33877841947SLeila Ghaffari     CeedQFunctionAddInput(ceed_data->qf_rhs_vol, "q_data", q_data_size_vol,
33977841947SLeila Ghaffari                           CEED_EVAL_NONE);
34077841947SLeila Ghaffari     CeedQFunctionAddInput(ceed_data->qf_rhs_vol, "x", num_comp_x, CEED_EVAL_INTERP);
34177841947SLeila Ghaffari     CeedQFunctionAddOutput(ceed_data->qf_rhs_vol, "v", num_comp_q,
34277841947SLeila Ghaffari                            CEED_EVAL_INTERP);
34377841947SLeila Ghaffari     CeedQFunctionAddOutput(ceed_data->qf_rhs_vol, "dv", num_comp_q*dim,
34477841947SLeila Ghaffari                            CEED_EVAL_GRAD);
34577841947SLeila Ghaffari   }
34677841947SLeila Ghaffari 
34777841947SLeila Ghaffari   // -- Create QFunction for IFunction
34877841947SLeila Ghaffari   if (problem->apply_vol_ifunction) {
34977841947SLeila Ghaffari     CeedQFunctionCreateInterior(ceed, 1, problem->apply_vol_ifunction,
35077841947SLeila Ghaffari                                 problem->apply_vol_ifunction_loc, &ceed_data->qf_ifunction_vol);
35177841947SLeila Ghaffari     CeedQFunctionAddInput(ceed_data->qf_ifunction_vol, "q", num_comp_q,
35277841947SLeila Ghaffari                           CEED_EVAL_INTERP);
35377841947SLeila Ghaffari     CeedQFunctionAddInput(ceed_data->qf_ifunction_vol, "dq", num_comp_q*dim,
35477841947SLeila Ghaffari                           CEED_EVAL_GRAD);
35577841947SLeila Ghaffari     CeedQFunctionAddInput(ceed_data->qf_ifunction_vol, "q_dot", num_comp_q,
35677841947SLeila Ghaffari                           CEED_EVAL_INTERP);
35777841947SLeila Ghaffari     CeedQFunctionAddInput(ceed_data->qf_ifunction_vol, "q_data", q_data_size_vol,
35877841947SLeila Ghaffari                           CEED_EVAL_NONE);
35977841947SLeila Ghaffari     CeedQFunctionAddInput(ceed_data->qf_ifunction_vol, "x", num_comp_x,
36077841947SLeila Ghaffari                           CEED_EVAL_INTERP);
36177841947SLeila Ghaffari     CeedQFunctionAddOutput(ceed_data->qf_ifunction_vol, "v", num_comp_q,
36277841947SLeila Ghaffari                            CEED_EVAL_INTERP);
36377841947SLeila Ghaffari     CeedQFunctionAddOutput(ceed_data->qf_ifunction_vol, "dv", num_comp_q*dim,
36477841947SLeila Ghaffari                            CEED_EVAL_GRAD);
36577841947SLeila Ghaffari   }
36677841947SLeila Ghaffari 
36777841947SLeila Ghaffari   // ---------------------------------------------------------------------------
36877841947SLeila Ghaffari   // Element coordinates
36977841947SLeila Ghaffari   // ---------------------------------------------------------------------------
37077841947SLeila Ghaffari   // -- Create CEED vector
37177841947SLeila Ghaffari   CeedElemRestrictionCreateVector(ceed_data->elem_restr_x, &ceed_data->x_coord,
37277841947SLeila Ghaffari                                   NULL);
37377841947SLeila Ghaffari 
37477841947SLeila Ghaffari   // -- Copy PETSc vector in CEED vector
37577841947SLeila Ghaffari   Vec               X_loc;
37677841947SLeila Ghaffari   const PetscScalar *X_loc_array;
37777841947SLeila Ghaffari   ierr = DMGetCoordinatesLocal(dm, &X_loc); CHKERRQ(ierr);
37877841947SLeila Ghaffari   ierr = VecGetArrayRead(X_loc, &X_loc_array); CHKERRQ(ierr);
37977841947SLeila Ghaffari   CeedVectorSetArray(ceed_data->x_coord, CEED_MEM_HOST, CEED_COPY_VALUES,
38077841947SLeila Ghaffari                      (PetscScalar *)X_loc_array);
38177841947SLeila Ghaffari   ierr = VecRestoreArrayRead(X_loc, &X_loc_array); CHKERRQ(ierr);
38277841947SLeila Ghaffari 
38377841947SLeila Ghaffari   // -----------------------------------------------------------------------------
38477841947SLeila Ghaffari   // CEED vectors
38577841947SLeila Ghaffari   // -----------------------------------------------------------------------------
38677841947SLeila Ghaffari   // -- Create CEED vector for geometric data
38777841947SLeila Ghaffari   CeedInt  num_qpts_vol;
38877841947SLeila Ghaffari   PetscInt loc_num_elem_vol;
38977841947SLeila Ghaffari   CeedBasisGetNumQuadraturePoints(ceed_data->basis_q, &num_qpts_vol);
39077841947SLeila Ghaffari   CeedElemRestrictionGetNumElements(ceed_data->elem_restr_q, &loc_num_elem_vol);
39177841947SLeila Ghaffari   CeedVectorCreate(ceed, q_data_size_vol*loc_num_elem_vol*num_qpts_vol,
39277841947SLeila Ghaffari                    &ceed_data->q_data);
39377841947SLeila Ghaffari 
39477841947SLeila Ghaffari   // -----------------------------------------------------------------------------
39577841947SLeila Ghaffari   // CEED Operators
39677841947SLeila Ghaffari   // -----------------------------------------------------------------------------
39777841947SLeila Ghaffari   // -- Create CEED operator for quadrature data
39877841947SLeila Ghaffari   CeedOperatorCreate(ceed, ceed_data->qf_setup_vol, NULL, NULL,
39977841947SLeila Ghaffari                      &ceed_data->op_setup_vol);
40077841947SLeila Ghaffari   CeedOperatorSetField(ceed_data->op_setup_vol, "dx", ceed_data->elem_restr_x,
40177841947SLeila Ghaffari                        ceed_data->basis_x, CEED_VECTOR_ACTIVE);
40277841947SLeila Ghaffari   CeedOperatorSetField(ceed_data->op_setup_vol, "weight",
403*e6225c47SLeila Ghaffari                        CEED_ELEMRESTRICTION_NONE, ceed_data->basis_x, CEED_VECTOR_NONE);
40477841947SLeila Ghaffari   CeedOperatorSetField(ceed_data->op_setup_vol, "q_data",
405*e6225c47SLeila Ghaffari                        ceed_data->elem_restr_qd_i, CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
40677841947SLeila Ghaffari 
40777841947SLeila Ghaffari   // -- Create CEED operator for ICs
40877841947SLeila Ghaffari   CeedOperatorCreate(ceed, ceed_data->qf_ics, NULL, NULL, &ceed_data->op_ics);
40977841947SLeila Ghaffari   CeedOperatorSetField(ceed_data->op_ics, "x", ceed_data->elem_restr_x,
41077841947SLeila Ghaffari                        ceed_data->basis_xc, CEED_VECTOR_ACTIVE);
41177841947SLeila Ghaffari   CeedOperatorSetField(ceed_data->op_ics, "q0", ceed_data->elem_restr_q,
41277841947SLeila Ghaffari                        CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
41377841947SLeila Ghaffari 
41477841947SLeila Ghaffari   // Create CEED operator for RHS
41577841947SLeila Ghaffari   if (ceed_data->qf_rhs_vol) {
41677841947SLeila Ghaffari     CeedOperator op;
41777841947SLeila Ghaffari     CeedOperatorCreate(ceed, ceed_data->qf_rhs_vol, NULL, NULL, &op);
41877841947SLeila Ghaffari     CeedOperatorSetField(op, "q", ceed_data->elem_restr_q, ceed_data->basis_q,
41977841947SLeila Ghaffari                          CEED_VECTOR_ACTIVE);
42077841947SLeila Ghaffari     CeedOperatorSetField(op, "dq", ceed_data->elem_restr_q, ceed_data->basis_q,
42177841947SLeila Ghaffari                          CEED_VECTOR_ACTIVE);
42277841947SLeila Ghaffari     CeedOperatorSetField(op, "q_data", ceed_data->elem_restr_qd_i,
423*e6225c47SLeila Ghaffari                          CEED_BASIS_COLLOCATED, ceed_data->q_data);
42477841947SLeila Ghaffari     CeedOperatorSetField(op, "x", ceed_data->elem_restr_x, ceed_data->basis_x,
42577841947SLeila Ghaffari                          ceed_data->x_coord);
42677841947SLeila Ghaffari     CeedOperatorSetField(op, "v", ceed_data->elem_restr_q, ceed_data->basis_q,
42777841947SLeila Ghaffari                          CEED_VECTOR_ACTIVE);
42877841947SLeila Ghaffari     CeedOperatorSetField(op, "dv", ceed_data->elem_restr_q, ceed_data->basis_q,
42977841947SLeila Ghaffari                          CEED_VECTOR_ACTIVE);
43077841947SLeila Ghaffari     user->op_rhs_vol = op;
43177841947SLeila Ghaffari   }
43277841947SLeila Ghaffari 
43377841947SLeila Ghaffari   // -- CEED operator for IFunction
43477841947SLeila Ghaffari   if (ceed_data->qf_ifunction_vol) {
43577841947SLeila Ghaffari     CeedOperator op;
43677841947SLeila Ghaffari     CeedOperatorCreate(ceed, ceed_data->qf_ifunction_vol, NULL, NULL, &op);
43777841947SLeila Ghaffari     CeedOperatorSetField(op, "q", ceed_data->elem_restr_q, ceed_data->basis_q,
43877841947SLeila Ghaffari                          CEED_VECTOR_ACTIVE);
43977841947SLeila Ghaffari     CeedOperatorSetField(op, "dq", ceed_data->elem_restr_q, ceed_data->basis_q,
44077841947SLeila Ghaffari                          CEED_VECTOR_ACTIVE);
44177841947SLeila Ghaffari     CeedOperatorSetField(op, "q_dot", ceed_data->elem_restr_q, ceed_data->basis_q,
44277841947SLeila Ghaffari                          user->q_dot_ceed);
44377841947SLeila Ghaffari     CeedOperatorSetField(op, "q_data", ceed_data->elem_restr_qd_i,
444*e6225c47SLeila Ghaffari                          CEED_BASIS_COLLOCATED, ceed_data->q_data);
44577841947SLeila Ghaffari     CeedOperatorSetField(op, "x", ceed_data->elem_restr_x, ceed_data->basis_x,
44677841947SLeila Ghaffari                          ceed_data->x_coord);
44777841947SLeila Ghaffari     CeedOperatorSetField(op, "v", ceed_data->elem_restr_q, ceed_data->basis_q,
44877841947SLeila Ghaffari                          CEED_VECTOR_ACTIVE);
44977841947SLeila Ghaffari     CeedOperatorSetField(op, "dv", ceed_data->elem_restr_q, ceed_data->basis_q,
45077841947SLeila Ghaffari                          CEED_VECTOR_ACTIVE);
45177841947SLeila Ghaffari     user->op_ifunction_vol = op;
45277841947SLeila Ghaffari   }
45377841947SLeila Ghaffari 
45477841947SLeila Ghaffari   // *****************************************************************************
45577841947SLeila Ghaffari   // Set up CEED objects for the exterior domain (surface)
45677841947SLeila Ghaffari   // *****************************************************************************
45777841947SLeila Ghaffari   CeedInt height  = 1,
45877841947SLeila Ghaffari           dim_sur = dim - height,
45977841947SLeila Ghaffari           P_sur   = app_ctx->degree + 1,
46077841947SLeila Ghaffari           Q_sur   = P_sur + app_ctx->q_extra;
46177841947SLeila Ghaffari   const CeedInt q_data_size_sur = problem->q_data_size_sur;
46277841947SLeila Ghaffari 
46377841947SLeila Ghaffari   // -----------------------------------------------------------------------------
46477841947SLeila Ghaffari   // CEED Bases
46577841947SLeila Ghaffari   // -----------------------------------------------------------------------------
46677841947SLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dim_sur, num_comp_q, P_sur, Q_sur,
46777841947SLeila Ghaffari                                   CEED_GAUSS, &ceed_data->basis_q_sur);
46877841947SLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dim_sur, num_comp_x, 2, Q_sur, CEED_GAUSS,
46977841947SLeila Ghaffari                                   &ceed_data->basis_x_sur);
47077841947SLeila Ghaffari 
47177841947SLeila Ghaffari   // -----------------------------------------------------------------------------
47277841947SLeila Ghaffari   // CEED QFunctions
47377841947SLeila Ghaffari   // -----------------------------------------------------------------------------
47477841947SLeila Ghaffari   // -- Create QFunction for quadrature data
47577841947SLeila Ghaffari   CeedQFunctionCreateInterior(ceed, 1, problem->setup_sur, problem->setup_sur_loc,
47677841947SLeila Ghaffari                               &ceed_data->qf_setup_sur);
47777841947SLeila Ghaffari   CeedQFunctionAddInput(ceed_data->qf_setup_sur, "dx", num_comp_x*dim_sur,
47877841947SLeila Ghaffari                         CEED_EVAL_GRAD);
47977841947SLeila Ghaffari   CeedQFunctionAddInput(ceed_data->qf_setup_sur, "weight", 1, CEED_EVAL_WEIGHT);
48077841947SLeila Ghaffari   CeedQFunctionAddOutput(ceed_data->qf_setup_sur, "q_data_sur", q_data_size_sur,
48177841947SLeila Ghaffari                          CEED_EVAL_NONE);
48277841947SLeila Ghaffari 
48377841947SLeila Ghaffari   // -- Creat QFunction for the physics on the boundaries
48477841947SLeila Ghaffari   if (problem->apply_sur) {
48577841947SLeila Ghaffari     CeedQFunctionCreateInterior(ceed, 1, problem->apply_sur, problem->apply_sur_loc,
48677841947SLeila Ghaffari                                 &ceed_data->qf_apply_sur);
48777841947SLeila Ghaffari     CeedQFunctionAddInput(ceed_data->qf_apply_sur, "q", num_comp_q,
48877841947SLeila Ghaffari                           CEED_EVAL_INTERP);
48977841947SLeila Ghaffari     CeedQFunctionAddInput(ceed_data->qf_apply_sur, "q_data_sur", q_data_size_sur,
49077841947SLeila Ghaffari                           CEED_EVAL_NONE);
49177841947SLeila Ghaffari     CeedQFunctionAddInput(ceed_data->qf_apply_sur, "x", num_comp_x,
49277841947SLeila Ghaffari                           CEED_EVAL_INTERP);
49377841947SLeila Ghaffari     CeedQFunctionAddOutput(ceed_data->qf_apply_sur, "v", num_comp_q,
49477841947SLeila Ghaffari                            CEED_EVAL_INTERP);
49577841947SLeila Ghaffari   }
49677841947SLeila Ghaffari 
49777841947SLeila Ghaffari   // *****************************************************************************
49877841947SLeila Ghaffari   // CEED Operator Apply
49977841947SLeila Ghaffari   // *****************************************************************************
50077841947SLeila Ghaffari   // -- Apply CEED Operator for the geometric data
50177841947SLeila Ghaffari   CeedOperatorApply(ceed_data->op_setup_vol, ceed_data->x_coord,
50277841947SLeila Ghaffari                     ceed_data->q_data, CEED_REQUEST_IMMEDIATE);
50377841947SLeila Ghaffari 
50477841947SLeila Ghaffari   // -- Create and apply CEED Composite Operator for the entire domain
50577841947SLeila Ghaffari   if (!user->phys->implicit) { // RHS
50677841947SLeila Ghaffari     ierr = CreateOperatorForDomain(ceed, dm, bc, ceed_data, user->phys,
50777841947SLeila Ghaffari                                    user->op_rhs_vol, height, P_sur, Q_sur,
50877841947SLeila Ghaffari                                    q_data_size_sur, &user->op_rhs); CHKERRQ(ierr);
50977841947SLeila Ghaffari   } else { // IFunction
51077841947SLeila Ghaffari     ierr = CreateOperatorForDomain(ceed, dm, bc, ceed_data, user->phys,
51177841947SLeila Ghaffari                                    user->op_ifunction_vol, height, P_sur, Q_sur,
51277841947SLeila Ghaffari                                    q_data_size_sur, &user->op_ifunction); CHKERRQ(ierr);
51377841947SLeila Ghaffari   }
51477841947SLeila Ghaffari 
51577841947SLeila Ghaffari   PetscFunctionReturn(0);
51677841947SLeila Ghaffari }
517