xref: /libCEED/examples/fluids/navierstokes.c (revision d7a15aec4117ebd68df2eb1b6738702ec327a5e8)
1ccaff030SJeremy L Thompson // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2ccaff030SJeremy L Thompson // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3ccaff030SJeremy L Thompson // reserved. See files LICENSE and NOTICE for details.
4ccaff030SJeremy L Thompson //
5ccaff030SJeremy L Thompson // This file is part of CEED, a collection of benchmarks, miniapps, software
6ccaff030SJeremy L Thompson // libraries and APIs for efficient high-order finite element and spectral
7ccaff030SJeremy L Thompson // element discretizations for exascale applications. For more information and
8ccaff030SJeremy L Thompson // source code availability see http://github.com/ceed.
9ccaff030SJeremy L Thompson //
10ccaff030SJeremy L Thompson // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11ccaff030SJeremy L Thompson // a collaborative effort of two U.S. Department of Energy organizations (Office
12ccaff030SJeremy L Thompson // of Science and the National Nuclear Security Administration) responsible for
13ccaff030SJeremy L Thompson // the planning and preparation of a capable exascale ecosystem, including
14ccaff030SJeremy L Thompson // software, applications, hardware, advanced system engineering and early
15ccaff030SJeremy L Thompson // testbed platforms, in support of the nation's exascale computing imperative.
16ccaff030SJeremy L Thompson 
17ccaff030SJeremy L Thompson //                        libCEED + PETSc Example: Navier-Stokes
18ccaff030SJeremy L Thompson //
19ccaff030SJeremy L Thompson // This example demonstrates a simple usage of libCEED with PETSc to solve a
20ccaff030SJeremy L Thompson // Navier-Stokes problem.
21ccaff030SJeremy L Thompson //
22ccaff030SJeremy L Thompson // The code is intentionally "raw", using only low-level communication
23ccaff030SJeremy L Thompson // primitives.
24ccaff030SJeremy L Thompson //
25ccaff030SJeremy L Thompson // Build with:
26ccaff030SJeremy L Thompson //
27ccaff030SJeremy L Thompson //     make [PETSC_DIR=</path/to/petsc>] [CEED_DIR=</path/to/libceed>] navierstokes
28ccaff030SJeremy L Thompson //
29ccaff030SJeremy L Thompson // Sample runs:
30ccaff030SJeremy L Thompson //
3184d34d69SLeila Ghaffari //     ./navierstokes -ceed /cpu/self -problem density_current -degree 1
3228688798Sjeremylt //     ./navierstokes -ceed /gpu/cuda -problem advection -degree 1
33ccaff030SJeremy L Thompson //
34dc8efd83SLeila Ghaffari //TESTARGS(name="dc_explicit") -ceed {ceed_resource} -test -degree 3 -dm_plex_box_faces 1,1,2 -units_kilogram 1e-9 -lx 125 -ly 125 -lz 250 -center 62.5,62.5,187.5 -rc 100. -thetaC -35. -ts_dt 1e-3 -compare_final_state_atol 1E-11 -compare_final_state_filename examples/fluids/tests-output/fluids-navierstokes-dc-explicit.bin
35dc8efd83SLeila Ghaffari //TESTARGS(name="dc_implicit_stab_none") -ceed {ceed_resource} -test -degree 3 -dm_plex_box_faces 1,1,2 -units_kilogram 1e-9 -lx 125 -ly 125 -lz 250 -center 62.5,62.5,187.5 -rc 100. -thetaC -35. -ksp_atol 1e-4 -ksp_rtol 1e-3 -ksp_type bcgs -snes_atol 1e-3 -snes_lag_jacobian 100 -snes_lag_jacobian_persists -snes_mf_operator -ts_dt 1e-3 -implicit -ts_type alpha -compare_final_state_atol 5E-4 -compare_final_state_filename examples/fluids/tests-output/fluids-navierstokes-dc-implicit-stab-none.bin
36dc8efd83SLeila Ghaffari //TESTARGS(name="adv_rotation_explicit_strong") -ceed {ceed_resource} -test -problem advection -strong_form 1 -degree 3 -dm_plex_box_faces 1,1,2 -units_kilogram 1e-9 -lx 125 -ly 125 -lz 250 -center 62.5,62.5,187.5 -rc 100. -ts_dt 1e-3 -compare_final_state_atol 1E-11 -compare_final_state_filename examples/fluids/tests-output/fluids-navierstokes-adv-rotation-explicit-strong.bin
37dc8efd83SLeila Ghaffari //TESTARGS(name="adv_rotation_implicit_stab_supg") -ceed {ceed_resource} -test -problem advection -CtauS .3 -stab supg -degree 3 -dm_plex_box_faces 1,1,2 -units_kilogram 1e-9 -lx 125 -ly 125 -lz 250 -center 62.5,62.5,187.5 -rc 100. -ksp_atol 1e-4 -ksp_rtol 1e-3 -ksp_type bcgs -snes_atol 1e-3 -snes_lag_jacobian 100 -snes_lag_jacobian_persists -snes_mf_operator -ts_dt 1e-3 -implicit -ts_type alpha -compare_final_state_atol 5E-4 -compare_final_state_filename examples/fluids/tests-output/fluids-navierstokes-adv-rotation-implicit-stab-supg.bin
38dc8efd83SLeila Ghaffari //TESTARGS(name="adv_translation_implicit_stab_su") -ceed {ceed_resource} -test -problem advection -CtauS .3 -stab su -degree 3 -dm_plex_box_faces 1,1,2 -units_kilogram 1e-9 -lx 125 -ly 125 -lz 250 -center 62.5,62.5,187.5 -rc 100. -ksp_atol 1e-4 -ksp_rtol 1e-3 -ksp_type bcgs -snes_atol 1e-3 -snes_lag_jacobian 100 -snes_lag_jacobian_persists -snes_mf_operator -ts_dt 1e-3 -implicit -ts_type alpha -problem_advection_wind translation -problem_advection_wind_translation .53,-1.33,-2.65 -compare_final_state_atol 5E-4 -compare_final_state_filename examples/fluids/tests-output/fluids-navierstokes-adv-translation-implicit-stab-su.bin
39dc8efd83SLeila Ghaffari //TESTARGS(name="adv2d_rotation_explicit_strong") -ceed {ceed_resource} -test -problem advection2d -strong_form 1 -degree 3 -dm_plex_box_faces 1,1,2 -units_kilogram 1e-9 -lx 125 -ly 125 -lz 250 -center 62.5,62.5,187.5 -rc 100. -ts_dt 1e-3 -compare_final_state_atol 1E-11 -compare_final_state_filename examples/fluids/tests-output/fluids-navierstokes-adv2d-rotation-explicit-strong.bin
40dc8efd83SLeila Ghaffari //TESTARGS(name="adv2d_rotation_implicit_stab_supg") -ceed {ceed_resource} -test -problem advection2d -CtauS .3 -stab supg -degree 3 -dm_plex_box_faces 1,1,2 -units_kilogram 1e-9 -lx 125 -ly 125 -lz 250 -center 62.5,62.5,187.5 -rc 100. -ksp_atol 1e-4 -ksp_rtol 1e-3 -ksp_type bcgs -snes_atol 1e-3 -snes_lag_jacobian 100 -snes_lag_jacobian_persists -snes_mf_operator -ts_dt 1e-3 -implicit -ts_type alpha -compare_final_state_atol 5E-4 -compare_final_state_filename examples/fluids/tests-output/fluids-navierstokes-adv2d-rotation-implicit-stab-supg.bin
41dc8efd83SLeila Ghaffari //TESTARGS(name="adv2d_translation_implicit_stab_su") -ceed {ceed_resource} -test -problem advection2d -CtauS .3 -stab su -degree 3 -dm_plex_box_faces 1,1,2 -units_kilogram 1e-9 -lx 125 -ly 125 -lz 250 -center 62.5,62.5,187.5 -rc 100. -ksp_atol 1e-4 -ksp_rtol 1e-3 -ksp_type bcgs -snes_atol 1e-3 -snes_lag_jacobian 100 -snes_lag_jacobian_persists -snes_mf_operator -ts_dt 1e-3 -implicit -ts_type alpha -problem_advection_wind translation -problem_advection_wind_translation .53,-1.33,0 -compare_final_state_atol 5E-4 -compare_final_state_filename examples/fluids/tests-output/fluids-navierstokes-adv2d-translation-implicit-stab-su.bin
42ccaff030SJeremy L Thompson 
43ccaff030SJeremy L Thompson /// @file
44ccaff030SJeremy L Thompson /// Navier-Stokes example using PETSc
45ccaff030SJeremy L Thompson 
46ccaff030SJeremy L Thompson const char help[] = "Solve Navier-Stokes using PETSc and libCEED\n";
47ccaff030SJeremy L Thompson 
48ccaff030SJeremy L Thompson #include <ceed.h>
493d576824SJeremy L Thompson #include <petscdmplex.h>
50ccaff030SJeremy L Thompson #include <petscsys.h>
513d576824SJeremy L Thompson #include <petscts.h>
523d576824SJeremy L Thompson #include <stdbool.h>
53ccaff030SJeremy L Thompson #include "advection.h"
54ccaff030SJeremy L Thompson #include "advection2d.h"
553d576824SJeremy L Thompson #include "common.h"
56eb088987SLeila Ghaffari #include "euler-vortex.h"
57ccaff030SJeremy L Thompson #include "densitycurrent.h"
583d576824SJeremy L Thompson #include "setup-boundary.h"
59ccaff030SJeremy L Thompson 
6084d34d69SLeila Ghaffari #if PETSC_VERSION_LT(3,14,0)
6184d34d69SLeila Ghaffari #  define DMPlexGetClosureIndices(a,b,c,d,e,f,g,h,i) DMPlexGetClosureIndices(a,b,c,d,f,g,i)
6284d34d69SLeila Ghaffari #  define DMPlexRestoreClosureIndices(a,b,c,d,e,f,g,h,i) DMPlexRestoreClosureIndices(a,b,c,d,f,g,i)
6384d34d69SLeila Ghaffari #endif
6484d34d69SLeila Ghaffari 
653ab4fca6SValeria Barra #if PETSC_VERSION_LT(3,14,0)
663ab4fca6SValeria Barra #  define DMAddBoundary(a,b,c,d,e,f,g,h,i,j,k,l) DMAddBoundary(a,b,c,d,e,f,g,h,j,k,l)
673ab4fca6SValeria Barra #endif
683ab4fca6SValeria Barra 
6984d34d69SLeila Ghaffari // MemType Options
7084d34d69SLeila Ghaffari static const char *const memTypes[] = {
7184d34d69SLeila Ghaffari   "host",
7284d34d69SLeila Ghaffari   "device",
7384d34d69SLeila Ghaffari   "memType", "CEED_MEM_", NULL
7484d34d69SLeila Ghaffari };
7584d34d69SLeila Ghaffari 
76ccaff030SJeremy L Thompson // Problem Options
77ccaff030SJeremy L Thompson typedef enum {
78ccaff030SJeremy L Thompson   NS_DENSITY_CURRENT = 0,
79ccaff030SJeremy L Thompson   NS_ADVECTION = 1,
80ccaff030SJeremy L Thompson   NS_ADVECTION2D = 2,
81eb088987SLeila Ghaffari   NS_EULER_VORTEX = 3,
82ccaff030SJeremy L Thompson } problemType;
83ccaff030SJeremy L Thompson static const char *const problemTypes[] = {
84ccaff030SJeremy L Thompson   "density_current",
85ccaff030SJeremy L Thompson   "advection",
86ccaff030SJeremy L Thompson   "advection2d",
87e5ed8c30SLeila Ghaffari   "euler_vortex",
8884d34d69SLeila Ghaffari   "problemType", "NS_", NULL
89ccaff030SJeremy L Thompson };
90ccaff030SJeremy L Thompson 
911184866aSLeila Ghaffari // Wind Options for Advection
921184866aSLeila Ghaffari typedef enum {
931184866aSLeila Ghaffari   ADVECTION_WIND_ROTATION = 0,
941184866aSLeila Ghaffari   ADVECTION_WIND_TRANSLATION = 1,
951184866aSLeila Ghaffari } WindType;
961184866aSLeila Ghaffari static const char *const WindTypes[] = {
971184866aSLeila Ghaffari   "rotation",
981184866aSLeila Ghaffari   "translation",
991184866aSLeila Ghaffari   "WindType", "ADVECTION_WIND_", NULL
1001184866aSLeila Ghaffari };
1011184866aSLeila Ghaffari 
102ccaff030SJeremy L Thompson typedef enum {
103ccaff030SJeremy L Thompson   STAB_NONE = 0,
104ccaff030SJeremy L Thompson   STAB_SU = 1,   // Streamline Upwind
105ccaff030SJeremy L Thompson   STAB_SUPG = 2, // Streamline Upwind Petrov-Galerkin
106ccaff030SJeremy L Thompson } StabilizationType;
107ccaff030SJeremy L Thompson static const char *const StabilizationTypes[] = {
10884d34d69SLeila Ghaffari   "none",
109ccaff030SJeremy L Thompson   "SU",
110ccaff030SJeremy L Thompson   "SUPG",
111ccaff030SJeremy L Thompson   "StabilizationType", "STAB_", NULL
112ccaff030SJeremy L Thompson };
113ccaff030SJeremy L Thompson 
114a3ddc43aSLeila Ghaffari typedef enum {
115a3ddc43aSLeila Ghaffari   EULER_TEST_NONE = 0,
116a3ddc43aSLeila Ghaffari   EULER_TEST_1 = 1,
117a3ddc43aSLeila Ghaffari   EULER_TEST_2 = 2,
118a3ddc43aSLeila Ghaffari   EULER_TEST_3 = 3,
119a3ddc43aSLeila Ghaffari   EULER_TEST_4 = 4,
120a3ddc43aSLeila Ghaffari } EulerTestType;
121a3ddc43aSLeila Ghaffari static const char *const EulerTestTypes[] = {
122a3ddc43aSLeila Ghaffari   "none",
123a3ddc43aSLeila Ghaffari   "t1",
124a3ddc43aSLeila Ghaffari   "t2",
125a3ddc43aSLeila Ghaffari   "t3",
126a3ddc43aSLeila Ghaffari   "t4",
127a3ddc43aSLeila Ghaffari   "EulerTestType", "EULER_TEST_", NULL
128a3ddc43aSLeila Ghaffari };
129a3ddc43aSLeila Ghaffari 
130ccaff030SJeremy L Thompson // Problem specific data
131ccaff030SJeremy L Thompson typedef struct {
1328b982baeSLeila Ghaffari   CeedInt dim, qdatasizeVol, qdatasizeSur;
133ebb4b9bdSLeila Ghaffari   CeedQFunctionUser setupVol, setupSur, ics, applyVol_rhs, applyVol_ifunction,
134e2043960SLeila Ghaffari                     applySur;
135ccaff030SJeremy L Thompson   PetscErrorCode (*bc)(PetscInt, PetscReal, const PetscReal[], PetscInt,
136ccaff030SJeremy L Thompson                        PetscScalar[], void *);
1377659d40cSLeila Ghaffari   const char *setupVol_loc, *setupSur_loc, *ics_loc, *applyVol_rhs_loc,
138e2043960SLeila Ghaffari         *applyVol_ifunction_loc, *applySur_loc;
139ccaff030SJeremy L Thompson   const bool non_zero_time;
140ccaff030SJeremy L Thompson } problemData;
141ccaff030SJeremy L Thompson 
142ccaff030SJeremy L Thompson problemData problemOptions[] = {
143ccaff030SJeremy L Thompson   [NS_DENSITY_CURRENT] = {
144ccaff030SJeremy L Thompson     .dim                       = 3,
145ea6e0f84SLeila Ghaffari     .qdatasizeVol              = 10,
1468b982baeSLeila Ghaffari     .qdatasizeSur              = 4,
147b0137797SLeila Ghaffari     .setupVol                  = Setup,
148b0137797SLeila Ghaffari     .setupVol_loc              = Setup_loc,
149356fbf4bSLeila Ghaffari     .setupSur                  = SetupBoundary,
150356fbf4bSLeila Ghaffari     .setupSur_loc              = SetupBoundary_loc,
151ccaff030SJeremy L Thompson     .ics                       = ICsDC,
152ccaff030SJeremy L Thompson     .ics_loc                   = ICsDC_loc,
153c96c872fSLeila Ghaffari     .applyVol_rhs              = DC,
154c96c872fSLeila Ghaffari     .applyVol_rhs_loc          = DC_loc,
155c96c872fSLeila Ghaffari     .applyVol_ifunction        = IFunction_DC,
156c96c872fSLeila Ghaffari     .applyVol_ifunction_loc    = IFunction_DC_loc,
157ccaff030SJeremy L Thompson     .bc                        = Exact_DC,
15884d34d69SLeila Ghaffari     .non_zero_time             = PETSC_FALSE,
159ccaff030SJeremy L Thompson   },
160ccaff030SJeremy L Thompson   [NS_ADVECTION] = {
161ccaff030SJeremy L Thompson     .dim                       = 3,
162ea6e0f84SLeila Ghaffari     .qdatasizeVol              = 10,
1638b982baeSLeila Ghaffari     .qdatasizeSur              = 4,
164b0137797SLeila Ghaffari     .setupVol                  = Setup,
165b0137797SLeila Ghaffari     .setupVol_loc              = Setup_loc,
166356fbf4bSLeila Ghaffari     .setupSur                  = SetupBoundary,
167356fbf4bSLeila Ghaffari     .setupSur_loc              = SetupBoundary_loc,
168ccaff030SJeremy L Thompson     .ics                       = ICsAdvection,
169ccaff030SJeremy L Thompson     .ics_loc                   = ICsAdvection_loc,
170c96c872fSLeila Ghaffari     .applyVol_rhs              = Advection,
171c96c872fSLeila Ghaffari     .applyVol_rhs_loc          = Advection_loc,
172c96c872fSLeila Ghaffari     .applyVol_ifunction        = IFunction_Advection,
173c96c872fSLeila Ghaffari     .applyVol_ifunction_loc    = IFunction_Advection_loc,
1747659d40cSLeila Ghaffari     .applySur                  = Advection_Sur,
1757659d40cSLeila Ghaffari     .applySur_loc              = Advection_Sur_loc,
176ccaff030SJeremy L Thompson     .bc                        = Exact_Advection,
17784d34d69SLeila Ghaffari     .non_zero_time             = PETSC_FALSE,
178ccaff030SJeremy L Thompson   },
179ccaff030SJeremy L Thompson   [NS_ADVECTION2D] = {
180ccaff030SJeremy L Thompson     .dim                       = 2,
181ea6e0f84SLeila Ghaffari     .qdatasizeVol              = 5,
1828b982baeSLeila Ghaffari     .qdatasizeSur              = 3,
183c96c872fSLeila Ghaffari     .setupVol                  = Setup2d,
184c96c872fSLeila Ghaffari     .setupVol_loc              = Setup2d_loc,
185b0137797SLeila Ghaffari     .setupSur                  = SetupBoundary2d,
186b0137797SLeila Ghaffari     .setupSur_loc              = SetupBoundary2d_loc,
187ccaff030SJeremy L Thompson     .ics                       = ICsAdvection2d,
188ccaff030SJeremy L Thompson     .ics_loc                   = ICsAdvection2d_loc,
189c96c872fSLeila Ghaffari     .applyVol_rhs              = Advection2d,
190c96c872fSLeila Ghaffari     .applyVol_rhs_loc          = Advection2d_loc,
191c96c872fSLeila Ghaffari     .applyVol_ifunction        = IFunction_Advection2d,
192c96c872fSLeila Ghaffari     .applyVol_ifunction_loc    = IFunction_Advection2d_loc,
1937659d40cSLeila Ghaffari     .applySur                  = Advection2d_Sur,
1947659d40cSLeila Ghaffari     .applySur_loc              = Advection2d_Sur_loc,
195ccaff030SJeremy L Thompson     .bc                        = Exact_Advection2d,
19684d34d69SLeila Ghaffari     .non_zero_time             = PETSC_TRUE,
197ccaff030SJeremy L Thompson   },
198eb088987SLeila Ghaffari   [NS_EULER_VORTEX] = {
199eb088987SLeila Ghaffari     .dim                       = 3,
200eb088987SLeila Ghaffari     .qdatasizeVol              = 10,
201eb088987SLeila Ghaffari     .qdatasizeSur              = 4,
202eb088987SLeila Ghaffari     .setupVol                  = Setup,
203eb088987SLeila Ghaffari     .setupVol_loc              = Setup_loc,
204eb088987SLeila Ghaffari     .setupSur                  = SetupBoundary,
205eb088987SLeila Ghaffari     .setupSur_loc              = SetupBoundary_loc,
206eb088987SLeila Ghaffari     .ics                       = ICsEuler,
207eb088987SLeila Ghaffari     .ics_loc                   = ICsEuler_loc,
208eb088987SLeila Ghaffari     .applyVol_rhs              = Euler,
209eb088987SLeila Ghaffari     .applyVol_rhs_loc          = Euler_loc,
21077b27584SLeila Ghaffari     .applyVol_ifunction        = IFunction_Euler,
21177b27584SLeila Ghaffari     .applyVol_ifunction_loc    = IFunction_Euler_loc,
212b6df2e11SLeila Ghaffari     .applySur                  = Euler_Sur,
213b6df2e11SLeila Ghaffari     .applySur_loc              = Euler_Sur_loc,
214eb088987SLeila Ghaffari     .bc                        = Exact_Euler,
21547ff3025SLeila Ghaffari     .non_zero_time             = PETSC_TRUE,
216eb088987SLeila Ghaffari   },
217ccaff030SJeremy L Thompson };
218ccaff030SJeremy L Thompson 
219ccaff030SJeremy L Thompson // PETSc user data
220ccaff030SJeremy L Thompson typedef struct User_ *User;
221ccaff030SJeremy L Thompson typedef struct Units_ *Units;
222ccaff030SJeremy L Thompson 
223ccaff030SJeremy L Thompson struct User_ {
224ccaff030SJeremy L Thompson   MPI_Comm comm;
225ccaff030SJeremy L Thompson   PetscInt outputfreq;
226ccaff030SJeremy L Thompson   DM dm;
227ccaff030SJeremy L Thompson   DM dmviz;
228ccaff030SJeremy L Thompson   Mat interpviz;
229ccaff030SJeremy L Thompson   Ceed ceed;
230ccaff030SJeremy L Thompson   Units units;
231ccaff030SJeremy L Thompson   CeedVector qceed, qdotceed, gceed;
2321e150236SLeila Ghaffari   CeedOperator op_rhs_vol, op_rhs, op_ifunction_vol, op_ifunction;
233ccaff030SJeremy L Thompson   Vec M;
234d99129b9SLeila Ghaffari   char outputdir[PETSC_MAX_PATH_LEN];
235ccaff030SJeremy L Thompson   PetscInt contsteps;
2365bf10c6fSLeila Ghaffari   EulerContext ctxEulerData;
237ccaff030SJeremy L Thompson };
238ccaff030SJeremy L Thompson 
239ccaff030SJeremy L Thompson struct Units_ {
240ccaff030SJeremy L Thompson   // fundamental units
241ccaff030SJeremy L Thompson   PetscScalar meter;
242ccaff030SJeremy L Thompson   PetscScalar kilogram;
243ccaff030SJeremy L Thompson   PetscScalar second;
244ccaff030SJeremy L Thompson   PetscScalar Kelvin;
245ccaff030SJeremy L Thompson   // derived units
246ccaff030SJeremy L Thompson   PetscScalar Pascal;
247ccaff030SJeremy L Thompson   PetscScalar JperkgK;
248ccaff030SJeremy L Thompson   PetscScalar mpersquareds;
249ccaff030SJeremy L Thompson   PetscScalar WpermK;
250ccaff030SJeremy L Thompson   PetscScalar kgpercubicm;
251ccaff030SJeremy L Thompson   PetscScalar kgpersquaredms;
252ccaff030SJeremy L Thompson   PetscScalar Joulepercubicm;
25316c0476cSLeila Ghaffari   PetscScalar Joule;
254ccaff030SJeremy L Thompson };
255ccaff030SJeremy L Thompson 
256ccaff030SJeremy L Thompson typedef struct SimpleBC_ *SimpleBC;
257ccaff030SJeremy L Thompson struct SimpleBC_ {
2587659d40cSLeila Ghaffari   PetscInt nwall, nslip[3];
2597659d40cSLeila Ghaffari   PetscInt walls[6], slips[3][6];
26084d34d69SLeila Ghaffari   PetscBool userbc;
261ccaff030SJeremy L Thompson };
262ccaff030SJeremy L Thompson 
263ccaff030SJeremy L Thompson // Essential BC dofs are encoded in closure indices as -(i+1).
264ccaff030SJeremy L Thompson static PetscInt Involute(PetscInt i) {
265ccaff030SJeremy L Thompson   return i >= 0 ? i : -(i+1);
266ccaff030SJeremy L Thompson }
267ccaff030SJeremy L Thompson 
268ccaff030SJeremy L Thompson // Utility function to create local CEED restriction
269ccaff030SJeremy L Thompson static PetscErrorCode CreateRestrictionFromPlex(Ceed ceed, DM dm, CeedInt P,
27084d34d69SLeila Ghaffari     CeedInt height, DMLabel domainLabel, CeedInt value,
271ccaff030SJeremy L Thompson     CeedElemRestriction *Erestrict) {
272ccaff030SJeremy L Thompson 
273ccaff030SJeremy L Thompson   PetscSection section;
2741184866aSLeila Ghaffari   PetscInt p, Nelem, Ndof, *erestrict, eoffset, nfields, dim, depth;
2750c6c0b13SLeila Ghaffari   DMLabel depthLabel;
2760c6c0b13SLeila Ghaffari   IS depthIS, iterIS;
27784d34d69SLeila Ghaffari   Vec Uloc;
2780c6c0b13SLeila Ghaffari   const PetscInt *iterIndices;
279ccaff030SJeremy L Thompson   PetscErrorCode ierr;
280ccaff030SJeremy L Thompson 
281ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
282ccaff030SJeremy L Thompson   ierr = DMGetDimension(dm, &dim); CHKERRQ(ierr);
283da51bdd9SLeila Ghaffari   dim -= height;
284ccaff030SJeremy L Thompson   ierr = DMGetLocalSection(dm, &section); CHKERRQ(ierr);
285ccaff030SJeremy L Thompson   ierr = PetscSectionGetNumFields(section, &nfields); CHKERRQ(ierr);
286ccaff030SJeremy L Thompson   PetscInt ncomp[nfields], fieldoff[nfields+1];
287ccaff030SJeremy L Thompson   fieldoff[0] = 0;
288ccaff030SJeremy L Thompson   for (PetscInt f=0; f<nfields; f++) {
289ccaff030SJeremy L Thompson     ierr = PetscSectionGetFieldComponents(section, f, &ncomp[f]); CHKERRQ(ierr);
290ccaff030SJeremy L Thompson     fieldoff[f+1] = fieldoff[f] + ncomp[f];
291ccaff030SJeremy L Thompson   }
292ccaff030SJeremy L Thompson 
2930c6c0b13SLeila Ghaffari   ierr = DMPlexGetDepth(dm, &depth); CHKERRQ(ierr);
2940c6c0b13SLeila Ghaffari   ierr = DMPlexGetDepthLabel(dm, &depthLabel); CHKERRQ(ierr);
2950c6c0b13SLeila Ghaffari   ierr = DMLabelGetStratumIS(depthLabel, depth - height, &depthIS); CHKERRQ(ierr);
2960c6c0b13SLeila Ghaffari   if (domainLabel) {
2970c6c0b13SLeila Ghaffari     IS domainIS;
2980c6c0b13SLeila Ghaffari     ierr = DMLabelGetStratumIS(domainLabel, value, &domainIS); CHKERRQ(ierr);
2991119eeeeSJed Brown     if (domainIS) { // domainIS is non-empty
3000c6c0b13SLeila Ghaffari       ierr = ISIntersect(depthIS, domainIS, &iterIS); CHKERRQ(ierr);
3010c6c0b13SLeila Ghaffari       ierr = ISDestroy(&domainIS); CHKERRQ(ierr);
3021119eeeeSJed Brown     } else { // domainIS is NULL (empty)
3031119eeeeSJed Brown       iterIS = NULL;
3041119eeeeSJed Brown     }
3050c6c0b13SLeila Ghaffari     ierr = ISDestroy(&depthIS); CHKERRQ(ierr);
3060c6c0b13SLeila Ghaffari   } else {
3070c6c0b13SLeila Ghaffari     iterIS = depthIS;
3080c6c0b13SLeila Ghaffari   }
3091119eeeeSJed Brown   if (iterIS) {
3100c6c0b13SLeila Ghaffari     ierr = ISGetLocalSize(iterIS, &Nelem); CHKERRQ(ierr);
3110c6c0b13SLeila Ghaffari     ierr = ISGetIndices(iterIS, &iterIndices); CHKERRQ(ierr);
3121119eeeeSJed Brown   } else {
3131119eeeeSJed Brown     Nelem = 0;
3141119eeeeSJed Brown     iterIndices = NULL;
3151119eeeeSJed Brown   }
316ccaff030SJeremy L Thompson   ierr = PetscMalloc1(Nelem*PetscPowInt(P, dim), &erestrict); CHKERRQ(ierr);
3170c6c0b13SLeila Ghaffari   for (p=0,eoffset=0; p<Nelem; p++) {
3180c6c0b13SLeila Ghaffari     PetscInt c = iterIndices[p];
319ccaff030SJeremy L Thompson     PetscInt numindices, *indices, nnodes;
32084d34d69SLeila Ghaffari     ierr = DMPlexGetClosureIndices(dm, section, section, c, PETSC_TRUE,
32184d34d69SLeila Ghaffari                                    &numindices, &indices, NULL, NULL);
32284d34d69SLeila Ghaffari     CHKERRQ(ierr);
32332b5ec5fSJed Brown     bool flip = false;
32432b5ec5fSJed Brown     if (height > 0) {
32532b5ec5fSJed Brown       PetscInt numCells, numFaces, start = -1;
32632b5ec5fSJed Brown       const PetscInt *orients, *faces, *cells;
32732b5ec5fSJed Brown       ierr = DMPlexGetSupport(dm, c, &cells); CHKERRQ(ierr);
32832b5ec5fSJed Brown       ierr = DMPlexGetSupportSize(dm, c, &numCells); CHKERRQ(ierr);
329ebb4b9bdSLeila Ghaffari       if (numCells != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
330f259b054Svaleriabarra                                     "Expected one cell in support of exterior face, but got %D cells",
331f259b054Svaleriabarra                                     numCells);
33232b5ec5fSJed Brown       ierr = DMPlexGetCone(dm, cells[0], &faces); CHKERRQ(ierr);
33332b5ec5fSJed Brown       ierr = DMPlexGetConeSize(dm, cells[0], &numFaces); CHKERRQ(ierr);
33432b5ec5fSJed Brown       for (PetscInt i=0; i<numFaces; i++) {if (faces[i] == c) start = i;}
335ebb4b9bdSLeila Ghaffari       if (start < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT,
336f259b054Svaleriabarra                                 "Could not find face %D in cone of its support",
337f259b054Svaleriabarra                                 c);
33832b5ec5fSJed Brown       ierr = DMPlexGetConeOrientation(dm, cells[0], &orients); CHKERRQ(ierr);
33932b5ec5fSJed Brown       if (orients[start] < 0) flip = true;
34032b5ec5fSJed Brown     }
34184d34d69SLeila Ghaffari     if (numindices % fieldoff[nfields]) SETERRQ1(PETSC_COMM_SELF,
34284d34d69SLeila Ghaffari           PETSC_ERR_ARG_INCOMP, "Number of closure indices not compatible with Cell %D",
34384d34d69SLeila Ghaffari           c);
344ccaff030SJeremy L Thompson     nnodes = numindices / fieldoff[nfields];
345ccaff030SJeremy L Thompson     for (PetscInt i=0; i<nnodes; i++) {
34632b5ec5fSJed Brown       PetscInt ii = i;
34732b5ec5fSJed Brown       if (flip) {
34832b5ec5fSJed Brown         if (P == nnodes) ii = nnodes - 1 - i;
34932b5ec5fSJed Brown         else if (P*P == nnodes) {
35032b5ec5fSJed Brown           PetscInt row = i / P, col = i % P;
35132b5ec5fSJed Brown           ii = row + col * P;
352ebb4b9bdSLeila Ghaffari         } else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP,
353f259b054Svaleriabarra                           "No support for flipping point with %D nodes != P (%D) or P^2",
354f259b054Svaleriabarra                           nnodes, P);
35532b5ec5fSJed Brown       }
356ccaff030SJeremy L Thompson       // Check that indices are blocked by node and thus can be coalesced as a single field with
357ccaff030SJeremy L Thompson       // fieldoff[nfields] = sum(ncomp) components.
358ccaff030SJeremy L Thompson       for (PetscInt f=0; f<nfields; f++) {
359ccaff030SJeremy L Thompson         for (PetscInt j=0; j<ncomp[f]; j++) {
36032b5ec5fSJed Brown           if (Involute(indices[fieldoff[f]*nnodes + ii*ncomp[f] + j])
36132b5ec5fSJed Brown               != Involute(indices[ii*ncomp[0]]) + fieldoff[f] + j)
362ccaff030SJeremy L Thompson             SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
363ccaff030SJeremy L Thompson                      "Cell %D closure indices not interlaced for node %D field %D component %D",
36432b5ec5fSJed Brown                      c, ii, f, j);
365ccaff030SJeremy L Thompson         }
366ccaff030SJeremy L Thompson       }
367ccaff030SJeremy L Thompson       // Essential boundary conditions are encoded as -(loc+1), but we don't care so we decode.
36832b5ec5fSJed Brown       PetscInt loc = Involute(indices[ii*ncomp[0]]);
3696f55dfd5Svaleriabarra       erestrict[eoffset++] = loc;
370ccaff030SJeremy L Thompson     }
37184d34d69SLeila Ghaffari     ierr = DMPlexRestoreClosureIndices(dm, section, section, c, PETSC_TRUE,
37284d34d69SLeila Ghaffari                                        &numindices, &indices, NULL, NULL);
37384d34d69SLeila Ghaffari     CHKERRQ(ierr);
374ccaff030SJeremy L Thompson   }
3750c6c0b13SLeila Ghaffari   if (eoffset != Nelem*PetscPowInt(P, dim))
3760c6c0b13SLeila Ghaffari     SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB,
3770c6c0b13SLeila Ghaffari              "ElemRestriction of size (%D,%D) initialized %D nodes", Nelem,
378ccaff030SJeremy L Thompson              PetscPowInt(P, dim),eoffset);
3791119eeeeSJed Brown   if (iterIS) {
3800c6c0b13SLeila Ghaffari     ierr = ISRestoreIndices(iterIS, &iterIndices); CHKERRQ(ierr);
3811119eeeeSJed Brown   }
3820c6c0b13SLeila Ghaffari   ierr = ISDestroy(&iterIS); CHKERRQ(ierr);
3830c6c0b13SLeila Ghaffari 
384ccaff030SJeremy L Thompson   ierr = DMGetLocalVector(dm, &Uloc); CHKERRQ(ierr);
385ccaff030SJeremy L Thompson   ierr = VecGetLocalSize(Uloc, &Ndof); CHKERRQ(ierr);
386ccaff030SJeremy L Thompson   ierr = DMRestoreLocalVector(dm, &Uloc); CHKERRQ(ierr);
3876f55dfd5Svaleriabarra   CeedElemRestrictionCreate(ceed, Nelem, PetscPowInt(P, dim), fieldoff[nfields],
3886f55dfd5Svaleriabarra                             1, Ndof, CEED_MEM_HOST, CEED_COPY_VALUES, erestrict,
3896f55dfd5Svaleriabarra                             Erestrict);
390ccaff030SJeremy L Thompson   ierr = PetscFree(erestrict); CHKERRQ(ierr);
391ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
392ccaff030SJeremy L Thompson }
393ccaff030SJeremy L Thompson 
394c96c872fSLeila Ghaffari // Utility function to get Ceed Restriction for each domain
3951e150236SLeila Ghaffari static PetscErrorCode GetRestrictionForDomain(Ceed ceed, DM dm, CeedInt height,
3961e150236SLeila Ghaffari     DMLabel domainLabel, PetscInt value, CeedInt P, CeedInt Q, CeedInt qdatasize,
3971e150236SLeila Ghaffari     CeedElemRestriction *restrictq, CeedElemRestriction *restrictx,
3981e150236SLeila Ghaffari     CeedElemRestriction *restrictqdi) {
399c96c872fSLeila Ghaffari 
400c96c872fSLeila Ghaffari   DM dmcoord;
4011e150236SLeila Ghaffari   CeedInt dim, localNelem;
4021e150236SLeila Ghaffari   CeedInt Qdim;
403c96c872fSLeila Ghaffari   PetscErrorCode ierr;
404c96c872fSLeila Ghaffari 
405c96c872fSLeila Ghaffari   PetscFunctionBeginUser;
4061e150236SLeila Ghaffari   ierr = DMGetDimension(dm, &dim); CHKERRQ(ierr);
4071e150236SLeila Ghaffari   dim -= height;
4081e150236SLeila Ghaffari   Qdim = CeedIntPow(Q, dim);
409c96c872fSLeila Ghaffari   ierr = DMGetCoordinateDM(dm, &dmcoord); CHKERRQ(ierr);
410c96c872fSLeila Ghaffari   ierr = DMPlexSetClosurePermutationTensor(dmcoord, PETSC_DETERMINE, NULL);
411c96c872fSLeila Ghaffari   CHKERRQ(ierr);
412ebb4b9bdSLeila Ghaffari   ierr = CreateRestrictionFromPlex(ceed, dm, P, height, domainLabel, value,
413ebb4b9bdSLeila Ghaffari                                    restrictq);
414c96c872fSLeila Ghaffari   CHKERRQ(ierr);
415ebb4b9bdSLeila Ghaffari   ierr = CreateRestrictionFromPlex(ceed, dmcoord, 2, height, domainLabel, value,
416ebb4b9bdSLeila Ghaffari                                    restrictx);
417c96c872fSLeila Ghaffari   CHKERRQ(ierr);
418c96c872fSLeila Ghaffari   CeedElemRestrictionGetNumElements(*restrictq, &localNelem);
419c96c872fSLeila Ghaffari   CeedElemRestrictionCreateStrided(ceed, localNelem, Qdim,
420c96c872fSLeila Ghaffari                                    qdatasize, qdatasize*localNelem*Qdim,
421c96c872fSLeila Ghaffari                                    CEED_STRIDES_BACKEND, restrictqdi);
422c96c872fSLeila Ghaffari   PetscFunctionReturn(0);
423c96c872fSLeila Ghaffari }
424c96c872fSLeila Ghaffari 
4251e150236SLeila Ghaffari // Utility function to create CEED Composite Operator for the entire domain
4267659d40cSLeila Ghaffari static PetscErrorCode CreateOperatorForDomain(Ceed ceed, DM dm, SimpleBC bc,
4274438636fSLeila Ghaffari     problemType problemChoice, WindType wind_type, CeedOperator op_applyVol,
428e2043960SLeila Ghaffari     CeedQFunction qf_applySur, CeedQFunction qf_setupSur,CeedInt height,
4294438636fSLeila Ghaffari     CeedInt numP_Sur, CeedInt numQ_Sur, CeedInt qdatasizeSur, CeedInt NqptsSur,
4304438636fSLeila Ghaffari     CeedBasis basisxSur, CeedBasis basisqSur, CeedOperator *op_apply) {
431ca3ac6ddSLeila Ghaffari 
4327659d40cSLeila Ghaffari   CeedInt dim, nFace;
4334438636fSLeila Ghaffari   PetscInt lsize;
4341e150236SLeila Ghaffari   Vec Xloc;
4354438636fSLeila Ghaffari   CeedVector xcorners;
436ca3ac6ddSLeila Ghaffari   DMLabel domainLabel;
4371e150236SLeila Ghaffari   PetscScalar *x;
438ca3ac6ddSLeila Ghaffari   PetscErrorCode ierr;
439ca3ac6ddSLeila Ghaffari 
440ca3ac6ddSLeila Ghaffari   PetscFunctionBeginUser;
441ca3ac6ddSLeila Ghaffari   // Composite Operaters
442ca3ac6ddSLeila Ghaffari   CeedCompositeOperatorCreate(ceed, op_apply);
4434438636fSLeila Ghaffari   // --Apply a Sub-Operator for the volume
4444438636fSLeila Ghaffari   CeedCompositeOperatorAddSub(*op_apply, op_applyVol);
445ca3ac6ddSLeila Ghaffari 
4464438636fSLeila Ghaffari   // Required data for in/outflow BCs
4471e150236SLeila Ghaffari   ierr = DMGetCoordinatesLocal(dm, &Xloc); CHKERRQ(ierr);
4481e150236SLeila Ghaffari   ierr = VecGetLocalSize(Xloc, &lsize); CHKERRQ(ierr);
4491e150236SLeila Ghaffari   ierr = CeedVectorCreate(ceed, lsize, &xcorners); CHKERRQ(ierr);
4501e150236SLeila Ghaffari   ierr = VecGetArray(Xloc, &x); CHKERRQ(ierr);
4511e150236SLeila Ghaffari   CeedVectorSetArray(xcorners, CEED_MEM_HOST, CEED_USE_POINTER, x);
452ca3ac6ddSLeila Ghaffari   ierr = DMGetLabel(dm, "Face Sets", &domainLabel); CHKERRQ(ierr);
4537659d40cSLeila Ghaffari   ierr = DMGetDimension(dm, &dim); CHKERRQ(ierr);
4544438636fSLeila Ghaffari 
45526aa2eeeSLeila Ghaffari   if (wind_type == ADVECTION_WIND_TRANSLATION
45626aa2eeeSLeila Ghaffari       || problemChoice == NS_EULER_VORTEX) {
4574438636fSLeila Ghaffari     // Ignore wall and slip BCs
4583d6e121fSLeila Ghaffari     if (wind_type == ADVECTION_WIND_TRANSLATION)
4593d6e121fSLeila Ghaffari       bc->nwall = bc->nslip[0] = bc->nslip[1] = bc->nslip[2] = 0;
4604438636fSLeila Ghaffari 
4614438636fSLeila Ghaffari     // Set number of faces
4627659d40cSLeila Ghaffari     if (dim == 2) nFace = 4;
4637659d40cSLeila Ghaffari     if (dim == 3) nFace = 6;
4649fe13df9SLeila Ghaffari 
4657659d40cSLeila Ghaffari     // Create CEED Operator for each boundary face
4664438636fSLeila Ghaffari     PetscInt localNelemSur[6];
4674438636fSLeila Ghaffari     CeedVector qdataSur[6];
4684438636fSLeila Ghaffari     CeedOperator op_setupSur[6], op_applySur[6];
4694438636fSLeila Ghaffari     CeedElemRestriction restrictxSur[6], restrictqSur[6], restrictqdiSur[6];
47086ba6f09SLeila Ghaffari 
4717659d40cSLeila Ghaffari     for (CeedInt i=0; i<nFace; i++) {
4727659d40cSLeila Ghaffari       ierr = GetRestrictionForDomain(ceed, dm, height, domainLabel, i+1, numP_Sur,
473f259b054Svaleriabarra                                      numQ_Sur, qdatasizeSur, &restrictqSur[i],
474f259b054Svaleriabarra                                      &restrictxSur[i], &restrictqdiSur[i]);
475f259b054Svaleriabarra       CHKERRQ(ierr);
4767659d40cSLeila Ghaffari       // Create the CEED vectors that will be needed in Boundary setup
4777659d40cSLeila Ghaffari       CeedElemRestrictionGetNumElements(restrictqSur[i], &localNelemSur[i]);
478f259b054Svaleriabarra       CeedVectorCreate(ceed, qdatasizeSur*localNelemSur[i]*NqptsSur,
479f259b054Svaleriabarra                        &qdataSur[i]);
4807659d40cSLeila Ghaffari       // Create the operator that builds the quadrature data for the Boundary operator
4817659d40cSLeila Ghaffari       CeedOperatorCreate(ceed, qf_setupSur, NULL, NULL, &op_setupSur[i]);
482ebb4b9bdSLeila Ghaffari       CeedOperatorSetField(op_setupSur[i], "dx", restrictxSur[i], basisxSur,
483ebb4b9bdSLeila Ghaffari                            CEED_VECTOR_ACTIVE);
4847659d40cSLeila Ghaffari       CeedOperatorSetField(op_setupSur[i], "weight", CEED_ELEMRESTRICTION_NONE,
485ca3ac6ddSLeila Ghaffari                            basisxSur, CEED_VECTOR_NONE);
4867659d40cSLeila Ghaffari       CeedOperatorSetField(op_setupSur[i], "qdataSur", restrictqdiSur[i],
487ca3ac6ddSLeila Ghaffari                            CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
4887659d40cSLeila Ghaffari       // Create Boundary operator
4897659d40cSLeila Ghaffari       CeedOperatorCreate(ceed, qf_applySur, NULL, NULL, &op_applySur[i]);
490ebb4b9bdSLeila Ghaffari       CeedOperatorSetField(op_applySur[i], "q", restrictqSur[i], basisqSur,
491ebb4b9bdSLeila Ghaffari                            CEED_VECTOR_ACTIVE);
4927659d40cSLeila Ghaffari       CeedOperatorSetField(op_applySur[i], "qdataSur", restrictqdiSur[i],
4937659d40cSLeila Ghaffari                            CEED_BASIS_COLLOCATED, qdataSur[i]);
494f259b054Svaleriabarra       CeedOperatorSetField(op_applySur[i], "x", restrictxSur[i], basisxSur,
495f259b054Svaleriabarra                            xcorners);
496ebb4b9bdSLeila Ghaffari       CeedOperatorSetField(op_applySur[i], "v", restrictqSur[i], basisqSur,
497ebb4b9bdSLeila Ghaffari                            CEED_VECTOR_ACTIVE);
4987659d40cSLeila Ghaffari       // Apply CEED operator for Boundary setup
499ebb4b9bdSLeila Ghaffari       CeedOperatorApply(op_setupSur[i], xcorners, qdataSur[i],
500ebb4b9bdSLeila Ghaffari                         CEED_REQUEST_IMMEDIATE);
5014438636fSLeila Ghaffari       // --Apply Sub-Operator for the Boundary
5027659d40cSLeila Ghaffari       CeedCompositeOperatorAddSub(*op_apply, op_applySur[i]);
5039fe13df9SLeila Ghaffari     }
5041e150236SLeila Ghaffari     CeedVectorDestroy(&xcorners);
505ca3ac6ddSLeila Ghaffari   }
506ca3ac6ddSLeila Ghaffari   PetscFunctionReturn(0);
507ca3ac6ddSLeila Ghaffari }
508ca3ac6ddSLeila Ghaffari 
509ccaff030SJeremy L Thompson static int CreateVectorFromPetscVec(Ceed ceed, Vec p, CeedVector *v) {
510ccaff030SJeremy L Thompson   PetscErrorCode ierr;
511ccaff030SJeremy L Thompson   PetscInt m;
512ccaff030SJeremy L Thompson 
513ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
514ccaff030SJeremy L Thompson   ierr = VecGetLocalSize(p, &m); CHKERRQ(ierr);
515ccaff030SJeremy L Thompson   ierr = CeedVectorCreate(ceed, m, v); CHKERRQ(ierr);
516ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
517ccaff030SJeremy L Thompson }
518ccaff030SJeremy L Thompson 
519ccaff030SJeremy L Thompson static int VectorPlacePetscVec(CeedVector c, Vec p) {
520ccaff030SJeremy L Thompson   PetscErrorCode ierr;
521ccaff030SJeremy L Thompson   PetscInt mceed, mpetsc;
522ccaff030SJeremy L Thompson   PetscScalar *a;
523ccaff030SJeremy L Thompson 
524ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
525ccaff030SJeremy L Thompson   ierr = CeedVectorGetLength(c, &mceed); CHKERRQ(ierr);
526ccaff030SJeremy L Thompson   ierr = VecGetLocalSize(p, &mpetsc); CHKERRQ(ierr);
527ccaff030SJeremy L Thompson   if (mceed != mpetsc) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
52884d34d69SLeila Ghaffari                                   "Cannot place PETSc Vec of length %D in CeedVector of length %D",
52984d34d69SLeila Ghaffari                                   mpetsc, mceed);
530ccaff030SJeremy L Thompson   ierr = VecGetArray(p, &a); CHKERRQ(ierr);
531ccaff030SJeremy L Thompson   CeedVectorSetArray(c, CEED_MEM_HOST, CEED_USE_POINTER, a);
532ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
533ccaff030SJeremy L Thompson }
534ccaff030SJeremy L Thompson 
535ccaff030SJeremy L Thompson static PetscErrorCode DMPlexInsertBoundaryValues_NS(DM dm,
536ccaff030SJeremy L Thompson     PetscBool insertEssential, Vec Qloc, PetscReal time, Vec faceGeomFVM,
537ccaff030SJeremy L Thompson     Vec cellGeomFVM, Vec gradFVM) {
538ccaff030SJeremy L Thompson   PetscErrorCode ierr;
539ccaff030SJeremy L Thompson   Vec Qbc;
540ccaff030SJeremy L Thompson 
541ccaff030SJeremy L Thompson   PetscFunctionBegin;
542ccaff030SJeremy L Thompson   ierr = DMGetNamedLocalVector(dm, "Qbc", &Qbc); CHKERRQ(ierr);
543ccaff030SJeremy L Thompson   ierr = VecAXPY(Qloc, 1., Qbc); CHKERRQ(ierr);
544ccaff030SJeremy L Thompson   ierr = DMRestoreNamedLocalVector(dm, "Qbc", &Qbc); CHKERRQ(ierr);
545ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
546ccaff030SJeremy L Thompson }
547ccaff030SJeremy L Thompson 
548ccaff030SJeremy L Thompson // This is the RHS of the ODE, given as u_t = G(t,u)
549ccaff030SJeremy L Thompson // This function takes in a state vector Q and writes into G
550ccaff030SJeremy L Thompson static PetscErrorCode RHS_NS(TS ts, PetscReal t, Vec Q, Vec G, void *userData) {
551ccaff030SJeremy L Thompson   PetscErrorCode ierr;
552ccaff030SJeremy L Thompson   User user = *(User *)userData;
553ccaff030SJeremy L Thompson   PetscScalar *q, *g;
554ccaff030SJeremy L Thompson   Vec Qloc, Gloc;
555ccaff030SJeremy L Thompson 
556ccaff030SJeremy L Thompson   // Global-to-local
557ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
5585bf10c6fSLeila Ghaffari   user->ctxEulerData->currentTime = t;
559ccaff030SJeremy L Thompson   ierr = DMGetLocalVector(user->dm, &Qloc); CHKERRQ(ierr);
560ccaff030SJeremy L Thompson   ierr = DMGetLocalVector(user->dm, &Gloc); CHKERRQ(ierr);
561ccaff030SJeremy L Thompson   ierr = VecZeroEntries(Qloc); CHKERRQ(ierr);
562ccaff030SJeremy L Thompson   ierr = DMGlobalToLocal(user->dm, Q, INSERT_VALUES, Qloc); CHKERRQ(ierr);
563ccaff030SJeremy L Thompson   ierr = DMPlexInsertBoundaryValues(user->dm, PETSC_TRUE, Qloc, 0.0,
564ccaff030SJeremy L Thompson                                     NULL, NULL, NULL); CHKERRQ(ierr);
565ccaff030SJeremy L Thompson   ierr = VecZeroEntries(Gloc); CHKERRQ(ierr);
566ccaff030SJeremy L Thompson 
567ccaff030SJeremy L Thompson   // Ceed Vectors
568ccaff030SJeremy L Thompson   ierr = VecGetArrayRead(Qloc, (const PetscScalar **)&q); CHKERRQ(ierr);
569ccaff030SJeremy L Thompson   ierr = VecGetArray(Gloc, &g); CHKERRQ(ierr);
570ccaff030SJeremy L Thompson   CeedVectorSetArray(user->qceed, CEED_MEM_HOST, CEED_USE_POINTER, q);
571ccaff030SJeremy L Thompson   CeedVectorSetArray(user->gceed, CEED_MEM_HOST, CEED_USE_POINTER, g);
572ccaff030SJeremy L Thompson 
573ccaff030SJeremy L Thompson   // Apply CEED operator
574ccaff030SJeremy L Thompson   CeedOperatorApply(user->op_rhs, user->qceed, user->gceed,
575ccaff030SJeremy L Thompson                     CEED_REQUEST_IMMEDIATE);
576ccaff030SJeremy L Thompson 
577ccaff030SJeremy L Thompson   // Restore vectors
578ccaff030SJeremy L Thompson   ierr = VecRestoreArrayRead(Qloc, (const PetscScalar **)&q); CHKERRQ(ierr);
579ccaff030SJeremy L Thompson   ierr = VecRestoreArray(Gloc, &g); CHKERRQ(ierr);
580ccaff030SJeremy L Thompson 
581ccaff030SJeremy L Thompson   ierr = VecZeroEntries(G); CHKERRQ(ierr);
582ccaff030SJeremy L Thompson   ierr = DMLocalToGlobal(user->dm, Gloc, ADD_VALUES, G); CHKERRQ(ierr);
583ccaff030SJeremy L Thompson 
584ccaff030SJeremy L Thompson   // Inverse of the lumped mass matrix
585ccaff030SJeremy L Thompson   ierr = VecPointwiseMult(G, G, user->M); // M is Minv
586ccaff030SJeremy L Thompson   CHKERRQ(ierr);
587ccaff030SJeremy L Thompson 
588ccaff030SJeremy L Thompson   ierr = DMRestoreLocalVector(user->dm, &Qloc); CHKERRQ(ierr);
589ccaff030SJeremy L Thompson   ierr = DMRestoreLocalVector(user->dm, &Gloc); CHKERRQ(ierr);
590ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
591ccaff030SJeremy L Thompson }
592ccaff030SJeremy L Thompson 
593ccaff030SJeremy L Thompson static PetscErrorCode IFunction_NS(TS ts, PetscReal t, Vec Q, Vec Qdot, Vec G,
594ccaff030SJeremy L Thompson                                    void *userData) {
595ccaff030SJeremy L Thompson   PetscErrorCode ierr;
596ccaff030SJeremy L Thompson   User user = *(User *)userData;
597ccaff030SJeremy L Thompson   const PetscScalar *q, *qdot;
598ccaff030SJeremy L Thompson   PetscScalar *g;
599ccaff030SJeremy L Thompson   Vec Qloc, Qdotloc, Gloc;
600ccaff030SJeremy L Thompson 
601ccaff030SJeremy L Thompson   // Global-to-local
602ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
603ccaff030SJeremy L Thompson   ierr = DMGetLocalVector(user->dm, &Qloc); CHKERRQ(ierr);
604ccaff030SJeremy L Thompson   ierr = DMGetLocalVector(user->dm, &Qdotloc); CHKERRQ(ierr);
605ccaff030SJeremy L Thompson   ierr = DMGetLocalVector(user->dm, &Gloc); CHKERRQ(ierr);
606ccaff030SJeremy L Thompson   ierr = VecZeroEntries(Qloc); CHKERRQ(ierr);
607ccaff030SJeremy L Thompson   ierr = DMGlobalToLocal(user->dm, Q, INSERT_VALUES, Qloc); CHKERRQ(ierr);
608ccaff030SJeremy L Thompson   ierr = DMPlexInsertBoundaryValues(user->dm, PETSC_TRUE, Qloc, 0.0,
609ccaff030SJeremy L Thompson                                     NULL, NULL, NULL); CHKERRQ(ierr);
610ccaff030SJeremy L Thompson   ierr = VecZeroEntries(Qdotloc); CHKERRQ(ierr);
611ccaff030SJeremy L Thompson   ierr = DMGlobalToLocal(user->dm, Qdot, INSERT_VALUES, Qdotloc); CHKERRQ(ierr);
612ccaff030SJeremy L Thompson   ierr = VecZeroEntries(Gloc); CHKERRQ(ierr);
613ccaff030SJeremy L Thompson 
614ccaff030SJeremy L Thompson   // Ceed Vectors
615ccaff030SJeremy L Thompson   ierr = VecGetArrayRead(Qloc, &q); CHKERRQ(ierr);
616ccaff030SJeremy L Thompson   ierr = VecGetArrayRead(Qdotloc, &qdot); CHKERRQ(ierr);
617ccaff030SJeremy L Thompson   ierr = VecGetArray(Gloc, &g); CHKERRQ(ierr);
618ccaff030SJeremy L Thompson   CeedVectorSetArray(user->qceed, CEED_MEM_HOST, CEED_USE_POINTER,
619ccaff030SJeremy L Thompson                      (PetscScalar *)q);
620ccaff030SJeremy L Thompson   CeedVectorSetArray(user->qdotceed, CEED_MEM_HOST, CEED_USE_POINTER,
621ccaff030SJeremy L Thompson                      (PetscScalar *)qdot);
622ccaff030SJeremy L Thompson   CeedVectorSetArray(user->gceed, CEED_MEM_HOST, CEED_USE_POINTER, g);
623ccaff030SJeremy L Thompson 
624ccaff030SJeremy L Thompson   // Apply CEED operator
625ccaff030SJeremy L Thompson   CeedOperatorApply(user->op_ifunction, user->qceed, user->gceed,
626ccaff030SJeremy L Thompson                     CEED_REQUEST_IMMEDIATE);
627ccaff030SJeremy L Thompson 
628ccaff030SJeremy L Thompson   // Restore vectors
629ccaff030SJeremy L Thompson   ierr = VecRestoreArrayRead(Qloc, &q); CHKERRQ(ierr);
630ccaff030SJeremy L Thompson   ierr = VecRestoreArrayRead(Qdotloc, &qdot); CHKERRQ(ierr);
631ccaff030SJeremy L Thompson   ierr = VecRestoreArray(Gloc, &g); CHKERRQ(ierr);
632ccaff030SJeremy L Thompson 
633ccaff030SJeremy L Thompson   ierr = VecZeroEntries(G); CHKERRQ(ierr);
634ccaff030SJeremy L Thompson   ierr = DMLocalToGlobal(user->dm, Gloc, ADD_VALUES, G); CHKERRQ(ierr);
635ccaff030SJeremy L Thompson 
636ccaff030SJeremy L Thompson   ierr = DMRestoreLocalVector(user->dm, &Qloc); CHKERRQ(ierr);
637ccaff030SJeremy L Thompson   ierr = DMRestoreLocalVector(user->dm, &Qdotloc); CHKERRQ(ierr);
638ccaff030SJeremy L Thompson   ierr = DMRestoreLocalVector(user->dm, &Gloc); CHKERRQ(ierr);
639ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
640ccaff030SJeremy L Thompson }
641ccaff030SJeremy L Thompson 
642ccaff030SJeremy L Thompson // User provided TS Monitor
643ccaff030SJeremy L Thompson static PetscErrorCode TSMonitor_NS(TS ts, PetscInt stepno, PetscReal time,
644ccaff030SJeremy L Thompson                                    Vec Q, void *ctx) {
645ccaff030SJeremy L Thompson   User user = ctx;
646ccaff030SJeremy L Thompson   Vec Qloc;
647ccaff030SJeremy L Thompson   char filepath[PETSC_MAX_PATH_LEN];
648ccaff030SJeremy L Thompson   PetscViewer viewer;
649ccaff030SJeremy L Thompson   PetscErrorCode ierr;
650ccaff030SJeremy L Thompson 
651ccaff030SJeremy L Thompson   // Set up output
652ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
653ccaff030SJeremy L Thompson   // Print every 'outputfreq' steps
654ccaff030SJeremy L Thompson   if (stepno % user->outputfreq != 0)
655ccaff030SJeremy L Thompson     PetscFunctionReturn(0);
656ccaff030SJeremy L Thompson   ierr = DMGetLocalVector(user->dm, &Qloc); CHKERRQ(ierr);
657ccaff030SJeremy L Thompson   ierr = PetscObjectSetName((PetscObject)Qloc, "StateVec"); CHKERRQ(ierr);
658ccaff030SJeremy L Thompson   ierr = VecZeroEntries(Qloc); CHKERRQ(ierr);
659ccaff030SJeremy L Thompson   ierr = DMGlobalToLocal(user->dm, Q, INSERT_VALUES, Qloc); CHKERRQ(ierr);
660ccaff030SJeremy L Thompson 
661ccaff030SJeremy L Thompson   // Output
662ccaff030SJeremy L Thompson   ierr = PetscSNPrintf(filepath, sizeof filepath, "%s/ns-%03D.vtu",
663d99129b9SLeila Ghaffari                        user->outputdir, stepno + user->contsteps);
664ccaff030SJeremy L Thompson   CHKERRQ(ierr);
665ccaff030SJeremy L Thompson   ierr = PetscViewerVTKOpen(PetscObjectComm((PetscObject)Q), filepath,
666ccaff030SJeremy L Thompson                             FILE_MODE_WRITE, &viewer); CHKERRQ(ierr);
667ccaff030SJeremy L Thompson   ierr = VecView(Qloc, viewer); CHKERRQ(ierr);
6689d801c56SJed Brown   ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
669ccaff030SJeremy L Thompson   if (user->dmviz) {
670ccaff030SJeremy L Thompson     Vec Qrefined, Qrefined_loc;
671ccaff030SJeremy L Thompson     char filepath_refined[PETSC_MAX_PATH_LEN];
672ccaff030SJeremy L Thompson     PetscViewer viewer_refined;
673ccaff030SJeremy L Thompson 
674ccaff030SJeremy L Thompson     ierr = DMGetGlobalVector(user->dmviz, &Qrefined); CHKERRQ(ierr);
675ccaff030SJeremy L Thompson     ierr = DMGetLocalVector(user->dmviz, &Qrefined_loc); CHKERRQ(ierr);
676ccaff030SJeremy L Thompson     ierr = PetscObjectSetName((PetscObject)Qrefined_loc, "Refined");
677ccaff030SJeremy L Thompson     CHKERRQ(ierr);
678ccaff030SJeremy L Thompson     ierr = MatInterpolate(user->interpviz, Q, Qrefined); CHKERRQ(ierr);
679ccaff030SJeremy L Thompson     ierr = VecZeroEntries(Qrefined_loc); CHKERRQ(ierr);
680ccaff030SJeremy L Thompson     ierr = DMGlobalToLocal(user->dmviz, Qrefined, INSERT_VALUES, Qrefined_loc);
681ccaff030SJeremy L Thompson     CHKERRQ(ierr);
682ccaff030SJeremy L Thompson     ierr = PetscSNPrintf(filepath_refined, sizeof filepath_refined,
683ccaff030SJeremy L Thompson                          "%s/nsrefined-%03D.vtu",
684d99129b9SLeila Ghaffari                          user->outputdir, stepno + user->contsteps);
685ccaff030SJeremy L Thompson     CHKERRQ(ierr);
686ccaff030SJeremy L Thompson     ierr = PetscViewerVTKOpen(PetscObjectComm((PetscObject)Qrefined),
687ccaff030SJeremy L Thompson                               filepath_refined,
688ccaff030SJeremy L Thompson                               FILE_MODE_WRITE, &viewer_refined); CHKERRQ(ierr);
689ccaff030SJeremy L Thompson     ierr = VecView(Qrefined_loc, viewer_refined); CHKERRQ(ierr);
690ccaff030SJeremy L Thompson     ierr = DMRestoreLocalVector(user->dmviz, &Qrefined_loc); CHKERRQ(ierr);
691ccaff030SJeremy L Thompson     ierr = DMRestoreGlobalVector(user->dmviz, &Qrefined); CHKERRQ(ierr);
692ccaff030SJeremy L Thompson     ierr = PetscViewerDestroy(&viewer_refined); CHKERRQ(ierr);
693ccaff030SJeremy L Thompson   }
694ccaff030SJeremy L Thompson   ierr = DMRestoreLocalVector(user->dm, &Qloc); CHKERRQ(ierr);
695ccaff030SJeremy L Thompson 
696ccaff030SJeremy L Thompson   // Save data in a binary file for continuation of simulations
697ccaff030SJeremy L Thompson   ierr = PetscSNPrintf(filepath, sizeof filepath, "%s/ns-solution.bin",
698d99129b9SLeila Ghaffari                        user->outputdir); CHKERRQ(ierr);
699ccaff030SJeremy L Thompson   ierr = PetscViewerBinaryOpen(user->comm, filepath, FILE_MODE_WRITE, &viewer);
700ccaff030SJeremy L Thompson   CHKERRQ(ierr);
701ccaff030SJeremy L Thompson   ierr = VecView(Q, viewer); CHKERRQ(ierr);
702ccaff030SJeremy L Thompson   ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
703ccaff030SJeremy L Thompson 
704ccaff030SJeremy L Thompson   // Save time stamp
705ccaff030SJeremy L Thompson   // Dimensionalize time back
706ccaff030SJeremy L Thompson   time /= user->units->second;
707ccaff030SJeremy L Thompson   ierr = PetscSNPrintf(filepath, sizeof filepath, "%s/ns-time.bin",
708d99129b9SLeila Ghaffari                        user->outputdir); CHKERRQ(ierr);
709ccaff030SJeremy L Thompson   ierr = PetscViewerBinaryOpen(user->comm, filepath, FILE_MODE_WRITE, &viewer);
710ccaff030SJeremy L Thompson   CHKERRQ(ierr);
711ccaff030SJeremy L Thompson   #if PETSC_VERSION_GE(3,13,0)
712ccaff030SJeremy L Thompson   ierr = PetscViewerBinaryWrite(viewer, &time, 1, PETSC_REAL);
713ccaff030SJeremy L Thompson   #else
714ccaff030SJeremy L Thompson   ierr = PetscViewerBinaryWrite(viewer, &time, 1, PETSC_REAL, true);
715ccaff030SJeremy L Thompson   #endif
716ccaff030SJeremy L Thompson   CHKERRQ(ierr);
717ccaff030SJeremy L Thompson   ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
718ccaff030SJeremy L Thompson 
719ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
720ccaff030SJeremy L Thompson }
721ccaff030SJeremy L Thompson 
72284d34d69SLeila Ghaffari static PetscErrorCode ICs_FixMultiplicity(CeedOperator op_ics,
723ccaff030SJeremy L Thompson     CeedVector xcorners, CeedVector q0ceed, DM dm, Vec Qloc, Vec Q,
724777ff853SJeremy L Thompson     CeedElemRestriction restrictq, CeedQFunctionContext ctxSetup, CeedScalar time) {
725ccaff030SJeremy L Thompson   PetscErrorCode ierr;
726ccaff030SJeremy L Thompson   CeedVector multlvec;
727ccaff030SJeremy L Thompson   Vec Multiplicity, MultiplicityLoc;
728ccaff030SJeremy L Thompson 
729777ff853SJeremy L Thompson   SetupContext ctxSetupData;
730777ff853SJeremy L Thompson   CeedQFunctionContextGetData(ctxSetup, CEED_MEM_HOST, (void **)&ctxSetupData);
731777ff853SJeremy L Thompson   ctxSetupData->time = time;
732777ff853SJeremy L Thompson   CeedQFunctionContextRestoreData(ctxSetup, (void **)&ctxSetupData);
733777ff853SJeremy L Thompson 
734ccaff030SJeremy L Thompson   ierr = VecZeroEntries(Qloc); CHKERRQ(ierr);
735ccaff030SJeremy L Thompson   ierr = VectorPlacePetscVec(q0ceed, Qloc); CHKERRQ(ierr);
736ccaff030SJeremy L Thompson   CeedOperatorApply(op_ics, xcorners, q0ceed, CEED_REQUEST_IMMEDIATE);
737ccaff030SJeremy L Thompson   ierr = VecZeroEntries(Q); CHKERRQ(ierr);
738ccaff030SJeremy L Thompson   ierr = DMLocalToGlobal(dm, Qloc, ADD_VALUES, Q); CHKERRQ(ierr);
739ccaff030SJeremy L Thompson 
740ccaff030SJeremy L Thompson   // Fix multiplicity for output of ICs
741ccaff030SJeremy L Thompson   ierr = DMGetLocalVector(dm, &MultiplicityLoc); CHKERRQ(ierr);
742ccaff030SJeremy L Thompson   CeedElemRestrictionCreateVector(restrictq, &multlvec, NULL);
743ccaff030SJeremy L Thompson   ierr = VectorPlacePetscVec(multlvec, MultiplicityLoc); CHKERRQ(ierr);
744ccaff030SJeremy L Thompson   CeedElemRestrictionGetMultiplicity(restrictq, multlvec);
745ccaff030SJeremy L Thompson   CeedVectorDestroy(&multlvec);
746ccaff030SJeremy L Thompson   ierr = DMGetGlobalVector(dm, &Multiplicity); CHKERRQ(ierr);
747ccaff030SJeremy L Thompson   ierr = VecZeroEntries(Multiplicity); CHKERRQ(ierr);
748ccaff030SJeremy L Thompson   ierr = DMLocalToGlobal(dm, MultiplicityLoc, ADD_VALUES, Multiplicity);
749ccaff030SJeremy L Thompson   CHKERRQ(ierr);
750ccaff030SJeremy L Thompson   ierr = VecPointwiseDivide(Q, Q, Multiplicity); CHKERRQ(ierr);
751ccaff030SJeremy L Thompson   ierr = VecPointwiseDivide(Qloc, Qloc, MultiplicityLoc); CHKERRQ(ierr);
752ccaff030SJeremy L Thompson   ierr = DMRestoreLocalVector(dm, &MultiplicityLoc); CHKERRQ(ierr);
753ccaff030SJeremy L Thompson   ierr = DMRestoreGlobalVector(dm, &Multiplicity); CHKERRQ(ierr);
754ccaff030SJeremy L Thompson 
755ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
756ccaff030SJeremy L Thompson }
757ccaff030SJeremy L Thompson 
758ccaff030SJeremy L Thompson static PetscErrorCode ComputeLumpedMassMatrix(Ceed ceed, DM dm,
759ccaff030SJeremy L Thompson     CeedElemRestriction restrictq, CeedBasis basisq,
760ccaff030SJeremy L Thompson     CeedElemRestriction restrictqdi, CeedVector qdata, Vec M) {
761ccaff030SJeremy L Thompson   PetscErrorCode ierr;
762ccaff030SJeremy L Thompson   CeedQFunction qf_mass;
763ccaff030SJeremy L Thompson   CeedOperator op_mass;
764ccaff030SJeremy L Thompson   CeedVector mceed;
765ccaff030SJeremy L Thompson   Vec Mloc;
766ccaff030SJeremy L Thompson   CeedInt ncompq, qdatasize;
767ccaff030SJeremy L Thompson 
768ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
769ccaff030SJeremy L Thompson   CeedElemRestrictionGetNumComponents(restrictq, &ncompq);
770ccaff030SJeremy L Thompson   CeedElemRestrictionGetNumComponents(restrictqdi, &qdatasize);
771ccaff030SJeremy L Thompson   // Create the Q-function that defines the action of the mass operator
772ccaff030SJeremy L Thompson   CeedQFunctionCreateInterior(ceed, 1, Mass, Mass_loc, &qf_mass);
773ccaff030SJeremy L Thompson   CeedQFunctionAddInput(qf_mass, "q", ncompq, CEED_EVAL_INTERP);
774ccaff030SJeremy L Thompson   CeedQFunctionAddInput(qf_mass, "qdata", qdatasize, CEED_EVAL_NONE);
775ccaff030SJeremy L Thompson   CeedQFunctionAddOutput(qf_mass, "v", ncompq, CEED_EVAL_INTERP);
776ccaff030SJeremy L Thompson 
777ccaff030SJeremy L Thompson   // Create the mass operator
778ccaff030SJeremy L Thompson   CeedOperatorCreate(ceed, qf_mass, NULL, NULL, &op_mass);
779ccaff030SJeremy L Thompson   CeedOperatorSetField(op_mass, "q", restrictq, basisq, CEED_VECTOR_ACTIVE);
780ccaff030SJeremy L Thompson   CeedOperatorSetField(op_mass, "qdata", restrictqdi,
781ccaff030SJeremy L Thompson                        CEED_BASIS_COLLOCATED, qdata);
782ccaff030SJeremy L Thompson   CeedOperatorSetField(op_mass, "v", restrictq, basisq, CEED_VECTOR_ACTIVE);
783ccaff030SJeremy L Thompson 
784ccaff030SJeremy L Thompson   ierr = DMGetLocalVector(dm, &Mloc); CHKERRQ(ierr);
785ccaff030SJeremy L Thompson   ierr = VecZeroEntries(Mloc); CHKERRQ(ierr);
786ccaff030SJeremy L Thompson   CeedElemRestrictionCreateVector(restrictq, &mceed, NULL);
787ccaff030SJeremy L Thompson   ierr = VectorPlacePetscVec(mceed, Mloc); CHKERRQ(ierr);
788ccaff030SJeremy L Thompson 
789ccaff030SJeremy L Thompson   {
790ccaff030SJeremy L Thompson     // Compute a lumped mass matrix
791ccaff030SJeremy L Thompson     CeedVector onesvec;
792ccaff030SJeremy L Thompson     CeedElemRestrictionCreateVector(restrictq, &onesvec, NULL);
793ccaff030SJeremy L Thompson     CeedVectorSetValue(onesvec, 1.0);
794ccaff030SJeremy L Thompson     CeedOperatorApply(op_mass, onesvec, mceed, CEED_REQUEST_IMMEDIATE);
795ccaff030SJeremy L Thompson     CeedVectorDestroy(&onesvec);
796ccaff030SJeremy L Thompson     CeedOperatorDestroy(&op_mass);
797ccaff030SJeremy L Thompson     CeedVectorDestroy(&mceed);
798ccaff030SJeremy L Thompson   }
799ccaff030SJeremy L Thompson   CeedQFunctionDestroy(&qf_mass);
800ccaff030SJeremy L Thompson 
801ccaff030SJeremy L Thompson   ierr = VecZeroEntries(M); CHKERRQ(ierr);
802ccaff030SJeremy L Thompson   ierr = DMLocalToGlobal(dm, Mloc, ADD_VALUES, M); CHKERRQ(ierr);
803ccaff030SJeremy L Thompson   ierr = DMRestoreLocalVector(dm, &Mloc); CHKERRQ(ierr);
804ccaff030SJeremy L Thompson 
805ccaff030SJeremy L Thompson   // Invert diagonally lumped mass vector for RHS function
806ccaff030SJeremy L Thompson   ierr = VecReciprocal(M); CHKERRQ(ierr);
807ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
808ccaff030SJeremy L Thompson }
809ccaff030SJeremy L Thompson 
81084d34d69SLeila Ghaffari static PetscErrorCode SetUpDM(DM dm, problemData *problem, PetscInt degree,
8115bf10c6fSLeila Ghaffari                               SimpleBC bc, void *ctxSetupData, void *ctxMMS) {
812ccaff030SJeremy L Thompson   PetscErrorCode ierr;
813ccaff030SJeremy L Thompson 
814ccaff030SJeremy L Thompson   PetscFunctionBeginUser;
815ccaff030SJeremy L Thompson   {
816ccaff030SJeremy L Thompson     // Configure the finite element space and boundary conditions
817ccaff030SJeremy L Thompson     PetscFE fe;
818ccaff030SJeremy L Thompson     PetscInt ncompq = 5;
819ff6701fcSJed Brown     ierr = PetscFECreateLagrange(PETSC_COMM_SELF, problem->dim, ncompq,
820ff6701fcSJed Brown                                  PETSC_FALSE, degree, PETSC_DECIDE,
82132ed2d11SJed Brown                                  &fe); CHKERRQ(ierr);
822ccaff030SJeremy L Thompson     ierr = PetscObjectSetName((PetscObject)fe, "Q"); CHKERRQ(ierr);
823ccaff030SJeremy L Thompson     ierr = DMAddField(dm, NULL,(PetscObject)fe); CHKERRQ(ierr);
824ccaff030SJeremy L Thompson     ierr = DMCreateDS(dm); CHKERRQ(ierr);
8253d6e121fSLeila Ghaffari     // Turn off slip and wall BCs for EULER_VORTEX
8263d6e121fSLeila Ghaffari     if (problem->bc == Exact_Euler)
8273d6e121fSLeila Ghaffari       bc->nwall = bc->nslip[0] = bc->nslip[1] = 0;
82807af6069Svaleriabarra     {
82907af6069Svaleriabarra       PetscInt comps[1] = {1};
83007af6069Svaleriabarra       ierr = DMAddBoundary(dm, DM_BC_ESSENTIAL, "slipx", "Face Sets", 0,
8313ab4fca6SValeria Barra                            1, comps, (void(*)(void))NULL, NULL, bc->nslip[0],
832777ff853SJeremy L Thompson                            bc->slips[0], ctxSetupData); CHKERRQ(ierr);
83307af6069Svaleriabarra       comps[0] = 2;
83407af6069Svaleriabarra       ierr = DMAddBoundary(dm, DM_BC_ESSENTIAL, "slipy", "Face Sets", 0,
8353ab4fca6SValeria Barra                            1, comps, (void(*)(void))NULL, NULL, bc->nslip[1],
836777ff853SJeremy L Thompson                            bc->slips[1], ctxSetupData); CHKERRQ(ierr);
83707af6069Svaleriabarra       comps[0] = 3;
83807af6069Svaleriabarra       ierr = DMAddBoundary(dm, DM_BC_ESSENTIAL, "slipz", "Face Sets", 0,
8393ab4fca6SValeria Barra                            1, comps, (void(*)(void))NULL, NULL, bc->nslip[2],
840777ff853SJeremy L Thompson                            bc->slips[2], ctxSetupData); CHKERRQ(ierr);
84107af6069Svaleriabarra     }
84284d34d69SLeila Ghaffari     if (bc->userbc == PETSC_TRUE) {
84384d34d69SLeila Ghaffari       for (PetscInt c = 0; c < 3; c++) {
84484d34d69SLeila Ghaffari         for (PetscInt s = 0; s < bc->nslip[c]; s++) {
84584d34d69SLeila Ghaffari           for (PetscInt w = 0; w < bc->nwall; w++) {
84684d34d69SLeila Ghaffari             if (bc->slips[c][s] == bc->walls[w])
84784d34d69SLeila Ghaffari               SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
848f259b054Svaleriabarra                        "Boundary condition already set on face %D!\n",
849f259b054Svaleriabarra                        bc->walls[w]);
85084d34d69SLeila Ghaffari           }
85184d34d69SLeila Ghaffari         }
85284d34d69SLeila Ghaffari       }
85384d34d69SLeila Ghaffari     }
85484d34d69SLeila Ghaffari     // Wall boundary conditions are zero energy density and zero flux for
85584d34d69SLeila Ghaffari     //   velocity in advection/advection2d, and zero velocity and zero flux
85684d34d69SLeila Ghaffari     //   for mass density and energy density in density_current
85784d34d69SLeila Ghaffari     {
85884d34d69SLeila Ghaffari       if (problem->bc == Exact_Advection || problem->bc == Exact_Advection2d) {
85984d34d69SLeila Ghaffari         PetscInt comps[1] = {4};
86084d34d69SLeila Ghaffari         ierr = DMAddBoundary(dm, DM_BC_ESSENTIAL, "wall", "Face Sets", 0,
8613ab4fca6SValeria Barra                              1, comps, (void(*)(void))problem->bc, NULL,
8620da62991SLeila Ghaffari                              bc->nwall, bc->walls, ctxSetupData); CHKERRQ(ierr);
863753d00aaSLeila Ghaffari       } else if (problem->bc == Exact_DC) {
86484d34d69SLeila Ghaffari         PetscInt comps[3] = {1, 2, 3};
86584d34d69SLeila Ghaffari         ierr = DMAddBoundary(dm, DM_BC_ESSENTIAL, "wall", "Face Sets", 0,
8663ab4fca6SValeria Barra                              3, comps, (void(*)(void))problem->bc, NULL,
867777ff853SJeremy L Thompson                              bc->nwall, bc->walls, ctxSetupData); CHKERRQ(ierr);
868753d00aaSLeila Ghaffari       } else if (problem->bc == Exact_Euler) {
8693d6e121fSLeila Ghaffari         // So far nwall=0 but we keep this support for
8702affbe43SLeila Ghaffari         //   the time when we add periodic BCs
8714a452432SLeila Ghaffari         PetscInt comps[3] = {1, 2, 3};
8724a452432SLeila Ghaffari         ierr = DMAddBoundary(dm, DM_BC_ESSENTIAL, "wall", "Face Sets", 0,
8734a452432SLeila Ghaffari                              3, comps, (void(*)(void))problem->bc, NULL,
8744a452432SLeila Ghaffari                              bc->nwall, bc->walls, ctxMMS); CHKERRQ(ierr);
87584d34d69SLeila Ghaffari       } else
87684d34d69SLeila Ghaffari         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
87784d34d69SLeila Ghaffari                 "Undefined boundary conditions for this problem");
87884d34d69SLeila Ghaffari     }
879ccaff030SJeremy L Thompson     ierr = DMPlexSetClosurePermutationTensor(dm, PETSC_DETERMINE, NULL);
880ccaff030SJeremy L Thompson     CHKERRQ(ierr);
881ccaff030SJeremy L Thompson     ierr = PetscFEDestroy(&fe); CHKERRQ(ierr);
882ccaff030SJeremy L Thompson   }
883ccaff030SJeremy L Thompson   {
884ccaff030SJeremy L Thompson     // Empty name for conserved field (because there is only one field)
885ccaff030SJeremy L Thompson     PetscSection section;
886ccaff030SJeremy L Thompson     ierr = DMGetLocalSection(dm, &section); CHKERRQ(ierr);
887ccaff030SJeremy L Thompson     ierr = PetscSectionSetFieldName(section, 0, ""); CHKERRQ(ierr);
888ccaff030SJeremy L Thompson     ierr = PetscSectionSetComponentName(section, 0, 0, "Density");
889ccaff030SJeremy L Thompson     CHKERRQ(ierr);
890ccaff030SJeremy L Thompson     ierr = PetscSectionSetComponentName(section, 0, 1, "MomentumX");
891ccaff030SJeremy L Thompson     CHKERRQ(ierr);
892ccaff030SJeremy L Thompson     ierr = PetscSectionSetComponentName(section, 0, 2, "MomentumY");
893ccaff030SJeremy L Thompson     CHKERRQ(ierr);
894ccaff030SJeremy L Thompson     ierr = PetscSectionSetComponentName(section, 0, 3, "MomentumZ");
895ccaff030SJeremy L Thompson     CHKERRQ(ierr);
896ccaff030SJeremy L Thompson     ierr = PetscSectionSetComponentName(section, 0, 4, "EnergyDensity");
897ccaff030SJeremy L Thompson     CHKERRQ(ierr);
898ccaff030SJeremy L Thompson   }
899ccaff030SJeremy L Thompson   PetscFunctionReturn(0);
900ccaff030SJeremy L Thompson }
901ccaff030SJeremy L Thompson 
902ccaff030SJeremy L Thompson int main(int argc, char **argv) {
903ccaff030SJeremy L Thompson   PetscInt ierr;
904ccaff030SJeremy L Thompson   MPI_Comm comm;
90584d34d69SLeila Ghaffari   DM dm, dmcoord, dmviz;
906ccaff030SJeremy L Thompson   Mat interpviz;
907ccaff030SJeremy L Thompson   TS ts;
908ccaff030SJeremy L Thompson   TSAdapt adapt;
909ccaff030SJeremy L Thompson   User user;
910ccaff030SJeremy L Thompson   Units units;
9115bf10c6fSLeila Ghaffari   EulerContext ctxEulerData;
912ccaff030SJeremy L Thompson   char ceedresource[4096] = "/cpu/self";
91384d34d69SLeila Ghaffari   PetscInt localNelemVol, lnodes, gnodes, steps;
914ccaff030SJeremy L Thompson   const PetscInt ncompq = 5;
915ccaff030SJeremy L Thompson   PetscMPIInt rank;
916ccaff030SJeremy L Thompson   PetscScalar ftime;
917ccaff030SJeremy L Thompson   Vec Q, Qloc, Xloc;
918ccaff030SJeremy L Thompson   Ceed ceed;
91984d34d69SLeila Ghaffari   CeedInt numP, numQ;
920cfa64770SLeila Ghaffari   CeedVector xcorners, qdata, q0ceed;
92184d34d69SLeila Ghaffari   CeedBasis basisx, basisxc, basisq;
92284d34d69SLeila Ghaffari   CeedElemRestriction restrictx, restrictq, restrictqdi;
923cfa64770SLeila Ghaffari   CeedQFunction qf_setupVol, qf_ics, qf_rhsVol, qf_ifunctionVol;
9245bf10c6fSLeila Ghaffari   CeedQFunctionContext ctxSetup, ctxNS, ctxAdvection2d, ctxSurface, ctxEuler;
925cfa64770SLeila Ghaffari   CeedOperator op_setupVol, op_ics;
926ccaff030SJeremy L Thompson   CeedScalar Rd;
92784d34d69SLeila Ghaffari   CeedMemType memtyperequested;
928ccaff030SJeremy L Thompson   PetscScalar WpermK, Pascal, JperkgK, mpersquareds, kgpercubicm,
92916c0476cSLeila Ghaffari               kgpersquaredms, Joulepercubicm, Joule;
930ccaff030SJeremy L Thompson   problemType problemChoice;
931ccaff030SJeremy L Thompson   problemData *problem = NULL;
9321184866aSLeila Ghaffari   WindType wind_type;
933ccaff030SJeremy L Thompson   StabilizationType stab;
934a3ddc43aSLeila Ghaffari   EulerTestType euler_test;
93584d34d69SLeila Ghaffari   PetscBool implicit;
936cb3e2689Svaleriabarra   PetscInt    viz_refine = 0;
937ccaff030SJeremy L Thompson   struct SimpleBC_ bc = {
93884d34d69SLeila Ghaffari     .nslip = {2, 2, 2},
93984d34d69SLeila Ghaffari     .slips = {{5, 6}, {3, 4}, {1, 2}}
940ccaff030SJeremy L Thompson   };
941ccaff030SJeremy L Thompson   double start, cpu_time_used;
942dc8efd83SLeila Ghaffari   // Test variables
943dc8efd83SLeila Ghaffari   PetscBool test;
944dc8efd83SLeila Ghaffari   PetscScalar testtol = 0.;
945dc8efd83SLeila Ghaffari   char filepath[PETSC_MAX_PATH_LEN];
94684d34d69SLeila Ghaffari   // Check PETSc CUDA support
94784d34d69SLeila Ghaffari   PetscBool petschavecuda, setmemtyperequest = PETSC_FALSE;
94884d34d69SLeila Ghaffari   // *INDENT-OFF*
94984d34d69SLeila Ghaffari   #ifdef PETSC_HAVE_CUDA
95084d34d69SLeila Ghaffari   petschavecuda = PETSC_TRUE;
95184d34d69SLeila Ghaffari   #else
95284d34d69SLeila Ghaffari   petschavecuda = PETSC_FALSE;
95384d34d69SLeila Ghaffari   #endif
95484d34d69SLeila Ghaffari   // *INDENT-ON*
955ccaff030SJeremy L Thompson 
956ccaff030SJeremy L Thompson   // Create the libCEED contexts
957ccaff030SJeremy L Thompson   PetscScalar meter          = 1e-2;     // 1 meter in scaled length units
958ccaff030SJeremy L Thompson   PetscScalar second         = 1e-2;     // 1 second in scaled time units
959ccaff030SJeremy L Thompson   PetscScalar kilogram       = 1e-6;     // 1 kilogram in scaled mass units
960ccaff030SJeremy L Thompson   PetscScalar Kelvin         = 1;        // 1 Kelvin in scaled temperature units
961ccaff030SJeremy L Thompson   CeedScalar theta0          = 300.;     // K
962ccaff030SJeremy L Thompson   CeedScalar thetaC          = -15.;     // K
963ccaff030SJeremy L Thompson   CeedScalar P0              = 1.e5;     // Pa
96416c0476cSLeila Ghaffari   CeedScalar E_wind          = 1.e6;     // J
965ccaff030SJeremy L Thompson   CeedScalar N               = 0.01;     // 1/s
966ccaff030SJeremy L Thompson   CeedScalar cv              = 717.;     // J/(kg K)
967ccaff030SJeremy L Thompson   CeedScalar cp              = 1004.;    // J/(kg K)
968011314a7SLeila Ghaffari   CeedScalar vortex_strength = 5.;       // -
96935e1ec25SLeila Ghaffari   CeedScalar T_inlet         = 1.;       // K
970c24ac85aSLeila Ghaffari   CeedScalar P_inlet         = 1.;       // Pa
971ccaff030SJeremy L Thompson   CeedScalar g               = 9.81;     // m/s^2
972ccaff030SJeremy L Thompson   CeedScalar lambda          = -2./3.;   // -
973ccaff030SJeremy L Thompson   CeedScalar mu              = 75.;      // Pa s, dynamic viscosity
974ccaff030SJeremy L Thompson   // mu = 75 is not physical for air, but is good for numerical stability
975ccaff030SJeremy L Thompson   CeedScalar k               = 0.02638;  // W/(m K)
976ccaff030SJeremy L Thompson   CeedScalar CtauS           = 0.;       // dimensionless
977ccaff030SJeremy L Thompson   CeedScalar strong_form     = 0.;       // [0,1]
978ccaff030SJeremy L Thompson   PetscScalar lx             = 8000.;    // m
979ccaff030SJeremy L Thompson   PetscScalar ly             = 8000.;    // m
980ccaff030SJeremy L Thompson   PetscScalar lz             = 4000.;    // m
981ccaff030SJeremy L Thompson   CeedScalar rc              = 1000.;    // m (Radius of bubble)
982ccaff030SJeremy L Thompson   PetscScalar resx           = 1000.;    // m (resolution in x)
983ccaff030SJeremy L Thompson   PetscScalar resy           = 1000.;    // m (resolution in y)
984ccaff030SJeremy L Thompson   PetscScalar resz           = 1000.;    // m (resolution in z)
985ccaff030SJeremy L Thompson   PetscInt outputfreq        = 10;       // -
986ccaff030SJeremy L Thompson   PetscInt contsteps         = 0;        // -
98784d34d69SLeila Ghaffari   PetscInt degree            = 1;        // -
98884d34d69SLeila Ghaffari   PetscInt qextra            = 2;        // -
989ea6e0f84SLeila Ghaffari   PetscInt qextraSur         = 2;        // -
990e8107fdaSLeila Ghaffari   PetscReal center[3], dc_axis[3] = {0, 0, 0}, wind[3] = {1., 0, 0},
9916bd16babSLeila Ghaffari                                     etv_mean_velocity[3] = {1., 1., 0};
992ccaff030SJeremy L Thompson   ierr = PetscInitialize(&argc, &argv, NULL, help);
993ccaff030SJeremy L Thompson   if (ierr) return ierr;
994ccaff030SJeremy L Thompson 
995ccaff030SJeremy L Thompson   // Allocate PETSc context
996ccaff030SJeremy L Thompson   ierr = PetscCalloc1(1, &user); CHKERRQ(ierr);
997ccaff030SJeremy L Thompson   ierr = PetscMalloc1(1, &units); CHKERRQ(ierr);
9985bf10c6fSLeila Ghaffari   ierr = PetscMalloc1(1, &ctxEulerData); CHKERRQ(ierr);
999ccaff030SJeremy L Thompson 
1000ccaff030SJeremy L Thompson   // Parse command line options
1001ccaff030SJeremy L Thompson   comm = PETSC_COMM_WORLD;
1002ccaff030SJeremy L Thompson   ierr = PetscOptionsBegin(comm, NULL, "Navier-Stokes in PETSc with libCEED",
1003ccaff030SJeremy L Thompson                            NULL); CHKERRQ(ierr);
1004ccaff030SJeremy L Thompson   ierr = PetscOptionsString("-ceed", "CEED resource specifier",
1005ccaff030SJeremy L Thompson                             NULL, ceedresource, ceedresource,
1006ccaff030SJeremy L Thompson                             sizeof(ceedresource), NULL); CHKERRQ(ierr);
1007dc8efd83SLeila Ghaffari   ierr = PetscOptionsBool("-test", "Run in test mode",
1008dc8efd83SLeila Ghaffari                           NULL, test=PETSC_FALSE, &test, NULL); CHKERRQ(ierr);
1009dc8efd83SLeila Ghaffari   ierr = PetscOptionsScalar("-compare_final_state_atol",
1010dc8efd83SLeila Ghaffari                             "Test absolute tolerance",
1011dc8efd83SLeila Ghaffari                             NULL, testtol, &testtol, NULL); CHKERRQ(ierr);
1012dc8efd83SLeila Ghaffari   ierr = PetscOptionsString("-compare_final_state_filename", "Test filename",
1013dc8efd83SLeila Ghaffari                             NULL, filepath, filepath,
1014dc8efd83SLeila Ghaffari                             sizeof(filepath), NULL); CHKERRQ(ierr);
1015ccaff030SJeremy L Thompson   problemChoice = NS_DENSITY_CURRENT;
1016ccaff030SJeremy L Thompson   ierr = PetscOptionsEnum("-problem", "Problem to solve", NULL,
1017ccaff030SJeremy L Thompson                           problemTypes, (PetscEnum)problemChoice,
1018ccaff030SJeremy L Thompson                           (PetscEnum *)&problemChoice, NULL); CHKERRQ(ierr);
1019ccaff030SJeremy L Thompson   problem = &problemOptions[problemChoice];
10201184866aSLeila Ghaffari   ierr = PetscOptionsEnum("-problem_advection_wind", "Wind type in Advection",
1021f259b054Svaleriabarra                           NULL, WindTypes,
1022f259b054Svaleriabarra                           (PetscEnum)(wind_type = ADVECTION_WIND_ROTATION),
10231184866aSLeila Ghaffari                           (PetscEnum *)&wind_type, NULL); CHKERRQ(ierr);
10241184866aSLeila Ghaffari   PetscInt n = problem->dim;
102582c09b01SLeila Ghaffari   PetscBool userWind;
1026ebb4b9bdSLeila Ghaffari   ierr = PetscOptionsRealArray("-problem_advection_wind_translation",
1027ebb4b9bdSLeila Ghaffari                                "Constant wind vector",
102882c09b01SLeila Ghaffari                                NULL, wind, &n, &userWind); CHKERRQ(ierr);
102982c09b01SLeila Ghaffari   if (wind_type == ADVECTION_WIND_ROTATION && userWind) {
1030ebb4b9bdSLeila Ghaffari     ierr = PetscPrintf(comm,
1031ebb4b9bdSLeila Ghaffari                        "Warning! Use -problem_advection_wind_translation only with -problem_advection_wind translation\n");
103282c09b01SLeila Ghaffari     CHKERRQ(ierr);
10331184866aSLeila Ghaffari   }
1034b9c3f7b3SLeila Ghaffari   if (wind_type == ADVECTION_WIND_TRANSLATION
1035b9c3f7b3SLeila Ghaffari       && (problemChoice == NS_DENSITY_CURRENT ||
1036b9c3f7b3SLeila Ghaffari           problemChoice == NS_EULER_VORTEX)) {
103767babd9cSLeila Ghaffari     SETERRQ(comm, PETSC_ERR_ARG_INCOMP,
1038b9c3f7b3SLeila Ghaffari             "-problem_advection_wind translation is not defined for -problem density_current or -problem euler_vortex");
103967babd9cSLeila Ghaffari   }
10400975b6e1SLeila Ghaffari   n = problem->dim;
1041e8107fdaSLeila Ghaffari   ierr = PetscOptionsRealArray("-problem_euler_mean_velocity",
1042e8107fdaSLeila Ghaffari                                "Mean velocity vector",
1043e8107fdaSLeila Ghaffari                                NULL, etv_mean_velocity, &n, NULL);
1044e8107fdaSLeila Ghaffari   CHKERRQ(ierr);
1045ccaff030SJeremy L Thompson   ierr = PetscOptionsEnum("-stab", "Stabilization method", NULL,
1046ccaff030SJeremy L Thompson                           StabilizationTypes, (PetscEnum)(stab = STAB_NONE),
1047ccaff030SJeremy L Thompson                           (PetscEnum *)&stab, NULL); CHKERRQ(ierr);
1048a3ddc43aSLeila Ghaffari   ierr = PetscOptionsEnum("-euler_test", "Euler test option", NULL,
1049a3ddc43aSLeila Ghaffari                           EulerTestTypes, (PetscEnum)(euler_test = EULER_TEST_NONE),
1050a3ddc43aSLeila Ghaffari                           (PetscEnum *)&euler_test, NULL); CHKERRQ(ierr);
1051ccaff030SJeremy L Thompson   ierr = PetscOptionsBool("-implicit", "Use implicit (IFunction) formulation",
1052ccaff030SJeremy L Thompson                           NULL, implicit=PETSC_FALSE, &implicit, NULL);
1053ccaff030SJeremy L Thompson   CHKERRQ(ierr);
105484d34d69SLeila Ghaffari   if (!implicit && stab != STAB_NONE) {
105584d34d69SLeila Ghaffari     ierr = PetscPrintf(comm, "Warning! Use -stab only with -implicit\n");
105684d34d69SLeila Ghaffari     CHKERRQ(ierr);
105784d34d69SLeila Ghaffari   }
1058ccaff030SJeremy L Thompson   {
10597573aee6SJed Brown     PetscInt len;
10607573aee6SJed Brown     PetscBool flg;
1061ccaff030SJeremy L Thompson     ierr = PetscOptionsIntArray("-bc_wall",
1062ccaff030SJeremy L Thompson                                 "Use wall boundary conditions on this list of faces",
1063ccaff030SJeremy L Thompson                                 NULL, bc.walls,
1064ccaff030SJeremy L Thompson                                 (len = sizeof(bc.walls) / sizeof(bc.walls[0]),
1065ccaff030SJeremy L Thompson                                  &len), &flg); CHKERRQ(ierr);
10667573aee6SJed Brown     if (flg) {
10677573aee6SJed Brown       bc.nwall = len;
10687573aee6SJed Brown       // Using a no-slip wall disables automatic slip walls (they must be set explicitly)
10697573aee6SJed Brown       bc.nslip[0] = bc.nslip[1] = bc.nslip[2] = 0;
10707573aee6SJed Brown     }
1071ccaff030SJeremy L Thompson     for (PetscInt j=0; j<3; j++) {
1072ccaff030SJeremy L Thompson       const char *flags[3] = {"-bc_slip_x", "-bc_slip_y", "-bc_slip_z"};
1073ccaff030SJeremy L Thompson       ierr = PetscOptionsIntArray(flags[j],
1074ccaff030SJeremy L Thompson                                   "Use slip boundary conditions on this list of faces",
1075ccaff030SJeremy L Thompson                                   NULL, bc.slips[j],
1076ccaff030SJeremy L Thompson                                   (len = sizeof(bc.slips[j]) / sizeof(bc.slips[j][0]),
1077ccaff030SJeremy L Thompson                                    &len), &flg);
1078ccaff030SJeremy L Thompson       CHKERRQ(ierr);
107984d34d69SLeila Ghaffari       if (flg) {
108084d34d69SLeila Ghaffari         bc.nslip[j] = len;
108184d34d69SLeila Ghaffari         bc.userbc = PETSC_TRUE;
108284d34d69SLeila Ghaffari       }
1083ccaff030SJeremy L Thompson     }
1084ccaff030SJeremy L Thompson   }
1085cb3e2689Svaleriabarra   ierr = PetscOptionsInt("-viz_refine",
1086cb3e2689Svaleriabarra                          "Regular refinement levels for visualization",
1087cb3e2689Svaleriabarra                          NULL, viz_refine, &viz_refine, NULL);
1088ccaff030SJeremy L Thompson   CHKERRQ(ierr);
1089ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-units_meter", "1 meter in scaled length units",
1090ccaff030SJeremy L Thompson                             NULL, meter, &meter, NULL); CHKERRQ(ierr);
1091ccaff030SJeremy L Thompson   meter = fabs(meter);
1092ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-units_second","1 second in scaled time units",
1093ccaff030SJeremy L Thompson                             NULL, second, &second, NULL); CHKERRQ(ierr);
1094ccaff030SJeremy L Thompson   second = fabs(second);
1095ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-units_kilogram","1 kilogram in scaled mass units",
1096ccaff030SJeremy L Thompson                             NULL, kilogram, &kilogram, NULL); CHKERRQ(ierr);
1097ccaff030SJeremy L Thompson   kilogram = fabs(kilogram);
1098ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-units_Kelvin",
1099ccaff030SJeremy L Thompson                             "1 Kelvin in scaled temperature units",
1100ccaff030SJeremy L Thompson                             NULL, Kelvin, &Kelvin, NULL); CHKERRQ(ierr);
1101ccaff030SJeremy L Thompson   Kelvin = fabs(Kelvin);
1102ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-theta0", "Reference potential temperature",
1103ccaff030SJeremy L Thompson                             NULL, theta0, &theta0, NULL); CHKERRQ(ierr);
1104ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-thetaC", "Perturbation of potential temperature",
1105ccaff030SJeremy L Thompson                             NULL, thetaC, &thetaC, NULL); CHKERRQ(ierr);
1106ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-P0", "Atmospheric pressure",
1107ccaff030SJeremy L Thompson                             NULL, P0, &P0, NULL); CHKERRQ(ierr);
110816c0476cSLeila Ghaffari   ierr = PetscOptionsScalar("-E_wind", "Total energy of inflow wind",
110916c0476cSLeila Ghaffari                             NULL, E_wind, &E_wind, NULL); CHKERRQ(ierr);
1110ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-N", "Brunt-Vaisala frequency",
1111ccaff030SJeremy L Thompson                             NULL, N, &N, NULL); CHKERRQ(ierr);
1112ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-cv", "Heat capacity at constant volume",
1113ccaff030SJeremy L Thompson                             NULL, cv, &cv, NULL); CHKERRQ(ierr);
1114ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-cp", "Heat capacity at constant pressure",
1115ccaff030SJeremy L Thompson                             NULL, cp, &cp, NULL); CHKERRQ(ierr);
1116011314a7SLeila Ghaffari   PetscBool userVortex;
1117011314a7SLeila Ghaffari   ierr = PetscOptionsScalar("-vortex_strength", "Strength of Vortex",
1118011314a7SLeila Ghaffari                             NULL, vortex_strength, &vortex_strength, &userVortex);
1119011314a7SLeila Ghaffari   CHKERRQ(ierr);
1120011314a7SLeila Ghaffari   if (problemChoice != NS_EULER_VORTEX && userVortex) {
1121011314a7SLeila Ghaffari     ierr = PetscPrintf(comm,
1122011314a7SLeila Ghaffari                        "Warning! Use -vortex_strength only with -problem euler_vortex\n");
1123011314a7SLeila Ghaffari     CHKERRQ(ierr);
1124011314a7SLeila Ghaffari   }
1125c8cb9b1fSLeila Ghaffari   PetscBool userTinlet;
1126c8cb9b1fSLeila Ghaffari   ierr = PetscOptionsScalar("-T_inlet", "Incoming Temperature",
1127c8cb9b1fSLeila Ghaffari                             NULL, T_inlet, &T_inlet, &userTinlet);
1128c8cb9b1fSLeila Ghaffari   CHKERRQ(ierr);
1129c8cb9b1fSLeila Ghaffari   if (problemChoice != NS_EULER_VORTEX && userTinlet) {
1130c8cb9b1fSLeila Ghaffari     ierr = PetscPrintf(comm,
1131c8cb9b1fSLeila Ghaffari                        "Warning! Use -T_inlet only with -problem euler_vortex\n");
1132c8cb9b1fSLeila Ghaffari     CHKERRQ(ierr);
1133c8cb9b1fSLeila Ghaffari   }
1134c8cb9b1fSLeila Ghaffari   PetscBool userPinlet;
1135c8cb9b1fSLeila Ghaffari   ierr = PetscOptionsScalar("-P_inlet", "Incoming Pressure",
1136c8cb9b1fSLeila Ghaffari                             NULL, P_inlet, &P_inlet, &userPinlet);
1137c8cb9b1fSLeila Ghaffari   CHKERRQ(ierr);
1138c8cb9b1fSLeila Ghaffari   if (problemChoice != NS_EULER_VORTEX && userPinlet) {
1139c8cb9b1fSLeila Ghaffari     ierr = PetscPrintf(comm,
1140c8cb9b1fSLeila Ghaffari                        "Warning! Use -P_inlet only with -problem euler_vortex\n");
1141c8cb9b1fSLeila Ghaffari     CHKERRQ(ierr);
1142c8cb9b1fSLeila Ghaffari   }
1143ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-g", "Gravitational acceleration",
1144ccaff030SJeremy L Thompson                             NULL, g, &g, NULL); CHKERRQ(ierr);
1145ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-lambda",
1146ccaff030SJeremy L Thompson                             "Stokes hypothesis second viscosity coefficient",
1147ccaff030SJeremy L Thompson                             NULL, lambda, &lambda, NULL); CHKERRQ(ierr);
1148ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-mu", "Shear dynamic viscosity coefficient",
1149ccaff030SJeremy L Thompson                             NULL, mu, &mu, NULL); CHKERRQ(ierr);
1150ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-k", "Thermal conductivity",
1151ccaff030SJeremy L Thompson                             NULL, k, &k, NULL); CHKERRQ(ierr);
1152ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-CtauS",
1153ccaff030SJeremy L Thompson                             "Scale coefficient for tau (nondimensional)",
1154ccaff030SJeremy L Thompson                             NULL, CtauS, &CtauS, NULL); CHKERRQ(ierr);
115584d34d69SLeila Ghaffari   if (stab == STAB_NONE && CtauS != 0) {
115684d34d69SLeila Ghaffari     ierr = PetscPrintf(comm,
115784d34d69SLeila Ghaffari                        "Warning! Use -CtauS only with -stab su or -stab supg\n");
115884d34d69SLeila Ghaffari     CHKERRQ(ierr);
115984d34d69SLeila Ghaffari   }
1160ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-strong_form",
1161ccaff030SJeremy L Thompson                             "Strong (1) or weak/integrated by parts (0) advection residual",
1162ccaff030SJeremy L Thompson                             NULL, strong_form, &strong_form, NULL);
1163ccaff030SJeremy L Thompson   CHKERRQ(ierr);
116484d34d69SLeila Ghaffari   if (problemChoice == NS_DENSITY_CURRENT && (CtauS != 0 || strong_form != 0)) {
116584d34d69SLeila Ghaffari     ierr = PetscPrintf(comm,
116684d34d69SLeila Ghaffari                        "Warning! Problem density_current does not support -CtauS or -strong_form\n");
116784d34d69SLeila Ghaffari     CHKERRQ(ierr);
116884d34d69SLeila Ghaffari   }
1169ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-lx", "Length scale in x direction",
1170ccaff030SJeremy L Thompson                             NULL, lx, &lx, NULL); CHKERRQ(ierr);
1171ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-ly", "Length scale in y direction",
1172ccaff030SJeremy L Thompson                             NULL, ly, &ly, NULL); CHKERRQ(ierr);
1173ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-lz", "Length scale in z direction",
1174ccaff030SJeremy L Thompson                             NULL, lz, &lz, NULL); CHKERRQ(ierr);
1175ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-rc", "Characteristic radius of thermal bubble",
1176ccaff030SJeremy L Thompson                             NULL, rc, &rc, NULL); CHKERRQ(ierr);
1177ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-resx","Target resolution in x",
1178ccaff030SJeremy L Thompson                             NULL, resx, &resx, NULL); CHKERRQ(ierr);
1179ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-resy","Target resolution in y",
1180ccaff030SJeremy L Thompson                             NULL, resy, &resy, NULL); CHKERRQ(ierr);
1181ccaff030SJeremy L Thompson   ierr = PetscOptionsScalar("-resz","Target resolution in z",
1182ccaff030SJeremy L Thompson                             NULL, resz, &resz, NULL); CHKERRQ(ierr);
118382c09b01SLeila Ghaffari   n = problem->dim;
1184ccaff030SJeremy L Thompson   center[0] = 0.5 * lx;
1185ccaff030SJeremy L Thompson   center[1] = 0.5 * ly;
1186ccaff030SJeremy L Thompson   center[2] = 0.5 * lz;
1187ccaff030SJeremy L Thompson   ierr = PetscOptionsRealArray("-center", "Location of bubble center",
1188ccaff030SJeremy L Thompson                                NULL, center, &n, NULL); CHKERRQ(ierr);
1189ccaff030SJeremy L Thompson   n = problem->dim;
1190ccaff030SJeremy L Thompson   ierr = PetscOptionsRealArray("-dc_axis",
1191ccaff030SJeremy L Thompson                                "Axis of density current cylindrical anomaly, or {0,0,0} for spherically symmetric",
1192ccaff030SJeremy L Thompson                                NULL, dc_axis, &n, NULL); CHKERRQ(ierr);
1193ccaff030SJeremy L Thompson   {
1194ccaff030SJeremy L Thompson     PetscReal norm = PetscSqrtReal(PetscSqr(dc_axis[0]) +
1195ccaff030SJeremy L Thompson                                    PetscSqr(dc_axis[1]) + PetscSqr(dc_axis[2]));
1196ccaff030SJeremy L Thompson     if (norm > 0) {
1197ccaff030SJeremy L Thompson       for (int i=0; i<3; i++) dc_axis[i] /= norm;
1198ccaff030SJeremy L Thompson     }
1199ccaff030SJeremy L Thompson   }
1200ccaff030SJeremy L Thompson   ierr = PetscOptionsInt("-output_freq",
1201ccaff030SJeremy L Thompson                          "Frequency of output, in number of steps",
1202ccaff030SJeremy L Thompson                          NULL, outputfreq, &outputfreq, NULL); CHKERRQ(ierr);
1203ccaff030SJeremy L Thompson   ierr = PetscOptionsInt("-continue", "Continue from previous solution",
1204ccaff030SJeremy L Thompson                          NULL, contsteps, &contsteps, NULL); CHKERRQ(ierr);
120584d34d69SLeila Ghaffari   ierr = PetscOptionsInt("-degree", "Polynomial degree of finite elements",
120684d34d69SLeila Ghaffari                          NULL, degree, &degree, NULL); CHKERRQ(ierr);
120784d34d69SLeila Ghaffari   ierr = PetscOptionsInt("-qextra", "Number of extra quadrature points",
120884d34d69SLeila Ghaffari                          NULL, qextra, &qextra, NULL); CHKERRQ(ierr);
120981f92cf0SLeila Ghaffari   PetscBool userQextraSur;
1210ebb4b9bdSLeila Ghaffari   ierr = PetscOptionsInt("-qextra_boundary",
1211ebb4b9bdSLeila Ghaffari                          "Number of extra quadrature points on in/outflow faces",
1212f259b054Svaleriabarra                          NULL, qextraSur, &qextraSur, &userQextraSur);
1213f259b054Svaleriabarra   CHKERRQ(ierr);
1214ebb4b9bdSLeila Ghaffari   if ((wind_type == ADVECTION_WIND_ROTATION
1215ebb4b9bdSLeila Ghaffari        || problemChoice == NS_DENSITY_CURRENT) && userQextraSur) {
1216ebb4b9bdSLeila Ghaffari     ierr = PetscPrintf(comm,
1217ebb4b9bdSLeila Ghaffari                        "Warning! Use -qextra_boundary only with -problem_advection_wind translation\n");
121881f92cf0SLeila Ghaffari     CHKERRQ(ierr);
121981f92cf0SLeila Ghaffari   }
1220d99129b9SLeila Ghaffari   ierr = PetscStrncpy(user->outputdir, ".", 2); CHKERRQ(ierr);
1221d99129b9SLeila Ghaffari   ierr = PetscOptionsString("-output_dir", "Output directory",
1222d99129b9SLeila Ghaffari                             NULL, user->outputdir, user->outputdir,
1223d99129b9SLeila Ghaffari                             sizeof(user->outputdir), NULL); CHKERRQ(ierr);
122484d34d69SLeila Ghaffari   memtyperequested = petschavecuda ? CEED_MEM_DEVICE : CEED_MEM_HOST;
122584d34d69SLeila Ghaffari   ierr = PetscOptionsEnum("-memtype",
122684d34d69SLeila Ghaffari                           "CEED MemType requested", NULL,
122784d34d69SLeila Ghaffari                           memTypes, (PetscEnum)memtyperequested,
122884d34d69SLeila Ghaffari                           (PetscEnum *)&memtyperequested, &setmemtyperequest);
122984d34d69SLeila Ghaffari   CHKERRQ(ierr);
1230ccaff030SJeremy L Thompson   ierr = PetscOptionsEnd(); CHKERRQ(ierr);
1231ccaff030SJeremy L Thompson 
1232ccaff030SJeremy L Thompson   // Define derived units
1233ccaff030SJeremy L Thompson   Pascal = kilogram / (meter * PetscSqr(second));
1234ccaff030SJeremy L Thompson   JperkgK =  PetscSqr(meter) / (PetscSqr(second) * Kelvin);
1235ccaff030SJeremy L Thompson   mpersquareds = meter / PetscSqr(second);
1236ccaff030SJeremy L Thompson   WpermK = kilogram * meter / (pow(second,3) * Kelvin);
1237ccaff030SJeremy L Thompson   kgpercubicm = kilogram / pow(meter,3);
1238ccaff030SJeremy L Thompson   kgpersquaredms = kilogram / (PetscSqr(meter) * second);
1239ccaff030SJeremy L Thompson   Joulepercubicm = kilogram / (meter * PetscSqr(second));
124016c0476cSLeila Ghaffari   Joule = kilogram * PetscSqr(meter) / PetscSqr(second);
1241ccaff030SJeremy L Thompson 
1242ccaff030SJeremy L Thompson   // Scale variables to desired units
1243ccaff030SJeremy L Thompson   theta0 *= Kelvin;
1244ccaff030SJeremy L Thompson   thetaC *= Kelvin;
1245ccaff030SJeremy L Thompson   P0 *= Pascal;
124616c0476cSLeila Ghaffari   E_wind *= Joule;
1247ccaff030SJeremy L Thompson   N *= (1./second);
1248ccaff030SJeremy L Thompson   cv *= JperkgK;
1249ccaff030SJeremy L Thompson   cp *= JperkgK;
1250ccaff030SJeremy L Thompson   Rd = cp - cv;
1251c8cb9b1fSLeila Ghaffari   T_inlet *= Kelvin;
1252c8cb9b1fSLeila Ghaffari   P_inlet *= Pascal;
1253ccaff030SJeremy L Thompson   g *= mpersquareds;
1254ccaff030SJeremy L Thompson   mu *= Pascal * second;
1255ccaff030SJeremy L Thompson   k *= WpermK;
1256ccaff030SJeremy L Thompson   lx = fabs(lx) * meter;
1257ccaff030SJeremy L Thompson   ly = fabs(ly) * meter;
1258ccaff030SJeremy L Thompson   lz = fabs(lz) * meter;
1259ccaff030SJeremy L Thompson   rc = fabs(rc) * meter;
1260ccaff030SJeremy L Thompson   resx = fabs(resx) * meter;
1261ccaff030SJeremy L Thompson   resy = fabs(resy) * meter;
1262ccaff030SJeremy L Thompson   resz = fabs(resz) * meter;
1263ccaff030SJeremy L Thompson   for (int i=0; i<3; i++) center[i] *= meter;
1264ccaff030SJeremy L Thompson 
1265ccaff030SJeremy L Thompson   const CeedInt dim = problem->dim, ncompx = problem->dim,
1266cfa64770SLeila Ghaffari                 qdatasizeVol = problem->qdatasizeVol;
1267ccaff030SJeremy L Thompson   // Set up the libCEED context
1268777ff853SJeremy L Thompson   struct SetupContext_ ctxSetupData = {
1269ccaff030SJeremy L Thompson     .theta0 = theta0,
1270ccaff030SJeremy L Thompson     .thetaC = thetaC,
1271ccaff030SJeremy L Thompson     .P0 = P0,
1272ccaff030SJeremy L Thompson     .N = N,
1273ccaff030SJeremy L Thompson     .cv = cv,
1274ccaff030SJeremy L Thompson     .cp = cp,
1275ccaff030SJeremy L Thompson     .Rd = Rd,
1276ccaff030SJeremy L Thompson     .g = g,
1277ccaff030SJeremy L Thompson     .rc = rc,
1278ccaff030SJeremy L Thompson     .lx = lx,
1279ccaff030SJeremy L Thompson     .ly = ly,
1280ccaff030SJeremy L Thompson     .lz = lz,
1281ccaff030SJeremy L Thompson     .center[0] = center[0],
1282ccaff030SJeremy L Thompson     .center[1] = center[1],
1283ccaff030SJeremy L Thompson     .center[2] = center[2],
1284ccaff030SJeremy L Thompson     .dc_axis[0] = dc_axis[0],
1285ccaff030SJeremy L Thompson     .dc_axis[1] = dc_axis[1],
1286ccaff030SJeremy L Thompson     .dc_axis[2] = dc_axis[2],
12871184866aSLeila Ghaffari     .wind[0] = wind[0],
12881184866aSLeila Ghaffari     .wind[1] = wind[1],
12891184866aSLeila Ghaffari     .wind[2] = wind[2],
12903a9f53b0SLeila Ghaffari     .time = 0,
1291011314a7SLeila Ghaffari     .vortex_strength = vortex_strength,
12921184866aSLeila Ghaffari     .wind_type = wind_type,
1293ccaff030SJeremy L Thompson   };
1294ccaff030SJeremy L Thompson 
129584d34d69SLeila Ghaffari   // Create the mesh
1296ccaff030SJeremy L Thompson   {
1297ccaff030SJeremy L Thompson     const PetscReal scale[3] = {lx, ly, lz};
1298ccaff030SJeremy L Thompson     ierr = DMPlexCreateBoxMesh(comm, dim, PETSC_FALSE, NULL, NULL, scale,
12992561194eSLeila Ghaffari                                NULL, PETSC_TRUE, &dm);
1300ccaff030SJeremy L Thompson     CHKERRQ(ierr);
1301ccaff030SJeremy L Thompson   }
130284d34d69SLeila Ghaffari 
130384d34d69SLeila Ghaffari   // Distribute the mesh over processes
130484d34d69SLeila Ghaffari   {
1305ccaff030SJeremy L Thompson     DM               dmDist = NULL;
1306ccaff030SJeremy L Thompson     PetscPartitioner part;
1307ccaff030SJeremy L Thompson 
1308ccaff030SJeremy L Thompson     ierr = DMPlexGetPartitioner(dm, &part); CHKERRQ(ierr);
1309ccaff030SJeremy L Thompson     ierr = PetscPartitionerSetFromOptions(part); CHKERRQ(ierr);
1310ccaff030SJeremy L Thompson     ierr = DMPlexDistribute(dm, 0, NULL, &dmDist); CHKERRQ(ierr);
1311ccaff030SJeremy L Thompson     if (dmDist) {
1312ccaff030SJeremy L Thompson       ierr = DMDestroy(&dm); CHKERRQ(ierr);
1313ccaff030SJeremy L Thompson       dm  = dmDist;
1314ccaff030SJeremy L Thompson     }
1315ccaff030SJeremy L Thompson   }
1316ccaff030SJeremy L Thompson   ierr = DMViewFromOptions(dm, NULL, "-dm_view"); CHKERRQ(ierr);
1317ccaff030SJeremy L Thompson 
131884d34d69SLeila Ghaffari   // Setup DM
1319ccaff030SJeremy L Thompson   ierr = DMLocalizeCoordinates(dm); CHKERRQ(ierr);
1320ccaff030SJeremy L Thompson   ierr = DMSetFromOptions(dm); CHKERRQ(ierr);
13215bf10c6fSLeila Ghaffari   ierr = SetUpDM(dm, problem, degree, &bc, &ctxSetupData, ctxEulerData);
13225bf10c6fSLeila Ghaffari   CHKERRQ(ierr);
132384d34d69SLeila Ghaffari 
132484d34d69SLeila Ghaffari   // Refine DM for high-order viz
1325ccaff030SJeremy L Thompson   dmviz = NULL;
1326ccaff030SJeremy L Thompson   interpviz = NULL;
1327ccaff030SJeremy L Thompson   if (viz_refine) {
1328ff6701fcSJed Brown     DM dmhierarchy[viz_refine+1];
1329ff6701fcSJed Brown 
1330ccaff030SJeremy L Thompson     ierr = DMPlexSetRefinementUniform(dm, PETSC_TRUE); CHKERRQ(ierr);
1331ff6701fcSJed Brown     dmhierarchy[0] = dm;
133284d34d69SLeila Ghaffari     for (PetscInt i = 0, d = degree; i < viz_refine; i++) {
1333ff6701fcSJed Brown       Mat interp_next;
1334ff6701fcSJed Brown 
1335ff6701fcSJed Brown       ierr = DMRefine(dmhierarchy[i], MPI_COMM_NULL, &dmhierarchy[i+1]);
1336ccaff030SJeremy L Thompson       CHKERRQ(ierr);
1337bc6a41f7SJed Brown       ierr = DMClearDS(dmhierarchy[i+1]); CHKERRQ(ierr);
1338bc6a41f7SJed Brown       ierr = DMClearFields(dmhierarchy[i+1]); CHKERRQ(ierr);
1339ff6701fcSJed Brown       ierr = DMSetCoarseDM(dmhierarchy[i+1], dmhierarchy[i]); CHKERRQ(ierr);
1340ff6701fcSJed Brown       d = (d + 1) / 2;
1341ff6701fcSJed Brown       if (i + 1 == viz_refine) d = 1;
13425bf10c6fSLeila Ghaffari       ierr = SetUpDM(dmhierarchy[i+1], problem, d, &bc, &ctxSetupData,
13435bf10c6fSLeila Ghaffari                      ctxEulerData); CHKERRQ(ierr);
1344ff6701fcSJed Brown       ierr = DMCreateInterpolation(dmhierarchy[i], dmhierarchy[i+1],
1345ff6701fcSJed Brown                                    &interp_next, NULL); CHKERRQ(ierr);
1346ff6701fcSJed Brown       if (!i) interpviz = interp_next;
1347ff6701fcSJed Brown       else {
1348ff6701fcSJed Brown         Mat C;
1349ff6701fcSJed Brown         ierr = MatMatMult(interp_next, interpviz, MAT_INITIAL_MATRIX,
1350ff6701fcSJed Brown                           PETSC_DECIDE, &C); CHKERRQ(ierr);
1351ff6701fcSJed Brown         ierr = MatDestroy(&interp_next); CHKERRQ(ierr);
1352ff6701fcSJed Brown         ierr = MatDestroy(&interpviz); CHKERRQ(ierr);
1353ff6701fcSJed Brown         interpviz = C;
1354ff6701fcSJed Brown       }
1355ff6701fcSJed Brown     }
1356cb3e2689Svaleriabarra     for (PetscInt i=1; i<viz_refine; i++) {
1357ff6701fcSJed Brown       ierr = DMDestroy(&dmhierarchy[i]); CHKERRQ(ierr);
1358cb3e2689Svaleriabarra     }
1359ff6701fcSJed Brown     dmviz = dmhierarchy[viz_refine];
1360ccaff030SJeremy L Thompson   }
1361ccaff030SJeremy L Thompson   ierr = DMCreateGlobalVector(dm, &Q); CHKERRQ(ierr);
1362ccaff030SJeremy L Thompson   ierr = DMGetLocalVector(dm, &Qloc); CHKERRQ(ierr);
1363ccaff030SJeremy L Thompson   ierr = VecGetSize(Qloc, &lnodes); CHKERRQ(ierr);
1364ccaff030SJeremy L Thompson   lnodes /= ncompq;
1365ccaff030SJeremy L Thompson 
136684d34d69SLeila Ghaffari   // Initialize CEED
136784d34d69SLeila Ghaffari   CeedInit(ceedresource, &ceed);
136884d34d69SLeila Ghaffari   // Set memtype
136984d34d69SLeila Ghaffari   CeedMemType memtypebackend;
137084d34d69SLeila Ghaffari   CeedGetPreferredMemType(ceed, &memtypebackend);
137184d34d69SLeila Ghaffari   // Check memtype compatibility
137284d34d69SLeila Ghaffari   if (!setmemtyperequest)
137384d34d69SLeila Ghaffari     memtyperequested = memtypebackend;
137484d34d69SLeila Ghaffari   else if (!petschavecuda && memtyperequested == CEED_MEM_DEVICE)
137584d34d69SLeila Ghaffari     SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS,
137684d34d69SLeila Ghaffari              "PETSc was not built with CUDA. "
137784d34d69SLeila Ghaffari              "Requested MemType CEED_MEM_DEVICE is not supported.", NULL);
137884d34d69SLeila Ghaffari 
137984d34d69SLeila Ghaffari   // Set number of 1D nodes and quadrature points
138084d34d69SLeila Ghaffari   numP = degree + 1;
138184d34d69SLeila Ghaffari   numQ = numP + qextra;
138284d34d69SLeila Ghaffari 
138384d34d69SLeila Ghaffari   // Print summary
1384dc8efd83SLeila Ghaffari   if (!test) {
1385ccaff030SJeremy L Thompson     CeedInt gdofs, odofs;
1386ccaff030SJeremy L Thompson     int comm_size;
1387ccaff030SJeremy L Thompson     char box_faces_str[PETSC_MAX_PATH_LEN] = "NONE";
1388ccaff030SJeremy L Thompson     ierr = VecGetSize(Q, &gdofs); CHKERRQ(ierr);
1389ccaff030SJeremy L Thompson     ierr = VecGetLocalSize(Q, &odofs); CHKERRQ(ierr);
139084d34d69SLeila Ghaffari     gnodes = gdofs/ncompq;
1391ccaff030SJeremy L Thompson     ierr = MPI_Comm_size(comm, &comm_size); CHKERRQ(ierr);
1392ccaff030SJeremy L Thompson     ierr = PetscOptionsGetString(NULL, NULL, "-dm_plex_box_faces", box_faces_str,
1393ccaff030SJeremy L Thompson                                  sizeof(box_faces_str), NULL); CHKERRQ(ierr);
139484d34d69SLeila Ghaffari     const char *usedresource;
139584d34d69SLeila Ghaffari     CeedGetResource(ceed, &usedresource);
1396ccaff030SJeremy L Thompson 
139784d34d69SLeila Ghaffari     ierr = PetscPrintf(comm,
139884d34d69SLeila Ghaffari                        "\n-- Navier-Stokes solver - libCEED + PETSc --\n"
139984d34d69SLeila Ghaffari                        "  rank(s)                              : %d\n"
140084d34d69SLeila Ghaffari                        "  Problem:\n"
140184d34d69SLeila Ghaffari                        "    Problem Name                       : %s\n"
140284d34d69SLeila Ghaffari                        "    Stabilization                      : %s\n"
140384d34d69SLeila Ghaffari                        "  PETSc:\n"
140484d34d69SLeila Ghaffari                        "    Box Faces                          : %s\n"
140584d34d69SLeila Ghaffari                        "  libCEED:\n"
140684d34d69SLeila Ghaffari                        "    libCEED Backend                    : %s\n"
140784d34d69SLeila Ghaffari                        "    libCEED Backend MemType            : %s\n"
140884d34d69SLeila Ghaffari                        "    libCEED User Requested MemType     : %s\n"
140984d34d69SLeila Ghaffari                        "  Mesh:\n"
141084d34d69SLeila Ghaffari                        "    Number of 1D Basis Nodes (P)       : %d\n"
141184d34d69SLeila Ghaffari                        "    Number of 1D Quadrature Points (Q) : %d\n"
141284d34d69SLeila Ghaffari                        "    Global DoFs                        : %D\n"
141384d34d69SLeila Ghaffari                        "    Owned DoFs                         : %D\n"
141484d34d69SLeila Ghaffari                        "    DoFs per node                      : %D\n"
141584d34d69SLeila Ghaffari                        "    Global nodes                       : %D\n"
141684d34d69SLeila Ghaffari                        "    Owned nodes                        : %D\n",
141784d34d69SLeila Ghaffari                        comm_size, problemTypes[problemChoice],
141884d34d69SLeila Ghaffari                        StabilizationTypes[stab], box_faces_str, usedresource,
141984d34d69SLeila Ghaffari                        CeedMemTypes[memtypebackend],
142084d34d69SLeila Ghaffari                        (setmemtyperequest) ?
142184d34d69SLeila Ghaffari                        CeedMemTypes[memtyperequested] : "none",
142284d34d69SLeila Ghaffari                        numP, numQ, gdofs, odofs, ncompq, gnodes, lnodes);
142384d34d69SLeila Ghaffari     CHKERRQ(ierr);
14240c6c0b13SLeila Ghaffari   }
14250c6c0b13SLeila Ghaffari 
1426ccaff030SJeremy L Thompson   // Set up global mass vector
1427ccaff030SJeremy L Thompson   ierr = VecDuplicate(Q, &user->M); CHKERRQ(ierr);
1428ccaff030SJeremy L Thompson 
142984d34d69SLeila Ghaffari   // Set up libCEED
1430ccaff030SJeremy L Thompson   // CEED Bases
1431ccaff030SJeremy L Thompson   CeedInit(ceedresource, &ceed);
143284d34d69SLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dim, ncompq, numP, numQ, CEED_GAUSS,
143384d34d69SLeila Ghaffari                                   &basisq);
143484d34d69SLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dim, ncompx, 2, numQ, CEED_GAUSS,
143584d34d69SLeila Ghaffari                                   &basisx);
143684d34d69SLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dim, ncompx, 2, numP,
143784d34d69SLeila Ghaffari                                   CEED_GAUSS_LOBATTO, &basisxc);
1438ccaff030SJeremy L Thompson   ierr = DMGetCoordinateDM(dm, &dmcoord); CHKERRQ(ierr);
1439ccaff030SJeremy L Thompson   ierr = DMPlexSetClosurePermutationTensor(dmcoord, PETSC_DETERMINE, NULL);
1440ccaff030SJeremy L Thompson   CHKERRQ(ierr);
1441ccaff030SJeremy L Thompson 
1442ccaff030SJeremy L Thompson   // CEED Restrictions
14431e150236SLeila Ghaffari   ierr = GetRestrictionForDomain(ceed, dm, 0, 0, 0, numP, numQ,
144484d34d69SLeila Ghaffari                                  qdatasizeVol, &restrictq, &restrictx,
144584d34d69SLeila Ghaffari                                  &restrictqdi); CHKERRQ(ierr);
1446ccaff030SJeremy L Thompson 
1447ccaff030SJeremy L Thompson   ierr = DMGetCoordinatesLocal(dm, &Xloc); CHKERRQ(ierr);
1448ccaff030SJeremy L Thompson   ierr = CreateVectorFromPetscVec(ceed, Xloc, &xcorners); CHKERRQ(ierr);
1449ccaff030SJeremy L Thompson 
1450ccaff030SJeremy L Thompson   // Create the CEED vectors that will be needed in setup
1451bd910870SLeila Ghaffari   CeedInt NqptsVol;
145284d34d69SLeila Ghaffari   CeedBasisGetNumQuadraturePoints(basisq, &NqptsVol);
145384d34d69SLeila Ghaffari   CeedElemRestrictionGetNumElements(restrictq, &localNelemVol);
14548b982baeSLeila Ghaffari   CeedVectorCreate(ceed, qdatasizeVol*localNelemVol*NqptsVol, &qdata);
145584d34d69SLeila Ghaffari   CeedElemRestrictionCreateVector(restrictq, &q0ceed, NULL);
1456ccaff030SJeremy L Thompson 
1457ccaff030SJeremy L Thompson   // Create the Q-function that builds the quadrature data for the NS operator
1458ea6e0f84SLeila Ghaffari   CeedQFunctionCreateInterior(ceed, 1, problem->setupVol, problem->setupVol_loc,
1459ea6e0f84SLeila Ghaffari                               &qf_setupVol);
1460ea6e0f84SLeila Ghaffari   CeedQFunctionAddInput(qf_setupVol, "dx", ncompx*dim, CEED_EVAL_GRAD);
1461ea6e0f84SLeila Ghaffari   CeedQFunctionAddInput(qf_setupVol, "weight", 1, CEED_EVAL_WEIGHT);
14628b982baeSLeila Ghaffari   CeedQFunctionAddOutput(qf_setupVol, "qdata", qdatasizeVol, CEED_EVAL_NONE);
1463ccaff030SJeremy L Thompson 
1464ccaff030SJeremy L Thompson   // Create the Q-function that sets the ICs of the operator
1465ccaff030SJeremy L Thompson   CeedQFunctionCreateInterior(ceed, 1, problem->ics, problem->ics_loc, &qf_ics);
1466ccaff030SJeremy L Thompson   CeedQFunctionAddInput(qf_ics, "x", ncompx, CEED_EVAL_INTERP);
1467ccaff030SJeremy L Thompson   CeedQFunctionAddOutput(qf_ics, "q0", ncompq, CEED_EVAL_NONE);
1468ccaff030SJeremy L Thompson 
1469ea6e0f84SLeila Ghaffari   qf_rhsVol = NULL;
1470ea6e0f84SLeila Ghaffari   if (problem->applyVol_rhs) { // Create the Q-function that defines the action of the RHS operator
1471ea6e0f84SLeila Ghaffari     CeedQFunctionCreateInterior(ceed, 1, problem->applyVol_rhs,
1472ea6e0f84SLeila Ghaffari                                 problem->applyVol_rhs_loc, &qf_rhsVol);
1473ea6e0f84SLeila Ghaffari     CeedQFunctionAddInput(qf_rhsVol, "q", ncompq, CEED_EVAL_INTERP);
1474ea6e0f84SLeila Ghaffari     CeedQFunctionAddInput(qf_rhsVol, "dq", ncompq*dim, CEED_EVAL_GRAD);
14758b982baeSLeila Ghaffari     CeedQFunctionAddInput(qf_rhsVol, "qdata", qdatasizeVol, CEED_EVAL_NONE);
1476ea6e0f84SLeila Ghaffari     CeedQFunctionAddInput(qf_rhsVol, "x", ncompx, CEED_EVAL_INTERP);
1477ea6e0f84SLeila Ghaffari     CeedQFunctionAddOutput(qf_rhsVol, "v", ncompq, CEED_EVAL_INTERP);
1478ea6e0f84SLeila Ghaffari     CeedQFunctionAddOutput(qf_rhsVol, "dv", ncompq*dim, CEED_EVAL_GRAD);
1479ccaff030SJeremy L Thompson   }
1480ccaff030SJeremy L Thompson 
1481ea6e0f84SLeila Ghaffari   qf_ifunctionVol = NULL;
1482ea6e0f84SLeila Ghaffari   if (problem->applyVol_ifunction) { // Create the Q-function that defines the action of the IFunction
1483ea6e0f84SLeila Ghaffari     CeedQFunctionCreateInterior(ceed, 1, problem->applyVol_ifunction,
1484ea6e0f84SLeila Ghaffari                                 problem->applyVol_ifunction_loc, &qf_ifunctionVol);
1485ea6e0f84SLeila Ghaffari     CeedQFunctionAddInput(qf_ifunctionVol, "q", ncompq, CEED_EVAL_INTERP);
1486ea6e0f84SLeila Ghaffari     CeedQFunctionAddInput(qf_ifunctionVol, "dq", ncompq*dim, CEED_EVAL_GRAD);
1487ea6e0f84SLeila Ghaffari     CeedQFunctionAddInput(qf_ifunctionVol, "qdot", ncompq, CEED_EVAL_INTERP);
14888b982baeSLeila Ghaffari     CeedQFunctionAddInput(qf_ifunctionVol, "qdata", qdatasizeVol, CEED_EVAL_NONE);
1489ea6e0f84SLeila Ghaffari     CeedQFunctionAddInput(qf_ifunctionVol, "x", ncompx, CEED_EVAL_INTERP);
1490ea6e0f84SLeila Ghaffari     CeedQFunctionAddOutput(qf_ifunctionVol, "v", ncompq, CEED_EVAL_INTERP);
1491ea6e0f84SLeila Ghaffari     CeedQFunctionAddOutput(qf_ifunctionVol, "dv", ncompq*dim, CEED_EVAL_GRAD);
1492ccaff030SJeremy L Thompson   }
1493ccaff030SJeremy L Thompson 
1494ccaff030SJeremy L Thompson   // Create the operator that builds the quadrature data for the NS operator
1495ea6e0f84SLeila Ghaffari   CeedOperatorCreate(ceed, qf_setupVol, NULL, NULL, &op_setupVol);
149684d34d69SLeila Ghaffari   CeedOperatorSetField(op_setupVol, "dx", restrictx, basisx, CEED_VECTOR_ACTIVE);
1497ea6e0f84SLeila Ghaffari   CeedOperatorSetField(op_setupVol, "weight", CEED_ELEMRESTRICTION_NONE,
149884d34d69SLeila Ghaffari                        basisx, CEED_VECTOR_NONE);
149984d34d69SLeila Ghaffari   CeedOperatorSetField(op_setupVol, "qdata", restrictqdi,
1500ccaff030SJeremy L Thompson                        CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
1501ccaff030SJeremy L Thompson 
1502ccaff030SJeremy L Thompson   // Create the operator that sets the ICs
1503ccaff030SJeremy L Thompson   CeedOperatorCreate(ceed, qf_ics, NULL, NULL, &op_ics);
150484d34d69SLeila Ghaffari   CeedOperatorSetField(op_ics, "x", restrictx, basisxc, CEED_VECTOR_ACTIVE);
150584d34d69SLeila Ghaffari   CeedOperatorSetField(op_ics, "q0", restrictq,
1506ccaff030SJeremy L Thompson                        CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
1507ccaff030SJeremy L Thompson 
150884d34d69SLeila Ghaffari   CeedElemRestrictionCreateVector(restrictq, &user->qceed, NULL);
150984d34d69SLeila Ghaffari   CeedElemRestrictionCreateVector(restrictq, &user->qdotceed, NULL);
151084d34d69SLeila Ghaffari   CeedElemRestrictionCreateVector(restrictq, &user->gceed, NULL);
1511ccaff030SJeremy L Thompson 
1512ea6e0f84SLeila Ghaffari   if (qf_rhsVol) { // Create the RHS physics operator
1513ccaff030SJeremy L Thompson     CeedOperator op;
1514ea6e0f84SLeila Ghaffari     CeedOperatorCreate(ceed, qf_rhsVol, NULL, NULL, &op);
151584d34d69SLeila Ghaffari     CeedOperatorSetField(op, "q", restrictq, basisq, CEED_VECTOR_ACTIVE);
151684d34d69SLeila Ghaffari     CeedOperatorSetField(op, "dq", restrictq, basisq, CEED_VECTOR_ACTIVE);
151784d34d69SLeila Ghaffari     CeedOperatorSetField(op, "qdata", restrictqdi,
15188b982baeSLeila Ghaffari                          CEED_BASIS_COLLOCATED, qdata);
151984d34d69SLeila Ghaffari     CeedOperatorSetField(op, "x", restrictx, basisx, xcorners);
152084d34d69SLeila Ghaffari     CeedOperatorSetField(op, "v", restrictq, basisq, CEED_VECTOR_ACTIVE);
152184d34d69SLeila Ghaffari     CeedOperatorSetField(op, "dv", restrictq, basisq, CEED_VECTOR_ACTIVE);
1522d3630711SJed Brown     user->op_rhs_vol = op;
1523ccaff030SJeremy L Thompson   }
1524ccaff030SJeremy L Thompson 
1525ea6e0f84SLeila Ghaffari   if (qf_ifunctionVol) { // Create the IFunction operator
1526ccaff030SJeremy L Thompson     CeedOperator op;
1527ea6e0f84SLeila Ghaffari     CeedOperatorCreate(ceed, qf_ifunctionVol, NULL, NULL, &op);
152884d34d69SLeila Ghaffari     CeedOperatorSetField(op, "q", restrictq, basisq, CEED_VECTOR_ACTIVE);
152984d34d69SLeila Ghaffari     CeedOperatorSetField(op, "dq", restrictq, basisq, CEED_VECTOR_ACTIVE);
153084d34d69SLeila Ghaffari     CeedOperatorSetField(op, "qdot", restrictq, basisq, user->qdotceed);
153184d34d69SLeila Ghaffari     CeedOperatorSetField(op, "qdata", restrictqdi,
15328b982baeSLeila Ghaffari                          CEED_BASIS_COLLOCATED, qdata);
153384d34d69SLeila Ghaffari     CeedOperatorSetField(op, "x", restrictx, basisx, xcorners);
153484d34d69SLeila Ghaffari     CeedOperatorSetField(op, "v", restrictq, basisq, CEED_VECTOR_ACTIVE);
153584d34d69SLeila Ghaffari     CeedOperatorSetField(op, "dv", restrictq, basisq, CEED_VECTOR_ACTIVE);
1536d3630711SJed Brown     user->op_ifunction_vol = op;
1537ccaff030SJeremy L Thompson   }
1538ccaff030SJeremy L Thompson 
15396a0edaf9SLeila Ghaffari   // Set up CEED for the boundaries
15406a0edaf9SLeila Ghaffari   CeedInt height = 1;
15416a0edaf9SLeila Ghaffari   CeedInt dimSur = dim - height;
15421e150236SLeila Ghaffari   CeedInt numP_Sur = degree + 1;
15431e150236SLeila Ghaffari   CeedInt numQ_Sur = numP_Sur + qextraSur;
1544cfa64770SLeila Ghaffari   const CeedInt qdatasizeSur = problem->qdatasizeSur;
1545cfa64770SLeila Ghaffari   CeedBasis basisxSur, basisxcSur, basisqSur;
1546cfa64770SLeila Ghaffari   CeedInt NqptsSur;
1547e2043960SLeila Ghaffari   CeedQFunction qf_setupSur, qf_applySur;
1548cfa64770SLeila Ghaffari 
1549cfa64770SLeila Ghaffari   // CEED bases for the boundaries
1550ebb4b9bdSLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dimSur, ncompq, numP_Sur, numQ_Sur,
1551ebb4b9bdSLeila Ghaffari                                   CEED_GAUSS,
15526a0edaf9SLeila Ghaffari                                   &basisqSur);
15536a0edaf9SLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dimSur, ncompx, 2, numQ_Sur, CEED_GAUSS,
15546a0edaf9SLeila Ghaffari                                   &basisxSur);
15556a0edaf9SLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dimSur, ncompx, 2, numP_Sur,
15566a0edaf9SLeila Ghaffari                                   CEED_GAUSS_LOBATTO, &basisxcSur);
15576a0edaf9SLeila Ghaffari   CeedBasisGetNumQuadraturePoints(basisqSur, &NqptsSur);
15586a0edaf9SLeila Ghaffari 
1559cfa64770SLeila Ghaffari   // Create the Q-function that builds the quadrature data for the Surface operator
15606a0edaf9SLeila Ghaffari   CeedQFunctionCreateInterior(ceed, 1, problem->setupSur, problem->setupSur_loc,
15616a0edaf9SLeila Ghaffari                               &qf_setupSur);
15626a0edaf9SLeila Ghaffari   CeedQFunctionAddInput(qf_setupSur, "dx", ncompx*dimSur, CEED_EVAL_GRAD);
15636a0edaf9SLeila Ghaffari   CeedQFunctionAddInput(qf_setupSur, "weight", 1, CEED_EVAL_WEIGHT);
15646a0edaf9SLeila Ghaffari   CeedQFunctionAddOutput(qf_setupSur, "qdataSur", qdatasizeSur, CEED_EVAL_NONE);
15656a0edaf9SLeila Ghaffari 
15667659d40cSLeila Ghaffari   // Creat Q-Function for Boundaries
156786ba6f09SLeila Ghaffari   // -- Defined for Advection(2d) test cases
15687ed8b9c7SLeila Ghaffari   qf_applySur = NULL;
15697659d40cSLeila Ghaffari   if (problem->applySur) {
15707659d40cSLeila Ghaffari     CeedQFunctionCreateInterior(ceed, 1, problem->applySur,
15717ed8b9c7SLeila Ghaffari                                 problem->applySur_loc, &qf_applySur);
15727ed8b9c7SLeila Ghaffari     CeedQFunctionAddInput(qf_applySur, "q", ncompq, CEED_EVAL_INTERP);
15737ed8b9c7SLeila Ghaffari     CeedQFunctionAddInput(qf_applySur, "qdataSur", qdatasizeSur, CEED_EVAL_NONE);
15747ed8b9c7SLeila Ghaffari     CeedQFunctionAddInput(qf_applySur, "x", ncompx, CEED_EVAL_INTERP);
15757ed8b9c7SLeila Ghaffari     CeedQFunctionAddOutput(qf_applySur, "v", ncompq, CEED_EVAL_INTERP);
15769fe13df9SLeila Ghaffari   }
15779fe13df9SLeila Ghaffari 
15789fe13df9SLeila Ghaffari   // Create CEED Operator for the whole domain
15799fe13df9SLeila Ghaffari   if (!implicit)
15804438636fSLeila Ghaffari     ierr = CreateOperatorForDomain(ceed, dm, &bc, problemChoice, wind_type,
15814438636fSLeila Ghaffari                                    user->op_rhs_vol, qf_applySur,
1582e2043960SLeila Ghaffari                                    qf_setupSur, height, numP_Sur, numQ_Sur,
15834438636fSLeila Ghaffari                                    qdatasizeSur, NqptsSur, basisxSur,
15844438636fSLeila Ghaffari                                    basisqSur, &user->op_rhs);
15854438636fSLeila Ghaffari   CHKERRQ(ierr);
15869fe13df9SLeila Ghaffari   if (implicit)
15874438636fSLeila Ghaffari     ierr = CreateOperatorForDomain(ceed, dm, &bc, problemChoice, wind_type,
15884438636fSLeila Ghaffari                                    user->op_ifunction_vol, qf_applySur,
1589e2043960SLeila Ghaffari                                    qf_setupSur, height, numP_Sur, numQ_Sur,
15904438636fSLeila Ghaffari                                    qdatasizeSur, NqptsSur, basisxSur,
15914438636fSLeila Ghaffari                                    basisqSur, &user->op_ifunction);
15924438636fSLeila Ghaffari   CHKERRQ(ierr);
15937659d40cSLeila Ghaffari   // Set up contex for QFunctions
1594777ff853SJeremy L Thompson   CeedQFunctionContextCreate(ceed, &ctxSetup);
1595777ff853SJeremy L Thompson   CeedQFunctionContextSetData(ctxSetup, CEED_MEM_HOST, CEED_USE_POINTER,
1596777ff853SJeremy L Thompson                               sizeof ctxSetupData, &ctxSetupData);
15975bf10c6fSLeila Ghaffari   if (qf_ics && problemChoice != NS_EULER_VORTEX)
1598777ff853SJeremy L Thompson     CeedQFunctionSetContext(qf_ics, ctxSetup);
1599777ff853SJeremy L Thompson 
16005bf10c6fSLeila Ghaffari   CeedScalar ctxNSData[8] = {lambda, mu, k, cv, cp, g, Rd};
1601777ff853SJeremy L Thompson   CeedQFunctionContextCreate(ceed, &ctxNS);
1602777ff853SJeremy L Thompson   CeedQFunctionContextSetData(ctxNS, CEED_MEM_HOST, CEED_USE_POINTER,
1603777ff853SJeremy L Thompson                               sizeof ctxNSData, &ctxNSData);
1604777ff853SJeremy L Thompson 
16050da62991SLeila Ghaffari   struct Advection2dContext_ ctxAdvection2dData = {
1606ccaff030SJeremy L Thompson     .CtauS = CtauS,
1607ccaff030SJeremy L Thompson     .strong_form = strong_form,
1608ccaff030SJeremy L Thompson     .stabilization = stab,
1609ccaff030SJeremy L Thompson   };
1610777ff853SJeremy L Thompson   CeedQFunctionContextCreate(ceed, &ctxAdvection2d);
1611777ff853SJeremy L Thompson   CeedQFunctionContextSetData(ctxAdvection2d, CEED_MEM_HOST, CEED_USE_POINTER,
1612777ff853SJeremy L Thompson                               sizeof ctxAdvection2dData, &ctxAdvection2dData);
1613777ff853SJeremy L Thompson 
1614777ff853SJeremy L Thompson   struct SurfaceContext_ ctxSurfaceData = {
161516c0476cSLeila Ghaffari     .E_wind = E_wind,
16167659d40cSLeila Ghaffari     .strong_form = strong_form,
1617e5ed8c30SLeila Ghaffari     .implicit = implicit,
1618e5ed8c30SLeila Ghaffari   };
1619777ff853SJeremy L Thompson   CeedQFunctionContextCreate(ceed, &ctxSurface);
1620777ff853SJeremy L Thompson   CeedQFunctionContextSetData(ctxSurface, CEED_MEM_HOST, CEED_USE_POINTER,
1621777ff853SJeremy L Thompson                               sizeof ctxSurfaceData, &ctxSurfaceData);
1622777ff853SJeremy L Thompson 
16235bf10c6fSLeila Ghaffari   // Set up ctxEulerData structure
16245bf10c6fSLeila Ghaffari   ctxEulerData->time = 0.;
16255bf10c6fSLeila Ghaffari   ctxEulerData->currentTime = 0.;
1626a3ddc43aSLeila Ghaffari   ctxEulerData->euler_test = euler_test;
16275bf10c6fSLeila Ghaffari   ctxEulerData->center[0] = center[0];
16285bf10c6fSLeila Ghaffari   ctxEulerData->center[1] = center[1];
16295bf10c6fSLeila Ghaffari   ctxEulerData->center[2] = center[2];
16305bf10c6fSLeila Ghaffari   ctxEulerData->vortex_strength = vortex_strength;
16310da62991SLeila Ghaffari   ctxEulerData->etv_mean_velocity[0] = etv_mean_velocity[0];
16320da62991SLeila Ghaffari   ctxEulerData->etv_mean_velocity[1] = etv_mean_velocity[1];
16330da62991SLeila Ghaffari   ctxEulerData->etv_mean_velocity[2] = etv_mean_velocity[2];
1634a45a933fSLeila Ghaffari   ctxEulerData->T_inlet = T_inlet;
1635a45a933fSLeila Ghaffari   ctxEulerData->P_inlet = P_inlet;
1636c52ac6b8SLeila Ghaffari   ctxEulerData->stabilization = stab;
163777b27584SLeila Ghaffari   ctxEulerData->implicit = implicit;
16385bf10c6fSLeila Ghaffari   user->ctxEulerData = ctxEulerData;
16395bf10c6fSLeila Ghaffari 
16405bf10c6fSLeila Ghaffari   CeedQFunctionContextCreate(ceed, &ctxEuler);
16415bf10c6fSLeila Ghaffari   CeedQFunctionContextSetData(ctxEuler, CEED_MEM_HOST, CEED_USE_POINTER,
16420da62991SLeila Ghaffari                               sizeof *ctxEulerData, ctxEulerData);
16435bf10c6fSLeila Ghaffari 
1644ccaff030SJeremy L Thompson   switch (problemChoice) {
1645ccaff030SJeremy L Thompson   case NS_DENSITY_CURRENT:
16465bf10c6fSLeila Ghaffari     if (qf_rhsVol) CeedQFunctionSetContext(qf_rhsVol, ctxNS);
16475bf10c6fSLeila Ghaffari     if (qf_ifunctionVol) CeedQFunctionSetContext(qf_ifunctionVol, ctxNS);
1648ccaff030SJeremy L Thompson     break;
1649ccaff030SJeremy L Thompson   case NS_ADVECTION:
1650ccaff030SJeremy L Thompson   case NS_ADVECTION2D:
16515bf10c6fSLeila Ghaffari     if (qf_rhsVol) CeedQFunctionSetContext(qf_rhsVol, ctxAdvection2d);
16525bf10c6fSLeila Ghaffari     if (qf_ifunctionVol) CeedQFunctionSetContext(qf_ifunctionVol, ctxAdvection2d);
16535bf10c6fSLeila Ghaffari     if (qf_applySur) CeedQFunctionSetContext(qf_applySur, ctxSurface);
1654e5ed8c30SLeila Ghaffari   case NS_EULER_VORTEX:
16550da62991SLeila Ghaffari     if (qf_ics) CeedQFunctionSetContext(qf_ics, ctxEuler);
16565bf10c6fSLeila Ghaffari     if (qf_rhsVol) CeedQFunctionSetContext(qf_rhsVol, ctxEuler);
165777b27584SLeila Ghaffari     if (qf_ifunctionVol) CeedQFunctionSetContext(qf_ifunctionVol, ctxEuler);
1658a45a933fSLeila Ghaffari     if (qf_applySur) CeedQFunctionSetContext(qf_applySur, ctxEuler);
1659ccaff030SJeremy L Thompson   }
1660ccaff030SJeremy L Thompson 
1661ccaff030SJeremy L Thompson   // Set up PETSc context
1662ccaff030SJeremy L Thompson   // Set up units structure
1663ccaff030SJeremy L Thompson   units->meter = meter;
1664ccaff030SJeremy L Thompson   units->kilogram = kilogram;
1665ccaff030SJeremy L Thompson   units->second = second;
1666ccaff030SJeremy L Thompson   units->Kelvin = Kelvin;
1667ccaff030SJeremy L Thompson   units->Pascal = Pascal;
1668ccaff030SJeremy L Thompson   units->JperkgK = JperkgK;
1669ccaff030SJeremy L Thompson   units->mpersquareds = mpersquareds;
1670ccaff030SJeremy L Thompson   units->WpermK = WpermK;
1671ccaff030SJeremy L Thompson   units->kgpercubicm = kgpercubicm;
1672ccaff030SJeremy L Thompson   units->kgpersquaredms = kgpersquaredms;
1673ccaff030SJeremy L Thompson   units->Joulepercubicm = Joulepercubicm;
167416c0476cSLeila Ghaffari   units->Joule = Joule;
1675ccaff030SJeremy L Thompson 
1676ccaff030SJeremy L Thompson   // Set up user structure
1677ccaff030SJeremy L Thompson   user->comm = comm;
1678ccaff030SJeremy L Thompson   user->outputfreq = outputfreq;
1679ccaff030SJeremy L Thompson   user->contsteps = contsteps;
1680ccaff030SJeremy L Thompson   user->units = units;
1681ccaff030SJeremy L Thompson   user->dm = dm;
1682ccaff030SJeremy L Thompson   user->dmviz = dmviz;
1683ccaff030SJeremy L Thompson   user->interpviz = interpviz;
1684ccaff030SJeremy L Thompson   user->ceed = ceed;
1685ccaff030SJeremy L Thompson 
16868b982baeSLeila Ghaffari   // Calculate qdata and ICs
1687ccaff030SJeremy L Thompson   // Set up state global and local vectors
1688ccaff030SJeremy L Thompson   ierr = VecZeroEntries(Q); CHKERRQ(ierr);
1689ccaff030SJeremy L Thompson 
1690cfa64770SLeila Ghaffari   ierr = VectorPlacePetscVec(q0ceed, Qloc); CHKERRQ(ierr);
1691ccaff030SJeremy L Thompson 
1692ccaff030SJeremy L Thompson   // Apply Setup Ceed Operators
1693ccaff030SJeremy L Thompson   ierr = VectorPlacePetscVec(xcorners, Xloc); CHKERRQ(ierr);
16948b982baeSLeila Ghaffari   CeedOperatorApply(op_setupVol, xcorners, qdata, CEED_REQUEST_IMMEDIATE);
169584d34d69SLeila Ghaffari   ierr = ComputeLumpedMassMatrix(ceed, dm, restrictq, basisq, restrictqdi, qdata,
1696ccaff030SJeremy L Thompson                                  user->M); CHKERRQ(ierr);
1697ccaff030SJeremy L Thompson 
169884d34d69SLeila Ghaffari   ierr = ICs_FixMultiplicity(op_ics, xcorners, q0ceed, dm, Qloc, Q, restrictq,
1699777ff853SJeremy L Thompson                              ctxSetup, 0.0); CHKERRQ(ierr);
1700ccaff030SJeremy L Thompson   if (1) { // Record boundary values from initial condition and override DMPlexInsertBoundaryValues()
1701ccaff030SJeremy L Thompson     // We use this for the main simulation DM because the reference DMPlexInsertBoundaryValues() is very slow.  If we
1702ccaff030SJeremy L Thompson     // disable this, we should still get the same results due to the problem->bc function, but with potentially much
1703ccaff030SJeremy L Thompson     // slower execution.
1704ccaff030SJeremy L Thompson     Vec Qbc;
1705ccaff030SJeremy L Thompson     ierr = DMGetNamedLocalVector(dm, "Qbc", &Qbc); CHKERRQ(ierr);
1706ccaff030SJeremy L Thompson     ierr = VecCopy(Qloc, Qbc); CHKERRQ(ierr);
1707ccaff030SJeremy L Thompson     ierr = VecZeroEntries(Qloc); CHKERRQ(ierr);
1708ccaff030SJeremy L Thompson     ierr = DMGlobalToLocal(dm, Q, INSERT_VALUES, Qloc); CHKERRQ(ierr);
1709ccaff030SJeremy L Thompson     ierr = VecAXPY(Qbc, -1., Qloc); CHKERRQ(ierr);
1710ccaff030SJeremy L Thompson     ierr = DMRestoreNamedLocalVector(dm, "Qbc", &Qbc); CHKERRQ(ierr);
1711ccaff030SJeremy L Thompson     ierr = PetscObjectComposeFunction((PetscObject)dm,
171284d34d69SLeila Ghaffari                                       "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_NS);
171384d34d69SLeila Ghaffari     CHKERRQ(ierr);
1714ccaff030SJeremy L Thompson   }
1715ccaff030SJeremy L Thompson 
1716ccaff030SJeremy L Thompson   MPI_Comm_rank(comm, &rank);
1717d99129b9SLeila Ghaffari   if (!rank) {ierr = PetscMkdir(user->outputdir); CHKERRQ(ierr);}
1718ccaff030SJeremy L Thompson   // Gather initial Q values
1719ccaff030SJeremy L Thompson   // In case of continuation of simulation, set up initial values from binary file
1720ccaff030SJeremy L Thompson   if (contsteps) { // continue from existent solution
1721ccaff030SJeremy L Thompson     PetscViewer viewer;
1722ccaff030SJeremy L Thompson     char filepath[PETSC_MAX_PATH_LEN];
1723ccaff030SJeremy L Thompson     // Read input
1724ccaff030SJeremy L Thompson     ierr = PetscSNPrintf(filepath, sizeof filepath, "%s/ns-solution.bin",
1725d99129b9SLeila Ghaffari                          user->outputdir);
1726ccaff030SJeremy L Thompson     CHKERRQ(ierr);
1727ccaff030SJeremy L Thompson     ierr = PetscViewerBinaryOpen(comm, filepath, FILE_MODE_READ, &viewer);
1728ccaff030SJeremy L Thompson     CHKERRQ(ierr);
1729ccaff030SJeremy L Thompson     ierr = VecLoad(Q, viewer); CHKERRQ(ierr);
1730ccaff030SJeremy L Thompson     ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
1731ccaff030SJeremy L Thompson   }
1732ccaff030SJeremy L Thompson   ierr = DMRestoreLocalVector(dm, &Qloc); CHKERRQ(ierr);
1733ccaff030SJeremy L Thompson 
1734ccaff030SJeremy L Thompson   // Create and setup TS
1735ccaff030SJeremy L Thompson   ierr = TSCreate(comm, &ts); CHKERRQ(ierr);
1736ccaff030SJeremy L Thompson   ierr = TSSetDM(ts, dm); CHKERRQ(ierr);
1737ccaff030SJeremy L Thompson   if (implicit) {
1738ccaff030SJeremy L Thompson     ierr = TSSetType(ts, TSBDF); CHKERRQ(ierr);
1739ccaff030SJeremy L Thompson     if (user->op_ifunction) {
1740ccaff030SJeremy L Thompson       ierr = TSSetIFunction(ts, NULL, IFunction_NS, &user); CHKERRQ(ierr);
1741ccaff030SJeremy L Thompson     } else {                    // Implicit integrators can fall back to using an RHSFunction
1742ccaff030SJeremy L Thompson       ierr = TSSetRHSFunction(ts, NULL, RHS_NS, &user); CHKERRQ(ierr);
1743ccaff030SJeremy L Thompson     }
1744ccaff030SJeremy L Thompson   } else {
1745ccaff030SJeremy L Thompson     if (!user->op_rhs) SETERRQ(comm, PETSC_ERR_ARG_NULL,
1746ccaff030SJeremy L Thompson                                  "Problem does not provide RHSFunction");
1747ccaff030SJeremy L Thompson     ierr = TSSetType(ts, TSRK); CHKERRQ(ierr);
1748ccaff030SJeremy L Thompson     ierr = TSRKSetType(ts, TSRK5F); CHKERRQ(ierr);
1749ccaff030SJeremy L Thompson     ierr = TSSetRHSFunction(ts, NULL, RHS_NS, &user); CHKERRQ(ierr);
1750ccaff030SJeremy L Thompson   }
1751ccaff030SJeremy L Thompson   ierr = TSSetMaxTime(ts, 500. * units->second); CHKERRQ(ierr);
1752ccaff030SJeremy L Thompson   ierr = TSSetExactFinalTime(ts, TS_EXACTFINALTIME_STEPOVER); CHKERRQ(ierr);
1753ccaff030SJeremy L Thompson   ierr = TSSetTimeStep(ts, 1.e-2 * units->second); CHKERRQ(ierr);
1754dc8efd83SLeila Ghaffari   if (test) {ierr = TSSetMaxSteps(ts, 10); CHKERRQ(ierr);}
1755ccaff030SJeremy L Thompson   ierr = TSGetAdapt(ts, &adapt); CHKERRQ(ierr);
1756ccaff030SJeremy L Thompson   ierr = TSAdaptSetStepLimits(adapt,
1757ccaff030SJeremy L Thompson                               1.e-12 * units->second,
1758ccaff030SJeremy L Thompson                               1.e2 * units->second); CHKERRQ(ierr);
1759ccaff030SJeremy L Thompson   ierr = TSSetFromOptions(ts); CHKERRQ(ierr);
1760ccaff030SJeremy L Thompson   if (!contsteps) { // print initial condition
1761dc8efd83SLeila Ghaffari     if (!test) {
1762ccaff030SJeremy L Thompson       ierr = TSMonitor_NS(ts, 0, 0., Q, user); CHKERRQ(ierr);
1763ccaff030SJeremy L Thompson     }
1764ccaff030SJeremy L Thompson   } else { // continue from time of last output
1765ccaff030SJeremy L Thompson     PetscReal time;
1766ccaff030SJeremy L Thompson     PetscInt count;
1767ccaff030SJeremy L Thompson     PetscViewer viewer;
1768ccaff030SJeremy L Thompson     char filepath[PETSC_MAX_PATH_LEN];
1769ccaff030SJeremy L Thompson     ierr = PetscSNPrintf(filepath, sizeof filepath, "%s/ns-time.bin",
1770d99129b9SLeila Ghaffari                          user->outputdir); CHKERRQ(ierr);
1771ccaff030SJeremy L Thompson     ierr = PetscViewerBinaryOpen(comm, filepath, FILE_MODE_READ, &viewer);
1772ccaff030SJeremy L Thompson     CHKERRQ(ierr);
1773ccaff030SJeremy L Thompson     ierr = PetscViewerBinaryRead(viewer, &time, 1, &count, PETSC_REAL);
1774ccaff030SJeremy L Thompson     CHKERRQ(ierr);
1775ccaff030SJeremy L Thompson     ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
1776ccaff030SJeremy L Thompson     ierr = TSSetTime(ts, time * user->units->second); CHKERRQ(ierr);
1777ccaff030SJeremy L Thompson   }
1778dc8efd83SLeila Ghaffari   if (!test) {
1779ccaff030SJeremy L Thompson     ierr = TSMonitorSet(ts, TSMonitor_NS, user, NULL); CHKERRQ(ierr);
1780ccaff030SJeremy L Thompson   }
1781ccaff030SJeremy L Thompson 
1782ccaff030SJeremy L Thompson   // Solve
1783ccaff030SJeremy L Thompson   start = MPI_Wtime();
1784ccaff030SJeremy L Thompson   ierr = PetscBarrier((PetscObject)ts); CHKERRQ(ierr);
1785ccaff030SJeremy L Thompson   ierr = TSSolve(ts, Q); CHKERRQ(ierr);
1786ccaff030SJeremy L Thompson   cpu_time_used = MPI_Wtime() - start;
1787ccaff030SJeremy L Thompson   ierr = TSGetSolveTime(ts, &ftime); CHKERRQ(ierr);
1788ccaff030SJeremy L Thompson   ierr = MPI_Allreduce(MPI_IN_PLACE, &cpu_time_used, 1, MPI_DOUBLE, MPI_MIN,
1789ccaff030SJeremy L Thompson                        comm); CHKERRQ(ierr);
1790dc8efd83SLeila Ghaffari   if (!test) {
1791ccaff030SJeremy L Thompson     ierr = PetscPrintf(PETSC_COMM_WORLD,
179284d34d69SLeila Ghaffari                        "Time taken for solution (sec): %g\n",
1793ccaff030SJeremy L Thompson                        (double)cpu_time_used); CHKERRQ(ierr);
1794ccaff030SJeremy L Thompson   }
1795ccaff030SJeremy L Thompson 
1796ccaff030SJeremy L Thompson   // Get error
1797dc8efd83SLeila Ghaffari   if (problem->non_zero_time && !test) {
1798ccaff030SJeremy L Thompson     Vec Qexact, Qexactloc;
1799ce58a7c9SLeila Ghaffari     PetscReal rel_error, norm_error, norm_exact;
1800ccaff030SJeremy L Thompson     ierr = DMCreateGlobalVector(dm, &Qexact); CHKERRQ(ierr);
1801ccaff030SJeremy L Thompson     ierr = DMGetLocalVector(dm, &Qexactloc); CHKERRQ(ierr);
1802ccaff030SJeremy L Thompson     ierr = VecGetSize(Qexactloc, &lnodes); CHKERRQ(ierr);
1803ccaff030SJeremy L Thompson 
180484d34d69SLeila Ghaffari     ierr = ICs_FixMultiplicity(op_ics, xcorners, q0ceed, dm, Qexactloc, Qexact,
1805777ff853SJeremy L Thompson                                restrictq, ctxSetup, ftime); CHKERRQ(ierr);
1806ce58a7c9SLeila Ghaffari     ierr = VecNorm(Qexact, NORM_1, &norm_exact); CHKERRQ(ierr);
1807ccaff030SJeremy L Thompson     ierr = VecAXPY(Q, -1.0, Qexact);  CHKERRQ(ierr);
1808ce58a7c9SLeila Ghaffari     ierr = VecNorm(Q, NORM_1, &norm_error); CHKERRQ(ierr);
1809ce58a7c9SLeila Ghaffari     rel_error = norm_error / norm_exact;
1810cfa64770SLeila Ghaffari     CeedVectorDestroy(&q0ceed);
1811ccaff030SJeremy L Thompson     ierr = PetscPrintf(PETSC_COMM_WORLD,
1812ce58a7c9SLeila Ghaffari                        "Relative Error: %g\n",
1813ce58a7c9SLeila Ghaffari                        (double)rel_error); CHKERRQ(ierr);
181484d34d69SLeila Ghaffari     // Clean up vectors
181584d34d69SLeila Ghaffari     ierr = DMRestoreLocalVector(dm, &Qexactloc); CHKERRQ(ierr);
181684d34d69SLeila Ghaffari     ierr = VecDestroy(&Qexact); CHKERRQ(ierr);
1817ccaff030SJeremy L Thompson   }
1818ccaff030SJeremy L Thompson 
1819ccaff030SJeremy L Thompson   // Output Statistics
1820ccaff030SJeremy L Thompson   ierr = TSGetStepNumber(ts, &steps); CHKERRQ(ierr);
1821dc8efd83SLeila Ghaffari   if (!test) {
1822ccaff030SJeremy L Thompson     ierr = PetscPrintf(PETSC_COMM_WORLD,
1823ccaff030SJeremy L Thompson                        "Time integrator took %D time steps to reach final time %g\n",
1824ccaff030SJeremy L Thompson                        steps, (double)ftime); CHKERRQ(ierr);
1825ccaff030SJeremy L Thompson   }
1826*d7a15aecSLeila Ghaffari   // Output numerical values from command line
1827*d7a15aecSLeila Ghaffari   ierr = VecViewFromOptions(Q, NULL, "-vec_view"); CHKERRQ(ierr);
182884d34d69SLeila Ghaffari 
1829335ea220SLeila Ghaffari   // Compare reference solution values with current test run for CI
1830dc8efd83SLeila Ghaffari   if (test) {
183184d34d69SLeila Ghaffari     PetscViewer viewer;
183284d34d69SLeila Ghaffari     // Read reference file
183384d34d69SLeila Ghaffari     Vec Qref;
183484d34d69SLeila Ghaffari     PetscReal error, Qrefnorm;
183584d34d69SLeila Ghaffari     ierr = VecDuplicate(Q, &Qref); CHKERRQ(ierr);
1836dc8efd83SLeila Ghaffari     ierr = PetscViewerBinaryOpen(comm, filepath, FILE_MODE_READ, &viewer);
183784d34d69SLeila Ghaffari     CHKERRQ(ierr);
183884d34d69SLeila Ghaffari     ierr = VecLoad(Qref, viewer); CHKERRQ(ierr);
183984d34d69SLeila Ghaffari     ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
184084d34d69SLeila Ghaffari 
184184d34d69SLeila Ghaffari     // Compute error with respect to reference solution
184284d34d69SLeila Ghaffari     ierr = VecAXPY(Q, -1.0, Qref);  CHKERRQ(ierr);
184384d34d69SLeila Ghaffari     ierr = VecNorm(Qref, NORM_MAX, &Qrefnorm); CHKERRQ(ierr);
184484d34d69SLeila Ghaffari     ierr = VecScale(Q, 1./Qrefnorm); CHKERRQ(ierr);
184584d34d69SLeila Ghaffari     ierr = VecNorm(Q, NORM_MAX, &error); CHKERRQ(ierr);
184684d34d69SLeila Ghaffari     ierr = VecDestroy(&Qref); CHKERRQ(ierr);
184784d34d69SLeila Ghaffari     // Check error
1848dc8efd83SLeila Ghaffari     if (error > testtol) {
184984d34d69SLeila Ghaffari       ierr = PetscPrintf(PETSC_COMM_WORLD,
185084d34d69SLeila Ghaffari                          "Test failed with error norm %g\n",
185184d34d69SLeila Ghaffari                          (double)error); CHKERRQ(ierr);
185284d34d69SLeila Ghaffari     }
185384d34d69SLeila Ghaffari     ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
185484d34d69SLeila Ghaffari   }
18559cf88b28Svaleriabarra 
1856ccaff030SJeremy L Thompson   // Clean up libCEED
18578b982baeSLeila Ghaffari   CeedVectorDestroy(&qdata);
1858ccaff030SJeremy L Thompson   CeedVectorDestroy(&user->qceed);
1859ccaff030SJeremy L Thompson   CeedVectorDestroy(&user->qdotceed);
1860ccaff030SJeremy L Thompson   CeedVectorDestroy(&user->gceed);
1861ccaff030SJeremy L Thompson   CeedVectorDestroy(&xcorners);
186284d34d69SLeila Ghaffari   CeedBasisDestroy(&basisq);
186384d34d69SLeila Ghaffari   CeedBasisDestroy(&basisx);
186484d34d69SLeila Ghaffari   CeedBasisDestroy(&basisxc);
186584d34d69SLeila Ghaffari   CeedElemRestrictionDestroy(&restrictq);
186684d34d69SLeila Ghaffari   CeedElemRestrictionDestroy(&restrictx);
186784d34d69SLeila Ghaffari   CeedElemRestrictionDestroy(&restrictqdi);
1868ea6e0f84SLeila Ghaffari   CeedQFunctionDestroy(&qf_setupVol);
1869ccaff030SJeremy L Thompson   CeedQFunctionDestroy(&qf_ics);
1870ea6e0f84SLeila Ghaffari   CeedQFunctionDestroy(&qf_rhsVol);
1871ea6e0f84SLeila Ghaffari   CeedQFunctionDestroy(&qf_ifunctionVol);
1872777ff853SJeremy L Thompson   CeedQFunctionContextDestroy(&ctxSetup);
1873777ff853SJeremy L Thompson   CeedQFunctionContextDestroy(&ctxNS);
1874777ff853SJeremy L Thompson   CeedQFunctionContextDestroy(&ctxAdvection2d);
1875777ff853SJeremy L Thompson   CeedQFunctionContextDestroy(&ctxSurface);
18760da62991SLeila Ghaffari   CeedQFunctionContextDestroy(&ctxEuler);
1877ea6e0f84SLeila Ghaffari   CeedOperatorDestroy(&op_setupVol);
1878ccaff030SJeremy L Thompson   CeedOperatorDestroy(&op_ics);
18796a0edaf9SLeila Ghaffari   CeedOperatorDestroy(&user->op_rhs_vol);
18806a0edaf9SLeila Ghaffari   CeedOperatorDestroy(&user->op_ifunction_vol);
18816a0edaf9SLeila Ghaffari   CeedDestroy(&ceed);
18826a0edaf9SLeila Ghaffari   CeedBasisDestroy(&basisqSur);
18836a0edaf9SLeila Ghaffari   CeedBasisDestroy(&basisxSur);
18846a0edaf9SLeila Ghaffari   CeedBasisDestroy(&basisxcSur);
18856a0edaf9SLeila Ghaffari   CeedQFunctionDestroy(&qf_setupSur);
18867ed8b9c7SLeila Ghaffari   CeedQFunctionDestroy(&qf_applySur);
1887ccaff030SJeremy L Thompson   CeedOperatorDestroy(&user->op_rhs);
1888ccaff030SJeremy L Thompson   CeedOperatorDestroy(&user->op_ifunction);
1889ccaff030SJeremy L Thompson 
1890ccaff030SJeremy L Thompson   // Clean up PETSc
1891ccaff030SJeremy L Thompson   ierr = VecDestroy(&Q); CHKERRQ(ierr);
1892ccaff030SJeremy L Thompson   ierr = VecDestroy(&user->M); CHKERRQ(ierr);
1893ccaff030SJeremy L Thompson   ierr = MatDestroy(&interpviz); CHKERRQ(ierr);
1894ccaff030SJeremy L Thompson   ierr = DMDestroy(&dmviz); CHKERRQ(ierr);
1895ccaff030SJeremy L Thompson   ierr = TSDestroy(&ts); CHKERRQ(ierr);
1896ccaff030SJeremy L Thompson   ierr = DMDestroy(&dm); CHKERRQ(ierr);
1897ccaff030SJeremy L Thompson   ierr = PetscFree(units); CHKERRQ(ierr);
1898ccaff030SJeremy L Thompson   ierr = PetscFree(user); CHKERRQ(ierr);
18995bf10c6fSLeila Ghaffari   ierr = PetscFree(ctxEulerData); CHKERRQ(ierr);
1900ccaff030SJeremy L Thompson   return PetscFinalize();
1901ccaff030SJeremy L Thompson }
1902