xref: /libCEED/examples/fluids/navierstokes.c (revision 2d1f40fd388729b6f38678d8a960348121c6b257)
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,
811*2d1f40fdSLeila Ghaffari                               SimpleBC bc, void *ctxSetupData) {
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,
874*2d1f40fdSLeila Ghaffari                              bc->nwall, bc->walls, ctxSetupData); 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,
12911184866aSLeila Ghaffari     .wind_type = wind_type,
1292ccaff030SJeremy L Thompson   };
1293ccaff030SJeremy L Thompson 
129484d34d69SLeila Ghaffari   // Create the mesh
1295ccaff030SJeremy L Thompson   {
1296ccaff030SJeremy L Thompson     const PetscReal scale[3] = {lx, ly, lz};
1297ccaff030SJeremy L Thompson     ierr = DMPlexCreateBoxMesh(comm, dim, PETSC_FALSE, NULL, NULL, scale,
12982561194eSLeila Ghaffari                                NULL, PETSC_TRUE, &dm);
1299ccaff030SJeremy L Thompson     CHKERRQ(ierr);
1300ccaff030SJeremy L Thompson   }
130184d34d69SLeila Ghaffari 
130284d34d69SLeila Ghaffari   // Distribute the mesh over processes
130384d34d69SLeila Ghaffari   {
1304ccaff030SJeremy L Thompson     DM               dmDist = NULL;
1305ccaff030SJeremy L Thompson     PetscPartitioner part;
1306ccaff030SJeremy L Thompson 
1307ccaff030SJeremy L Thompson     ierr = DMPlexGetPartitioner(dm, &part); CHKERRQ(ierr);
1308ccaff030SJeremy L Thompson     ierr = PetscPartitionerSetFromOptions(part); CHKERRQ(ierr);
1309ccaff030SJeremy L Thompson     ierr = DMPlexDistribute(dm, 0, NULL, &dmDist); CHKERRQ(ierr);
1310ccaff030SJeremy L Thompson     if (dmDist) {
1311ccaff030SJeremy L Thompson       ierr = DMDestroy(&dm); CHKERRQ(ierr);
1312ccaff030SJeremy L Thompson       dm  = dmDist;
1313ccaff030SJeremy L Thompson     }
1314ccaff030SJeremy L Thompson   }
1315ccaff030SJeremy L Thompson   ierr = DMViewFromOptions(dm, NULL, "-dm_view"); CHKERRQ(ierr);
1316ccaff030SJeremy L Thompson 
131784d34d69SLeila Ghaffari   // Setup DM
1318ccaff030SJeremy L Thompson   ierr = DMLocalizeCoordinates(dm); CHKERRQ(ierr);
1319ccaff030SJeremy L Thompson   ierr = DMSetFromOptions(dm); CHKERRQ(ierr);
1320*2d1f40fdSLeila Ghaffari   ierr = SetUpDM(dm, problem, degree, &bc, &ctxSetupData);
13215bf10c6fSLeila Ghaffari   CHKERRQ(ierr);
132284d34d69SLeila Ghaffari 
132384d34d69SLeila Ghaffari   // Refine DM for high-order viz
1324ccaff030SJeremy L Thompson   dmviz = NULL;
1325ccaff030SJeremy L Thompson   interpviz = NULL;
1326ccaff030SJeremy L Thompson   if (viz_refine) {
1327ff6701fcSJed Brown     DM dmhierarchy[viz_refine+1];
1328ff6701fcSJed Brown 
1329ccaff030SJeremy L Thompson     ierr = DMPlexSetRefinementUniform(dm, PETSC_TRUE); CHKERRQ(ierr);
1330ff6701fcSJed Brown     dmhierarchy[0] = dm;
133184d34d69SLeila Ghaffari     for (PetscInt i = 0, d = degree; i < viz_refine; i++) {
1332ff6701fcSJed Brown       Mat interp_next;
1333ff6701fcSJed Brown 
1334ff6701fcSJed Brown       ierr = DMRefine(dmhierarchy[i], MPI_COMM_NULL, &dmhierarchy[i+1]);
1335ccaff030SJeremy L Thompson       CHKERRQ(ierr);
1336bc6a41f7SJed Brown       ierr = DMClearDS(dmhierarchy[i+1]); CHKERRQ(ierr);
1337bc6a41f7SJed Brown       ierr = DMClearFields(dmhierarchy[i+1]); CHKERRQ(ierr);
1338ff6701fcSJed Brown       ierr = DMSetCoarseDM(dmhierarchy[i+1], dmhierarchy[i]); CHKERRQ(ierr);
1339ff6701fcSJed Brown       d = (d + 1) / 2;
1340ff6701fcSJed Brown       if (i + 1 == viz_refine) d = 1;
1341*2d1f40fdSLeila Ghaffari       ierr = SetUpDM(dmhierarchy[i+1], problem, d, &bc, &ctxSetupData);
1342*2d1f40fdSLeila Ghaffari       CHKERRQ(ierr);
1343ff6701fcSJed Brown       ierr = DMCreateInterpolation(dmhierarchy[i], dmhierarchy[i+1],
1344ff6701fcSJed Brown                                    &interp_next, NULL); CHKERRQ(ierr);
1345ff6701fcSJed Brown       if (!i) interpviz = interp_next;
1346ff6701fcSJed Brown       else {
1347ff6701fcSJed Brown         Mat C;
1348ff6701fcSJed Brown         ierr = MatMatMult(interp_next, interpviz, MAT_INITIAL_MATRIX,
1349ff6701fcSJed Brown                           PETSC_DECIDE, &C); CHKERRQ(ierr);
1350ff6701fcSJed Brown         ierr = MatDestroy(&interp_next); CHKERRQ(ierr);
1351ff6701fcSJed Brown         ierr = MatDestroy(&interpviz); CHKERRQ(ierr);
1352ff6701fcSJed Brown         interpviz = C;
1353ff6701fcSJed Brown       }
1354ff6701fcSJed Brown     }
1355cb3e2689Svaleriabarra     for (PetscInt i=1; i<viz_refine; i++) {
1356ff6701fcSJed Brown       ierr = DMDestroy(&dmhierarchy[i]); CHKERRQ(ierr);
1357cb3e2689Svaleriabarra     }
1358ff6701fcSJed Brown     dmviz = dmhierarchy[viz_refine];
1359ccaff030SJeremy L Thompson   }
1360ccaff030SJeremy L Thompson   ierr = DMCreateGlobalVector(dm, &Q); CHKERRQ(ierr);
1361ccaff030SJeremy L Thompson   ierr = DMGetLocalVector(dm, &Qloc); CHKERRQ(ierr);
1362ccaff030SJeremy L Thompson   ierr = VecGetSize(Qloc, &lnodes); CHKERRQ(ierr);
1363ccaff030SJeremy L Thompson   lnodes /= ncompq;
1364ccaff030SJeremy L Thompson 
136584d34d69SLeila Ghaffari   // Initialize CEED
136684d34d69SLeila Ghaffari   CeedInit(ceedresource, &ceed);
136784d34d69SLeila Ghaffari   // Set memtype
136884d34d69SLeila Ghaffari   CeedMemType memtypebackend;
136984d34d69SLeila Ghaffari   CeedGetPreferredMemType(ceed, &memtypebackend);
137084d34d69SLeila Ghaffari   // Check memtype compatibility
137184d34d69SLeila Ghaffari   if (!setmemtyperequest)
137284d34d69SLeila Ghaffari     memtyperequested = memtypebackend;
137384d34d69SLeila Ghaffari   else if (!petschavecuda && memtyperequested == CEED_MEM_DEVICE)
137484d34d69SLeila Ghaffari     SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS,
137584d34d69SLeila Ghaffari              "PETSc was not built with CUDA. "
137684d34d69SLeila Ghaffari              "Requested MemType CEED_MEM_DEVICE is not supported.", NULL);
137784d34d69SLeila Ghaffari 
137884d34d69SLeila Ghaffari   // Set number of 1D nodes and quadrature points
137984d34d69SLeila Ghaffari   numP = degree + 1;
138084d34d69SLeila Ghaffari   numQ = numP + qextra;
138184d34d69SLeila Ghaffari 
138284d34d69SLeila Ghaffari   // Print summary
1383dc8efd83SLeila Ghaffari   if (!test) {
1384ccaff030SJeremy L Thompson     CeedInt gdofs, odofs;
1385ccaff030SJeremy L Thompson     int comm_size;
1386ccaff030SJeremy L Thompson     char box_faces_str[PETSC_MAX_PATH_LEN] = "NONE";
1387ccaff030SJeremy L Thompson     ierr = VecGetSize(Q, &gdofs); CHKERRQ(ierr);
1388ccaff030SJeremy L Thompson     ierr = VecGetLocalSize(Q, &odofs); CHKERRQ(ierr);
138984d34d69SLeila Ghaffari     gnodes = gdofs/ncompq;
1390ccaff030SJeremy L Thompson     ierr = MPI_Comm_size(comm, &comm_size); CHKERRQ(ierr);
1391ccaff030SJeremy L Thompson     ierr = PetscOptionsGetString(NULL, NULL, "-dm_plex_box_faces", box_faces_str,
1392ccaff030SJeremy L Thompson                                  sizeof(box_faces_str), NULL); CHKERRQ(ierr);
139384d34d69SLeila Ghaffari     const char *usedresource;
139484d34d69SLeila Ghaffari     CeedGetResource(ceed, &usedresource);
1395ccaff030SJeremy L Thompson 
139684d34d69SLeila Ghaffari     ierr = PetscPrintf(comm,
139784d34d69SLeila Ghaffari                        "\n-- Navier-Stokes solver - libCEED + PETSc --\n"
139884d34d69SLeila Ghaffari                        "  rank(s)                              : %d\n"
139984d34d69SLeila Ghaffari                        "  Problem:\n"
140084d34d69SLeila Ghaffari                        "    Problem Name                       : %s\n"
140184d34d69SLeila Ghaffari                        "    Stabilization                      : %s\n"
140284d34d69SLeila Ghaffari                        "  PETSc:\n"
140384d34d69SLeila Ghaffari                        "    Box Faces                          : %s\n"
140484d34d69SLeila Ghaffari                        "  libCEED:\n"
140584d34d69SLeila Ghaffari                        "    libCEED Backend                    : %s\n"
140684d34d69SLeila Ghaffari                        "    libCEED Backend MemType            : %s\n"
140784d34d69SLeila Ghaffari                        "    libCEED User Requested MemType     : %s\n"
140884d34d69SLeila Ghaffari                        "  Mesh:\n"
140984d34d69SLeila Ghaffari                        "    Number of 1D Basis Nodes (P)       : %d\n"
141084d34d69SLeila Ghaffari                        "    Number of 1D Quadrature Points (Q) : %d\n"
141184d34d69SLeila Ghaffari                        "    Global DoFs                        : %D\n"
141284d34d69SLeila Ghaffari                        "    Owned DoFs                         : %D\n"
141384d34d69SLeila Ghaffari                        "    DoFs per node                      : %D\n"
141484d34d69SLeila Ghaffari                        "    Global nodes                       : %D\n"
141584d34d69SLeila Ghaffari                        "    Owned nodes                        : %D\n",
141684d34d69SLeila Ghaffari                        comm_size, problemTypes[problemChoice],
141784d34d69SLeila Ghaffari                        StabilizationTypes[stab], box_faces_str, usedresource,
141884d34d69SLeila Ghaffari                        CeedMemTypes[memtypebackend],
141984d34d69SLeila Ghaffari                        (setmemtyperequest) ?
142084d34d69SLeila Ghaffari                        CeedMemTypes[memtyperequested] : "none",
142184d34d69SLeila Ghaffari                        numP, numQ, gdofs, odofs, ncompq, gnodes, lnodes);
142284d34d69SLeila Ghaffari     CHKERRQ(ierr);
14230c6c0b13SLeila Ghaffari   }
14240c6c0b13SLeila Ghaffari 
1425ccaff030SJeremy L Thompson   // Set up global mass vector
1426ccaff030SJeremy L Thompson   ierr = VecDuplicate(Q, &user->M); CHKERRQ(ierr);
1427ccaff030SJeremy L Thompson 
142884d34d69SLeila Ghaffari   // Set up libCEED
1429ccaff030SJeremy L Thompson   // CEED Bases
1430ccaff030SJeremy L Thompson   CeedInit(ceedresource, &ceed);
143184d34d69SLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dim, ncompq, numP, numQ, CEED_GAUSS,
143284d34d69SLeila Ghaffari                                   &basisq);
143384d34d69SLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dim, ncompx, 2, numQ, CEED_GAUSS,
143484d34d69SLeila Ghaffari                                   &basisx);
143584d34d69SLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dim, ncompx, 2, numP,
143684d34d69SLeila Ghaffari                                   CEED_GAUSS_LOBATTO, &basisxc);
1437ccaff030SJeremy L Thompson   ierr = DMGetCoordinateDM(dm, &dmcoord); CHKERRQ(ierr);
1438ccaff030SJeremy L Thompson   ierr = DMPlexSetClosurePermutationTensor(dmcoord, PETSC_DETERMINE, NULL);
1439ccaff030SJeremy L Thompson   CHKERRQ(ierr);
1440ccaff030SJeremy L Thompson 
1441ccaff030SJeremy L Thompson   // CEED Restrictions
14421e150236SLeila Ghaffari   ierr = GetRestrictionForDomain(ceed, dm, 0, 0, 0, numP, numQ,
144384d34d69SLeila Ghaffari                                  qdatasizeVol, &restrictq, &restrictx,
144484d34d69SLeila Ghaffari                                  &restrictqdi); CHKERRQ(ierr);
1445ccaff030SJeremy L Thompson 
1446ccaff030SJeremy L Thompson   ierr = DMGetCoordinatesLocal(dm, &Xloc); CHKERRQ(ierr);
1447ccaff030SJeremy L Thompson   ierr = CreateVectorFromPetscVec(ceed, Xloc, &xcorners); CHKERRQ(ierr);
1448ccaff030SJeremy L Thompson 
1449ccaff030SJeremy L Thompson   // Create the CEED vectors that will be needed in setup
1450bd910870SLeila Ghaffari   CeedInt NqptsVol;
145184d34d69SLeila Ghaffari   CeedBasisGetNumQuadraturePoints(basisq, &NqptsVol);
145284d34d69SLeila Ghaffari   CeedElemRestrictionGetNumElements(restrictq, &localNelemVol);
14538b982baeSLeila Ghaffari   CeedVectorCreate(ceed, qdatasizeVol*localNelemVol*NqptsVol, &qdata);
145484d34d69SLeila Ghaffari   CeedElemRestrictionCreateVector(restrictq, &q0ceed, NULL);
1455ccaff030SJeremy L Thompson 
1456ccaff030SJeremy L Thompson   // Create the Q-function that builds the quadrature data for the NS operator
1457ea6e0f84SLeila Ghaffari   CeedQFunctionCreateInterior(ceed, 1, problem->setupVol, problem->setupVol_loc,
1458ea6e0f84SLeila Ghaffari                               &qf_setupVol);
1459ea6e0f84SLeila Ghaffari   CeedQFunctionAddInput(qf_setupVol, "dx", ncompx*dim, CEED_EVAL_GRAD);
1460ea6e0f84SLeila Ghaffari   CeedQFunctionAddInput(qf_setupVol, "weight", 1, CEED_EVAL_WEIGHT);
14618b982baeSLeila Ghaffari   CeedQFunctionAddOutput(qf_setupVol, "qdata", qdatasizeVol, CEED_EVAL_NONE);
1462ccaff030SJeremy L Thompson 
1463ccaff030SJeremy L Thompson   // Create the Q-function that sets the ICs of the operator
1464ccaff030SJeremy L Thompson   CeedQFunctionCreateInterior(ceed, 1, problem->ics, problem->ics_loc, &qf_ics);
1465ccaff030SJeremy L Thompson   CeedQFunctionAddInput(qf_ics, "x", ncompx, CEED_EVAL_INTERP);
1466ccaff030SJeremy L Thompson   CeedQFunctionAddOutput(qf_ics, "q0", ncompq, CEED_EVAL_NONE);
1467ccaff030SJeremy L Thompson 
1468ea6e0f84SLeila Ghaffari   qf_rhsVol = NULL;
1469ea6e0f84SLeila Ghaffari   if (problem->applyVol_rhs) { // Create the Q-function that defines the action of the RHS operator
1470ea6e0f84SLeila Ghaffari     CeedQFunctionCreateInterior(ceed, 1, problem->applyVol_rhs,
1471ea6e0f84SLeila Ghaffari                                 problem->applyVol_rhs_loc, &qf_rhsVol);
1472ea6e0f84SLeila Ghaffari     CeedQFunctionAddInput(qf_rhsVol, "q", ncompq, CEED_EVAL_INTERP);
1473ea6e0f84SLeila Ghaffari     CeedQFunctionAddInput(qf_rhsVol, "dq", ncompq*dim, CEED_EVAL_GRAD);
14748b982baeSLeila Ghaffari     CeedQFunctionAddInput(qf_rhsVol, "qdata", qdatasizeVol, CEED_EVAL_NONE);
1475ea6e0f84SLeila Ghaffari     CeedQFunctionAddInput(qf_rhsVol, "x", ncompx, CEED_EVAL_INTERP);
1476ea6e0f84SLeila Ghaffari     CeedQFunctionAddOutput(qf_rhsVol, "v", ncompq, CEED_EVAL_INTERP);
1477ea6e0f84SLeila Ghaffari     CeedQFunctionAddOutput(qf_rhsVol, "dv", ncompq*dim, CEED_EVAL_GRAD);
1478ccaff030SJeremy L Thompson   }
1479ccaff030SJeremy L Thompson 
1480ea6e0f84SLeila Ghaffari   qf_ifunctionVol = NULL;
1481ea6e0f84SLeila Ghaffari   if (problem->applyVol_ifunction) { // Create the Q-function that defines the action of the IFunction
1482ea6e0f84SLeila Ghaffari     CeedQFunctionCreateInterior(ceed, 1, problem->applyVol_ifunction,
1483ea6e0f84SLeila Ghaffari                                 problem->applyVol_ifunction_loc, &qf_ifunctionVol);
1484ea6e0f84SLeila Ghaffari     CeedQFunctionAddInput(qf_ifunctionVol, "q", ncompq, CEED_EVAL_INTERP);
1485ea6e0f84SLeila Ghaffari     CeedQFunctionAddInput(qf_ifunctionVol, "dq", ncompq*dim, CEED_EVAL_GRAD);
1486ea6e0f84SLeila Ghaffari     CeedQFunctionAddInput(qf_ifunctionVol, "qdot", ncompq, CEED_EVAL_INTERP);
14878b982baeSLeila Ghaffari     CeedQFunctionAddInput(qf_ifunctionVol, "qdata", qdatasizeVol, CEED_EVAL_NONE);
1488ea6e0f84SLeila Ghaffari     CeedQFunctionAddInput(qf_ifunctionVol, "x", ncompx, CEED_EVAL_INTERP);
1489ea6e0f84SLeila Ghaffari     CeedQFunctionAddOutput(qf_ifunctionVol, "v", ncompq, CEED_EVAL_INTERP);
1490ea6e0f84SLeila Ghaffari     CeedQFunctionAddOutput(qf_ifunctionVol, "dv", ncompq*dim, CEED_EVAL_GRAD);
1491ccaff030SJeremy L Thompson   }
1492ccaff030SJeremy L Thompson 
1493ccaff030SJeremy L Thompson   // Create the operator that builds the quadrature data for the NS operator
1494ea6e0f84SLeila Ghaffari   CeedOperatorCreate(ceed, qf_setupVol, NULL, NULL, &op_setupVol);
149584d34d69SLeila Ghaffari   CeedOperatorSetField(op_setupVol, "dx", restrictx, basisx, CEED_VECTOR_ACTIVE);
1496ea6e0f84SLeila Ghaffari   CeedOperatorSetField(op_setupVol, "weight", CEED_ELEMRESTRICTION_NONE,
149784d34d69SLeila Ghaffari                        basisx, CEED_VECTOR_NONE);
149884d34d69SLeila Ghaffari   CeedOperatorSetField(op_setupVol, "qdata", restrictqdi,
1499ccaff030SJeremy L Thompson                        CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
1500ccaff030SJeremy L Thompson 
1501ccaff030SJeremy L Thompson   // Create the operator that sets the ICs
1502ccaff030SJeremy L Thompson   CeedOperatorCreate(ceed, qf_ics, NULL, NULL, &op_ics);
150384d34d69SLeila Ghaffari   CeedOperatorSetField(op_ics, "x", restrictx, basisxc, CEED_VECTOR_ACTIVE);
150484d34d69SLeila Ghaffari   CeedOperatorSetField(op_ics, "q0", restrictq,
1505ccaff030SJeremy L Thompson                        CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE);
1506ccaff030SJeremy L Thompson 
150784d34d69SLeila Ghaffari   CeedElemRestrictionCreateVector(restrictq, &user->qceed, NULL);
150884d34d69SLeila Ghaffari   CeedElemRestrictionCreateVector(restrictq, &user->qdotceed, NULL);
150984d34d69SLeila Ghaffari   CeedElemRestrictionCreateVector(restrictq, &user->gceed, NULL);
1510ccaff030SJeremy L Thompson 
1511ea6e0f84SLeila Ghaffari   if (qf_rhsVol) { // Create the RHS physics operator
1512ccaff030SJeremy L Thompson     CeedOperator op;
1513ea6e0f84SLeila Ghaffari     CeedOperatorCreate(ceed, qf_rhsVol, NULL, NULL, &op);
151484d34d69SLeila Ghaffari     CeedOperatorSetField(op, "q", restrictq, basisq, CEED_VECTOR_ACTIVE);
151584d34d69SLeila Ghaffari     CeedOperatorSetField(op, "dq", restrictq, basisq, CEED_VECTOR_ACTIVE);
151684d34d69SLeila Ghaffari     CeedOperatorSetField(op, "qdata", restrictqdi,
15178b982baeSLeila Ghaffari                          CEED_BASIS_COLLOCATED, qdata);
151884d34d69SLeila Ghaffari     CeedOperatorSetField(op, "x", restrictx, basisx, xcorners);
151984d34d69SLeila Ghaffari     CeedOperatorSetField(op, "v", restrictq, basisq, CEED_VECTOR_ACTIVE);
152084d34d69SLeila Ghaffari     CeedOperatorSetField(op, "dv", restrictq, basisq, CEED_VECTOR_ACTIVE);
1521d3630711SJed Brown     user->op_rhs_vol = op;
1522ccaff030SJeremy L Thompson   }
1523ccaff030SJeremy L Thompson 
1524ea6e0f84SLeila Ghaffari   if (qf_ifunctionVol) { // Create the IFunction operator
1525ccaff030SJeremy L Thompson     CeedOperator op;
1526ea6e0f84SLeila Ghaffari     CeedOperatorCreate(ceed, qf_ifunctionVol, NULL, NULL, &op);
152784d34d69SLeila Ghaffari     CeedOperatorSetField(op, "q", restrictq, basisq, CEED_VECTOR_ACTIVE);
152884d34d69SLeila Ghaffari     CeedOperatorSetField(op, "dq", restrictq, basisq, CEED_VECTOR_ACTIVE);
152984d34d69SLeila Ghaffari     CeedOperatorSetField(op, "qdot", restrictq, basisq, user->qdotceed);
153084d34d69SLeila Ghaffari     CeedOperatorSetField(op, "qdata", restrictqdi,
15318b982baeSLeila Ghaffari                          CEED_BASIS_COLLOCATED, qdata);
153284d34d69SLeila Ghaffari     CeedOperatorSetField(op, "x", restrictx, basisx, xcorners);
153384d34d69SLeila Ghaffari     CeedOperatorSetField(op, "v", restrictq, basisq, CEED_VECTOR_ACTIVE);
153484d34d69SLeila Ghaffari     CeedOperatorSetField(op, "dv", restrictq, basisq, CEED_VECTOR_ACTIVE);
1535d3630711SJed Brown     user->op_ifunction_vol = op;
1536ccaff030SJeremy L Thompson   }
1537ccaff030SJeremy L Thompson 
15386a0edaf9SLeila Ghaffari   // Set up CEED for the boundaries
15396a0edaf9SLeila Ghaffari   CeedInt height = 1;
15406a0edaf9SLeila Ghaffari   CeedInt dimSur = dim - height;
15411e150236SLeila Ghaffari   CeedInt numP_Sur = degree + 1;
15421e150236SLeila Ghaffari   CeedInt numQ_Sur = numP_Sur + qextraSur;
1543cfa64770SLeila Ghaffari   const CeedInt qdatasizeSur = problem->qdatasizeSur;
1544cfa64770SLeila Ghaffari   CeedBasis basisxSur, basisxcSur, basisqSur;
1545cfa64770SLeila Ghaffari   CeedInt NqptsSur;
1546e2043960SLeila Ghaffari   CeedQFunction qf_setupSur, qf_applySur;
1547cfa64770SLeila Ghaffari 
1548cfa64770SLeila Ghaffari   // CEED bases for the boundaries
1549ebb4b9bdSLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dimSur, ncompq, numP_Sur, numQ_Sur,
1550ebb4b9bdSLeila Ghaffari                                   CEED_GAUSS,
15516a0edaf9SLeila Ghaffari                                   &basisqSur);
15526a0edaf9SLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dimSur, ncompx, 2, numQ_Sur, CEED_GAUSS,
15536a0edaf9SLeila Ghaffari                                   &basisxSur);
15546a0edaf9SLeila Ghaffari   CeedBasisCreateTensorH1Lagrange(ceed, dimSur, ncompx, 2, numP_Sur,
15556a0edaf9SLeila Ghaffari                                   CEED_GAUSS_LOBATTO, &basisxcSur);
15566a0edaf9SLeila Ghaffari   CeedBasisGetNumQuadraturePoints(basisqSur, &NqptsSur);
15576a0edaf9SLeila Ghaffari 
1558cfa64770SLeila Ghaffari   // Create the Q-function that builds the quadrature data for the Surface operator
15596a0edaf9SLeila Ghaffari   CeedQFunctionCreateInterior(ceed, 1, problem->setupSur, problem->setupSur_loc,
15606a0edaf9SLeila Ghaffari                               &qf_setupSur);
15616a0edaf9SLeila Ghaffari   CeedQFunctionAddInput(qf_setupSur, "dx", ncompx*dimSur, CEED_EVAL_GRAD);
15626a0edaf9SLeila Ghaffari   CeedQFunctionAddInput(qf_setupSur, "weight", 1, CEED_EVAL_WEIGHT);
15636a0edaf9SLeila Ghaffari   CeedQFunctionAddOutput(qf_setupSur, "qdataSur", qdatasizeSur, CEED_EVAL_NONE);
15646a0edaf9SLeila Ghaffari 
15657659d40cSLeila Ghaffari   // Creat Q-Function for Boundaries
156686ba6f09SLeila Ghaffari   // -- Defined for Advection(2d) test cases
15677ed8b9c7SLeila Ghaffari   qf_applySur = NULL;
15687659d40cSLeila Ghaffari   if (problem->applySur) {
15697659d40cSLeila Ghaffari     CeedQFunctionCreateInterior(ceed, 1, problem->applySur,
15707ed8b9c7SLeila Ghaffari                                 problem->applySur_loc, &qf_applySur);
15717ed8b9c7SLeila Ghaffari     CeedQFunctionAddInput(qf_applySur, "q", ncompq, CEED_EVAL_INTERP);
15727ed8b9c7SLeila Ghaffari     CeedQFunctionAddInput(qf_applySur, "qdataSur", qdatasizeSur, CEED_EVAL_NONE);
15737ed8b9c7SLeila Ghaffari     CeedQFunctionAddInput(qf_applySur, "x", ncompx, CEED_EVAL_INTERP);
15747ed8b9c7SLeila Ghaffari     CeedQFunctionAddOutput(qf_applySur, "v", ncompq, CEED_EVAL_INTERP);
15759fe13df9SLeila Ghaffari   }
15769fe13df9SLeila Ghaffari 
15779fe13df9SLeila Ghaffari   // Create CEED Operator for the whole domain
15789fe13df9SLeila Ghaffari   if (!implicit)
15794438636fSLeila Ghaffari     ierr = CreateOperatorForDomain(ceed, dm, &bc, problemChoice, wind_type,
15804438636fSLeila Ghaffari                                    user->op_rhs_vol, qf_applySur,
1581e2043960SLeila Ghaffari                                    qf_setupSur, height, numP_Sur, numQ_Sur,
15824438636fSLeila Ghaffari                                    qdatasizeSur, NqptsSur, basisxSur,
15834438636fSLeila Ghaffari                                    basisqSur, &user->op_rhs);
15844438636fSLeila Ghaffari   CHKERRQ(ierr);
15859fe13df9SLeila Ghaffari   if (implicit)
15864438636fSLeila Ghaffari     ierr = CreateOperatorForDomain(ceed, dm, &bc, problemChoice, wind_type,
15874438636fSLeila Ghaffari                                    user->op_ifunction_vol, qf_applySur,
1588e2043960SLeila Ghaffari                                    qf_setupSur, height, numP_Sur, numQ_Sur,
15894438636fSLeila Ghaffari                                    qdatasizeSur, NqptsSur, basisxSur,
15904438636fSLeila Ghaffari                                    basisqSur, &user->op_ifunction);
15914438636fSLeila Ghaffari   CHKERRQ(ierr);
15927659d40cSLeila Ghaffari   // Set up contex for QFunctions
1593777ff853SJeremy L Thompson   CeedQFunctionContextCreate(ceed, &ctxSetup);
1594777ff853SJeremy L Thompson   CeedQFunctionContextSetData(ctxSetup, CEED_MEM_HOST, CEED_USE_POINTER,
1595777ff853SJeremy L Thompson                               sizeof ctxSetupData, &ctxSetupData);
15965bf10c6fSLeila Ghaffari   if (qf_ics && problemChoice != NS_EULER_VORTEX)
1597777ff853SJeremy L Thompson     CeedQFunctionSetContext(qf_ics, ctxSetup);
1598777ff853SJeremy L Thompson 
15995bf10c6fSLeila Ghaffari   CeedScalar ctxNSData[8] = {lambda, mu, k, cv, cp, g, Rd};
1600777ff853SJeremy L Thompson   CeedQFunctionContextCreate(ceed, &ctxNS);
1601777ff853SJeremy L Thompson   CeedQFunctionContextSetData(ctxNS, CEED_MEM_HOST, CEED_USE_POINTER,
1602777ff853SJeremy L Thompson                               sizeof ctxNSData, &ctxNSData);
1603777ff853SJeremy L Thompson 
16040da62991SLeila Ghaffari   struct Advection2dContext_ ctxAdvection2dData = {
1605ccaff030SJeremy L Thompson     .CtauS = CtauS,
1606ccaff030SJeremy L Thompson     .strong_form = strong_form,
1607ccaff030SJeremy L Thompson     .stabilization = stab,
1608ccaff030SJeremy L Thompson   };
1609777ff853SJeremy L Thompson   CeedQFunctionContextCreate(ceed, &ctxAdvection2d);
1610777ff853SJeremy L Thompson   CeedQFunctionContextSetData(ctxAdvection2d, CEED_MEM_HOST, CEED_USE_POINTER,
1611777ff853SJeremy L Thompson                               sizeof ctxAdvection2dData, &ctxAdvection2dData);
1612777ff853SJeremy L Thompson 
1613777ff853SJeremy L Thompson   struct SurfaceContext_ ctxSurfaceData = {
161416c0476cSLeila Ghaffari     .E_wind = E_wind,
16157659d40cSLeila Ghaffari     .strong_form = strong_form,
1616e5ed8c30SLeila Ghaffari     .implicit = implicit,
1617e5ed8c30SLeila Ghaffari   };
1618777ff853SJeremy L Thompson   CeedQFunctionContextCreate(ceed, &ctxSurface);
1619777ff853SJeremy L Thompson   CeedQFunctionContextSetData(ctxSurface, CEED_MEM_HOST, CEED_USE_POINTER,
1620777ff853SJeremy L Thompson                               sizeof ctxSurfaceData, &ctxSurfaceData);
1621777ff853SJeremy L Thompson 
16225bf10c6fSLeila Ghaffari   // Set up ctxEulerData structure
16235bf10c6fSLeila Ghaffari   ctxEulerData->time = 0.;
16245bf10c6fSLeila Ghaffari   ctxEulerData->currentTime = 0.;
1625a3ddc43aSLeila Ghaffari   ctxEulerData->euler_test = euler_test;
16265bf10c6fSLeila Ghaffari   ctxEulerData->center[0] = center[0];
16275bf10c6fSLeila Ghaffari   ctxEulerData->center[1] = center[1];
16285bf10c6fSLeila Ghaffari   ctxEulerData->center[2] = center[2];
16295bf10c6fSLeila Ghaffari   ctxEulerData->vortex_strength = vortex_strength;
16300da62991SLeila Ghaffari   ctxEulerData->etv_mean_velocity[0] = etv_mean_velocity[0];
16310da62991SLeila Ghaffari   ctxEulerData->etv_mean_velocity[1] = etv_mean_velocity[1];
16320da62991SLeila Ghaffari   ctxEulerData->etv_mean_velocity[2] = etv_mean_velocity[2];
1633a45a933fSLeila Ghaffari   ctxEulerData->T_inlet = T_inlet;
1634a45a933fSLeila Ghaffari   ctxEulerData->P_inlet = P_inlet;
1635c52ac6b8SLeila Ghaffari   ctxEulerData->stabilization = stab;
163677b27584SLeila Ghaffari   ctxEulerData->implicit = implicit;
16375bf10c6fSLeila Ghaffari   user->ctxEulerData = ctxEulerData;
16385bf10c6fSLeila Ghaffari 
16395bf10c6fSLeila Ghaffari   CeedQFunctionContextCreate(ceed, &ctxEuler);
16405bf10c6fSLeila Ghaffari   CeedQFunctionContextSetData(ctxEuler, CEED_MEM_HOST, CEED_USE_POINTER,
16410da62991SLeila Ghaffari                               sizeof *ctxEulerData, ctxEulerData);
16425bf10c6fSLeila Ghaffari 
1643ccaff030SJeremy L Thompson   switch (problemChoice) {
1644ccaff030SJeremy L Thompson   case NS_DENSITY_CURRENT:
16455bf10c6fSLeila Ghaffari     if (qf_rhsVol) CeedQFunctionSetContext(qf_rhsVol, ctxNS);
16465bf10c6fSLeila Ghaffari     if (qf_ifunctionVol) CeedQFunctionSetContext(qf_ifunctionVol, ctxNS);
1647ccaff030SJeremy L Thompson     break;
1648ccaff030SJeremy L Thompson   case NS_ADVECTION:
1649ccaff030SJeremy L Thompson   case NS_ADVECTION2D:
16505bf10c6fSLeila Ghaffari     if (qf_rhsVol) CeedQFunctionSetContext(qf_rhsVol, ctxAdvection2d);
16515bf10c6fSLeila Ghaffari     if (qf_ifunctionVol) CeedQFunctionSetContext(qf_ifunctionVol, ctxAdvection2d);
16525bf10c6fSLeila Ghaffari     if (qf_applySur) CeedQFunctionSetContext(qf_applySur, ctxSurface);
1653e5ed8c30SLeila Ghaffari   case NS_EULER_VORTEX:
16540da62991SLeila Ghaffari     if (qf_ics) CeedQFunctionSetContext(qf_ics, ctxEuler);
16555bf10c6fSLeila Ghaffari     if (qf_rhsVol) CeedQFunctionSetContext(qf_rhsVol, ctxEuler);
165677b27584SLeila Ghaffari     if (qf_ifunctionVol) CeedQFunctionSetContext(qf_ifunctionVol, ctxEuler);
1657a45a933fSLeila Ghaffari     if (qf_applySur) CeedQFunctionSetContext(qf_applySur, ctxEuler);
1658ccaff030SJeremy L Thompson   }
1659ccaff030SJeremy L Thompson 
1660ccaff030SJeremy L Thompson   // Set up PETSc context
1661ccaff030SJeremy L Thompson   // Set up units structure
1662ccaff030SJeremy L Thompson   units->meter = meter;
1663ccaff030SJeremy L Thompson   units->kilogram = kilogram;
1664ccaff030SJeremy L Thompson   units->second = second;
1665ccaff030SJeremy L Thompson   units->Kelvin = Kelvin;
1666ccaff030SJeremy L Thompson   units->Pascal = Pascal;
1667ccaff030SJeremy L Thompson   units->JperkgK = JperkgK;
1668ccaff030SJeremy L Thompson   units->mpersquareds = mpersquareds;
1669ccaff030SJeremy L Thompson   units->WpermK = WpermK;
1670ccaff030SJeremy L Thompson   units->kgpercubicm = kgpercubicm;
1671ccaff030SJeremy L Thompson   units->kgpersquaredms = kgpersquaredms;
1672ccaff030SJeremy L Thompson   units->Joulepercubicm = Joulepercubicm;
167316c0476cSLeila Ghaffari   units->Joule = Joule;
1674ccaff030SJeremy L Thompson 
1675ccaff030SJeremy L Thompson   // Set up user structure
1676ccaff030SJeremy L Thompson   user->comm = comm;
1677ccaff030SJeremy L Thompson   user->outputfreq = outputfreq;
1678ccaff030SJeremy L Thompson   user->contsteps = contsteps;
1679ccaff030SJeremy L Thompson   user->units = units;
1680ccaff030SJeremy L Thompson   user->dm = dm;
1681ccaff030SJeremy L Thompson   user->dmviz = dmviz;
1682ccaff030SJeremy L Thompson   user->interpviz = interpviz;
1683ccaff030SJeremy L Thompson   user->ceed = ceed;
1684ccaff030SJeremy L Thompson 
16858b982baeSLeila Ghaffari   // Calculate qdata and ICs
1686ccaff030SJeremy L Thompson   // Set up state global and local vectors
1687ccaff030SJeremy L Thompson   ierr = VecZeroEntries(Q); CHKERRQ(ierr);
1688ccaff030SJeremy L Thompson 
1689cfa64770SLeila Ghaffari   ierr = VectorPlacePetscVec(q0ceed, Qloc); CHKERRQ(ierr);
1690ccaff030SJeremy L Thompson 
1691ccaff030SJeremy L Thompson   // Apply Setup Ceed Operators
1692ccaff030SJeremy L Thompson   ierr = VectorPlacePetscVec(xcorners, Xloc); CHKERRQ(ierr);
16938b982baeSLeila Ghaffari   CeedOperatorApply(op_setupVol, xcorners, qdata, CEED_REQUEST_IMMEDIATE);
169484d34d69SLeila Ghaffari   ierr = ComputeLumpedMassMatrix(ceed, dm, restrictq, basisq, restrictqdi, qdata,
1695ccaff030SJeremy L Thompson                                  user->M); CHKERRQ(ierr);
1696ccaff030SJeremy L Thompson 
169784d34d69SLeila Ghaffari   ierr = ICs_FixMultiplicity(op_ics, xcorners, q0ceed, dm, Qloc, Q, restrictq,
1698777ff853SJeremy L Thompson                              ctxSetup, 0.0); CHKERRQ(ierr);
1699ccaff030SJeremy L Thompson   if (1) { // Record boundary values from initial condition and override DMPlexInsertBoundaryValues()
1700ccaff030SJeremy L Thompson     // We use this for the main simulation DM because the reference DMPlexInsertBoundaryValues() is very slow.  If we
1701ccaff030SJeremy L Thompson     // disable this, we should still get the same results due to the problem->bc function, but with potentially much
1702ccaff030SJeremy L Thompson     // slower execution.
1703ccaff030SJeremy L Thompson     Vec Qbc;
1704ccaff030SJeremy L Thompson     ierr = DMGetNamedLocalVector(dm, "Qbc", &Qbc); CHKERRQ(ierr);
1705ccaff030SJeremy L Thompson     ierr = VecCopy(Qloc, Qbc); CHKERRQ(ierr);
1706ccaff030SJeremy L Thompson     ierr = VecZeroEntries(Qloc); CHKERRQ(ierr);
1707ccaff030SJeremy L Thompson     ierr = DMGlobalToLocal(dm, Q, INSERT_VALUES, Qloc); CHKERRQ(ierr);
1708ccaff030SJeremy L Thompson     ierr = VecAXPY(Qbc, -1., Qloc); CHKERRQ(ierr);
1709ccaff030SJeremy L Thompson     ierr = DMRestoreNamedLocalVector(dm, "Qbc", &Qbc); CHKERRQ(ierr);
1710ccaff030SJeremy L Thompson     ierr = PetscObjectComposeFunction((PetscObject)dm,
171184d34d69SLeila Ghaffari                                       "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_NS);
171284d34d69SLeila Ghaffari     CHKERRQ(ierr);
1713ccaff030SJeremy L Thompson   }
1714ccaff030SJeremy L Thompson 
1715ccaff030SJeremy L Thompson   MPI_Comm_rank(comm, &rank);
1716d99129b9SLeila Ghaffari   if (!rank) {ierr = PetscMkdir(user->outputdir); CHKERRQ(ierr);}
1717ccaff030SJeremy L Thompson   // Gather initial Q values
1718ccaff030SJeremy L Thompson   // In case of continuation of simulation, set up initial values from binary file
1719ccaff030SJeremy L Thompson   if (contsteps) { // continue from existent solution
1720ccaff030SJeremy L Thompson     PetscViewer viewer;
1721ccaff030SJeremy L Thompson     char filepath[PETSC_MAX_PATH_LEN];
1722ccaff030SJeremy L Thompson     // Read input
1723ccaff030SJeremy L Thompson     ierr = PetscSNPrintf(filepath, sizeof filepath, "%s/ns-solution.bin",
1724d99129b9SLeila Ghaffari                          user->outputdir);
1725ccaff030SJeremy L Thompson     CHKERRQ(ierr);
1726ccaff030SJeremy L Thompson     ierr = PetscViewerBinaryOpen(comm, filepath, FILE_MODE_READ, &viewer);
1727ccaff030SJeremy L Thompson     CHKERRQ(ierr);
1728ccaff030SJeremy L Thompson     ierr = VecLoad(Q, viewer); CHKERRQ(ierr);
1729ccaff030SJeremy L Thompson     ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
1730ccaff030SJeremy L Thompson   }
1731ccaff030SJeremy L Thompson   ierr = DMRestoreLocalVector(dm, &Qloc); CHKERRQ(ierr);
1732ccaff030SJeremy L Thompson 
1733ccaff030SJeremy L Thompson   // Create and setup TS
1734ccaff030SJeremy L Thompson   ierr = TSCreate(comm, &ts); CHKERRQ(ierr);
1735ccaff030SJeremy L Thompson   ierr = TSSetDM(ts, dm); CHKERRQ(ierr);
1736ccaff030SJeremy L Thompson   if (implicit) {
1737ccaff030SJeremy L Thompson     ierr = TSSetType(ts, TSBDF); CHKERRQ(ierr);
1738ccaff030SJeremy L Thompson     if (user->op_ifunction) {
1739ccaff030SJeremy L Thompson       ierr = TSSetIFunction(ts, NULL, IFunction_NS, &user); CHKERRQ(ierr);
1740ccaff030SJeremy L Thompson     } else {                    // Implicit integrators can fall back to using an RHSFunction
1741ccaff030SJeremy L Thompson       ierr = TSSetRHSFunction(ts, NULL, RHS_NS, &user); CHKERRQ(ierr);
1742ccaff030SJeremy L Thompson     }
1743ccaff030SJeremy L Thompson   } else {
1744ccaff030SJeremy L Thompson     if (!user->op_rhs) SETERRQ(comm, PETSC_ERR_ARG_NULL,
1745ccaff030SJeremy L Thompson                                  "Problem does not provide RHSFunction");
1746ccaff030SJeremy L Thompson     ierr = TSSetType(ts, TSRK); CHKERRQ(ierr);
1747ccaff030SJeremy L Thompson     ierr = TSRKSetType(ts, TSRK5F); CHKERRQ(ierr);
1748ccaff030SJeremy L Thompson     ierr = TSSetRHSFunction(ts, NULL, RHS_NS, &user); CHKERRQ(ierr);
1749ccaff030SJeremy L Thompson   }
1750ccaff030SJeremy L Thompson   ierr = TSSetMaxTime(ts, 500. * units->second); CHKERRQ(ierr);
1751ccaff030SJeremy L Thompson   ierr = TSSetExactFinalTime(ts, TS_EXACTFINALTIME_STEPOVER); CHKERRQ(ierr);
1752ccaff030SJeremy L Thompson   ierr = TSSetTimeStep(ts, 1.e-2 * units->second); CHKERRQ(ierr);
1753dc8efd83SLeila Ghaffari   if (test) {ierr = TSSetMaxSteps(ts, 10); CHKERRQ(ierr);}
1754ccaff030SJeremy L Thompson   ierr = TSGetAdapt(ts, &adapt); CHKERRQ(ierr);
1755ccaff030SJeremy L Thompson   ierr = TSAdaptSetStepLimits(adapt,
1756ccaff030SJeremy L Thompson                               1.e-12 * units->second,
1757ccaff030SJeremy L Thompson                               1.e2 * units->second); CHKERRQ(ierr);
1758ccaff030SJeremy L Thompson   ierr = TSSetFromOptions(ts); CHKERRQ(ierr);
1759ccaff030SJeremy L Thompson   if (!contsteps) { // print initial condition
1760dc8efd83SLeila Ghaffari     if (!test) {
1761ccaff030SJeremy L Thompson       ierr = TSMonitor_NS(ts, 0, 0., Q, user); CHKERRQ(ierr);
1762ccaff030SJeremy L Thompson     }
1763ccaff030SJeremy L Thompson   } else { // continue from time of last output
1764ccaff030SJeremy L Thompson     PetscReal time;
1765ccaff030SJeremy L Thompson     PetscInt count;
1766ccaff030SJeremy L Thompson     PetscViewer viewer;
1767ccaff030SJeremy L Thompson     char filepath[PETSC_MAX_PATH_LEN];
1768ccaff030SJeremy L Thompson     ierr = PetscSNPrintf(filepath, sizeof filepath, "%s/ns-time.bin",
1769d99129b9SLeila Ghaffari                          user->outputdir); CHKERRQ(ierr);
1770ccaff030SJeremy L Thompson     ierr = PetscViewerBinaryOpen(comm, filepath, FILE_MODE_READ, &viewer);
1771ccaff030SJeremy L Thompson     CHKERRQ(ierr);
1772ccaff030SJeremy L Thompson     ierr = PetscViewerBinaryRead(viewer, &time, 1, &count, PETSC_REAL);
1773ccaff030SJeremy L Thompson     CHKERRQ(ierr);
1774ccaff030SJeremy L Thompson     ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
1775ccaff030SJeremy L Thompson     ierr = TSSetTime(ts, time * user->units->second); CHKERRQ(ierr);
1776ccaff030SJeremy L Thompson   }
1777dc8efd83SLeila Ghaffari   if (!test) {
1778ccaff030SJeremy L Thompson     ierr = TSMonitorSet(ts, TSMonitor_NS, user, NULL); CHKERRQ(ierr);
1779ccaff030SJeremy L Thompson   }
1780ccaff030SJeremy L Thompson 
1781ccaff030SJeremy L Thompson   // Solve
1782ccaff030SJeremy L Thompson   start = MPI_Wtime();
1783ccaff030SJeremy L Thompson   ierr = PetscBarrier((PetscObject)ts); CHKERRQ(ierr);
1784ccaff030SJeremy L Thompson   ierr = TSSolve(ts, Q); CHKERRQ(ierr);
1785ccaff030SJeremy L Thompson   cpu_time_used = MPI_Wtime() - start;
1786ccaff030SJeremy L Thompson   ierr = TSGetSolveTime(ts, &ftime); CHKERRQ(ierr);
1787ccaff030SJeremy L Thompson   ierr = MPI_Allreduce(MPI_IN_PLACE, &cpu_time_used, 1, MPI_DOUBLE, MPI_MIN,
1788ccaff030SJeremy L Thompson                        comm); CHKERRQ(ierr);
1789dc8efd83SLeila Ghaffari   if (!test) {
1790ccaff030SJeremy L Thompson     ierr = PetscPrintf(PETSC_COMM_WORLD,
179184d34d69SLeila Ghaffari                        "Time taken for solution (sec): %g\n",
1792ccaff030SJeremy L Thompson                        (double)cpu_time_used); CHKERRQ(ierr);
1793ccaff030SJeremy L Thompson   }
1794ccaff030SJeremy L Thompson 
1795ccaff030SJeremy L Thompson   // Get error
1796dc8efd83SLeila Ghaffari   if (problem->non_zero_time && !test) {
1797ccaff030SJeremy L Thompson     Vec Qexact, Qexactloc;
1798ce58a7c9SLeila Ghaffari     PetscReal rel_error, norm_error, norm_exact;
1799ccaff030SJeremy L Thompson     ierr = DMCreateGlobalVector(dm, &Qexact); CHKERRQ(ierr);
1800ccaff030SJeremy L Thompson     ierr = DMGetLocalVector(dm, &Qexactloc); CHKERRQ(ierr);
1801ccaff030SJeremy L Thompson     ierr = VecGetSize(Qexactloc, &lnodes); CHKERRQ(ierr);
1802ccaff030SJeremy L Thompson 
180384d34d69SLeila Ghaffari     ierr = ICs_FixMultiplicity(op_ics, xcorners, q0ceed, dm, Qexactloc, Qexact,
1804777ff853SJeremy L Thompson                                restrictq, ctxSetup, ftime); CHKERRQ(ierr);
1805ce58a7c9SLeila Ghaffari     ierr = VecNorm(Qexact, NORM_1, &norm_exact); CHKERRQ(ierr);
1806ccaff030SJeremy L Thompson     ierr = VecAXPY(Q, -1.0, Qexact);  CHKERRQ(ierr);
1807ce58a7c9SLeila Ghaffari     ierr = VecNorm(Q, NORM_1, &norm_error); CHKERRQ(ierr);
1808ce58a7c9SLeila Ghaffari     rel_error = norm_error / norm_exact;
1809cfa64770SLeila Ghaffari     CeedVectorDestroy(&q0ceed);
1810ccaff030SJeremy L Thompson     ierr = PetscPrintf(PETSC_COMM_WORLD,
1811ce58a7c9SLeila Ghaffari                        "Relative Error: %g\n",
1812ce58a7c9SLeila Ghaffari                        (double)rel_error); CHKERRQ(ierr);
181384d34d69SLeila Ghaffari     // Clean up vectors
181484d34d69SLeila Ghaffari     ierr = DMRestoreLocalVector(dm, &Qexactloc); CHKERRQ(ierr);
181584d34d69SLeila Ghaffari     ierr = VecDestroy(&Qexact); CHKERRQ(ierr);
1816ccaff030SJeremy L Thompson   }
1817ccaff030SJeremy L Thompson 
1818ccaff030SJeremy L Thompson   // Output Statistics
1819ccaff030SJeremy L Thompson   ierr = TSGetStepNumber(ts, &steps); CHKERRQ(ierr);
1820dc8efd83SLeila Ghaffari   if (!test) {
1821ccaff030SJeremy L Thompson     ierr = PetscPrintf(PETSC_COMM_WORLD,
1822ccaff030SJeremy L Thompson                        "Time integrator took %D time steps to reach final time %g\n",
1823ccaff030SJeremy L Thompson                        steps, (double)ftime); CHKERRQ(ierr);
1824ccaff030SJeremy L Thompson   }
1825d7a15aecSLeila Ghaffari   // Output numerical values from command line
1826d7a15aecSLeila Ghaffari   ierr = VecViewFromOptions(Q, NULL, "-vec_view"); CHKERRQ(ierr);
182784d34d69SLeila Ghaffari 
1828335ea220SLeila Ghaffari   // Compare reference solution values with current test run for CI
1829dc8efd83SLeila Ghaffari   if (test) {
183084d34d69SLeila Ghaffari     PetscViewer viewer;
183184d34d69SLeila Ghaffari     // Read reference file
183284d34d69SLeila Ghaffari     Vec Qref;
183384d34d69SLeila Ghaffari     PetscReal error, Qrefnorm;
183484d34d69SLeila Ghaffari     ierr = VecDuplicate(Q, &Qref); CHKERRQ(ierr);
1835dc8efd83SLeila Ghaffari     ierr = PetscViewerBinaryOpen(comm, filepath, FILE_MODE_READ, &viewer);
183684d34d69SLeila Ghaffari     CHKERRQ(ierr);
183784d34d69SLeila Ghaffari     ierr = VecLoad(Qref, viewer); CHKERRQ(ierr);
183884d34d69SLeila Ghaffari     ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
183984d34d69SLeila Ghaffari 
184084d34d69SLeila Ghaffari     // Compute error with respect to reference solution
184184d34d69SLeila Ghaffari     ierr = VecAXPY(Q, -1.0, Qref);  CHKERRQ(ierr);
184284d34d69SLeila Ghaffari     ierr = VecNorm(Qref, NORM_MAX, &Qrefnorm); CHKERRQ(ierr);
184384d34d69SLeila Ghaffari     ierr = VecScale(Q, 1./Qrefnorm); CHKERRQ(ierr);
184484d34d69SLeila Ghaffari     ierr = VecNorm(Q, NORM_MAX, &error); CHKERRQ(ierr);
184584d34d69SLeila Ghaffari     ierr = VecDestroy(&Qref); CHKERRQ(ierr);
184684d34d69SLeila Ghaffari     // Check error
1847dc8efd83SLeila Ghaffari     if (error > testtol) {
184884d34d69SLeila Ghaffari       ierr = PetscPrintf(PETSC_COMM_WORLD,
184984d34d69SLeila Ghaffari                          "Test failed with error norm %g\n",
185084d34d69SLeila Ghaffari                          (double)error); CHKERRQ(ierr);
185184d34d69SLeila Ghaffari     }
185284d34d69SLeila Ghaffari     ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
185384d34d69SLeila Ghaffari   }
18549cf88b28Svaleriabarra 
1855ccaff030SJeremy L Thompson   // Clean up libCEED
18568b982baeSLeila Ghaffari   CeedVectorDestroy(&qdata);
1857ccaff030SJeremy L Thompson   CeedVectorDestroy(&user->qceed);
1858ccaff030SJeremy L Thompson   CeedVectorDestroy(&user->qdotceed);
1859ccaff030SJeremy L Thompson   CeedVectorDestroy(&user->gceed);
1860ccaff030SJeremy L Thompson   CeedVectorDestroy(&xcorners);
186184d34d69SLeila Ghaffari   CeedBasisDestroy(&basisq);
186284d34d69SLeila Ghaffari   CeedBasisDestroy(&basisx);
186384d34d69SLeila Ghaffari   CeedBasisDestroy(&basisxc);
186484d34d69SLeila Ghaffari   CeedElemRestrictionDestroy(&restrictq);
186584d34d69SLeila Ghaffari   CeedElemRestrictionDestroy(&restrictx);
186684d34d69SLeila Ghaffari   CeedElemRestrictionDestroy(&restrictqdi);
1867ea6e0f84SLeila Ghaffari   CeedQFunctionDestroy(&qf_setupVol);
1868ccaff030SJeremy L Thompson   CeedQFunctionDestroy(&qf_ics);
1869ea6e0f84SLeila Ghaffari   CeedQFunctionDestroy(&qf_rhsVol);
1870ea6e0f84SLeila Ghaffari   CeedQFunctionDestroy(&qf_ifunctionVol);
1871777ff853SJeremy L Thompson   CeedQFunctionContextDestroy(&ctxSetup);
1872777ff853SJeremy L Thompson   CeedQFunctionContextDestroy(&ctxNS);
1873777ff853SJeremy L Thompson   CeedQFunctionContextDestroy(&ctxAdvection2d);
1874777ff853SJeremy L Thompson   CeedQFunctionContextDestroy(&ctxSurface);
18750da62991SLeila Ghaffari   CeedQFunctionContextDestroy(&ctxEuler);
1876ea6e0f84SLeila Ghaffari   CeedOperatorDestroy(&op_setupVol);
1877ccaff030SJeremy L Thompson   CeedOperatorDestroy(&op_ics);
18786a0edaf9SLeila Ghaffari   CeedOperatorDestroy(&user->op_rhs_vol);
18796a0edaf9SLeila Ghaffari   CeedOperatorDestroy(&user->op_ifunction_vol);
18806a0edaf9SLeila Ghaffari   CeedDestroy(&ceed);
18816a0edaf9SLeila Ghaffari   CeedBasisDestroy(&basisqSur);
18826a0edaf9SLeila Ghaffari   CeedBasisDestroy(&basisxSur);
18836a0edaf9SLeila Ghaffari   CeedBasisDestroy(&basisxcSur);
18846a0edaf9SLeila Ghaffari   CeedQFunctionDestroy(&qf_setupSur);
18857ed8b9c7SLeila Ghaffari   CeedQFunctionDestroy(&qf_applySur);
1886ccaff030SJeremy L Thompson   CeedOperatorDestroy(&user->op_rhs);
1887ccaff030SJeremy L Thompson   CeedOperatorDestroy(&user->op_ifunction);
1888ccaff030SJeremy L Thompson 
1889ccaff030SJeremy L Thompson   // Clean up PETSc
1890ccaff030SJeremy L Thompson   ierr = VecDestroy(&Q); CHKERRQ(ierr);
1891ccaff030SJeremy L Thompson   ierr = VecDestroy(&user->M); CHKERRQ(ierr);
1892ccaff030SJeremy L Thompson   ierr = MatDestroy(&interpviz); CHKERRQ(ierr);
1893ccaff030SJeremy L Thompson   ierr = DMDestroy(&dmviz); CHKERRQ(ierr);
1894ccaff030SJeremy L Thompson   ierr = TSDestroy(&ts); CHKERRQ(ierr);
1895ccaff030SJeremy L Thompson   ierr = DMDestroy(&dm); CHKERRQ(ierr);
1896ccaff030SJeremy L Thompson   ierr = PetscFree(units); CHKERRQ(ierr);
1897ccaff030SJeremy L Thompson   ierr = PetscFree(user); CHKERRQ(ierr);
18985bf10c6fSLeila Ghaffari   ierr = PetscFree(ctxEulerData); CHKERRQ(ierr);
1899ccaff030SJeremy L Thompson   return PetscFinalize();
1900ccaff030SJeremy L Thompson }
1901