xref: /petsc/src/dm/dt/fv/interface/fv.c (revision ffeef943c8ee50edff320d8a3135bb0c94853e4c)
1c0ce001eSMatthew G. Knepley #include <petsc/private/petscfvimpl.h> /*I "petscfv.h" I*/
2412e9a14SMatthew G. Knepley #include <petscdmplex.h>
3012bc364SMatthew G. Knepley #include <petscdmplextransform.h>
4c0ce001eSMatthew G. Knepley #include <petscds.h>
5c0ce001eSMatthew G. Knepley 
6c0ce001eSMatthew G. Knepley PetscClassId PETSCLIMITER_CLASSID = 0;
7c0ce001eSMatthew G. Knepley 
8c0ce001eSMatthew G. Knepley PetscFunctionList PetscLimiterList              = NULL;
9c0ce001eSMatthew G. Knepley PetscBool         PetscLimiterRegisterAllCalled = PETSC_FALSE;
10c0ce001eSMatthew G. Knepley 
11c0ce001eSMatthew G. Knepley PetscBool  Limitercite       = PETSC_FALSE;
12c0ce001eSMatthew G. Knepley const char LimiterCitation[] = "@article{BergerAftosmisMurman2005,\n"
13c0ce001eSMatthew G. Knepley                                "  title   = {Analysis of slope limiters on irregular grids},\n"
14c0ce001eSMatthew G. Knepley                                "  journal = {AIAA paper},\n"
15c0ce001eSMatthew G. Knepley                                "  author  = {Marsha Berger and Michael J. Aftosmis and Scott M. Murman},\n"
16c0ce001eSMatthew G. Knepley                                "  volume  = {490},\n"
17c0ce001eSMatthew G. Knepley                                "  year    = {2005}\n}\n";
18c0ce001eSMatthew G. Knepley 
19c0ce001eSMatthew G. Knepley /*@C
20dce8aebaSBarry Smith   PetscLimiterRegister - Adds a new `PetscLimiter` implementation
21c0ce001eSMatthew G. Knepley 
22cc4c1da9SBarry Smith   Not Collective, No Fortran Support
23c0ce001eSMatthew G. Knepley 
24c0ce001eSMatthew G. Knepley   Input Parameters:
252fe279fdSBarry Smith + sname    - The name of a new user-defined creation routine
262fe279fdSBarry Smith - function - The creation routine
27c0ce001eSMatthew G. Knepley 
2860225df5SJacob Faibussowitsch   Example Usage:
29c0ce001eSMatthew G. Knepley .vb
30c0ce001eSMatthew G. Knepley     PetscLimiterRegister("my_lim", MyPetscLimiterCreate);
31c0ce001eSMatthew G. Knepley .ve
32c0ce001eSMatthew G. Knepley 
33dce8aebaSBarry Smith   Then, your `PetscLimiter` type can be chosen with the procedural interface via
34c0ce001eSMatthew G. Knepley .vb
35c0ce001eSMatthew G. Knepley     PetscLimiterCreate(MPI_Comm, PetscLimiter *);
36c0ce001eSMatthew G. Knepley     PetscLimiterSetType(PetscLimiter, "my_lim");
37c0ce001eSMatthew G. Knepley .ve
38c0ce001eSMatthew G. Knepley   or at runtime via the option
39c0ce001eSMatthew G. Knepley .vb
40c0ce001eSMatthew G. Knepley     -petsclimiter_type my_lim
41c0ce001eSMatthew G. Knepley .ve
42c0ce001eSMatthew G. Knepley 
43c0ce001eSMatthew G. Knepley   Level: advanced
44c0ce001eSMatthew G. Knepley 
45dce8aebaSBarry Smith   Note:
46dce8aebaSBarry Smith   `PetscLimiterRegister()` may be called multiple times to add several user-defined PetscLimiters
47c0ce001eSMatthew G. Knepley 
48dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterRegisterAll()`, `PetscLimiterRegisterDestroy()`
49c0ce001eSMatthew G. Knepley @*/
50d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterRegister(const char sname[], PetscErrorCode (*function)(PetscLimiter))
51d71ae5a4SJacob Faibussowitsch {
52c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
539566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&PetscLimiterList, sname, function));
543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55c0ce001eSMatthew G. Knepley }
56c0ce001eSMatthew G. Knepley 
57cc4c1da9SBarry Smith /*@
58dce8aebaSBarry Smith   PetscLimiterSetType - Builds a `PetscLimiter` for a given `PetscLimiterType`
59c0ce001eSMatthew G. Knepley 
6020f4b53cSBarry Smith   Collective
61c0ce001eSMatthew G. Knepley 
62c0ce001eSMatthew G. Knepley   Input Parameters:
63dce8aebaSBarry Smith + lim  - The `PetscLimiter` object
64c0ce001eSMatthew G. Knepley - name - The kind of limiter
65c0ce001eSMatthew G. Knepley 
66c0ce001eSMatthew G. Knepley   Options Database Key:
67c0ce001eSMatthew G. Knepley . -petsclimiter_type <type> - Sets the PetscLimiter type; use -help for a list of available types
68c0ce001eSMatthew G. Knepley 
69c0ce001eSMatthew G. Knepley   Level: intermediate
70c0ce001eSMatthew G. Knepley 
71dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterGetType()`, `PetscLimiterCreate()`
72c0ce001eSMatthew G. Knepley @*/
73d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterSetType(PetscLimiter lim, PetscLimiterType name)
74d71ae5a4SJacob Faibussowitsch {
75c0ce001eSMatthew G. Knepley   PetscErrorCode (*r)(PetscLimiter);
76c0ce001eSMatthew G. Knepley   PetscBool match;
77c0ce001eSMatthew G. Knepley 
78c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
79c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
809566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)lim, name, &match));
813ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
82c0ce001eSMatthew G. Knepley 
839566063dSJacob Faibussowitsch   PetscCall(PetscLimiterRegisterAll());
849566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(PetscLimiterList, name, &r));
8528b400f6SJacob Faibussowitsch   PetscCheck(r, PetscObjectComm((PetscObject)lim), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscLimiter type: %s", name);
86c0ce001eSMatthew G. Knepley 
879927e4dfSBarry Smith   PetscTryTypeMethod(lim, destroy);
88c0ce001eSMatthew G. Knepley   lim->ops->destroy = NULL;
899927e4dfSBarry Smith 
909566063dSJacob Faibussowitsch   PetscCall((*r)(lim));
919566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)lim, name));
923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
93c0ce001eSMatthew G. Knepley }
94c0ce001eSMatthew G. Knepley 
95cc4c1da9SBarry Smith /*@
96dce8aebaSBarry Smith   PetscLimiterGetType - Gets the `PetscLimiterType` name (as a string) from the `PetscLimiter`.
97c0ce001eSMatthew G. Knepley 
98c0ce001eSMatthew G. Knepley   Not Collective
99c0ce001eSMatthew G. Knepley 
100c0ce001eSMatthew G. Knepley   Input Parameter:
101dce8aebaSBarry Smith . lim - The `PetscLimiter`
102c0ce001eSMatthew G. Knepley 
103c0ce001eSMatthew G. Knepley   Output Parameter:
104dce8aebaSBarry Smith . name - The `PetscLimiterType`
105c0ce001eSMatthew G. Knepley 
106c0ce001eSMatthew G. Knepley   Level: intermediate
107c0ce001eSMatthew G. Knepley 
108dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterSetType()`, `PetscLimiterCreate()`
109c0ce001eSMatthew G. Knepley @*/
110d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterGetType(PetscLimiter lim, PetscLimiterType *name)
111d71ae5a4SJacob Faibussowitsch {
112c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
113c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
1144f572ea9SToby Isaac   PetscAssertPointer(name, 2);
1159566063dSJacob Faibussowitsch   PetscCall(PetscLimiterRegisterAll());
116c0ce001eSMatthew G. Knepley   *name = ((PetscObject)lim)->type_name;
1173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
118c0ce001eSMatthew G. Knepley }
119c0ce001eSMatthew G. Knepley 
120*ffeef943SBarry Smith /*@
121dce8aebaSBarry Smith   PetscLimiterViewFromOptions - View a `PetscLimiter` based on values in the options database
122fe2efc57SMark 
12320f4b53cSBarry Smith   Collective
124fe2efc57SMark 
125fe2efc57SMark   Input Parameters:
126dce8aebaSBarry Smith + A    - the `PetscLimiter` object to view
127dce8aebaSBarry Smith . obj  - Optional object that provides the options prefix to use
128dce8aebaSBarry Smith - name - command line option name
129fe2efc57SMark 
130fe2efc57SMark   Level: intermediate
131dce8aebaSBarry Smith 
132dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterView()`, `PetscObjectViewFromOptions()`, `PetscLimiterCreate()`
133fe2efc57SMark @*/
134d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterViewFromOptions(PetscLimiter A, PetscObject obj, const char name[])
135d71ae5a4SJacob Faibussowitsch {
136fe2efc57SMark   PetscFunctionBegin;
137fe2efc57SMark   PetscValidHeaderSpecific(A, PETSCLIMITER_CLASSID, 1);
1389566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
140fe2efc57SMark }
141fe2efc57SMark 
142*ffeef943SBarry Smith /*@
143dce8aebaSBarry Smith   PetscLimiterView - Views a `PetscLimiter`
144c0ce001eSMatthew G. Knepley 
14520f4b53cSBarry Smith   Collective
146c0ce001eSMatthew G. Knepley 
147d8d19677SJose E. Roman   Input Parameters:
148dce8aebaSBarry Smith + lim - the `PetscLimiter` object to view
149c0ce001eSMatthew G. Knepley - v   - the viewer
150c0ce001eSMatthew G. Knepley 
15188f5f89eSMatthew G. Knepley   Level: beginner
152c0ce001eSMatthew G. Knepley 
153dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscViewer`, `PetscLimiterDestroy()`, `PetscLimiterViewFromOptions()`
154c0ce001eSMatthew G. Knepley @*/
155d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterView(PetscLimiter lim, PetscViewer v)
156d71ae5a4SJacob Faibussowitsch {
157c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
158c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
1599566063dSJacob Faibussowitsch   if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)lim), &v));
160dbbe0bcdSBarry Smith   PetscTryTypeMethod(lim, view, v);
1613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
162c0ce001eSMatthew G. Knepley }
163c0ce001eSMatthew G. Knepley 
164c0ce001eSMatthew G. Knepley /*@
165dce8aebaSBarry Smith   PetscLimiterSetFromOptions - sets parameters in a `PetscLimiter` from the options database
166c0ce001eSMatthew G. Knepley 
16720f4b53cSBarry Smith   Collective
168c0ce001eSMatthew G. Knepley 
169c0ce001eSMatthew G. Knepley   Input Parameter:
170dce8aebaSBarry Smith . lim - the `PetscLimiter` object to set options for
171c0ce001eSMatthew G. Knepley 
17288f5f89eSMatthew G. Knepley   Level: intermediate
173c0ce001eSMatthew G. Knepley 
174dce8aebaSBarry Smith .seealso: `PetscLimiter`, ``PetscLimiterView()`
175c0ce001eSMatthew G. Knepley @*/
176d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterSetFromOptions(PetscLimiter lim)
177d71ae5a4SJacob Faibussowitsch {
178c0ce001eSMatthew G. Knepley   const char *defaultType;
179c0ce001eSMatthew G. Knepley   char        name[256];
180c0ce001eSMatthew G. Knepley   PetscBool   flg;
181c0ce001eSMatthew G. Knepley 
182c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
183c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
184c0ce001eSMatthew G. Knepley   if (!((PetscObject)lim)->type_name) defaultType = PETSCLIMITERSIN;
185c0ce001eSMatthew G. Knepley   else defaultType = ((PetscObject)lim)->type_name;
1869566063dSJacob Faibussowitsch   PetscCall(PetscLimiterRegisterAll());
187c0ce001eSMatthew G. Knepley 
188d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)lim);
1899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-petsclimiter_type", "Finite volume slope limiter", "PetscLimiterSetType", PetscLimiterList, defaultType, name, 256, &flg));
190c0ce001eSMatthew G. Knepley   if (flg) {
1919566063dSJacob Faibussowitsch     PetscCall(PetscLimiterSetType(lim, name));
192c0ce001eSMatthew G. Knepley   } else if (!((PetscObject)lim)->type_name) {
1939566063dSJacob Faibussowitsch     PetscCall(PetscLimiterSetType(lim, defaultType));
194c0ce001eSMatthew G. Knepley   }
195dbbe0bcdSBarry Smith   PetscTryTypeMethod(lim, setfromoptions);
196c0ce001eSMatthew G. Knepley   /* process any options handlers added with PetscObjectAddOptionsHandler() */
197dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)lim, PetscOptionsObject));
198d0609cedSBarry Smith   PetscOptionsEnd();
1999566063dSJacob Faibussowitsch   PetscCall(PetscLimiterViewFromOptions(lim, NULL, "-petsclimiter_view"));
2003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
201c0ce001eSMatthew G. Knepley }
202c0ce001eSMatthew G. Knepley 
203cc4c1da9SBarry Smith /*@
204dce8aebaSBarry Smith   PetscLimiterSetUp - Construct data structures for the `PetscLimiter`
205c0ce001eSMatthew G. Knepley 
20620f4b53cSBarry Smith   Collective
207c0ce001eSMatthew G. Knepley 
208c0ce001eSMatthew G. Knepley   Input Parameter:
209dce8aebaSBarry Smith . lim - the `PetscLimiter` object to setup
210c0ce001eSMatthew G. Knepley 
21188f5f89eSMatthew G. Knepley   Level: intermediate
212c0ce001eSMatthew G. Knepley 
213dce8aebaSBarry Smith .seealso: `PetscLimiter`, ``PetscLimiterView()`, `PetscLimiterDestroy()`
214c0ce001eSMatthew G. Knepley @*/
215d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterSetUp(PetscLimiter lim)
216d71ae5a4SJacob Faibussowitsch {
217c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
218c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
219dbbe0bcdSBarry Smith   PetscTryTypeMethod(lim, setup);
2203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
221c0ce001eSMatthew G. Knepley }
222c0ce001eSMatthew G. Knepley 
223c0ce001eSMatthew G. Knepley /*@
224dce8aebaSBarry Smith   PetscLimiterDestroy - Destroys a `PetscLimiter` object
225c0ce001eSMatthew G. Knepley 
22620f4b53cSBarry Smith   Collective
227c0ce001eSMatthew G. Knepley 
228c0ce001eSMatthew G. Knepley   Input Parameter:
229dce8aebaSBarry Smith . lim - the `PetscLimiter` object to destroy
230c0ce001eSMatthew G. Knepley 
23188f5f89eSMatthew G. Knepley   Level: beginner
232c0ce001eSMatthew G. Knepley 
233dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterView()`
234c0ce001eSMatthew G. Knepley @*/
235d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterDestroy(PetscLimiter *lim)
236d71ae5a4SJacob Faibussowitsch {
237c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2383ba16761SJacob Faibussowitsch   if (!*lim) PetscFunctionReturn(PETSC_SUCCESS);
239f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*lim, PETSCLIMITER_CLASSID, 1);
240c0ce001eSMatthew G. Knepley 
241f4f49eeaSPierre Jolivet   if (--((PetscObject)*lim)->refct > 0) {
2429371c9d4SSatish Balay     *lim = NULL;
2433ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2449371c9d4SSatish Balay   }
245f4f49eeaSPierre Jolivet   ((PetscObject)*lim)->refct = 0;
246c0ce001eSMatthew G. Knepley 
247f4f49eeaSPierre Jolivet   PetscTryTypeMethod(*lim, destroy);
2489566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(lim));
2493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
250c0ce001eSMatthew G. Knepley }
251c0ce001eSMatthew G. Knepley 
252c0ce001eSMatthew G. Knepley /*@
253dce8aebaSBarry Smith   PetscLimiterCreate - Creates an empty `PetscLimiter` object. The type can then be set with `PetscLimiterSetType()`.
254c0ce001eSMatthew G. Knepley 
255c0ce001eSMatthew G. Knepley   Collective
256c0ce001eSMatthew G. Knepley 
257c0ce001eSMatthew G. Knepley   Input Parameter:
258dce8aebaSBarry Smith . comm - The communicator for the `PetscLimiter` object
259c0ce001eSMatthew G. Knepley 
260c0ce001eSMatthew G. Knepley   Output Parameter:
261dce8aebaSBarry Smith . lim - The `PetscLimiter` object
262c0ce001eSMatthew G. Knepley 
263c0ce001eSMatthew G. Knepley   Level: beginner
264c0ce001eSMatthew G. Knepley 
26560225df5SJacob Faibussowitsch .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterSetType()`, `PETSCLIMITERSIN`
266c0ce001eSMatthew G. Knepley @*/
267d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterCreate(MPI_Comm comm, PetscLimiter *lim)
268d71ae5a4SJacob Faibussowitsch {
269c0ce001eSMatthew G. Knepley   PetscLimiter l;
270c0ce001eSMatthew G. Knepley 
271c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2724f572ea9SToby Isaac   PetscAssertPointer(lim, 2);
2739566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(LimiterCitation, &Limitercite));
274c0ce001eSMatthew G. Knepley   *lim = NULL;
2759566063dSJacob Faibussowitsch   PetscCall(PetscFVInitializePackage());
276c0ce001eSMatthew G. Knepley 
2779566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(l, PETSCLIMITER_CLASSID, "PetscLimiter", "Finite Volume Slope Limiter", "PetscLimiter", comm, PetscLimiterDestroy, PetscLimiterView));
278c0ce001eSMatthew G. Knepley 
279c0ce001eSMatthew G. Knepley   *lim = l;
2803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
281c0ce001eSMatthew G. Knepley }
282c0ce001eSMatthew G. Knepley 
28388f5f89eSMatthew G. Knepley /*@
28488f5f89eSMatthew G. Knepley   PetscLimiterLimit - Limit the flux
28588f5f89eSMatthew G. Knepley 
28688f5f89eSMatthew G. Knepley   Input Parameters:
287dce8aebaSBarry Smith + lim  - The `PetscLimiter`
28888f5f89eSMatthew G. Knepley - flim - The input field
28988f5f89eSMatthew G. Knepley 
29088f5f89eSMatthew G. Knepley   Output Parameter:
29188f5f89eSMatthew G. Knepley . phi - The limited field
29288f5f89eSMatthew G. Knepley 
29388f5f89eSMatthew G. Knepley   Level: beginner
29488f5f89eSMatthew G. Knepley 
295dce8aebaSBarry Smith   Note:
296dce8aebaSBarry Smith   Limiters given in symmetric form following Berger, Aftosmis, and Murman 2005
297dce8aebaSBarry Smith .vb
298dce8aebaSBarry Smith  The classical flux-limited formulation is psi(r) where
299dce8aebaSBarry Smith 
300dce8aebaSBarry Smith  r = (u[0] - u[-1]) / (u[1] - u[0])
301dce8aebaSBarry Smith 
302dce8aebaSBarry Smith  The second order TVD region is bounded by
303dce8aebaSBarry Smith 
304dce8aebaSBarry Smith  psi_minmod(r) = min(r,1)      and        psi_superbee(r) = min(2, 2r, max(1,r))
305dce8aebaSBarry Smith 
306dce8aebaSBarry Smith  where all limiters are implicitly clipped to be non-negative. A more convenient slope-limited form is psi(r) =
307dce8aebaSBarry Smith  phi(r)(r+1)/2 in which the reconstructed interface values are
308dce8aebaSBarry Smith 
309dce8aebaSBarry Smith  u(v) = u[0] + phi(r) (grad u)[0] v
310dce8aebaSBarry Smith 
311dce8aebaSBarry Smith  where v is the vector from centroid to quadrature point. In these variables, the usual limiters become
312dce8aebaSBarry Smith 
313dce8aebaSBarry Smith  phi_minmod(r) = 2 min(1/(1+r),r/(1+r))   phi_superbee(r) = 2 min(2/(1+r), 2r/(1+r), max(1,r)/(1+r))
314dce8aebaSBarry Smith 
315dce8aebaSBarry Smith  For a nicer symmetric formulation, rewrite in terms of
316dce8aebaSBarry Smith 
317dce8aebaSBarry Smith  f = (u[0] - u[-1]) / (u[1] - u[-1])
318dce8aebaSBarry Smith 
319dce8aebaSBarry Smith  where r(f) = f/(1-f). Not that r(1-f) = (1-f)/f = 1/r(f) so the symmetry condition
320dce8aebaSBarry Smith 
321dce8aebaSBarry Smith  phi(r) = phi(1/r)
322dce8aebaSBarry Smith 
323dce8aebaSBarry Smith  becomes
324dce8aebaSBarry Smith 
325dce8aebaSBarry Smith  w(f) = w(1-f).
326dce8aebaSBarry Smith 
327dce8aebaSBarry Smith  The limiters below implement this final form w(f). The reference methods are
328dce8aebaSBarry Smith 
329dce8aebaSBarry Smith  w_minmod(f) = 2 min(f,(1-f))             w_superbee(r) = 4 min((1-f), f)
330dce8aebaSBarry Smith .ve
331dce8aebaSBarry Smith 
332dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterSetType()`, `PetscLimiterCreate()`
33388f5f89eSMatthew G. Knepley @*/
334d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterLimit(PetscLimiter lim, PetscReal flim, PetscReal *phi)
335d71ae5a4SJacob Faibussowitsch {
336c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
337c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
3384f572ea9SToby Isaac   PetscAssertPointer(phi, 3);
339dbbe0bcdSBarry Smith   PetscUseTypeMethod(lim, limit, flim, phi);
3403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
341c0ce001eSMatthew G. Knepley }
342c0ce001eSMatthew G. Knepley 
343d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterDestroy_Sin(PetscLimiter lim)
344d71ae5a4SJacob Faibussowitsch {
345c0ce001eSMatthew G. Knepley   PetscLimiter_Sin *l = (PetscLimiter_Sin *)lim->data;
346c0ce001eSMatthew G. Knepley 
347c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
3489566063dSJacob Faibussowitsch   PetscCall(PetscFree(l));
3493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
350c0ce001eSMatthew G. Knepley }
351c0ce001eSMatthew G. Knepley 
352d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_Sin_Ascii(PetscLimiter lim, PetscViewer viewer)
353d71ae5a4SJacob Faibussowitsch {
354c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
355c0ce001eSMatthew G. Knepley 
356c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
3579566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
3589566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Sin Slope Limiter:\n"));
3593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
360c0ce001eSMatthew G. Knepley }
361c0ce001eSMatthew G. Knepley 
362d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_Sin(PetscLimiter lim, PetscViewer viewer)
363d71ae5a4SJacob Faibussowitsch {
364c0ce001eSMatthew G. Knepley   PetscBool iascii;
365c0ce001eSMatthew G. Knepley 
366c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
367c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
368c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
3699566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
3709566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscLimiterView_Sin_Ascii(lim, viewer));
3713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
372c0ce001eSMatthew G. Knepley }
373c0ce001eSMatthew G. Knepley 
374d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterLimit_Sin(PetscLimiter lim, PetscReal f, PetscReal *phi)
375d71ae5a4SJacob Faibussowitsch {
376c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
377c0ce001eSMatthew G. Knepley   *phi = PetscSinReal(PETSC_PI * PetscMax(0, PetscMin(f, 1)));
3783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
379c0ce001eSMatthew G. Knepley }
380c0ce001eSMatthew G. Knepley 
381d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterInitialize_Sin(PetscLimiter lim)
382d71ae5a4SJacob Faibussowitsch {
383c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
384c0ce001eSMatthew G. Knepley   lim->ops->view    = PetscLimiterView_Sin;
385c0ce001eSMatthew G. Knepley   lim->ops->destroy = PetscLimiterDestroy_Sin;
386c0ce001eSMatthew G. Knepley   lim->ops->limit   = PetscLimiterLimit_Sin;
3873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
388c0ce001eSMatthew G. Knepley }
389c0ce001eSMatthew G. Knepley 
390c0ce001eSMatthew G. Knepley /*MC
391dce8aebaSBarry Smith   PETSCLIMITERSIN = "sin" - A `PetscLimiter` implementation
392c0ce001eSMatthew G. Knepley 
393c0ce001eSMatthew G. Knepley   Level: intermediate
394c0ce001eSMatthew G. Knepley 
395dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterCreate()`, `PetscLimiterSetType()`
396c0ce001eSMatthew G. Knepley M*/
397c0ce001eSMatthew G. Knepley 
398d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscLimiterCreate_Sin(PetscLimiter lim)
399d71ae5a4SJacob Faibussowitsch {
400c0ce001eSMatthew G. Knepley   PetscLimiter_Sin *l;
401c0ce001eSMatthew G. Knepley 
402c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
403c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
4044dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&l));
405c0ce001eSMatthew G. Knepley   lim->data = l;
406c0ce001eSMatthew G. Knepley 
4079566063dSJacob Faibussowitsch   PetscCall(PetscLimiterInitialize_Sin(lim));
4083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
409c0ce001eSMatthew G. Knepley }
410c0ce001eSMatthew G. Knepley 
411d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterDestroy_Zero(PetscLimiter lim)
412d71ae5a4SJacob Faibussowitsch {
413c0ce001eSMatthew G. Knepley   PetscLimiter_Zero *l = (PetscLimiter_Zero *)lim->data;
414c0ce001eSMatthew G. Knepley 
415c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
4169566063dSJacob Faibussowitsch   PetscCall(PetscFree(l));
4173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
418c0ce001eSMatthew G. Knepley }
419c0ce001eSMatthew G. Knepley 
420d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_Zero_Ascii(PetscLimiter lim, PetscViewer viewer)
421d71ae5a4SJacob Faibussowitsch {
422c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
423c0ce001eSMatthew G. Knepley 
424c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
4259566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
4269566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Zero Slope Limiter:\n"));
4273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
428c0ce001eSMatthew G. Knepley }
429c0ce001eSMatthew G. Knepley 
430d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_Zero(PetscLimiter lim, PetscViewer viewer)
431d71ae5a4SJacob Faibussowitsch {
432c0ce001eSMatthew G. Knepley   PetscBool iascii;
433c0ce001eSMatthew G. Knepley 
434c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
435c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
436c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
4379566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4389566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscLimiterView_Zero_Ascii(lim, viewer));
4393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
440c0ce001eSMatthew G. Knepley }
441c0ce001eSMatthew G. Knepley 
442d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterLimit_Zero(PetscLimiter lim, PetscReal f, PetscReal *phi)
443d71ae5a4SJacob Faibussowitsch {
444c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
445c0ce001eSMatthew G. Knepley   *phi = 0.0;
4463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
447c0ce001eSMatthew G. Knepley }
448c0ce001eSMatthew G. Knepley 
449d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterInitialize_Zero(PetscLimiter lim)
450d71ae5a4SJacob Faibussowitsch {
451c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
452c0ce001eSMatthew G. Knepley   lim->ops->view    = PetscLimiterView_Zero;
453c0ce001eSMatthew G. Knepley   lim->ops->destroy = PetscLimiterDestroy_Zero;
454c0ce001eSMatthew G. Knepley   lim->ops->limit   = PetscLimiterLimit_Zero;
4553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
456c0ce001eSMatthew G. Knepley }
457c0ce001eSMatthew G. Knepley 
458c0ce001eSMatthew G. Knepley /*MC
459dce8aebaSBarry Smith   PETSCLIMITERZERO = "zero" - A simple `PetscLimiter` implementation
460c0ce001eSMatthew G. Knepley 
461c0ce001eSMatthew G. Knepley   Level: intermediate
462c0ce001eSMatthew G. Knepley 
463dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterCreate()`, `PetscLimiterSetType()`
464c0ce001eSMatthew G. Knepley M*/
465c0ce001eSMatthew G. Knepley 
466d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscLimiterCreate_Zero(PetscLimiter lim)
467d71ae5a4SJacob Faibussowitsch {
468c0ce001eSMatthew G. Knepley   PetscLimiter_Zero *l;
469c0ce001eSMatthew G. Knepley 
470c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
471c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
4724dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&l));
473c0ce001eSMatthew G. Knepley   lim->data = l;
474c0ce001eSMatthew G. Knepley 
4759566063dSJacob Faibussowitsch   PetscCall(PetscLimiterInitialize_Zero(lim));
4763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
477c0ce001eSMatthew G. Knepley }
478c0ce001eSMatthew G. Knepley 
479d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterDestroy_None(PetscLimiter lim)
480d71ae5a4SJacob Faibussowitsch {
481c0ce001eSMatthew G. Knepley   PetscLimiter_None *l = (PetscLimiter_None *)lim->data;
482c0ce001eSMatthew G. Knepley 
483c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
4849566063dSJacob Faibussowitsch   PetscCall(PetscFree(l));
4853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
486c0ce001eSMatthew G. Knepley }
487c0ce001eSMatthew G. Knepley 
488d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_None_Ascii(PetscLimiter lim, PetscViewer viewer)
489d71ae5a4SJacob Faibussowitsch {
490c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
491c0ce001eSMatthew G. Knepley 
492c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
4939566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
4949566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "None Slope Limiter:\n"));
4953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
496c0ce001eSMatthew G. Knepley }
497c0ce001eSMatthew G. Knepley 
498d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_None(PetscLimiter lim, PetscViewer viewer)
499d71ae5a4SJacob Faibussowitsch {
500c0ce001eSMatthew G. Knepley   PetscBool iascii;
501c0ce001eSMatthew G. Knepley 
502c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
503c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
504c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
5059566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
5069566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscLimiterView_None_Ascii(lim, viewer));
5073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
508c0ce001eSMatthew G. Knepley }
509c0ce001eSMatthew G. Knepley 
510d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterLimit_None(PetscLimiter lim, PetscReal f, PetscReal *phi)
511d71ae5a4SJacob Faibussowitsch {
512c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
513c0ce001eSMatthew G. Knepley   *phi = 1.0;
5143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
515c0ce001eSMatthew G. Knepley }
516c0ce001eSMatthew G. Knepley 
517d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterInitialize_None(PetscLimiter lim)
518d71ae5a4SJacob Faibussowitsch {
519c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
520c0ce001eSMatthew G. Knepley   lim->ops->view    = PetscLimiterView_None;
521c0ce001eSMatthew G. Knepley   lim->ops->destroy = PetscLimiterDestroy_None;
522c0ce001eSMatthew G. Knepley   lim->ops->limit   = PetscLimiterLimit_None;
5233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
524c0ce001eSMatthew G. Knepley }
525c0ce001eSMatthew G. Knepley 
526c0ce001eSMatthew G. Knepley /*MC
527dce8aebaSBarry Smith   PETSCLIMITERNONE = "none" - A trivial `PetscLimiter` implementation
528c0ce001eSMatthew G. Knepley 
529c0ce001eSMatthew G. Knepley   Level: intermediate
530c0ce001eSMatthew G. Knepley 
531dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterCreate()`, `PetscLimiterSetType()`
532c0ce001eSMatthew G. Knepley M*/
533c0ce001eSMatthew G. Knepley 
534d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscLimiterCreate_None(PetscLimiter lim)
535d71ae5a4SJacob Faibussowitsch {
536c0ce001eSMatthew G. Knepley   PetscLimiter_None *l;
537c0ce001eSMatthew G. Knepley 
538c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
539c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
5404dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&l));
541c0ce001eSMatthew G. Knepley   lim->data = l;
542c0ce001eSMatthew G. Knepley 
5439566063dSJacob Faibussowitsch   PetscCall(PetscLimiterInitialize_None(lim));
5443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
545c0ce001eSMatthew G. Knepley }
546c0ce001eSMatthew G. Knepley 
547d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterDestroy_Minmod(PetscLimiter lim)
548d71ae5a4SJacob Faibussowitsch {
549c0ce001eSMatthew G. Knepley   PetscLimiter_Minmod *l = (PetscLimiter_Minmod *)lim->data;
550c0ce001eSMatthew G. Knepley 
551c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
5529566063dSJacob Faibussowitsch   PetscCall(PetscFree(l));
5533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
554c0ce001eSMatthew G. Knepley }
555c0ce001eSMatthew G. Knepley 
556d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_Minmod_Ascii(PetscLimiter lim, PetscViewer viewer)
557d71ae5a4SJacob Faibussowitsch {
558c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
559c0ce001eSMatthew G. Knepley 
560c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
5619566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
5629566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Minmod Slope Limiter:\n"));
5633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
564c0ce001eSMatthew G. Knepley }
565c0ce001eSMatthew G. Knepley 
566d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_Minmod(PetscLimiter lim, PetscViewer viewer)
567d71ae5a4SJacob Faibussowitsch {
568c0ce001eSMatthew G. Knepley   PetscBool iascii;
569c0ce001eSMatthew G. Knepley 
570c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
571c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
572c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
5739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
5749566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscLimiterView_Minmod_Ascii(lim, viewer));
5753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
576c0ce001eSMatthew G. Knepley }
577c0ce001eSMatthew G. Knepley 
578d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterLimit_Minmod(PetscLimiter lim, PetscReal f, PetscReal *phi)
579d71ae5a4SJacob Faibussowitsch {
580c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
581c0ce001eSMatthew G. Knepley   *phi = 2 * PetscMax(0, PetscMin(f, 1 - f));
5823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
583c0ce001eSMatthew G. Knepley }
584c0ce001eSMatthew G. Knepley 
585d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterInitialize_Minmod(PetscLimiter lim)
586d71ae5a4SJacob Faibussowitsch {
587c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
588c0ce001eSMatthew G. Knepley   lim->ops->view    = PetscLimiterView_Minmod;
589c0ce001eSMatthew G. Knepley   lim->ops->destroy = PetscLimiterDestroy_Minmod;
590c0ce001eSMatthew G. Knepley   lim->ops->limit   = PetscLimiterLimit_Minmod;
5913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
592c0ce001eSMatthew G. Knepley }
593c0ce001eSMatthew G. Knepley 
594c0ce001eSMatthew G. Knepley /*MC
595dce8aebaSBarry Smith   PETSCLIMITERMINMOD = "minmod" - A `PetscLimiter` implementation
596c0ce001eSMatthew G. Knepley 
597c0ce001eSMatthew G. Knepley   Level: intermediate
598c0ce001eSMatthew G. Knepley 
599dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterCreate()`, `PetscLimiterSetType()`
600c0ce001eSMatthew G. Knepley M*/
601c0ce001eSMatthew G. Knepley 
602d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscLimiterCreate_Minmod(PetscLimiter lim)
603d71ae5a4SJacob Faibussowitsch {
604c0ce001eSMatthew G. Knepley   PetscLimiter_Minmod *l;
605c0ce001eSMatthew G. Knepley 
606c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
607c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
6084dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&l));
609c0ce001eSMatthew G. Knepley   lim->data = l;
610c0ce001eSMatthew G. Knepley 
6119566063dSJacob Faibussowitsch   PetscCall(PetscLimiterInitialize_Minmod(lim));
6123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
613c0ce001eSMatthew G. Knepley }
614c0ce001eSMatthew G. Knepley 
615d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterDestroy_VanLeer(PetscLimiter lim)
616d71ae5a4SJacob Faibussowitsch {
617c0ce001eSMatthew G. Knepley   PetscLimiter_VanLeer *l = (PetscLimiter_VanLeer *)lim->data;
618c0ce001eSMatthew G. Knepley 
619c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
6209566063dSJacob Faibussowitsch   PetscCall(PetscFree(l));
6213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
622c0ce001eSMatthew G. Knepley }
623c0ce001eSMatthew G. Knepley 
624d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_VanLeer_Ascii(PetscLimiter lim, PetscViewer viewer)
625d71ae5a4SJacob Faibussowitsch {
626c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
627c0ce001eSMatthew G. Knepley 
628c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
6299566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6309566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Van Leer Slope Limiter:\n"));
6313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
632c0ce001eSMatthew G. Knepley }
633c0ce001eSMatthew G. Knepley 
634d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_VanLeer(PetscLimiter lim, PetscViewer viewer)
635d71ae5a4SJacob Faibussowitsch {
636c0ce001eSMatthew G. Knepley   PetscBool iascii;
637c0ce001eSMatthew G. Knepley 
638c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
639c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
640c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
6419566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
6429566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscLimiterView_VanLeer_Ascii(lim, viewer));
6433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
644c0ce001eSMatthew G. Knepley }
645c0ce001eSMatthew G. Knepley 
646d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterLimit_VanLeer(PetscLimiter lim, PetscReal f, PetscReal *phi)
647d71ae5a4SJacob Faibussowitsch {
648c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
649c0ce001eSMatthew G. Knepley   *phi = PetscMax(0, 4 * f * (1 - f));
6503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
651c0ce001eSMatthew G. Knepley }
652c0ce001eSMatthew G. Knepley 
653d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterInitialize_VanLeer(PetscLimiter lim)
654d71ae5a4SJacob Faibussowitsch {
655c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
656c0ce001eSMatthew G. Knepley   lim->ops->view    = PetscLimiterView_VanLeer;
657c0ce001eSMatthew G. Knepley   lim->ops->destroy = PetscLimiterDestroy_VanLeer;
658c0ce001eSMatthew G. Knepley   lim->ops->limit   = PetscLimiterLimit_VanLeer;
6593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
660c0ce001eSMatthew G. Knepley }
661c0ce001eSMatthew G. Knepley 
662c0ce001eSMatthew G. Knepley /*MC
663dce8aebaSBarry Smith   PETSCLIMITERVANLEER = "vanleer" - A `PetscLimiter` implementation
664c0ce001eSMatthew G. Knepley 
665c0ce001eSMatthew G. Knepley   Level: intermediate
666c0ce001eSMatthew G. Knepley 
667dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterCreate()`, `PetscLimiterSetType()`
668c0ce001eSMatthew G. Knepley M*/
669c0ce001eSMatthew G. Knepley 
670d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscLimiterCreate_VanLeer(PetscLimiter lim)
671d71ae5a4SJacob Faibussowitsch {
672c0ce001eSMatthew G. Knepley   PetscLimiter_VanLeer *l;
673c0ce001eSMatthew G. Knepley 
674c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
675c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
6764dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&l));
677c0ce001eSMatthew G. Knepley   lim->data = l;
678c0ce001eSMatthew G. Knepley 
6799566063dSJacob Faibussowitsch   PetscCall(PetscLimiterInitialize_VanLeer(lim));
6803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
681c0ce001eSMatthew G. Knepley }
682c0ce001eSMatthew G. Knepley 
683d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterDestroy_VanAlbada(PetscLimiter lim)
684d71ae5a4SJacob Faibussowitsch {
685c0ce001eSMatthew G. Knepley   PetscLimiter_VanAlbada *l = (PetscLimiter_VanAlbada *)lim->data;
686c0ce001eSMatthew G. Knepley 
687c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
6889566063dSJacob Faibussowitsch   PetscCall(PetscFree(l));
6893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
690c0ce001eSMatthew G. Knepley }
691c0ce001eSMatthew G. Knepley 
692d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_VanAlbada_Ascii(PetscLimiter lim, PetscViewer viewer)
693d71ae5a4SJacob Faibussowitsch {
694c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
695c0ce001eSMatthew G. Knepley 
696c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
6979566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6989566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Van Albada Slope Limiter:\n"));
6993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
700c0ce001eSMatthew G. Knepley }
701c0ce001eSMatthew G. Knepley 
702d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_VanAlbada(PetscLimiter lim, PetscViewer viewer)
703d71ae5a4SJacob Faibussowitsch {
704c0ce001eSMatthew G. Knepley   PetscBool iascii;
705c0ce001eSMatthew G. Knepley 
706c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
707c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
708c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
7099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
7109566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscLimiterView_VanAlbada_Ascii(lim, viewer));
7113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
712c0ce001eSMatthew G. Knepley }
713c0ce001eSMatthew G. Knepley 
714d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterLimit_VanAlbada(PetscLimiter lim, PetscReal f, PetscReal *phi)
715d71ae5a4SJacob Faibussowitsch {
716c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
717c0ce001eSMatthew G. Knepley   *phi = PetscMax(0, 2 * f * (1 - f) / (PetscSqr(f) + PetscSqr(1 - f)));
7183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
719c0ce001eSMatthew G. Knepley }
720c0ce001eSMatthew G. Knepley 
721d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterInitialize_VanAlbada(PetscLimiter lim)
722d71ae5a4SJacob Faibussowitsch {
723c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
724c0ce001eSMatthew G. Knepley   lim->ops->view    = PetscLimiterView_VanAlbada;
725c0ce001eSMatthew G. Knepley   lim->ops->destroy = PetscLimiterDestroy_VanAlbada;
726c0ce001eSMatthew G. Knepley   lim->ops->limit   = PetscLimiterLimit_VanAlbada;
7273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
728c0ce001eSMatthew G. Knepley }
729c0ce001eSMatthew G. Knepley 
730c0ce001eSMatthew G. Knepley /*MC
731dce8aebaSBarry Smith   PETSCLIMITERVANALBADA = "vanalbada" - A PetscLimiter implementation
732c0ce001eSMatthew G. Knepley 
733c0ce001eSMatthew G. Knepley   Level: intermediate
734c0ce001eSMatthew G. Knepley 
735dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterCreate()`, `PetscLimiterSetType()`
736c0ce001eSMatthew G. Knepley M*/
737c0ce001eSMatthew G. Knepley 
738d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscLimiterCreate_VanAlbada(PetscLimiter lim)
739d71ae5a4SJacob Faibussowitsch {
740c0ce001eSMatthew G. Knepley   PetscLimiter_VanAlbada *l;
741c0ce001eSMatthew G. Knepley 
742c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
743c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
7444dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&l));
745c0ce001eSMatthew G. Knepley   lim->data = l;
746c0ce001eSMatthew G. Knepley 
7479566063dSJacob Faibussowitsch   PetscCall(PetscLimiterInitialize_VanAlbada(lim));
7483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
749c0ce001eSMatthew G. Knepley }
750c0ce001eSMatthew G. Knepley 
751d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterDestroy_Superbee(PetscLimiter lim)
752d71ae5a4SJacob Faibussowitsch {
753c0ce001eSMatthew G. Knepley   PetscLimiter_Superbee *l = (PetscLimiter_Superbee *)lim->data;
754c0ce001eSMatthew G. Knepley 
755c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
7569566063dSJacob Faibussowitsch   PetscCall(PetscFree(l));
7573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
758c0ce001eSMatthew G. Knepley }
759c0ce001eSMatthew G. Knepley 
760d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_Superbee_Ascii(PetscLimiter lim, PetscViewer viewer)
761d71ae5a4SJacob Faibussowitsch {
762c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
763c0ce001eSMatthew G. Knepley 
764c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
7659566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
7669566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Superbee Slope Limiter:\n"));
7673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
768c0ce001eSMatthew G. Knepley }
769c0ce001eSMatthew G. Knepley 
770d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_Superbee(PetscLimiter lim, PetscViewer viewer)
771d71ae5a4SJacob Faibussowitsch {
772c0ce001eSMatthew G. Knepley   PetscBool iascii;
773c0ce001eSMatthew G. Knepley 
774c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
775c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
776c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
7779566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
7789566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscLimiterView_Superbee_Ascii(lim, viewer));
7793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
780c0ce001eSMatthew G. Knepley }
781c0ce001eSMatthew G. Knepley 
782d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterLimit_Superbee(PetscLimiter lim, PetscReal f, PetscReal *phi)
783d71ae5a4SJacob Faibussowitsch {
784c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
785c0ce001eSMatthew G. Knepley   *phi = 4 * PetscMax(0, PetscMin(f, 1 - f));
7863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
787c0ce001eSMatthew G. Knepley }
788c0ce001eSMatthew G. Knepley 
789d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterInitialize_Superbee(PetscLimiter lim)
790d71ae5a4SJacob Faibussowitsch {
791c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
792c0ce001eSMatthew G. Knepley   lim->ops->view    = PetscLimiterView_Superbee;
793c0ce001eSMatthew G. Knepley   lim->ops->destroy = PetscLimiterDestroy_Superbee;
794c0ce001eSMatthew G. Knepley   lim->ops->limit   = PetscLimiterLimit_Superbee;
7953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
796c0ce001eSMatthew G. Knepley }
797c0ce001eSMatthew G. Knepley 
798c0ce001eSMatthew G. Knepley /*MC
799dce8aebaSBarry Smith   PETSCLIMITERSUPERBEE = "superbee" - A `PetscLimiter` implementation
800c0ce001eSMatthew G. Knepley 
801c0ce001eSMatthew G. Knepley   Level: intermediate
802c0ce001eSMatthew G. Knepley 
803dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterCreate()`, `PetscLimiterSetType()`
804c0ce001eSMatthew G. Knepley M*/
805c0ce001eSMatthew G. Knepley 
806d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscLimiterCreate_Superbee(PetscLimiter lim)
807d71ae5a4SJacob Faibussowitsch {
808c0ce001eSMatthew G. Knepley   PetscLimiter_Superbee *l;
809c0ce001eSMatthew G. Knepley 
810c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
811c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
8124dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&l));
813c0ce001eSMatthew G. Knepley   lim->data = l;
814c0ce001eSMatthew G. Knepley 
8159566063dSJacob Faibussowitsch   PetscCall(PetscLimiterInitialize_Superbee(lim));
8163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
817c0ce001eSMatthew G. Knepley }
818c0ce001eSMatthew G. Knepley 
819d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterDestroy_MC(PetscLimiter lim)
820d71ae5a4SJacob Faibussowitsch {
821c0ce001eSMatthew G. Knepley   PetscLimiter_MC *l = (PetscLimiter_MC *)lim->data;
822c0ce001eSMatthew G. Knepley 
823c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
8249566063dSJacob Faibussowitsch   PetscCall(PetscFree(l));
8253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
826c0ce001eSMatthew G. Knepley }
827c0ce001eSMatthew G. Knepley 
828d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_MC_Ascii(PetscLimiter lim, PetscViewer viewer)
829d71ae5a4SJacob Faibussowitsch {
830c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
831c0ce001eSMatthew G. Knepley 
832c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
8339566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
8349566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "MC Slope Limiter:\n"));
8353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
836c0ce001eSMatthew G. Knepley }
837c0ce001eSMatthew G. Knepley 
838d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_MC(PetscLimiter lim, PetscViewer viewer)
839d71ae5a4SJacob Faibussowitsch {
840c0ce001eSMatthew G. Knepley   PetscBool iascii;
841c0ce001eSMatthew G. Knepley 
842c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
843c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
844c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
8459566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
8469566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscLimiterView_MC_Ascii(lim, viewer));
8473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
848c0ce001eSMatthew G. Knepley }
849c0ce001eSMatthew G. Knepley 
850c0ce001eSMatthew G. Knepley /* aka Barth-Jespersen */
851d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterLimit_MC(PetscLimiter lim, PetscReal f, PetscReal *phi)
852d71ae5a4SJacob Faibussowitsch {
853c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
854c0ce001eSMatthew G. Knepley   *phi = PetscMin(1, 4 * PetscMax(0, PetscMin(f, 1 - f)));
8553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
856c0ce001eSMatthew G. Knepley }
857c0ce001eSMatthew G. Knepley 
858d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterInitialize_MC(PetscLimiter lim)
859d71ae5a4SJacob Faibussowitsch {
860c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
861c0ce001eSMatthew G. Knepley   lim->ops->view    = PetscLimiterView_MC;
862c0ce001eSMatthew G. Knepley   lim->ops->destroy = PetscLimiterDestroy_MC;
863c0ce001eSMatthew G. Knepley   lim->ops->limit   = PetscLimiterLimit_MC;
8643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
865c0ce001eSMatthew G. Knepley }
866c0ce001eSMatthew G. Knepley 
867c0ce001eSMatthew G. Knepley /*MC
868dce8aebaSBarry Smith   PETSCLIMITERMC = "mc" - A `PetscLimiter` implementation
869c0ce001eSMatthew G. Knepley 
870c0ce001eSMatthew G. Knepley   Level: intermediate
871c0ce001eSMatthew G. Knepley 
872dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterCreate()`, `PetscLimiterSetType()`
873c0ce001eSMatthew G. Knepley M*/
874c0ce001eSMatthew G. Knepley 
875d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscLimiterCreate_MC(PetscLimiter lim)
876d71ae5a4SJacob Faibussowitsch {
877c0ce001eSMatthew G. Knepley   PetscLimiter_MC *l;
878c0ce001eSMatthew G. Knepley 
879c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
880c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
8814dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&l));
882c0ce001eSMatthew G. Knepley   lim->data = l;
883c0ce001eSMatthew G. Knepley 
8849566063dSJacob Faibussowitsch   PetscCall(PetscLimiterInitialize_MC(lim));
8853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
886c0ce001eSMatthew G. Knepley }
887c0ce001eSMatthew G. Knepley 
888c0ce001eSMatthew G. Knepley PetscClassId PETSCFV_CLASSID = 0;
889c0ce001eSMatthew G. Knepley 
890c0ce001eSMatthew G. Knepley PetscFunctionList PetscFVList              = NULL;
891c0ce001eSMatthew G. Knepley PetscBool         PetscFVRegisterAllCalled = PETSC_FALSE;
892c0ce001eSMatthew G. Knepley 
893c0ce001eSMatthew G. Knepley /*@C
894dce8aebaSBarry Smith   PetscFVRegister - Adds a new `PetscFV` implementation
895c0ce001eSMatthew G. Knepley 
896cc4c1da9SBarry Smith   Not Collective, No Fortran Support
897c0ce001eSMatthew G. Knepley 
898c0ce001eSMatthew G. Knepley   Input Parameters:
8992fe279fdSBarry Smith + sname    - The name of a new user-defined creation routine
9002fe279fdSBarry Smith - function - The creation routine itself
901c0ce001eSMatthew G. Knepley 
90260225df5SJacob Faibussowitsch   Example Usage:
903c0ce001eSMatthew G. Knepley .vb
904c0ce001eSMatthew G. Knepley     PetscFVRegister("my_fv", MyPetscFVCreate);
905c0ce001eSMatthew G. Knepley .ve
906c0ce001eSMatthew G. Knepley 
907c0ce001eSMatthew G. Knepley   Then, your PetscFV type can be chosen with the procedural interface via
908c0ce001eSMatthew G. Knepley .vb
909c0ce001eSMatthew G. Knepley     PetscFVCreate(MPI_Comm, PetscFV *);
910c0ce001eSMatthew G. Knepley     PetscFVSetType(PetscFV, "my_fv");
911c0ce001eSMatthew G. Knepley .ve
912c0ce001eSMatthew G. Knepley   or at runtime via the option
913c0ce001eSMatthew G. Knepley .vb
914c0ce001eSMatthew G. Knepley     -petscfv_type my_fv
915c0ce001eSMatthew G. Knepley .ve
916c0ce001eSMatthew G. Knepley 
917c0ce001eSMatthew G. Knepley   Level: advanced
918c0ce001eSMatthew G. Knepley 
919dce8aebaSBarry Smith   Note:
920dce8aebaSBarry Smith   `PetscFVRegister()` may be called multiple times to add several user-defined PetscFVs
921c0ce001eSMatthew G. Knepley 
922dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVRegisterAll()`, `PetscFVRegisterDestroy()`
923c0ce001eSMatthew G. Knepley @*/
924d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVRegister(const char sname[], PetscErrorCode (*function)(PetscFV))
925d71ae5a4SJacob Faibussowitsch {
926c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
9279566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&PetscFVList, sname, function));
9283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
929c0ce001eSMatthew G. Knepley }
930c0ce001eSMatthew G. Knepley 
931cc4c1da9SBarry Smith /*@
932dce8aebaSBarry Smith   PetscFVSetType - Builds a particular `PetscFV`
933c0ce001eSMatthew G. Knepley 
93420f4b53cSBarry Smith   Collective
935c0ce001eSMatthew G. Knepley 
936c0ce001eSMatthew G. Knepley   Input Parameters:
937dce8aebaSBarry Smith + fvm  - The `PetscFV` object
938dce8aebaSBarry Smith - name - The type of FVM space
939c0ce001eSMatthew G. Knepley 
940c0ce001eSMatthew G. Knepley   Options Database Key:
941dce8aebaSBarry Smith . -petscfv_type <type> - Sets the `PetscFVType`; use -help for a list of available types
942c0ce001eSMatthew G. Knepley 
943c0ce001eSMatthew G. Knepley   Level: intermediate
944c0ce001eSMatthew G. Knepley 
945dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVGetType()`, `PetscFVCreate()`
946c0ce001eSMatthew G. Knepley @*/
947d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetType(PetscFV fvm, PetscFVType name)
948d71ae5a4SJacob Faibussowitsch {
949c0ce001eSMatthew G. Knepley   PetscErrorCode (*r)(PetscFV);
950c0ce001eSMatthew G. Knepley   PetscBool match;
951c0ce001eSMatthew G. Knepley 
952c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
953c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
9549566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)fvm, name, &match));
9553ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
956c0ce001eSMatthew G. Knepley 
9579566063dSJacob Faibussowitsch   PetscCall(PetscFVRegisterAll());
9589566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(PetscFVList, name, &r));
95928b400f6SJacob Faibussowitsch   PetscCheck(r, PetscObjectComm((PetscObject)fvm), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscFV type: %s", name);
960c0ce001eSMatthew G. Knepley 
961dbbe0bcdSBarry Smith   PetscTryTypeMethod(fvm, destroy);
962c0ce001eSMatthew G. Knepley   fvm->ops->destroy = NULL;
963dbbe0bcdSBarry Smith 
9649566063dSJacob Faibussowitsch   PetscCall((*r)(fvm));
9659566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)fvm, name));
9663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
967c0ce001eSMatthew G. Knepley }
968c0ce001eSMatthew G. Knepley 
969cc4c1da9SBarry Smith /*@
970dce8aebaSBarry Smith   PetscFVGetType - Gets the `PetscFVType` (as a string) from a `PetscFV`.
971c0ce001eSMatthew G. Knepley 
972c0ce001eSMatthew G. Knepley   Not Collective
973c0ce001eSMatthew G. Knepley 
974c0ce001eSMatthew G. Knepley   Input Parameter:
975dce8aebaSBarry Smith . fvm - The `PetscFV`
976c0ce001eSMatthew G. Knepley 
977c0ce001eSMatthew G. Knepley   Output Parameter:
978dce8aebaSBarry Smith . name - The `PetscFVType` name
979c0ce001eSMatthew G. Knepley 
980c0ce001eSMatthew G. Knepley   Level: intermediate
981c0ce001eSMatthew G. Knepley 
982dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVSetType()`, `PetscFVCreate()`
983c0ce001eSMatthew G. Knepley @*/
984d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetType(PetscFV fvm, PetscFVType *name)
985d71ae5a4SJacob Faibussowitsch {
986c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
987c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
9884f572ea9SToby Isaac   PetscAssertPointer(name, 2);
9899566063dSJacob Faibussowitsch   PetscCall(PetscFVRegisterAll());
990c0ce001eSMatthew G. Knepley   *name = ((PetscObject)fvm)->type_name;
9913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
992c0ce001eSMatthew G. Knepley }
993c0ce001eSMatthew G. Knepley 
994*ffeef943SBarry Smith /*@
995dce8aebaSBarry Smith   PetscFVViewFromOptions - View a `PetscFV` based on values in the options database
996fe2efc57SMark 
99720f4b53cSBarry Smith   Collective
998fe2efc57SMark 
999fe2efc57SMark   Input Parameters:
1000dce8aebaSBarry Smith + A    - the `PetscFV` object
1001dce8aebaSBarry Smith . obj  - Optional object that provides the options prefix
1002dce8aebaSBarry Smith - name - command line option name
1003fe2efc57SMark 
1004fe2efc57SMark   Level: intermediate
1005dce8aebaSBarry Smith 
1006dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVView()`, `PetscObjectViewFromOptions()`, `PetscFVCreate()`
1007fe2efc57SMark @*/
1008d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVViewFromOptions(PetscFV A, PetscObject obj, const char name[])
1009d71ae5a4SJacob Faibussowitsch {
1010fe2efc57SMark   PetscFunctionBegin;
1011fe2efc57SMark   PetscValidHeaderSpecific(A, PETSCFV_CLASSID, 1);
10129566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
10133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1014fe2efc57SMark }
1015fe2efc57SMark 
1016*ffeef943SBarry Smith /*@
1017dce8aebaSBarry Smith   PetscFVView - Views a `PetscFV`
1018c0ce001eSMatthew G. Knepley 
101920f4b53cSBarry Smith   Collective
1020c0ce001eSMatthew G. Knepley 
1021d8d19677SJose E. Roman   Input Parameters:
1022dce8aebaSBarry Smith + fvm - the `PetscFV` object to view
1023c0ce001eSMatthew G. Knepley - v   - the viewer
1024c0ce001eSMatthew G. Knepley 
102588f5f89eSMatthew G. Knepley   Level: beginner
1026c0ce001eSMatthew G. Knepley 
1027dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscViewer`, `PetscFVDestroy()`
1028c0ce001eSMatthew G. Knepley @*/
1029d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVView(PetscFV fvm, PetscViewer v)
1030d71ae5a4SJacob Faibussowitsch {
1031c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1032c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
10339566063dSJacob Faibussowitsch   if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)fvm), &v));
1034dbbe0bcdSBarry Smith   PetscTryTypeMethod(fvm, view, v);
10353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1036c0ce001eSMatthew G. Knepley }
1037c0ce001eSMatthew G. Knepley 
1038c0ce001eSMatthew G. Knepley /*@
1039dce8aebaSBarry Smith   PetscFVSetFromOptions - sets parameters in a `PetscFV` from the options database
1040c0ce001eSMatthew G. Knepley 
104120f4b53cSBarry Smith   Collective
1042c0ce001eSMatthew G. Knepley 
1043c0ce001eSMatthew G. Knepley   Input Parameter:
1044dce8aebaSBarry Smith . fvm - the `PetscFV` object to set options for
1045c0ce001eSMatthew G. Knepley 
1046c0ce001eSMatthew G. Knepley   Options Database Key:
1047c0ce001eSMatthew G. Knepley . -petscfv_compute_gradients <bool> - Determines whether cell gradients are calculated
1048c0ce001eSMatthew G. Knepley 
104988f5f89eSMatthew G. Knepley   Level: intermediate
1050c0ce001eSMatthew G. Knepley 
1051dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVView()`
1052c0ce001eSMatthew G. Knepley @*/
1053d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetFromOptions(PetscFV fvm)
1054d71ae5a4SJacob Faibussowitsch {
1055c0ce001eSMatthew G. Knepley   const char *defaultType;
1056c0ce001eSMatthew G. Knepley   char        name[256];
1057c0ce001eSMatthew G. Knepley   PetscBool   flg;
1058c0ce001eSMatthew G. Knepley 
1059c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1060c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1061c0ce001eSMatthew G. Knepley   if (!((PetscObject)fvm)->type_name) defaultType = PETSCFVUPWIND;
1062c0ce001eSMatthew G. Knepley   else defaultType = ((PetscObject)fvm)->type_name;
10639566063dSJacob Faibussowitsch   PetscCall(PetscFVRegisterAll());
1064c0ce001eSMatthew G. Knepley 
1065d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)fvm);
10669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-petscfv_type", "Finite volume discretization", "PetscFVSetType", PetscFVList, defaultType, name, 256, &flg));
1067c0ce001eSMatthew G. Knepley   if (flg) {
10689566063dSJacob Faibussowitsch     PetscCall(PetscFVSetType(fvm, name));
1069c0ce001eSMatthew G. Knepley   } else if (!((PetscObject)fvm)->type_name) {
10709566063dSJacob Faibussowitsch     PetscCall(PetscFVSetType(fvm, defaultType));
1071c0ce001eSMatthew G. Knepley   }
10729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-petscfv_compute_gradients", "Compute cell gradients", "PetscFVSetComputeGradients", fvm->computeGradients, &fvm->computeGradients, NULL));
1073dbbe0bcdSBarry Smith   PetscTryTypeMethod(fvm, setfromoptions);
1074c0ce001eSMatthew G. Knepley   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1075dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)fvm, PetscOptionsObject));
10769566063dSJacob Faibussowitsch   PetscCall(PetscLimiterSetFromOptions(fvm->limiter));
1077d0609cedSBarry Smith   PetscOptionsEnd();
10789566063dSJacob Faibussowitsch   PetscCall(PetscFVViewFromOptions(fvm, NULL, "-petscfv_view"));
10793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1080c0ce001eSMatthew G. Knepley }
1081c0ce001eSMatthew G. Knepley 
1082c0ce001eSMatthew G. Knepley /*@
1083dce8aebaSBarry Smith   PetscFVSetUp - Setup the data structures for the `PetscFV` based on the `PetscFVType` provided by `PetscFVSetType()`
1084c0ce001eSMatthew G. Knepley 
108520f4b53cSBarry Smith   Collective
1086c0ce001eSMatthew G. Knepley 
1087c0ce001eSMatthew G. Knepley   Input Parameter:
1088dce8aebaSBarry Smith . fvm - the `PetscFV` object to setup
1089c0ce001eSMatthew G. Knepley 
109088f5f89eSMatthew G. Knepley   Level: intermediate
1091c0ce001eSMatthew G. Knepley 
1092dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVView()`, `PetscFVDestroy()`
1093c0ce001eSMatthew G. Knepley @*/
1094d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetUp(PetscFV fvm)
1095d71ae5a4SJacob Faibussowitsch {
1096c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1097c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
10989566063dSJacob Faibussowitsch   PetscCall(PetscLimiterSetUp(fvm->limiter));
1099dbbe0bcdSBarry Smith   PetscTryTypeMethod(fvm, setup);
11003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1101c0ce001eSMatthew G. Knepley }
1102c0ce001eSMatthew G. Knepley 
1103c0ce001eSMatthew G. Knepley /*@
1104dce8aebaSBarry Smith   PetscFVDestroy - Destroys a `PetscFV` object
1105c0ce001eSMatthew G. Knepley 
110620f4b53cSBarry Smith   Collective
1107c0ce001eSMatthew G. Knepley 
1108c0ce001eSMatthew G. Knepley   Input Parameter:
1109dce8aebaSBarry Smith . fvm - the `PetscFV` object to destroy
1110c0ce001eSMatthew G. Knepley 
111188f5f89eSMatthew G. Knepley   Level: beginner
1112c0ce001eSMatthew G. Knepley 
1113dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVCreate()`, `PetscFVView()`
1114c0ce001eSMatthew G. Knepley @*/
1115d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVDestroy(PetscFV *fvm)
1116d71ae5a4SJacob Faibussowitsch {
1117c0ce001eSMatthew G. Knepley   PetscInt i;
1118c0ce001eSMatthew G. Knepley 
1119c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
11203ba16761SJacob Faibussowitsch   if (!*fvm) PetscFunctionReturn(PETSC_SUCCESS);
1121f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*fvm, PETSCFV_CLASSID, 1);
1122c0ce001eSMatthew G. Knepley 
1123f4f49eeaSPierre Jolivet   if (--((PetscObject)*fvm)->refct > 0) {
11249371c9d4SSatish Balay     *fvm = NULL;
11253ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
11269371c9d4SSatish Balay   }
1127f4f49eeaSPierre Jolivet   ((PetscObject)*fvm)->refct = 0;
1128c0ce001eSMatthew G. Knepley 
112948a46eb9SPierre Jolivet   for (i = 0; i < (*fvm)->numComponents; i++) PetscCall(PetscFree((*fvm)->componentNames[i]));
11309566063dSJacob Faibussowitsch   PetscCall(PetscFree((*fvm)->componentNames));
11319566063dSJacob Faibussowitsch   PetscCall(PetscLimiterDestroy(&(*fvm)->limiter));
11329566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDestroy(&(*fvm)->dualSpace));
11339566063dSJacob Faibussowitsch   PetscCall(PetscFree((*fvm)->fluxWork));
11349566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&(*fvm)->quadrature));
11359566063dSJacob Faibussowitsch   PetscCall(PetscTabulationDestroy(&(*fvm)->T));
1136c0ce001eSMatthew G. Knepley 
1137f4f49eeaSPierre Jolivet   PetscTryTypeMethod(*fvm, destroy);
11389566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(fvm));
11393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1140c0ce001eSMatthew G. Knepley }
1141c0ce001eSMatthew G. Knepley 
1142c0ce001eSMatthew G. Knepley /*@
1143dce8aebaSBarry Smith   PetscFVCreate - Creates an empty `PetscFV` object. The type can then be set with `PetscFVSetType()`.
1144c0ce001eSMatthew G. Knepley 
1145c0ce001eSMatthew G. Knepley   Collective
1146c0ce001eSMatthew G. Knepley 
1147c0ce001eSMatthew G. Knepley   Input Parameter:
1148dce8aebaSBarry Smith . comm - The communicator for the `PetscFV` object
1149c0ce001eSMatthew G. Knepley 
1150c0ce001eSMatthew G. Knepley   Output Parameter:
1151dce8aebaSBarry Smith . fvm - The `PetscFV` object
1152c0ce001eSMatthew G. Knepley 
1153c0ce001eSMatthew G. Knepley   Level: beginner
1154c0ce001eSMatthew G. Knepley 
11551d27aa22SBarry Smith .seealso: `PetscFVSetUp()`, `PetscFVSetType()`, `PETSCFVUPWIND`, `PetscFVDestroy()`
1156c0ce001eSMatthew G. Knepley @*/
1157d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVCreate(MPI_Comm comm, PetscFV *fvm)
1158d71ae5a4SJacob Faibussowitsch {
1159c0ce001eSMatthew G. Knepley   PetscFV f;
1160c0ce001eSMatthew G. Knepley 
1161c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
11624f572ea9SToby Isaac   PetscAssertPointer(fvm, 2);
1163c0ce001eSMatthew G. Knepley   *fvm = NULL;
11649566063dSJacob Faibussowitsch   PetscCall(PetscFVInitializePackage());
1165c0ce001eSMatthew G. Knepley 
11669566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(f, PETSCFV_CLASSID, "PetscFV", "Finite Volume", "PetscFV", comm, PetscFVDestroy, PetscFVView));
11679566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(f->ops, sizeof(struct _PetscFVOps)));
1168c0ce001eSMatthew G. Knepley 
11699566063dSJacob Faibussowitsch   PetscCall(PetscLimiterCreate(comm, &f->limiter));
1170c0ce001eSMatthew G. Knepley   f->numComponents    = 1;
1171c0ce001eSMatthew G. Knepley   f->dim              = 0;
1172c0ce001eSMatthew G. Knepley   f->computeGradients = PETSC_FALSE;
1173c0ce001eSMatthew G. Knepley   f->fluxWork         = NULL;
11749566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(f->numComponents, &f->componentNames));
1175c0ce001eSMatthew G. Knepley 
1176c0ce001eSMatthew G. Knepley   *fvm = f;
11773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1178c0ce001eSMatthew G. Knepley }
1179c0ce001eSMatthew G. Knepley 
1180c0ce001eSMatthew G. Knepley /*@
1181dce8aebaSBarry Smith   PetscFVSetLimiter - Set the `PetscLimiter` to the `PetscFV`
1182c0ce001eSMatthew G. Knepley 
118320f4b53cSBarry Smith   Logically Collective
1184c0ce001eSMatthew G. Knepley 
1185c0ce001eSMatthew G. Knepley   Input Parameters:
1186dce8aebaSBarry Smith + fvm - the `PetscFV` object
1187dce8aebaSBarry Smith - lim - The `PetscLimiter`
1188c0ce001eSMatthew G. Knepley 
118988f5f89eSMatthew G. Knepley   Level: intermediate
1190c0ce001eSMatthew G. Knepley 
1191dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscLimiter`, `PetscFVGetLimiter()`
1192c0ce001eSMatthew G. Knepley @*/
1193d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetLimiter(PetscFV fvm, PetscLimiter lim)
1194d71ae5a4SJacob Faibussowitsch {
1195c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1196c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1197c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 2);
11989566063dSJacob Faibussowitsch   PetscCall(PetscLimiterDestroy(&fvm->limiter));
11999566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)lim));
1200c0ce001eSMatthew G. Knepley   fvm->limiter = lim;
12013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1202c0ce001eSMatthew G. Knepley }
1203c0ce001eSMatthew G. Knepley 
1204c0ce001eSMatthew G. Knepley /*@
1205dce8aebaSBarry Smith   PetscFVGetLimiter - Get the `PetscLimiter` object from the `PetscFV`
1206c0ce001eSMatthew G. Knepley 
120720f4b53cSBarry Smith   Not Collective
1208c0ce001eSMatthew G. Knepley 
1209c0ce001eSMatthew G. Knepley   Input Parameter:
1210dce8aebaSBarry Smith . fvm - the `PetscFV` object
1211c0ce001eSMatthew G. Knepley 
1212c0ce001eSMatthew G. Knepley   Output Parameter:
1213dce8aebaSBarry Smith . lim - The `PetscLimiter`
1214c0ce001eSMatthew G. Knepley 
121588f5f89eSMatthew G. Knepley   Level: intermediate
1216c0ce001eSMatthew G. Knepley 
1217dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscLimiter`, `PetscFVSetLimiter()`
1218c0ce001eSMatthew G. Knepley @*/
1219d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetLimiter(PetscFV fvm, PetscLimiter *lim)
1220d71ae5a4SJacob Faibussowitsch {
1221c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1222c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
12234f572ea9SToby Isaac   PetscAssertPointer(lim, 2);
1224c0ce001eSMatthew G. Knepley   *lim = fvm->limiter;
12253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1226c0ce001eSMatthew G. Knepley }
1227c0ce001eSMatthew G. Knepley 
1228c0ce001eSMatthew G. Knepley /*@
1229dce8aebaSBarry Smith   PetscFVSetNumComponents - Set the number of field components in a `PetscFV`
1230c0ce001eSMatthew G. Knepley 
123120f4b53cSBarry Smith   Logically Collective
1232c0ce001eSMatthew G. Knepley 
1233c0ce001eSMatthew G. Knepley   Input Parameters:
1234dce8aebaSBarry Smith + fvm  - the `PetscFV` object
1235c0ce001eSMatthew G. Knepley - comp - The number of components
1236c0ce001eSMatthew G. Knepley 
123788f5f89eSMatthew G. Knepley   Level: intermediate
1238c0ce001eSMatthew G. Knepley 
1239dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVGetNumComponents()`
1240c0ce001eSMatthew G. Knepley @*/
1241d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetNumComponents(PetscFV fvm, PetscInt comp)
1242d71ae5a4SJacob Faibussowitsch {
1243c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1244c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1245c0ce001eSMatthew G. Knepley   if (fvm->numComponents != comp) {
1246c0ce001eSMatthew G. Knepley     PetscInt i;
1247c0ce001eSMatthew G. Knepley 
124848a46eb9SPierre Jolivet     for (i = 0; i < fvm->numComponents; i++) PetscCall(PetscFree(fvm->componentNames[i]));
12499566063dSJacob Faibussowitsch     PetscCall(PetscFree(fvm->componentNames));
12509566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(comp, &fvm->componentNames));
1251c0ce001eSMatthew G. Knepley   }
1252c0ce001eSMatthew G. Knepley   fvm->numComponents = comp;
12539566063dSJacob Faibussowitsch   PetscCall(PetscFree(fvm->fluxWork));
12549566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(comp, &fvm->fluxWork));
12553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1256c0ce001eSMatthew G. Knepley }
1257c0ce001eSMatthew G. Knepley 
1258c0ce001eSMatthew G. Knepley /*@
1259dce8aebaSBarry Smith   PetscFVGetNumComponents - Get the number of field components in a `PetscFV`
1260c0ce001eSMatthew G. Knepley 
126120f4b53cSBarry Smith   Not Collective
1262c0ce001eSMatthew G. Knepley 
1263c0ce001eSMatthew G. Knepley   Input Parameter:
1264dce8aebaSBarry Smith . fvm - the `PetscFV` object
1265c0ce001eSMatthew G. Knepley 
1266c0ce001eSMatthew G. Knepley   Output Parameter:
1267a4e35b19SJacob Faibussowitsch . comp - The number of components
1268c0ce001eSMatthew G. Knepley 
126988f5f89eSMatthew G. Knepley   Level: intermediate
1270c0ce001eSMatthew G. Knepley 
1271dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVSetNumComponents()`, `PetscFVSetComponentName()`
1272c0ce001eSMatthew G. Knepley @*/
1273d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetNumComponents(PetscFV fvm, PetscInt *comp)
1274d71ae5a4SJacob Faibussowitsch {
1275c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1276c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
12774f572ea9SToby Isaac   PetscAssertPointer(comp, 2);
1278c0ce001eSMatthew G. Knepley   *comp = fvm->numComponents;
12793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1280c0ce001eSMatthew G. Knepley }
1281c0ce001eSMatthew G. Knepley 
1282c0ce001eSMatthew G. Knepley /*@C
1283dce8aebaSBarry Smith   PetscFVSetComponentName - Set the name of a component (used in output and viewing) in a `PetscFV`
1284c0ce001eSMatthew G. Knepley 
128520f4b53cSBarry Smith   Logically Collective
1286dce8aebaSBarry Smith 
1287c0ce001eSMatthew G. Knepley   Input Parameters:
1288dce8aebaSBarry Smith + fvm  - the `PetscFV` object
1289c0ce001eSMatthew G. Knepley . comp - the component number
1290c0ce001eSMatthew G. Knepley - name - the component name
1291c0ce001eSMatthew G. Knepley 
129288f5f89eSMatthew G. Knepley   Level: intermediate
1293c0ce001eSMatthew G. Knepley 
1294dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVGetComponentName()`
1295c0ce001eSMatthew G. Knepley @*/
1296d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetComponentName(PetscFV fvm, PetscInt comp, const char *name)
1297d71ae5a4SJacob Faibussowitsch {
1298c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
12999566063dSJacob Faibussowitsch   PetscCall(PetscFree(fvm->componentNames[comp]));
13009566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(name, &fvm->componentNames[comp]));
13013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1302c0ce001eSMatthew G. Knepley }
1303c0ce001eSMatthew G. Knepley 
1304cc4c1da9SBarry Smith /*@
1305dce8aebaSBarry Smith   PetscFVGetComponentName - Get the name of a component (used in output and viewing) in a `PetscFV`
1306c0ce001eSMatthew G. Knepley 
130720f4b53cSBarry Smith   Logically Collective
130860225df5SJacob Faibussowitsch 
1309c0ce001eSMatthew G. Knepley   Input Parameters:
1310dce8aebaSBarry Smith + fvm  - the `PetscFV` object
1311c0ce001eSMatthew G. Knepley - comp - the component number
1312c0ce001eSMatthew G. Knepley 
1313c0ce001eSMatthew G. Knepley   Output Parameter:
1314c0ce001eSMatthew G. Knepley . name - the component name
1315c0ce001eSMatthew G. Knepley 
131688f5f89eSMatthew G. Knepley   Level: intermediate
1317c0ce001eSMatthew G. Knepley 
1318dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVSetComponentName()`
1319c0ce001eSMatthew G. Knepley @*/
1320cc4c1da9SBarry Smith PetscErrorCode PetscFVGetComponentName(PetscFV fvm, PetscInt comp, const char *name[])
1321d71ae5a4SJacob Faibussowitsch {
1322c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1323c0ce001eSMatthew G. Knepley   *name = fvm->componentNames[comp];
13243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1325c0ce001eSMatthew G. Knepley }
1326c0ce001eSMatthew G. Knepley 
1327c0ce001eSMatthew G. Knepley /*@
1328dce8aebaSBarry Smith   PetscFVSetSpatialDimension - Set the spatial dimension of a `PetscFV`
1329c0ce001eSMatthew G. Knepley 
133020f4b53cSBarry Smith   Logically Collective
1331c0ce001eSMatthew G. Knepley 
1332c0ce001eSMatthew G. Knepley   Input Parameters:
1333dce8aebaSBarry Smith + fvm - the `PetscFV` object
1334c0ce001eSMatthew G. Knepley - dim - The spatial dimension
1335c0ce001eSMatthew G. Knepley 
133688f5f89eSMatthew G. Knepley   Level: intermediate
1337c0ce001eSMatthew G. Knepley 
1338dce8aebaSBarry Smith .seealso: `PetscFV`, ``PetscFVGetSpatialDimension()`
1339c0ce001eSMatthew G. Knepley @*/
1340d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetSpatialDimension(PetscFV fvm, PetscInt dim)
1341d71ae5a4SJacob Faibussowitsch {
1342c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1343c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1344c0ce001eSMatthew G. Knepley   fvm->dim = dim;
13453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1346c0ce001eSMatthew G. Knepley }
1347c0ce001eSMatthew G. Knepley 
1348c0ce001eSMatthew G. Knepley /*@
1349dce8aebaSBarry Smith   PetscFVGetSpatialDimension - Get the spatial dimension of a `PetscFV`
1350c0ce001eSMatthew G. Knepley 
135120f4b53cSBarry Smith   Not Collective
1352c0ce001eSMatthew G. Knepley 
1353c0ce001eSMatthew G. Knepley   Input Parameter:
1354dce8aebaSBarry Smith . fvm - the `PetscFV` object
1355c0ce001eSMatthew G. Knepley 
1356c0ce001eSMatthew G. Knepley   Output Parameter:
1357c0ce001eSMatthew G. Knepley . dim - The spatial dimension
1358c0ce001eSMatthew G. Knepley 
135988f5f89eSMatthew G. Knepley   Level: intermediate
1360c0ce001eSMatthew G. Knepley 
1361dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVSetSpatialDimension()`
1362c0ce001eSMatthew G. Knepley @*/
1363d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetSpatialDimension(PetscFV fvm, PetscInt *dim)
1364d71ae5a4SJacob Faibussowitsch {
1365c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1366c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
13674f572ea9SToby Isaac   PetscAssertPointer(dim, 2);
1368c0ce001eSMatthew G. Knepley   *dim = fvm->dim;
13693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1370c0ce001eSMatthew G. Knepley }
1371c0ce001eSMatthew G. Knepley 
1372c0ce001eSMatthew G. Knepley /*@
1373dce8aebaSBarry Smith   PetscFVSetComputeGradients - Toggle computation of cell gradients on a `PetscFV`
1374c0ce001eSMatthew G. Knepley 
137520f4b53cSBarry Smith   Logically Collective
1376c0ce001eSMatthew G. Knepley 
1377c0ce001eSMatthew G. Knepley   Input Parameters:
1378dce8aebaSBarry Smith + fvm              - the `PetscFV` object
1379c0ce001eSMatthew G. Knepley - computeGradients - Flag to compute cell gradients
1380c0ce001eSMatthew G. Knepley 
138188f5f89eSMatthew G. Knepley   Level: intermediate
1382c0ce001eSMatthew G. Knepley 
1383dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVGetComputeGradients()`
1384c0ce001eSMatthew G. Knepley @*/
1385d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetComputeGradients(PetscFV fvm, PetscBool computeGradients)
1386d71ae5a4SJacob Faibussowitsch {
1387c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1388c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1389c0ce001eSMatthew G. Knepley   fvm->computeGradients = computeGradients;
13903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1391c0ce001eSMatthew G. Knepley }
1392c0ce001eSMatthew G. Knepley 
1393c0ce001eSMatthew G. Knepley /*@
1394dce8aebaSBarry Smith   PetscFVGetComputeGradients - Return flag for computation of cell gradients on a `PetscFV`
1395c0ce001eSMatthew G. Knepley 
139620f4b53cSBarry Smith   Not Collective
1397c0ce001eSMatthew G. Knepley 
1398c0ce001eSMatthew G. Knepley   Input Parameter:
1399dce8aebaSBarry Smith . fvm - the `PetscFV` object
1400c0ce001eSMatthew G. Knepley 
1401c0ce001eSMatthew G. Knepley   Output Parameter:
1402c0ce001eSMatthew G. Knepley . computeGradients - Flag to compute cell gradients
1403c0ce001eSMatthew G. Knepley 
140488f5f89eSMatthew G. Knepley   Level: intermediate
1405c0ce001eSMatthew G. Knepley 
1406dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVSetComputeGradients()`
1407c0ce001eSMatthew G. Knepley @*/
1408d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetComputeGradients(PetscFV fvm, PetscBool *computeGradients)
1409d71ae5a4SJacob Faibussowitsch {
1410c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1411c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
14124f572ea9SToby Isaac   PetscAssertPointer(computeGradients, 2);
1413c0ce001eSMatthew G. Knepley   *computeGradients = fvm->computeGradients;
14143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1415c0ce001eSMatthew G. Knepley }
1416c0ce001eSMatthew G. Knepley 
1417c0ce001eSMatthew G. Knepley /*@
1418dce8aebaSBarry Smith   PetscFVSetQuadrature - Set the `PetscQuadrature` object for a `PetscFV`
1419c0ce001eSMatthew G. Knepley 
142020f4b53cSBarry Smith   Logically Collective
1421c0ce001eSMatthew G. Knepley 
1422c0ce001eSMatthew G. Knepley   Input Parameters:
1423dce8aebaSBarry Smith + fvm - the `PetscFV` object
1424dce8aebaSBarry Smith - q   - The `PetscQuadrature`
1425c0ce001eSMatthew G. Knepley 
142688f5f89eSMatthew G. Knepley   Level: intermediate
1427c0ce001eSMatthew G. Knepley 
1428dce8aebaSBarry Smith .seealso: `PetscQuadrature`, `PetscFV`, `PetscFVGetQuadrature()`
1429c0ce001eSMatthew G. Knepley @*/
1430d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetQuadrature(PetscFV fvm, PetscQuadrature q)
1431d71ae5a4SJacob Faibussowitsch {
1432c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1433c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
14349566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)q));
1435f6feae9bSMatthew G. Knepley   PetscCall(PetscQuadratureDestroy(&fvm->quadrature));
1436c0ce001eSMatthew G. Knepley   fvm->quadrature = q;
14373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1438c0ce001eSMatthew G. Knepley }
1439c0ce001eSMatthew G. Knepley 
1440c0ce001eSMatthew G. Knepley /*@
1441dce8aebaSBarry Smith   PetscFVGetQuadrature - Get the `PetscQuadrature` from a `PetscFV`
1442c0ce001eSMatthew G. Knepley 
144320f4b53cSBarry Smith   Not Collective
1444c0ce001eSMatthew G. Knepley 
1445c0ce001eSMatthew G. Knepley   Input Parameter:
1446dce8aebaSBarry Smith . fvm - the `PetscFV` object
1447c0ce001eSMatthew G. Knepley 
1448c0ce001eSMatthew G. Knepley   Output Parameter:
144960225df5SJacob Faibussowitsch . q - The `PetscQuadrature`
1450c0ce001eSMatthew G. Knepley 
145188f5f89eSMatthew G. Knepley   Level: intermediate
1452c0ce001eSMatthew G. Knepley 
1453dce8aebaSBarry Smith .seealso: `PetscQuadrature`, `PetscFV`, `PetscFVSetQuadrature()`
1454c0ce001eSMatthew G. Knepley @*/
1455d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetQuadrature(PetscFV fvm, PetscQuadrature *q)
1456d71ae5a4SJacob Faibussowitsch {
1457c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1458c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
14594f572ea9SToby Isaac   PetscAssertPointer(q, 2);
1460c0ce001eSMatthew G. Knepley   if (!fvm->quadrature) {
1461c0ce001eSMatthew G. Knepley     /* Create default 1-point quadrature */
1462c0ce001eSMatthew G. Knepley     PetscReal *points, *weights;
1463c0ce001eSMatthew G. Knepley 
14649566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, &fvm->quadrature));
14659566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(fvm->dim, &points));
14669566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(1, &weights));
1467c0ce001eSMatthew G. Knepley     weights[0] = 1.0;
14689566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureSetData(fvm->quadrature, fvm->dim, 1, 1, points, weights));
1469c0ce001eSMatthew G. Knepley   }
1470c0ce001eSMatthew G. Knepley   *q = fvm->quadrature;
14713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1472c0ce001eSMatthew G. Knepley }
1473c0ce001eSMatthew G. Knepley 
1474c0ce001eSMatthew G. Knepley /*@
14752f86f8c5SMatthew G. Knepley   PetscFVCreateDualSpace - Creates a `PetscDualSpace` appropriate for the `PetscFV`
14762f86f8c5SMatthew G. Knepley 
14772f86f8c5SMatthew G. Knepley   Not Collective
14782f86f8c5SMatthew G. Knepley 
14799cde84edSJose E. Roman   Input Parameters:
14802f86f8c5SMatthew G. Knepley + fvm - The `PetscFV` object
14812f86f8c5SMatthew G. Knepley - ct  - The `DMPolytopeType` for the cell
14822f86f8c5SMatthew G. Knepley 
14832f86f8c5SMatthew G. Knepley   Level: intermediate
14842f86f8c5SMatthew G. Knepley 
14852f86f8c5SMatthew G. Knepley .seealso: `PetscFVGetDualSpace()`, `PetscFVSetDualSpace()`, `PetscDualSpace`, `PetscFV`, `PetscFVCreate()`
14862f86f8c5SMatthew G. Knepley @*/
14872f86f8c5SMatthew G. Knepley PetscErrorCode PetscFVCreateDualSpace(PetscFV fvm, DMPolytopeType ct)
14882f86f8c5SMatthew G. Knepley {
14892f86f8c5SMatthew G. Knepley   DM       K;
14902f86f8c5SMatthew G. Knepley   PetscInt dim, Nc;
14912f86f8c5SMatthew G. Knepley 
14922f86f8c5SMatthew G. Knepley   PetscFunctionBegin;
14932f86f8c5SMatthew G. Knepley   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
14942f86f8c5SMatthew G. Knepley   PetscCall(PetscFVGetNumComponents(fvm, &Nc));
14952f86f8c5SMatthew G. Knepley   PetscCall(PetscDualSpaceCreate(PetscObjectComm((PetscObject)fvm), &fvm->dualSpace));
14962f86f8c5SMatthew G. Knepley   PetscCall(PetscDualSpaceSetType(fvm->dualSpace, PETSCDUALSPACESIMPLE));
14972f86f8c5SMatthew G. Knepley   PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, ct, &K));
14982f86f8c5SMatthew G. Knepley   PetscCall(PetscDualSpaceSetNumComponents(fvm->dualSpace, Nc));
14992f86f8c5SMatthew G. Knepley   PetscCall(PetscDualSpaceSetDM(fvm->dualSpace, K));
15002f86f8c5SMatthew G. Knepley   PetscCall(DMDestroy(&K));
15012f86f8c5SMatthew G. Knepley   PetscCall(PetscDualSpaceSimpleSetDimension(fvm->dualSpace, Nc));
15022f86f8c5SMatthew G. Knepley   // Should we be using PetscFVGetQuadrature() here?
15032f86f8c5SMatthew G. Knepley   for (PetscInt c = 0; c < Nc; ++c) {
15042f86f8c5SMatthew G. Knepley     PetscQuadrature qc;
15052f86f8c5SMatthew G. Knepley     PetscReal      *points, *weights;
15062f86f8c5SMatthew G. Knepley 
15072f86f8c5SMatthew G. Knepley     PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, &qc));
15082f86f8c5SMatthew G. Knepley     PetscCall(PetscCalloc1(dim, &points));
15092f86f8c5SMatthew G. Knepley     PetscCall(PetscCalloc1(Nc, &weights));
15102f86f8c5SMatthew G. Knepley     weights[c] = 1.0;
15112f86f8c5SMatthew G. Knepley     PetscCall(PetscQuadratureSetData(qc, dim, Nc, 1, points, weights));
15122f86f8c5SMatthew G. Knepley     PetscCall(PetscDualSpaceSimpleSetFunctional(fvm->dualSpace, c, qc));
15132f86f8c5SMatthew G. Knepley     PetscCall(PetscQuadratureDestroy(&qc));
15142f86f8c5SMatthew G. Knepley   }
15152f86f8c5SMatthew G. Knepley   PetscCall(PetscDualSpaceSetUp(fvm->dualSpace));
15162f86f8c5SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
15172f86f8c5SMatthew G. Knepley }
15182f86f8c5SMatthew G. Knepley 
15192f86f8c5SMatthew G. Knepley /*@
1520dce8aebaSBarry Smith   PetscFVGetDualSpace - Returns the `PetscDualSpace` used to define the inner product on a `PetscFV`
1521c0ce001eSMatthew G. Knepley 
152220f4b53cSBarry Smith   Not Collective
1523c0ce001eSMatthew G. Knepley 
1524c0ce001eSMatthew G. Knepley   Input Parameter:
1525dce8aebaSBarry Smith . fvm - The `PetscFV` object
1526c0ce001eSMatthew G. Knepley 
1527c0ce001eSMatthew G. Knepley   Output Parameter:
152820f4b53cSBarry Smith . sp - The `PetscDualSpace` object
1529c0ce001eSMatthew G. Knepley 
153088f5f89eSMatthew G. Knepley   Level: intermediate
1531c0ce001eSMatthew G. Knepley 
153260225df5SJacob Faibussowitsch   Developer Notes:
1533dce8aebaSBarry Smith   There is overlap between the methods of `PetscFE` and `PetscFV`, they should probably share a common parent class
1534dce8aebaSBarry Smith 
15352f86f8c5SMatthew G. Knepley .seealso: `PetscFVSetDualSpace()`, `PetscFVCreateDualSpace()`, `PetscDualSpace`, `PetscFV`, `PetscFVCreate()`
1536c0ce001eSMatthew G. Knepley @*/
1537d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetDualSpace(PetscFV fvm, PetscDualSpace *sp)
1538d71ae5a4SJacob Faibussowitsch {
1539c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1540c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
15414f572ea9SToby Isaac   PetscAssertPointer(sp, 2);
1542c0ce001eSMatthew G. Knepley   if (!fvm->dualSpace) {
15432f86f8c5SMatthew G. Knepley     PetscInt dim;
1544c0ce001eSMatthew G. Knepley 
15459566063dSJacob Faibussowitsch     PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
15462f86f8c5SMatthew G. Knepley     PetscCall(PetscFVCreateDualSpace(fvm, DMPolytopeTypeSimpleShape(dim, PETSC_FALSE)));
1547c0ce001eSMatthew G. Knepley   }
1548c0ce001eSMatthew G. Knepley   *sp = fvm->dualSpace;
15493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1550c0ce001eSMatthew G. Knepley }
1551c0ce001eSMatthew G. Knepley 
1552c0ce001eSMatthew G. Knepley /*@
1553dce8aebaSBarry Smith   PetscFVSetDualSpace - Sets the `PetscDualSpace` used to define the inner product
1554c0ce001eSMatthew G. Knepley 
155520f4b53cSBarry Smith   Not Collective
1556c0ce001eSMatthew G. Knepley 
1557c0ce001eSMatthew G. Knepley   Input Parameters:
1558dce8aebaSBarry Smith + fvm - The `PetscFV` object
1559dce8aebaSBarry Smith - sp  - The `PetscDualSpace` object
1560c0ce001eSMatthew G. Knepley 
1561c0ce001eSMatthew G. Knepley   Level: intermediate
1562c0ce001eSMatthew G. Knepley 
1563dce8aebaSBarry Smith   Note:
1564dce8aebaSBarry Smith   A simple dual space is provided automatically, and the user typically will not need to override it.
1565c0ce001eSMatthew G. Knepley 
15662f86f8c5SMatthew G. Knepley .seealso: `PetscFVGetDualSpace()`, `PetscFVCreateDualSpace()`, `PetscDualSpace`, `PetscFV`, `PetscFVCreate()`
1567c0ce001eSMatthew G. Knepley @*/
1568d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetDualSpace(PetscFV fvm, PetscDualSpace sp)
1569d71ae5a4SJacob Faibussowitsch {
1570c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1571c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1572c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 2);
15739566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDestroy(&fvm->dualSpace));
1574c0ce001eSMatthew G. Knepley   fvm->dualSpace = sp;
15759566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fvm->dualSpace));
15763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1577c0ce001eSMatthew G. Knepley }
1578c0ce001eSMatthew G. Knepley 
157988f5f89eSMatthew G. Knepley /*@C
1580ef0bb6c7SMatthew G. Knepley   PetscFVGetCellTabulation - Returns the tabulation of the basis functions at the quadrature points
158188f5f89eSMatthew G. Knepley 
158220f4b53cSBarry Smith   Not Collective
158388f5f89eSMatthew G. Knepley 
158488f5f89eSMatthew G. Knepley   Input Parameter:
1585dce8aebaSBarry Smith . fvm - The `PetscFV` object
158688f5f89eSMatthew G. Knepley 
1587ef0bb6c7SMatthew G. Knepley   Output Parameter:
1588a5b23f4aSJose E. Roman . T - The basis function values and derivatives at quadrature points
158988f5f89eSMatthew G. Knepley 
159088f5f89eSMatthew G. Knepley   Level: intermediate
159188f5f89eSMatthew G. Knepley 
1592dce8aebaSBarry Smith   Note:
1593dce8aebaSBarry Smith .vb
1594dce8aebaSBarry Smith   T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
1595dce8aebaSBarry Smith   T->T[1] = D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d
1596dce8aebaSBarry Smith   T->T[2] = H[(((p*pdim + i)*Nc + c)*dim + d)*dim + e] is the value at point p for basis function i, component c, in directions d and e
1597dce8aebaSBarry Smith .ve
1598dce8aebaSBarry Smith 
1599dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscTabulation`, `PetscFEGetCellTabulation()`, `PetscFVCreateTabulation()`, `PetscFVGetQuadrature()`, `PetscQuadratureGetData()`
160088f5f89eSMatthew G. Knepley @*/
1601d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetCellTabulation(PetscFV fvm, PetscTabulation *T)
1602d71ae5a4SJacob Faibussowitsch {
1603c0ce001eSMatthew G. Knepley   PetscInt         npoints;
1604c0ce001eSMatthew G. Knepley   const PetscReal *points;
1605c0ce001eSMatthew G. Knepley 
1606c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1607c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
16084f572ea9SToby Isaac   PetscAssertPointer(T, 2);
16099566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureGetData(fvm->quadrature, NULL, NULL, &npoints, &points, NULL));
16109566063dSJacob Faibussowitsch   if (!fvm->T) PetscCall(PetscFVCreateTabulation(fvm, 1, npoints, points, 1, &fvm->T));
1611ef0bb6c7SMatthew G. Knepley   *T = fvm->T;
16123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1613c0ce001eSMatthew G. Knepley }
1614c0ce001eSMatthew G. Knepley 
161588f5f89eSMatthew G. Knepley /*@C
1616ef0bb6c7SMatthew G. Knepley   PetscFVCreateTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided.
161788f5f89eSMatthew G. Knepley 
161820f4b53cSBarry Smith   Not Collective
161988f5f89eSMatthew G. Knepley 
162088f5f89eSMatthew G. Knepley   Input Parameters:
1621dce8aebaSBarry Smith + fvm     - The `PetscFV` object
1622ef0bb6c7SMatthew G. Knepley . nrepl   - The number of replicas
1623ef0bb6c7SMatthew G. Knepley . npoints - The number of tabulation points in a replica
1624ef0bb6c7SMatthew G. Knepley . points  - The tabulation point coordinates
1625ef0bb6c7SMatthew G. Knepley - K       - The order of derivative to tabulate
162688f5f89eSMatthew G. Knepley 
1627ef0bb6c7SMatthew G. Knepley   Output Parameter:
1628a5b23f4aSJose E. Roman . T - The basis function values and derivative at tabulation points
162988f5f89eSMatthew G. Knepley 
163088f5f89eSMatthew G. Knepley   Level: intermediate
163188f5f89eSMatthew G. Knepley 
1632dce8aebaSBarry Smith   Note:
1633dce8aebaSBarry Smith .vb
1634dce8aebaSBarry Smith   T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
1635dce8aebaSBarry Smith   T->T[1] = D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d
1636dce8aebaSBarry Smith   T->T[2] = H[(((p*pdim + i)*Nc + c)*dim + d)*dim + e] is the value at point p for basis function i, component c, in directions d and e
1637dce8aebaSBarry Smith .ve
1638dce8aebaSBarry Smith 
1639dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscTabulation`, `PetscFECreateTabulation()`, `PetscTabulationDestroy()`, `PetscFEGetCellTabulation()`
164088f5f89eSMatthew G. Knepley @*/
1641d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVCreateTabulation(PetscFV fvm, PetscInt nrepl, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation *T)
1642d71ae5a4SJacob Faibussowitsch {
16432f86f8c5SMatthew G. Knepley   PetscInt pdim; // Dimension of approximation space P
16442f86f8c5SMatthew G. Knepley   PetscInt cdim; // Spatial dimension
16452f86f8c5SMatthew G. Knepley   PetscInt Nc;   // Field components
1646ef0bb6c7SMatthew G. Knepley   PetscInt k, p, d, c, e;
1647c0ce001eSMatthew G. Knepley 
1648c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1649ef0bb6c7SMatthew G. Knepley   if (!npoints || K < 0) {
1650ef0bb6c7SMatthew G. Knepley     *T = NULL;
16513ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1652c0ce001eSMatthew G. Knepley   }
1653c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
16544f572ea9SToby Isaac   PetscAssertPointer(points, 4);
16554f572ea9SToby Isaac   PetscAssertPointer(T, 6);
16569566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &cdim));
16579566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fvm, &Nc));
16582f86f8c5SMatthew G. Knepley   pdim = Nc;
16599566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1, T));
1660ef0bb6c7SMatthew G. Knepley   (*T)->K    = !cdim ? 0 : K;
1661ef0bb6c7SMatthew G. Knepley   (*T)->Nr   = nrepl;
1662ef0bb6c7SMatthew G. Knepley   (*T)->Np   = npoints;
1663ef0bb6c7SMatthew G. Knepley   (*T)->Nb   = pdim;
1664ef0bb6c7SMatthew G. Knepley   (*T)->Nc   = Nc;
1665ef0bb6c7SMatthew G. Knepley   (*T)->cdim = cdim;
16669566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*T)->K + 1, &(*T)->T));
166748a46eb9SPierre Jolivet   for (k = 0; k <= (*T)->K; ++k) PetscCall(PetscMalloc1(nrepl * npoints * pdim * Nc * PetscPowInt(cdim, k), &(*T)->T[k]));
16689371c9d4SSatish Balay   if (K >= 0) {
16699371c9d4SSatish Balay     for (p = 0; p < nrepl * npoints; ++p)
16709371c9d4SSatish Balay       for (d = 0; d < pdim; ++d)
16712f86f8c5SMatthew G. Knepley         for (c = 0; c < Nc; ++c) (*T)->T[0][(p * pdim + d) * Nc + c] = 1.;
1672ef0bb6c7SMatthew G. Knepley   }
16739371c9d4SSatish Balay   if (K >= 1) {
16749371c9d4SSatish Balay     for (p = 0; p < nrepl * npoints; ++p)
16759371c9d4SSatish Balay       for (d = 0; d < pdim; ++d)
16769371c9d4SSatish Balay         for (c = 0; c < Nc; ++c)
16779371c9d4SSatish Balay           for (e = 0; e < cdim; ++e) (*T)->T[1][((p * pdim + d) * Nc + c) * cdim + e] = 0.0;
16789371c9d4SSatish Balay   }
16799371c9d4SSatish Balay   if (K >= 2) {
16809371c9d4SSatish Balay     for (p = 0; p < nrepl * npoints; ++p)
16819371c9d4SSatish Balay       for (d = 0; d < pdim; ++d)
16829371c9d4SSatish Balay         for (c = 0; c < Nc; ++c)
16839371c9d4SSatish Balay           for (e = 0; e < cdim * cdim; ++e) (*T)->T[2][((p * pdim + d) * Nc + c) * cdim * cdim + e] = 0.0;
16849371c9d4SSatish Balay   }
16853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1686c0ce001eSMatthew G. Knepley }
1687c0ce001eSMatthew G. Knepley 
1688cc4c1da9SBarry Smith /*@
1689c0ce001eSMatthew G. Knepley   PetscFVComputeGradient - Compute the gradient reconstruction matrix for a given cell
1690c0ce001eSMatthew G. Knepley 
1691c0ce001eSMatthew G. Knepley   Input Parameters:
1692dce8aebaSBarry Smith + fvm      - The `PetscFV` object
1693c0ce001eSMatthew G. Knepley . numFaces - The number of cell faces which are not constrained
1694c0ce001eSMatthew G. Knepley - dx       - The vector from the cell centroid to the neighboring cell centroid for each face
1695c0ce001eSMatthew G. Knepley 
1696a4e35b19SJacob Faibussowitsch   Output Parameter:
1697a4e35b19SJacob Faibussowitsch . grad - the gradient
1698a4e35b19SJacob Faibussowitsch 
169988f5f89eSMatthew G. Knepley   Level: advanced
1700c0ce001eSMatthew G. Knepley 
1701dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVCreate()`
1702c0ce001eSMatthew G. Knepley @*/
1703d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVComputeGradient(PetscFV fvm, PetscInt numFaces, PetscScalar dx[], PetscScalar grad[])
1704d71ae5a4SJacob Faibussowitsch {
1705c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1706c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1707dbbe0bcdSBarry Smith   PetscTryTypeMethod(fvm, computegradient, numFaces, dx, grad);
17083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1709c0ce001eSMatthew G. Knepley }
1710c0ce001eSMatthew G. Knepley 
171188f5f89eSMatthew G. Knepley /*@C
1712c0ce001eSMatthew G. Knepley   PetscFVIntegrateRHSFunction - Produce the cell residual vector for a chunk of elements by quadrature integration
1713c0ce001eSMatthew G. Knepley 
171420f4b53cSBarry Smith   Not Collective
1715c0ce001eSMatthew G. Knepley 
1716c0ce001eSMatthew G. Knepley   Input Parameters:
1717dce8aebaSBarry Smith + fvm         - The `PetscFV` object for the field being integrated
1718da81f932SPierre Jolivet . prob        - The `PetscDS` specifying the discretizations and continuum functions
1719c0ce001eSMatthew G. Knepley . field       - The field being integrated
1720c0ce001eSMatthew G. Knepley . Nf          - The number of faces in the chunk
1721c0ce001eSMatthew G. Knepley . fgeom       - The face geometry for each face in the chunk
1722c0ce001eSMatthew G. Knepley . neighborVol - The volume for each pair of cells in the chunk
1723c0ce001eSMatthew G. Knepley . uL          - The state from the cell on the left
1724c0ce001eSMatthew G. Knepley - uR          - The state from the cell on the right
1725c0ce001eSMatthew G. Knepley 
1726d8d19677SJose E. Roman   Output Parameters:
1727c0ce001eSMatthew G. Knepley + fluxL - the left fluxes for each face
1728c0ce001eSMatthew G. Knepley - fluxR - the right fluxes for each face
172988f5f89eSMatthew G. Knepley 
173088f5f89eSMatthew G. Knepley   Level: developer
173188f5f89eSMatthew G. Knepley 
1732dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscDS`, `PetscFVFaceGeom`, `PetscFVCreate()`
173388f5f89eSMatthew G. Knepley @*/
1734d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVIntegrateRHSFunction(PetscFV fvm, PetscDS prob, PetscInt field, PetscInt Nf, PetscFVFaceGeom *fgeom, PetscReal *neighborVol, PetscScalar uL[], PetscScalar uR[], PetscScalar fluxL[], PetscScalar fluxR[])
1735d71ae5a4SJacob Faibussowitsch {
1736c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1737c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1738dbbe0bcdSBarry Smith   PetscTryTypeMethod(fvm, integraterhsfunction, prob, field, Nf, fgeom, neighborVol, uL, uR, fluxL, fluxR);
17393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1740c0ce001eSMatthew G. Knepley }
1741c0ce001eSMatthew G. Knepley 
1742c0ce001eSMatthew G. Knepley /*@
1743d8b4a066SPierre Jolivet   PetscFVClone - Create a shallow copy of a `PetscFV` object that just references the internal objects.
1744f6feae9bSMatthew G. Knepley 
1745f6feae9bSMatthew G. Knepley   Input Parameter:
1746f6feae9bSMatthew G. Knepley . fv - The initial `PetscFV`
1747f6feae9bSMatthew G. Knepley 
1748f6feae9bSMatthew G. Knepley   Output Parameter:
1749f6feae9bSMatthew G. Knepley . fvNew - A clone of the `PetscFV`
1750f6feae9bSMatthew G. Knepley 
1751f6feae9bSMatthew G. Knepley   Level: advanced
1752f6feae9bSMatthew G. Knepley 
1753f6feae9bSMatthew G. Knepley   Notes:
1754f6feae9bSMatthew G. Knepley   This is typically used to change the number of components.
1755f6feae9bSMatthew G. Knepley 
1756f6feae9bSMatthew G. Knepley .seealso: `PetscFV`, `PetscFVType`, `PetscFVCreate()`, `PetscFVSetType()`
1757f6feae9bSMatthew G. Knepley @*/
1758f6feae9bSMatthew G. Knepley PetscErrorCode PetscFVClone(PetscFV fv, PetscFV *fvNew)
1759f6feae9bSMatthew G. Knepley {
1760f6feae9bSMatthew G. Knepley   PetscDualSpace  Q;
1761f6feae9bSMatthew G. Knepley   DM              K;
1762f6feae9bSMatthew G. Knepley   PetscQuadrature q;
1763f6feae9bSMatthew G. Knepley   PetscInt        Nc, cdim;
1764f6feae9bSMatthew G. Knepley 
1765f6feae9bSMatthew G. Knepley   PetscFunctionBegin;
1766f6feae9bSMatthew G. Knepley   PetscCall(PetscFVGetDualSpace(fv, &Q));
1767f6feae9bSMatthew G. Knepley   PetscCall(PetscFVGetQuadrature(fv, &q));
1768f6feae9bSMatthew G. Knepley   PetscCall(PetscDualSpaceGetDM(Q, &K));
1769f6feae9bSMatthew G. Knepley 
1770f6feae9bSMatthew G. Knepley   PetscCall(PetscFVCreate(PetscObjectComm((PetscObject)fv), fvNew));
1771f6feae9bSMatthew G. Knepley   PetscCall(PetscFVSetDualSpace(*fvNew, Q));
1772f6feae9bSMatthew G. Knepley   PetscCall(PetscFVGetNumComponents(fv, &Nc));
1773f6feae9bSMatthew G. Knepley   PetscCall(PetscFVSetNumComponents(*fvNew, Nc));
1774f6feae9bSMatthew G. Knepley   PetscCall(PetscFVGetSpatialDimension(fv, &cdim));
1775f6feae9bSMatthew G. Knepley   PetscCall(PetscFVSetSpatialDimension(*fvNew, cdim));
1776f6feae9bSMatthew G. Knepley   PetscCall(PetscFVSetQuadrature(*fvNew, q));
1777f6feae9bSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1778f6feae9bSMatthew G. Knepley }
1779f6feae9bSMatthew G. Knepley 
1780f6feae9bSMatthew G. Knepley /*@
1781a4e35b19SJacob Faibussowitsch   PetscFVRefine - Create a "refined" `PetscFV` object that refines the reference cell into
1782a4e35b19SJacob Faibussowitsch   smaller copies.
1783c0ce001eSMatthew G. Knepley 
1784c0ce001eSMatthew G. Knepley   Input Parameter:
1785dce8aebaSBarry Smith . fv - The initial `PetscFV`
1786c0ce001eSMatthew G. Knepley 
1787c0ce001eSMatthew G. Knepley   Output Parameter:
1788dce8aebaSBarry Smith . fvRef - The refined `PetscFV`
1789c0ce001eSMatthew G. Knepley 
179088f5f89eSMatthew G. Knepley   Level: advanced
1791c0ce001eSMatthew G. Knepley 
1792a4e35b19SJacob Faibussowitsch   Notes:
1793a4e35b19SJacob Faibussowitsch   This is typically used to generate a preconditioner for a high order method from a lower order method on a
1794a4e35b19SJacob Faibussowitsch   refined mesh having the same number of dofs (but more sparsity). It is also used to create an
1795a4e35b19SJacob Faibussowitsch   interpolation between regularly refined meshes.
1796a4e35b19SJacob Faibussowitsch 
1797dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVCreate()`, `PetscFVSetType()`
1798c0ce001eSMatthew G. Knepley @*/
1799d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVRefine(PetscFV fv, PetscFV *fvRef)
1800d71ae5a4SJacob Faibussowitsch {
1801c0ce001eSMatthew G. Knepley   PetscDualSpace  Q, Qref;
1802c0ce001eSMatthew G. Knepley   DM              K, Kref;
1803c0ce001eSMatthew G. Knepley   PetscQuadrature q, qref;
1804412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
1805012bc364SMatthew G. Knepley   DMPlexTransform tr;
1806c0ce001eSMatthew G. Knepley   PetscReal      *v0;
1807c0ce001eSMatthew G. Knepley   PetscReal      *jac, *invjac;
1808c0ce001eSMatthew G. Knepley   PetscInt        numComp, numSubelements, s;
1809c0ce001eSMatthew G. Knepley 
1810c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
18119566063dSJacob Faibussowitsch   PetscCall(PetscFVGetDualSpace(fv, &Q));
18129566063dSJacob Faibussowitsch   PetscCall(PetscFVGetQuadrature(fv, &q));
18139566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceGetDM(Q, &K));
1814c0ce001eSMatthew G. Knepley   /* Create dual space */
18159566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDuplicate(Q, &Qref));
18169566063dSJacob Faibussowitsch   PetscCall(DMRefine(K, PetscObjectComm((PetscObject)fv), &Kref));
18179566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetDM(Qref, Kref));
18189566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&Kref));
18199566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetUp(Qref));
1820c0ce001eSMatthew G. Knepley   /* Create volume */
18219566063dSJacob Faibussowitsch   PetscCall(PetscFVCreate(PetscObjectComm((PetscObject)fv), fvRef));
18229566063dSJacob Faibussowitsch   PetscCall(PetscFVSetDualSpace(*fvRef, Qref));
18239566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fv, &numComp));
18249566063dSJacob Faibussowitsch   PetscCall(PetscFVSetNumComponents(*fvRef, numComp));
18259566063dSJacob Faibussowitsch   PetscCall(PetscFVSetUp(*fvRef));
1826c0ce001eSMatthew G. Knepley   /* Create quadrature */
18279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(K, 0, &ct));
18289566063dSJacob Faibussowitsch   PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
18299566063dSJacob Faibussowitsch   PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
18309566063dSJacob Faibussowitsch   PetscCall(DMPlexRefineRegularGetAffineTransforms(tr, ct, &numSubelements, &v0, &jac, &invjac));
18319566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureExpandComposite(q, numSubelements, v0, jac, &qref));
18329566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSimpleSetDimension(Qref, numSubelements));
1833c0ce001eSMatthew G. Knepley   for (s = 0; s < numSubelements; ++s) {
1834c0ce001eSMatthew G. Knepley     PetscQuadrature  qs;
1835c0ce001eSMatthew G. Knepley     const PetscReal *points, *weights;
1836c0ce001eSMatthew G. Knepley     PetscReal       *p, *w;
1837c0ce001eSMatthew G. Knepley     PetscInt         dim, Nc, npoints, np;
1838c0ce001eSMatthew G. Knepley 
18399566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, &qs));
18409566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureGetData(q, &dim, &Nc, &npoints, &points, &weights));
1841c0ce001eSMatthew G. Knepley     np = npoints / numSubelements;
18429566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(np * dim, &p));
18439566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(np * Nc, &w));
18449566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(p, &points[s * np * dim], np * dim));
18459566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(w, &weights[s * np * Nc], np * Nc));
18469566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureSetData(qs, dim, Nc, np, p, w));
18479566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSimpleSetFunctional(Qref, s, qs));
18489566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureDestroy(&qs));
1849c0ce001eSMatthew G. Knepley   }
18509566063dSJacob Faibussowitsch   PetscCall(PetscFVSetQuadrature(*fvRef, qref));
18519566063dSJacob Faibussowitsch   PetscCall(DMPlexTransformDestroy(&tr));
18529566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&qref));
18539566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDestroy(&Qref));
18543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1855c0ce001eSMatthew G. Knepley }
1856c0ce001eSMatthew G. Knepley 
1857d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVDestroy_Upwind(PetscFV fvm)
1858d71ae5a4SJacob Faibussowitsch {
1859c0ce001eSMatthew G. Knepley   PetscFV_Upwind *b = (PetscFV_Upwind *)fvm->data;
1860c0ce001eSMatthew G. Knepley 
1861c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
18629566063dSJacob Faibussowitsch   PetscCall(PetscFree(b));
18633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1864c0ce001eSMatthew G. Knepley }
1865c0ce001eSMatthew G. Knepley 
1866d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVView_Upwind_Ascii(PetscFV fv, PetscViewer viewer)
1867d71ae5a4SJacob Faibussowitsch {
1868c0ce001eSMatthew G. Knepley   PetscInt          Nc, c;
1869c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
1870c0ce001eSMatthew G. Knepley 
1871c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
18729566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fv, &Nc));
18739566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
18749566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Upwind Finite Volume:\n"));
187563a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  num components: %" PetscInt_FMT "\n", Nc));
1876c0ce001eSMatthew G. Knepley   for (c = 0; c < Nc; c++) {
187748a46eb9SPierre Jolivet     if (fv->componentNames[c]) PetscCall(PetscViewerASCIIPrintf(viewer, "    component %" PetscInt_FMT ": %s\n", c, fv->componentNames[c]));
1878c0ce001eSMatthew G. Knepley   }
18793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1880c0ce001eSMatthew G. Knepley }
1881c0ce001eSMatthew G. Knepley 
1882d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVView_Upwind(PetscFV fv, PetscViewer viewer)
1883d71ae5a4SJacob Faibussowitsch {
1884c0ce001eSMatthew G. Knepley   PetscBool iascii;
1885c0ce001eSMatthew G. Knepley 
1886c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1887c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 1);
1888c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18899566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
18909566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscFVView_Upwind_Ascii(fv, viewer));
18913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1892c0ce001eSMatthew G. Knepley }
1893c0ce001eSMatthew G. Knepley 
1894d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVSetUp_Upwind(PetscFV fvm)
1895d71ae5a4SJacob Faibussowitsch {
1896c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
18973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1898c0ce001eSMatthew G. Knepley }
1899c0ce001eSMatthew G. Knepley 
19006f6f020cSMatthew G. Knepley static PetscErrorCode PetscFVComputeGradient_Upwind(PetscFV fv, PetscInt numFaces, const PetscScalar dx[], PetscScalar grad[])
19016f6f020cSMatthew G. Knepley {
19026f6f020cSMatthew G. Knepley   PetscInt dim;
19036f6f020cSMatthew G. Knepley 
19046f6f020cSMatthew G. Knepley   PetscFunctionBegin;
19056f6f020cSMatthew G. Knepley   PetscCall(PetscFVGetSpatialDimension(fv, &dim));
19066f6f020cSMatthew G. Knepley   for (PetscInt f = 0; f < numFaces; ++f) {
19076f6f020cSMatthew G. Knepley     for (PetscInt d = 0; d < dim; ++d) grad[f * dim + d] = 0.;
19086f6f020cSMatthew G. Knepley   }
19096f6f020cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
19106f6f020cSMatthew G. Knepley }
19116f6f020cSMatthew G. Knepley 
1912c0ce001eSMatthew G. Knepley /*
1913c0ce001eSMatthew G. Knepley   neighborVol[f*2+0] contains the left  geom
1914c0ce001eSMatthew G. Knepley   neighborVol[f*2+1] contains the right geom
1915c0ce001eSMatthew G. Knepley */
1916d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVIntegrateRHSFunction_Upwind(PetscFV fvm, PetscDS prob, PetscInt field, PetscInt Nf, PetscFVFaceGeom *fgeom, PetscReal *neighborVol, PetscScalar uL[], PetscScalar uR[], PetscScalar fluxL[], PetscScalar fluxR[])
1917d71ae5a4SJacob Faibussowitsch {
1918c0ce001eSMatthew G. Knepley   void (*riemann)(PetscInt, PetscInt, const PetscReal[], const PetscReal[], const PetscScalar[], const PetscScalar[], PetscInt, const PetscScalar[], PetscScalar[], void *);
1919c0ce001eSMatthew G. Knepley   void              *rctx;
1920c0ce001eSMatthew G. Knepley   PetscScalar       *flux = fvm->fluxWork;
1921c0ce001eSMatthew G. Knepley   const PetscScalar *constants;
1922c0ce001eSMatthew G. Knepley   PetscInt           dim, numConstants, pdim, totDim, Nc, off, f, d;
1923c0ce001eSMatthew G. Knepley 
1924c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
19259566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(prob, &Nc));
19269566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
19279566063dSJacob Faibussowitsch   PetscCall(PetscDSGetFieldOffset(prob, field, &off));
19289566063dSJacob Faibussowitsch   PetscCall(PetscDSGetRiemannSolver(prob, field, &riemann));
19299566063dSJacob Faibussowitsch   PetscCall(PetscDSGetContext(prob, field, &rctx));
19309566063dSJacob Faibussowitsch   PetscCall(PetscDSGetConstants(prob, &numConstants, &constants));
19319566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
19329566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fvm, &pdim));
1933c0ce001eSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
1934c0ce001eSMatthew G. Knepley     (*riemann)(dim, pdim, fgeom[f].centroid, fgeom[f].normal, &uL[f * Nc], &uR[f * Nc], numConstants, constants, flux, rctx);
1935c0ce001eSMatthew G. Knepley     for (d = 0; d < pdim; ++d) {
1936c0ce001eSMatthew G. Knepley       fluxL[f * totDim + off + d] = flux[d] / neighborVol[f * 2 + 0];
1937c0ce001eSMatthew G. Knepley       fluxR[f * totDim + off + d] = flux[d] / neighborVol[f * 2 + 1];
1938c0ce001eSMatthew G. Knepley     }
1939c0ce001eSMatthew G. Knepley   }
19403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1941c0ce001eSMatthew G. Knepley }
1942c0ce001eSMatthew G. Knepley 
1943d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVInitialize_Upwind(PetscFV fvm)
1944d71ae5a4SJacob Faibussowitsch {
1945c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1946c0ce001eSMatthew G. Knepley   fvm->ops->setfromoptions       = NULL;
1947c0ce001eSMatthew G. Knepley   fvm->ops->setup                = PetscFVSetUp_Upwind;
1948c0ce001eSMatthew G. Knepley   fvm->ops->view                 = PetscFVView_Upwind;
1949c0ce001eSMatthew G. Knepley   fvm->ops->destroy              = PetscFVDestroy_Upwind;
19506f6f020cSMatthew G. Knepley   fvm->ops->computegradient      = PetscFVComputeGradient_Upwind;
1951c0ce001eSMatthew G. Knepley   fvm->ops->integraterhsfunction = PetscFVIntegrateRHSFunction_Upwind;
19523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1953c0ce001eSMatthew G. Knepley }
1954c0ce001eSMatthew G. Knepley 
1955c0ce001eSMatthew G. Knepley /*MC
1956dce8aebaSBarry Smith   PETSCFVUPWIND = "upwind" - A `PetscFV` implementation
1957c0ce001eSMatthew G. Knepley 
1958c0ce001eSMatthew G. Knepley   Level: intermediate
1959c0ce001eSMatthew G. Knepley 
1960dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVCreate()`, `PetscFVSetType()`
1961c0ce001eSMatthew G. Knepley M*/
1962c0ce001eSMatthew G. Knepley 
1963d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscFVCreate_Upwind(PetscFV fvm)
1964d71ae5a4SJacob Faibussowitsch {
1965c0ce001eSMatthew G. Knepley   PetscFV_Upwind *b;
1966c0ce001eSMatthew G. Knepley 
1967c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1968c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
19694dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
1970c0ce001eSMatthew G. Knepley   fvm->data = b;
1971c0ce001eSMatthew G. Knepley 
19729566063dSJacob Faibussowitsch   PetscCall(PetscFVInitialize_Upwind(fvm));
19733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1974c0ce001eSMatthew G. Knepley }
1975c0ce001eSMatthew G. Knepley 
1976c0ce001eSMatthew G. Knepley #include <petscblaslapack.h>
1977c0ce001eSMatthew G. Knepley 
1978d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVDestroy_LeastSquares(PetscFV fvm)
1979d71ae5a4SJacob Faibussowitsch {
1980c0ce001eSMatthew G. Knepley   PetscFV_LeastSquares *ls = (PetscFV_LeastSquares *)fvm->data;
1981c0ce001eSMatthew G. Knepley 
1982c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
19839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fvm, "PetscFVLeastSquaresSetMaxFaces_C", NULL));
19849566063dSJacob Faibussowitsch   PetscCall(PetscFree4(ls->B, ls->Binv, ls->tau, ls->work));
19859566063dSJacob Faibussowitsch   PetscCall(PetscFree(ls));
19863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1987c0ce001eSMatthew G. Knepley }
1988c0ce001eSMatthew G. Knepley 
1989d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVView_LeastSquares_Ascii(PetscFV fv, PetscViewer viewer)
1990d71ae5a4SJacob Faibussowitsch {
1991c0ce001eSMatthew G. Knepley   PetscInt          Nc, c;
1992c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
1993c0ce001eSMatthew G. Knepley 
1994c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
19959566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fv, &Nc));
19969566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
19979566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Finite Volume with Least Squares Reconstruction:\n"));
199863a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  num components: %" PetscInt_FMT "\n", Nc));
1999c0ce001eSMatthew G. Knepley   for (c = 0; c < Nc; c++) {
200048a46eb9SPierre Jolivet     if (fv->componentNames[c]) PetscCall(PetscViewerASCIIPrintf(viewer, "    component %" PetscInt_FMT ": %s\n", c, fv->componentNames[c]));
2001c0ce001eSMatthew G. Knepley   }
20023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2003c0ce001eSMatthew G. Knepley }
2004c0ce001eSMatthew G. Knepley 
2005d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVView_LeastSquares(PetscFV fv, PetscViewer viewer)
2006d71ae5a4SJacob Faibussowitsch {
2007c0ce001eSMatthew G. Knepley   PetscBool iascii;
2008c0ce001eSMatthew G. Knepley 
2009c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2010c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 1);
2011c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20129566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
20139566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscFVView_LeastSquares_Ascii(fv, viewer));
20143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2015c0ce001eSMatthew G. Knepley }
2016c0ce001eSMatthew G. Knepley 
2017d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVSetUp_LeastSquares(PetscFV fvm)
2018d71ae5a4SJacob Faibussowitsch {
2019c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
20203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2021c0ce001eSMatthew G. Knepley }
2022c0ce001eSMatthew G. Knepley 
2023c0ce001eSMatthew G. Knepley /* Overwrites A. Can only handle full-rank problems with m>=n */
2024d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVLeastSquaresPseudoInverse_Static(PetscInt m, PetscInt mstride, PetscInt n, PetscScalar *A, PetscScalar *Ainv, PetscScalar *tau, PetscInt worksize, PetscScalar *work)
2025d71ae5a4SJacob Faibussowitsch {
2026c0ce001eSMatthew G. Knepley   PetscBool    debug = PETSC_FALSE;
2027c0ce001eSMatthew G. Knepley   PetscBLASInt M, N, K, lda, ldb, ldwork, info;
2028c0ce001eSMatthew G. Knepley   PetscScalar *R, *Q, *Aback, Alpha;
2029c0ce001eSMatthew G. Knepley 
2030c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2031c0ce001eSMatthew G. Knepley   if (debug) {
20329566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m * n, &Aback));
20339566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(Aback, A, m * n));
2034c0ce001eSMatthew G. Knepley   }
2035c0ce001eSMatthew G. Knepley 
20369566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &M));
20379566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(n, &N));
20389566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(mstride, &lda));
20399566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(worksize, &ldwork));
20409566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
2041792fecdfSBarry Smith   PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&M, &N, A, &lda, tau, work, &ldwork, &info));
20429566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
204328b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "xGEQRF error");
2044c0ce001eSMatthew G. Knepley   R = A; /* Upper triangular part of A now contains R, the rest contains the elementary reflectors */
2045c0ce001eSMatthew G. Knepley 
2046c0ce001eSMatthew G. Knepley   /* Extract an explicit representation of Q */
2047c0ce001eSMatthew G. Knepley   Q = Ainv;
20489566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(Q, A, mstride * n));
2049c0ce001eSMatthew G. Knepley   K = N; /* full rank */
2050792fecdfSBarry Smith   PetscCallBLAS("LAPACKorgqr", LAPACKorgqr_(&M, &N, &K, Q, &lda, tau, work, &ldwork, &info));
205128b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "xORGQR/xUNGQR error");
2052c0ce001eSMatthew G. Knepley 
2053c0ce001eSMatthew G. Knepley   /* Compute A^{-T} = (R^{-1} Q^T)^T = Q R^{-T} */
2054c0ce001eSMatthew G. Knepley   Alpha = 1.0;
2055c0ce001eSMatthew G. Knepley   ldb   = lda;
2056c0ce001eSMatthew G. Knepley   BLAStrsm_("Right", "Upper", "ConjugateTranspose", "NotUnitTriangular", &M, &N, &Alpha, R, &lda, Q, &ldb);
2057c0ce001eSMatthew G. Knepley   /* Ainv is Q, overwritten with inverse */
2058c0ce001eSMatthew G. Knepley 
2059c0ce001eSMatthew G. Knepley   if (debug) { /* Check that pseudo-inverse worked */
2060c0ce001eSMatthew G. Knepley     PetscScalar  Beta = 0.0;
2061c0ce001eSMatthew G. Knepley     PetscBLASInt ldc;
2062c0ce001eSMatthew G. Knepley     K   = N;
2063c0ce001eSMatthew G. Knepley     ldc = N;
2064c0ce001eSMatthew G. Knepley     BLASgemm_("ConjugateTranspose", "Normal", &N, &K, &M, &Alpha, Ainv, &lda, Aback, &ldb, &Beta, work, &ldc);
20659566063dSJacob Faibussowitsch     PetscCall(PetscScalarView(n * n, work, PETSC_VIEWER_STDOUT_SELF));
20669566063dSJacob Faibussowitsch     PetscCall(PetscFree(Aback));
2067c0ce001eSMatthew G. Knepley   }
20683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2069c0ce001eSMatthew G. Knepley }
2070c0ce001eSMatthew G. Knepley 
2071c0ce001eSMatthew G. Knepley /* Overwrites A. Can handle degenerate problems and m<n. */
2072d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVLeastSquaresPseudoInverseSVD_Static(PetscInt m, PetscInt mstride, PetscInt n, PetscScalar *A, PetscScalar *Ainv, PetscScalar *tau, PetscInt worksize, PetscScalar *work)
2073d71ae5a4SJacob Faibussowitsch {
20746bb27163SBarry Smith   PetscScalar *Brhs;
2075c0ce001eSMatthew G. Knepley   PetscScalar *tmpwork;
2076c0ce001eSMatthew G. Knepley   PetscReal    rcond;
2077c0ce001eSMatthew G. Knepley #if defined(PETSC_USE_COMPLEX)
2078c0ce001eSMatthew G. Knepley   PetscInt   rworkSize;
2079c0ce001eSMatthew G. Knepley   PetscReal *rwork;
2080c0ce001eSMatthew G. Knepley #endif
2081c0ce001eSMatthew G. Knepley   PetscInt     i, j, maxmn;
2082c0ce001eSMatthew G. Knepley   PetscBLASInt M, N, lda, ldb, ldwork;
2083c0ce001eSMatthew G. Knepley   PetscBLASInt nrhs, irank, info;
2084c0ce001eSMatthew G. Knepley 
2085c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2086c0ce001eSMatthew G. Knepley   /* initialize to identity */
2087736d4f42SpierreXVI   tmpwork = work;
2088736d4f42SpierreXVI   Brhs    = Ainv;
2089c0ce001eSMatthew G. Knepley   maxmn   = PetscMax(m, n);
2090c0ce001eSMatthew G. Knepley   for (j = 0; j < maxmn; j++) {
2091c0ce001eSMatthew G. Knepley     for (i = 0; i < maxmn; i++) Brhs[i + j * maxmn] = 1.0 * (i == j);
2092c0ce001eSMatthew G. Knepley   }
2093c0ce001eSMatthew G. Knepley 
20949566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &M));
20959566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(n, &N));
20969566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(mstride, &lda));
20979566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(maxmn, &ldb));
20989566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(worksize, &ldwork));
2099c0ce001eSMatthew G. Knepley   rcond = -1;
2100c0ce001eSMatthew G. Knepley   nrhs  = M;
2101c0ce001eSMatthew G. Knepley #if defined(PETSC_USE_COMPLEX)
2102c0ce001eSMatthew G. Knepley   rworkSize = 5 * PetscMin(M, N);
21039566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(rworkSize, &rwork));
21046bb27163SBarry Smith   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
2105792fecdfSBarry Smith   PetscCallBLAS("LAPACKgelss", LAPACKgelss_(&M, &N, &nrhs, A, &lda, Brhs, &ldb, (PetscReal *)tau, &rcond, &irank, tmpwork, &ldwork, rwork, &info));
21069566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
21079566063dSJacob Faibussowitsch   PetscCall(PetscFree(rwork));
2108c0ce001eSMatthew G. Knepley #else
2109c0ce001eSMatthew G. Knepley   nrhs = M;
21106bb27163SBarry Smith   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
2111792fecdfSBarry Smith   PetscCallBLAS("LAPACKgelss", LAPACKgelss_(&M, &N, &nrhs, A, &lda, Brhs, &ldb, (PetscReal *)tau, &rcond, &irank, tmpwork, &ldwork, &info));
21129566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
2113c0ce001eSMatthew G. Knepley #endif
211428b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "xGELSS error");
2115c0ce001eSMatthew G. Knepley   /* The following check should be turned into a diagnostic as soon as someone wants to do this intentionally */
211608401ef6SPierre Jolivet   PetscCheck(irank >= PetscMin(M, N), PETSC_COMM_SELF, PETSC_ERR_USER, "Rank deficient least squares fit, indicates an isolated cell with two colinear points");
21173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2118c0ce001eSMatthew G. Knepley }
2119c0ce001eSMatthew G. Knepley 
2120c0ce001eSMatthew G. Knepley #if 0
2121c0ce001eSMatthew G. Knepley static PetscErrorCode PetscFVLeastSquaresDebugCell_Static(PetscFV fvm, PetscInt cell, DM dm, DM dmFace, PetscScalar *fgeom, DM dmCell, PetscScalar *cgeom)
2122c0ce001eSMatthew G. Knepley {
2123c0ce001eSMatthew G. Knepley   PetscReal       grad[2] = {0, 0};
2124c0ce001eSMatthew G. Knepley   const PetscInt *faces;
2125c0ce001eSMatthew G. Knepley   PetscInt        numFaces, f;
2126c0ce001eSMatthew G. Knepley 
2127c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
21289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, cell, &numFaces));
21299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, cell, &faces));
2130c0ce001eSMatthew G. Knepley   for (f = 0; f < numFaces; ++f) {
2131c0ce001eSMatthew G. Knepley     const PetscInt *fcells;
2132c0ce001eSMatthew G. Knepley     const CellGeom *cg1;
2133c0ce001eSMatthew G. Knepley     const FaceGeom *fg;
2134c0ce001eSMatthew G. Knepley 
21359566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, faces[f], &fcells));
21369566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmFace, faces[f], fgeom, &fg));
2137c0ce001eSMatthew G. Knepley     for (i = 0; i < 2; ++i) {
2138c0ce001eSMatthew G. Knepley       PetscScalar du;
2139c0ce001eSMatthew G. Knepley 
2140c0ce001eSMatthew G. Knepley       if (fcells[i] == c) continue;
21419566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, fcells[i], cgeom, &cg1));
2142c0ce001eSMatthew G. Knepley       du   = cg1->centroid[0] + 3*cg1->centroid[1] - (cg->centroid[0] + 3*cg->centroid[1]);
2143c0ce001eSMatthew G. Knepley       grad[0] += fg->grad[!i][0] * du;
2144c0ce001eSMatthew G. Knepley       grad[1] += fg->grad[!i][1] * du;
2145c0ce001eSMatthew G. Knepley     }
2146c0ce001eSMatthew G. Knepley   }
21479566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "cell[%d] grad (%g, %g)\n", cell, grad[0], grad[1]));
21483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2149c0ce001eSMatthew G. Knepley }
2150c0ce001eSMatthew G. Knepley #endif
2151c0ce001eSMatthew G. Knepley 
2152c0ce001eSMatthew G. Knepley /*
21536f6f020cSMatthew G. Knepley   PetscFVComputeGradient_LeastSquares - Compute the gradient reconstruction matrix for a given cell
2154c0ce001eSMatthew G. Knepley 
2155c0ce001eSMatthew G. Knepley   Input Parameters:
2156dce8aebaSBarry Smith + fvm      - The `PetscFV` object
2157c0ce001eSMatthew G. Knepley . numFaces - The number of cell faces which are not constrained
2158c0ce001eSMatthew G. Knepley . dx       - The vector from the cell centroid to the neighboring cell centroid for each face
2159c0ce001eSMatthew G. Knepley 
2160c0ce001eSMatthew G. Knepley   Level: developer
2161c0ce001eSMatthew G. Knepley 
2162dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVCreate()`
2163c0ce001eSMatthew G. Knepley */
2164d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVComputeGradient_LeastSquares(PetscFV fvm, PetscInt numFaces, const PetscScalar dx[], PetscScalar grad[])
2165d71ae5a4SJacob Faibussowitsch {
2166c0ce001eSMatthew G. Knepley   PetscFV_LeastSquares *ls       = (PetscFV_LeastSquares *)fvm->data;
2167c0ce001eSMatthew G. Knepley   const PetscBool       useSVD   = PETSC_TRUE;
2168c0ce001eSMatthew G. Knepley   const PetscInt        maxFaces = ls->maxFaces;
2169c0ce001eSMatthew G. Knepley   PetscInt              dim, f, d;
2170c0ce001eSMatthew G. Knepley 
2171c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2172c0ce001eSMatthew G. Knepley   if (numFaces > maxFaces) {
217308401ef6SPierre Jolivet     PetscCheck(maxFaces >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Reconstruction has not been initialized, call PetscFVLeastSquaresSetMaxFaces()");
217463a3b9bcSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input faces %" PetscInt_FMT " > %" PetscInt_FMT " maxfaces", numFaces, maxFaces);
2175c0ce001eSMatthew G. Knepley   }
21769566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
2177c0ce001eSMatthew G. Knepley   for (f = 0; f < numFaces; ++f) {
2178c0ce001eSMatthew G. Knepley     for (d = 0; d < dim; ++d) ls->B[d * maxFaces + f] = dx[f * dim + d];
2179c0ce001eSMatthew G. Knepley   }
2180c0ce001eSMatthew G. Knepley   /* Overwrites B with garbage, returns Binv in row-major format */
2181736d4f42SpierreXVI   if (useSVD) {
2182736d4f42SpierreXVI     PetscInt maxmn = PetscMax(numFaces, dim);
21839566063dSJacob Faibussowitsch     PetscCall(PetscFVLeastSquaresPseudoInverseSVD_Static(numFaces, maxFaces, dim, ls->B, ls->Binv, ls->tau, ls->workSize, ls->work));
2184736d4f42SpierreXVI     /* Binv shaped in column-major, coldim=maxmn.*/
2185736d4f42SpierreXVI     for (f = 0; f < numFaces; ++f) {
2186736d4f42SpierreXVI       for (d = 0; d < dim; ++d) grad[f * dim + d] = ls->Binv[d + maxmn * f];
2187736d4f42SpierreXVI     }
2188736d4f42SpierreXVI   } else {
21899566063dSJacob Faibussowitsch     PetscCall(PetscFVLeastSquaresPseudoInverse_Static(numFaces, maxFaces, dim, ls->B, ls->Binv, ls->tau, ls->workSize, ls->work));
2190736d4f42SpierreXVI     /* Binv shaped in row-major, rowdim=maxFaces.*/
2191c0ce001eSMatthew G. Knepley     for (f = 0; f < numFaces; ++f) {
2192c0ce001eSMatthew G. Knepley       for (d = 0; d < dim; ++d) grad[f * dim + d] = ls->Binv[d * maxFaces + f];
2193c0ce001eSMatthew G. Knepley     }
2194736d4f42SpierreXVI   }
21953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2196c0ce001eSMatthew G. Knepley }
2197c0ce001eSMatthew G. Knepley 
2198c0ce001eSMatthew G. Knepley /*
2199c0ce001eSMatthew G. Knepley   neighborVol[f*2+0] contains the left  geom
2200c0ce001eSMatthew G. Knepley   neighborVol[f*2+1] contains the right geom
2201c0ce001eSMatthew G. Knepley */
2202d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVIntegrateRHSFunction_LeastSquares(PetscFV fvm, PetscDS prob, PetscInt field, PetscInt Nf, PetscFVFaceGeom *fgeom, PetscReal *neighborVol, PetscScalar uL[], PetscScalar uR[], PetscScalar fluxL[], PetscScalar fluxR[])
2203d71ae5a4SJacob Faibussowitsch {
2204c0ce001eSMatthew G. Knepley   void (*riemann)(PetscInt, PetscInt, const PetscReal[], const PetscReal[], const PetscScalar[], const PetscScalar[], PetscInt, const PetscScalar[], PetscScalar[], void *);
2205c0ce001eSMatthew G. Knepley   void              *rctx;
2206c0ce001eSMatthew G. Knepley   PetscScalar       *flux = fvm->fluxWork;
2207c0ce001eSMatthew G. Knepley   const PetscScalar *constants;
2208c0ce001eSMatthew G. Knepley   PetscInt           dim, numConstants, pdim, Nc, totDim, off, f, d;
2209c0ce001eSMatthew G. Knepley 
2210c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
22119566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(prob, &Nc));
22129566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
22139566063dSJacob Faibussowitsch   PetscCall(PetscDSGetFieldOffset(prob, field, &off));
22149566063dSJacob Faibussowitsch   PetscCall(PetscDSGetRiemannSolver(prob, field, &riemann));
22159566063dSJacob Faibussowitsch   PetscCall(PetscDSGetContext(prob, field, &rctx));
22169566063dSJacob Faibussowitsch   PetscCall(PetscDSGetConstants(prob, &numConstants, &constants));
22179566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
22189566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fvm, &pdim));
2219c0ce001eSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
2220c0ce001eSMatthew G. Knepley     (*riemann)(dim, pdim, fgeom[f].centroid, fgeom[f].normal, &uL[f * Nc], &uR[f * Nc], numConstants, constants, flux, rctx);
2221c0ce001eSMatthew G. Knepley     for (d = 0; d < pdim; ++d) {
2222c0ce001eSMatthew G. Knepley       fluxL[f * totDim + off + d] = flux[d] / neighborVol[f * 2 + 0];
2223c0ce001eSMatthew G. Knepley       fluxR[f * totDim + off + d] = flux[d] / neighborVol[f * 2 + 1];
2224c0ce001eSMatthew G. Knepley     }
2225c0ce001eSMatthew G. Knepley   }
22263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2227c0ce001eSMatthew G. Knepley }
2228c0ce001eSMatthew G. Knepley 
2229d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVLeastSquaresSetMaxFaces_LS(PetscFV fvm, PetscInt maxFaces)
2230d71ae5a4SJacob Faibussowitsch {
2231c0ce001eSMatthew G. Knepley   PetscFV_LeastSquares *ls = (PetscFV_LeastSquares *)fvm->data;
2232736d4f42SpierreXVI   PetscInt              dim, m, n, nrhs, minmn, maxmn;
2233c0ce001eSMatthew G. Knepley 
2234c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2235c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
22369566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
22379566063dSJacob Faibussowitsch   PetscCall(PetscFree4(ls->B, ls->Binv, ls->tau, ls->work));
2238c0ce001eSMatthew G. Knepley   ls->maxFaces = maxFaces;
2239c0ce001eSMatthew G. Knepley   m            = ls->maxFaces;
2240c0ce001eSMatthew G. Knepley   n            = dim;
2241c0ce001eSMatthew G. Knepley   nrhs         = ls->maxFaces;
2242736d4f42SpierreXVI   minmn        = PetscMin(m, n);
2243736d4f42SpierreXVI   maxmn        = PetscMax(m, n);
2244736d4f42SpierreXVI   ls->workSize = 3 * minmn + PetscMax(2 * minmn, PetscMax(maxmn, nrhs)); /* required by LAPACK */
22459566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(m * n, &ls->B, maxmn * maxmn, &ls->Binv, minmn, &ls->tau, ls->workSize, &ls->work));
22463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2247c0ce001eSMatthew G. Knepley }
2248c0ce001eSMatthew G. Knepley 
224966976f2fSJacob Faibussowitsch static PetscErrorCode PetscFVInitialize_LeastSquares(PetscFV fvm)
2250d71ae5a4SJacob Faibussowitsch {
2251c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2252c0ce001eSMatthew G. Knepley   fvm->ops->setfromoptions       = NULL;
2253c0ce001eSMatthew G. Knepley   fvm->ops->setup                = PetscFVSetUp_LeastSquares;
2254c0ce001eSMatthew G. Knepley   fvm->ops->view                 = PetscFVView_LeastSquares;
2255c0ce001eSMatthew G. Knepley   fvm->ops->destroy              = PetscFVDestroy_LeastSquares;
2256c0ce001eSMatthew G. Knepley   fvm->ops->computegradient      = PetscFVComputeGradient_LeastSquares;
2257c0ce001eSMatthew G. Knepley   fvm->ops->integraterhsfunction = PetscFVIntegrateRHSFunction_LeastSquares;
22583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2259c0ce001eSMatthew G. Knepley }
2260c0ce001eSMatthew G. Knepley 
2261c0ce001eSMatthew G. Knepley /*MC
2262dce8aebaSBarry Smith   PETSCFVLEASTSQUARES = "leastsquares" - A `PetscFV` implementation
2263c0ce001eSMatthew G. Knepley 
2264c0ce001eSMatthew G. Knepley   Level: intermediate
2265c0ce001eSMatthew G. Knepley 
2266dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVCreate()`, `PetscFVSetType()`
2267c0ce001eSMatthew G. Knepley M*/
2268c0ce001eSMatthew G. Knepley 
2269d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscFVCreate_LeastSquares(PetscFV fvm)
2270d71ae5a4SJacob Faibussowitsch {
2271c0ce001eSMatthew G. Knepley   PetscFV_LeastSquares *ls;
2272c0ce001eSMatthew G. Knepley 
2273c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2274c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
22754dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&ls));
2276c0ce001eSMatthew G. Knepley   fvm->data = ls;
2277c0ce001eSMatthew G. Knepley 
2278c0ce001eSMatthew G. Knepley   ls->maxFaces = -1;
2279c0ce001eSMatthew G. Knepley   ls->workSize = -1;
2280c0ce001eSMatthew G. Knepley   ls->B        = NULL;
2281c0ce001eSMatthew G. Knepley   ls->Binv     = NULL;
2282c0ce001eSMatthew G. Knepley   ls->tau      = NULL;
2283c0ce001eSMatthew G. Knepley   ls->work     = NULL;
2284c0ce001eSMatthew G. Knepley 
22859566063dSJacob Faibussowitsch   PetscCall(PetscFVSetComputeGradients(fvm, PETSC_TRUE));
22869566063dSJacob Faibussowitsch   PetscCall(PetscFVInitialize_LeastSquares(fvm));
22879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fvm, "PetscFVLeastSquaresSetMaxFaces_C", PetscFVLeastSquaresSetMaxFaces_LS));
22883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2289c0ce001eSMatthew G. Knepley }
2290c0ce001eSMatthew G. Knepley 
2291c0ce001eSMatthew G. Knepley /*@
2292c0ce001eSMatthew G. Knepley   PetscFVLeastSquaresSetMaxFaces - Set the maximum number of cell faces for gradient reconstruction
2293c0ce001eSMatthew G. Knepley 
229420f4b53cSBarry Smith   Not Collective
2295c0ce001eSMatthew G. Knepley 
229660225df5SJacob Faibussowitsch   Input Parameters:
2297dce8aebaSBarry Smith + fvm      - The `PetscFV` object
2298c0ce001eSMatthew G. Knepley - maxFaces - The maximum number of cell faces
2299c0ce001eSMatthew G. Knepley 
2300c0ce001eSMatthew G. Knepley   Level: intermediate
2301c0ce001eSMatthew G. Knepley 
2302dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVCreate()`, `PETSCFVLEASTSQUARES`, `PetscFVComputeGradient()`
2303c0ce001eSMatthew G. Knepley @*/
2304d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVLeastSquaresSetMaxFaces(PetscFV fvm, PetscInt maxFaces)
2305d71ae5a4SJacob Faibussowitsch {
2306c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2307c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
2308cac4c232SBarry Smith   PetscTryMethod(fvm, "PetscFVLeastSquaresSetMaxFaces_C", (PetscFV, PetscInt), (fvm, maxFaces));
23093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2310c0ce001eSMatthew G. Knepley }
2311