xref: /petsc/src/dm/dt/fv/interface/fv.c (revision f6feae9b43250ce03bc7de7cceea6f31403e1baa)
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 
22c0ce001eSMatthew G. Knepley   Not Collective
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 
57c0ce001eSMatthew G. Knepley /*@C
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 
95c0ce001eSMatthew G. Knepley /*@C
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 
120c0ce001eSMatthew G. Knepley /*@C
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 
142fe2efc57SMark /*@C
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 
203c0ce001eSMatthew G. Knepley /*@C
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);
239c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific((*lim), PETSCLIMITER_CLASSID, 1);
240c0ce001eSMatthew G. Knepley 
2419371c9d4SSatish Balay   if (--((PetscObject)(*lim))->refct > 0) {
2429371c9d4SSatish Balay     *lim = NULL;
2433ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2449371c9d4SSatish Balay   }
245c0ce001eSMatthew G. Knepley   ((PetscObject)(*lim))->refct = 0;
246c0ce001eSMatthew G. Knepley 
247dbbe0bcdSBarry Smith   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 
896c0ce001eSMatthew G. Knepley   Not Collective
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 
931c0ce001eSMatthew G. Knepley /*@C
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 
969c0ce001eSMatthew G. Knepley /*@C
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 
994c0ce001eSMatthew G. Knepley /*@C
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 
1016fe2efc57SMark /*@C
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);
1121c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific((*fvm), PETSCFV_CLASSID, 1);
1122c0ce001eSMatthew G. Knepley 
11239371c9d4SSatish Balay   if (--((PetscObject)(*fvm))->refct > 0) {
11249371c9d4SSatish Balay     *fvm = NULL;
11253ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
11269371c9d4SSatish Balay   }
1127c0ce001eSMatthew G. Knepley   ((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 
1137dbbe0bcdSBarry Smith   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 
1304c0ce001eSMatthew G. Knepley /*@C
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 @*/
1320d71ae5a4SJacob Faibussowitsch 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));
1435*f6feae9bSMatthew 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 /*@
1475dce8aebaSBarry Smith   PetscFVGetDualSpace - Returns the `PetscDualSpace` used to define the inner product on a `PetscFV`
1476c0ce001eSMatthew G. Knepley 
147720f4b53cSBarry Smith   Not Collective
1478c0ce001eSMatthew G. Knepley 
1479c0ce001eSMatthew G. Knepley   Input Parameter:
1480dce8aebaSBarry Smith . fvm - The `PetscFV` object
1481c0ce001eSMatthew G. Knepley 
1482c0ce001eSMatthew G. Knepley   Output Parameter:
148320f4b53cSBarry Smith . sp - The `PetscDualSpace` object
1484c0ce001eSMatthew G. Knepley 
148588f5f89eSMatthew G. Knepley   Level: intermediate
1486c0ce001eSMatthew G. Knepley 
148760225df5SJacob Faibussowitsch   Developer Notes:
1488dce8aebaSBarry Smith   There is overlap between the methods of `PetscFE` and `PetscFV`, they should probably share a common parent class
1489dce8aebaSBarry Smith 
1490dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscFV`, `PetscFVCreate()`
1491c0ce001eSMatthew G. Knepley @*/
1492d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetDualSpace(PetscFV fvm, PetscDualSpace *sp)
1493d71ae5a4SJacob Faibussowitsch {
1494c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1495c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
14964f572ea9SToby Isaac   PetscAssertPointer(sp, 2);
1497c0ce001eSMatthew G. Knepley   if (!fvm->dualSpace) {
1498c0ce001eSMatthew G. Knepley     DM       K;
1499c0ce001eSMatthew G. Knepley     PetscInt dim, Nc, c;
1500c0ce001eSMatthew G. Knepley 
15019566063dSJacob Faibussowitsch     PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
15029566063dSJacob Faibussowitsch     PetscCall(PetscFVGetNumComponents(fvm, &Nc));
15039566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceCreate(PetscObjectComm((PetscObject)fvm), &fvm->dualSpace));
15049566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSetType(fvm->dualSpace, PETSCDUALSPACESIMPLE));
15059566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, PETSC_FALSE), &K));
15069566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSetNumComponents(fvm->dualSpace, Nc));
15079566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSetDM(fvm->dualSpace, K));
15089566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&K));
15099566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSimpleSetDimension(fvm->dualSpace, Nc));
1510c0ce001eSMatthew G. Knepley     /* Should we be using PetscFVGetQuadrature() here? */
1511c0ce001eSMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
1512c0ce001eSMatthew G. Knepley       PetscQuadrature qc;
1513c0ce001eSMatthew G. Knepley       PetscReal      *points, *weights;
1514c0ce001eSMatthew G. Knepley 
15159566063dSJacob Faibussowitsch       PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, &qc));
15169566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(dim, &points));
15179566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(Nc, &weights));
1518c0ce001eSMatthew G. Knepley       weights[c] = 1.0;
15199566063dSJacob Faibussowitsch       PetscCall(PetscQuadratureSetData(qc, dim, Nc, 1, points, weights));
15209566063dSJacob Faibussowitsch       PetscCall(PetscDualSpaceSimpleSetFunctional(fvm->dualSpace, c, qc));
15219566063dSJacob Faibussowitsch       PetscCall(PetscQuadratureDestroy(&qc));
1522c0ce001eSMatthew G. Knepley     }
15239566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSetUp(fvm->dualSpace));
1524c0ce001eSMatthew G. Knepley   }
1525c0ce001eSMatthew G. Knepley   *sp = fvm->dualSpace;
15263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1527c0ce001eSMatthew G. Knepley }
1528c0ce001eSMatthew G. Knepley 
1529c0ce001eSMatthew G. Knepley /*@
1530dce8aebaSBarry Smith   PetscFVSetDualSpace - Sets the `PetscDualSpace` used to define the inner product
1531c0ce001eSMatthew G. Knepley 
153220f4b53cSBarry Smith   Not Collective
1533c0ce001eSMatthew G. Knepley 
1534c0ce001eSMatthew G. Knepley   Input Parameters:
1535dce8aebaSBarry Smith + fvm - The `PetscFV` object
1536dce8aebaSBarry Smith - sp  - The `PetscDualSpace` object
1537c0ce001eSMatthew G. Knepley 
1538c0ce001eSMatthew G. Knepley   Level: intermediate
1539c0ce001eSMatthew G. Knepley 
1540dce8aebaSBarry Smith   Note:
1541dce8aebaSBarry Smith   A simple dual space is provided automatically, and the user typically will not need to override it.
1542c0ce001eSMatthew G. Knepley 
1543dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscFV`, `PetscFVCreate()`
1544c0ce001eSMatthew G. Knepley @*/
1545d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetDualSpace(PetscFV fvm, PetscDualSpace sp)
1546d71ae5a4SJacob Faibussowitsch {
1547c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1548c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1549c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 2);
15509566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDestroy(&fvm->dualSpace));
1551c0ce001eSMatthew G. Knepley   fvm->dualSpace = sp;
15529566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fvm->dualSpace));
15533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1554c0ce001eSMatthew G. Knepley }
1555c0ce001eSMatthew G. Knepley 
155688f5f89eSMatthew G. Knepley /*@C
1557ef0bb6c7SMatthew G. Knepley   PetscFVGetCellTabulation - Returns the tabulation of the basis functions at the quadrature points
155888f5f89eSMatthew G. Knepley 
155920f4b53cSBarry Smith   Not Collective
156088f5f89eSMatthew G. Knepley 
156188f5f89eSMatthew G. Knepley   Input Parameter:
1562dce8aebaSBarry Smith . fvm - The `PetscFV` object
156388f5f89eSMatthew G. Knepley 
1564ef0bb6c7SMatthew G. Knepley   Output Parameter:
1565a5b23f4aSJose E. Roman . T - The basis function values and derivatives at quadrature points
156688f5f89eSMatthew G. Knepley 
156788f5f89eSMatthew G. Knepley   Level: intermediate
156888f5f89eSMatthew G. Knepley 
1569dce8aebaSBarry Smith   Note:
1570dce8aebaSBarry Smith .vb
1571dce8aebaSBarry Smith   T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
1572dce8aebaSBarry 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
1573dce8aebaSBarry 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
1574dce8aebaSBarry Smith .ve
1575dce8aebaSBarry Smith 
1576dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscTabulation`, `PetscFEGetCellTabulation()`, `PetscFVCreateTabulation()`, `PetscFVGetQuadrature()`, `PetscQuadratureGetData()`
157788f5f89eSMatthew G. Knepley @*/
1578d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetCellTabulation(PetscFV fvm, PetscTabulation *T)
1579d71ae5a4SJacob Faibussowitsch {
1580c0ce001eSMatthew G. Knepley   PetscInt         npoints;
1581c0ce001eSMatthew G. Knepley   const PetscReal *points;
1582c0ce001eSMatthew G. Knepley 
1583c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1584c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
15854f572ea9SToby Isaac   PetscAssertPointer(T, 2);
15869566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureGetData(fvm->quadrature, NULL, NULL, &npoints, &points, NULL));
15879566063dSJacob Faibussowitsch   if (!fvm->T) PetscCall(PetscFVCreateTabulation(fvm, 1, npoints, points, 1, &fvm->T));
1588ef0bb6c7SMatthew G. Knepley   *T = fvm->T;
15893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1590c0ce001eSMatthew G. Knepley }
1591c0ce001eSMatthew G. Knepley 
159288f5f89eSMatthew G. Knepley /*@C
1593ef0bb6c7SMatthew G. Knepley   PetscFVCreateTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided.
159488f5f89eSMatthew G. Knepley 
159520f4b53cSBarry Smith   Not Collective
159688f5f89eSMatthew G. Knepley 
159788f5f89eSMatthew G. Knepley   Input Parameters:
1598dce8aebaSBarry Smith + fvm     - The `PetscFV` object
1599ef0bb6c7SMatthew G. Knepley . nrepl   - The number of replicas
1600ef0bb6c7SMatthew G. Knepley . npoints - The number of tabulation points in a replica
1601ef0bb6c7SMatthew G. Knepley . points  - The tabulation point coordinates
1602ef0bb6c7SMatthew G. Knepley - K       - The order of derivative to tabulate
160388f5f89eSMatthew G. Knepley 
1604ef0bb6c7SMatthew G. Knepley   Output Parameter:
1605a5b23f4aSJose E. Roman . T - The basis function values and derivative at tabulation points
160688f5f89eSMatthew G. Knepley 
160788f5f89eSMatthew G. Knepley   Level: intermediate
160888f5f89eSMatthew G. Knepley 
1609dce8aebaSBarry Smith   Note:
1610dce8aebaSBarry Smith .vb
1611dce8aebaSBarry Smith   T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
1612dce8aebaSBarry 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
1613dce8aebaSBarry 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
1614dce8aebaSBarry Smith .ve
1615dce8aebaSBarry Smith 
1616dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscTabulation`, `PetscFECreateTabulation()`, `PetscTabulationDestroy()`, `PetscFEGetCellTabulation()`
161788f5f89eSMatthew G. Knepley @*/
1618d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVCreateTabulation(PetscFV fvm, PetscInt nrepl, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation *T)
1619d71ae5a4SJacob Faibussowitsch {
1620c0ce001eSMatthew G. Knepley   PetscInt pdim = 1; /* Dimension of approximation space P */
1621ef0bb6c7SMatthew G. Knepley   PetscInt cdim;     /* Spatial dimension */
1622ef0bb6c7SMatthew G. Knepley   PetscInt Nc;       /* Field components */
1623ef0bb6c7SMatthew G. Knepley   PetscInt k, p, d, c, e;
1624c0ce001eSMatthew G. Knepley 
1625c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1626ef0bb6c7SMatthew G. Knepley   if (!npoints || K < 0) {
1627ef0bb6c7SMatthew G. Knepley     *T = NULL;
16283ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1629c0ce001eSMatthew G. Knepley   }
1630c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
16314f572ea9SToby Isaac   PetscAssertPointer(points, 4);
16324f572ea9SToby Isaac   PetscAssertPointer(T, 6);
16339566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &cdim));
16349566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fvm, &Nc));
16359566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1, T));
1636ef0bb6c7SMatthew G. Knepley   (*T)->K    = !cdim ? 0 : K;
1637ef0bb6c7SMatthew G. Knepley   (*T)->Nr   = nrepl;
1638ef0bb6c7SMatthew G. Knepley   (*T)->Np   = npoints;
1639ef0bb6c7SMatthew G. Knepley   (*T)->Nb   = pdim;
1640ef0bb6c7SMatthew G. Knepley   (*T)->Nc   = Nc;
1641ef0bb6c7SMatthew G. Knepley   (*T)->cdim = cdim;
16429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*T)->K + 1, &(*T)->T));
164348a46eb9SPierre Jolivet   for (k = 0; k <= (*T)->K; ++k) PetscCall(PetscMalloc1(nrepl * npoints * pdim * Nc * PetscPowInt(cdim, k), &(*T)->T[k]));
16449371c9d4SSatish Balay   if (K >= 0) {
16459371c9d4SSatish Balay     for (p = 0; p < nrepl * npoints; ++p)
16469371c9d4SSatish Balay       for (d = 0; d < pdim; ++d)
16479371c9d4SSatish Balay         for (c = 0; c < Nc; ++c) (*T)->T[0][(p * pdim + d) * Nc + c] = 1.0;
1648ef0bb6c7SMatthew G. Knepley   }
16499371c9d4SSatish Balay   if (K >= 1) {
16509371c9d4SSatish Balay     for (p = 0; p < nrepl * npoints; ++p)
16519371c9d4SSatish Balay       for (d = 0; d < pdim; ++d)
16529371c9d4SSatish Balay         for (c = 0; c < Nc; ++c)
16539371c9d4SSatish Balay           for (e = 0; e < cdim; ++e) (*T)->T[1][((p * pdim + d) * Nc + c) * cdim + e] = 0.0;
16549371c9d4SSatish Balay   }
16559371c9d4SSatish Balay   if (K >= 2) {
16569371c9d4SSatish Balay     for (p = 0; p < nrepl * npoints; ++p)
16579371c9d4SSatish Balay       for (d = 0; d < pdim; ++d)
16589371c9d4SSatish Balay         for (c = 0; c < Nc; ++c)
16599371c9d4SSatish Balay           for (e = 0; e < cdim * cdim; ++e) (*T)->T[2][((p * pdim + d) * Nc + c) * cdim * cdim + e] = 0.0;
16609371c9d4SSatish Balay   }
16613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1662c0ce001eSMatthew G. Knepley }
1663c0ce001eSMatthew G. Knepley 
1664c0ce001eSMatthew G. Knepley /*@C
1665c0ce001eSMatthew G. Knepley   PetscFVComputeGradient - Compute the gradient reconstruction matrix for a given cell
1666c0ce001eSMatthew G. Knepley 
1667c0ce001eSMatthew G. Knepley   Input Parameters:
1668dce8aebaSBarry Smith + fvm      - The `PetscFV` object
1669c0ce001eSMatthew G. Knepley . numFaces - The number of cell faces which are not constrained
1670c0ce001eSMatthew G. Knepley - dx       - The vector from the cell centroid to the neighboring cell centroid for each face
1671c0ce001eSMatthew G. Knepley 
1672a4e35b19SJacob Faibussowitsch   Output Parameter:
1673a4e35b19SJacob Faibussowitsch . grad - the gradient
1674a4e35b19SJacob Faibussowitsch 
167588f5f89eSMatthew G. Knepley   Level: advanced
1676c0ce001eSMatthew G. Knepley 
1677dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVCreate()`
1678c0ce001eSMatthew G. Knepley @*/
1679d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVComputeGradient(PetscFV fvm, PetscInt numFaces, PetscScalar dx[], PetscScalar grad[])
1680d71ae5a4SJacob Faibussowitsch {
1681c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1682c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1683dbbe0bcdSBarry Smith   PetscTryTypeMethod(fvm, computegradient, numFaces, dx, grad);
16843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1685c0ce001eSMatthew G. Knepley }
1686c0ce001eSMatthew G. Knepley 
168788f5f89eSMatthew G. Knepley /*@C
1688c0ce001eSMatthew G. Knepley   PetscFVIntegrateRHSFunction - Produce the cell residual vector for a chunk of elements by quadrature integration
1689c0ce001eSMatthew G. Knepley 
169020f4b53cSBarry Smith   Not Collective
1691c0ce001eSMatthew G. Knepley 
1692c0ce001eSMatthew G. Knepley   Input Parameters:
1693dce8aebaSBarry Smith + fvm         - The `PetscFV` object for the field being integrated
1694da81f932SPierre Jolivet . prob        - The `PetscDS` specifying the discretizations and continuum functions
1695c0ce001eSMatthew G. Knepley . field       - The field being integrated
1696c0ce001eSMatthew G. Knepley . Nf          - The number of faces in the chunk
1697c0ce001eSMatthew G. Knepley . fgeom       - The face geometry for each face in the chunk
1698c0ce001eSMatthew G. Knepley . neighborVol - The volume for each pair of cells in the chunk
1699c0ce001eSMatthew G. Knepley . uL          - The state from the cell on the left
1700c0ce001eSMatthew G. Knepley - uR          - The state from the cell on the right
1701c0ce001eSMatthew G. Knepley 
1702d8d19677SJose E. Roman   Output Parameters:
1703c0ce001eSMatthew G. Knepley + fluxL - the left fluxes for each face
1704c0ce001eSMatthew G. Knepley - fluxR - the right fluxes for each face
170588f5f89eSMatthew G. Knepley 
170688f5f89eSMatthew G. Knepley   Level: developer
170788f5f89eSMatthew G. Knepley 
1708dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscDS`, `PetscFVFaceGeom`, `PetscFVCreate()`
170988f5f89eSMatthew G. Knepley @*/
1710d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVIntegrateRHSFunction(PetscFV fvm, PetscDS prob, PetscInt field, PetscInt Nf, PetscFVFaceGeom *fgeom, PetscReal *neighborVol, PetscScalar uL[], PetscScalar uR[], PetscScalar fluxL[], PetscScalar fluxR[])
1711d71ae5a4SJacob Faibussowitsch {
1712c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1713c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1714dbbe0bcdSBarry Smith   PetscTryTypeMethod(fvm, integraterhsfunction, prob, field, Nf, fgeom, neighborVol, uL, uR, fluxL, fluxR);
17153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1716c0ce001eSMatthew G. Knepley }
1717c0ce001eSMatthew G. Knepley 
1718c0ce001eSMatthew G. Knepley /*@
1719*f6feae9bSMatthew G. Knepley   PetscFVClone - Create a shallow copy of a `PetscFV` object that jsut references the internal objects.
1720*f6feae9bSMatthew G. Knepley 
1721*f6feae9bSMatthew G. Knepley   Input Parameter:
1722*f6feae9bSMatthew G. Knepley . fv - The initial `PetscFV`
1723*f6feae9bSMatthew G. Knepley 
1724*f6feae9bSMatthew G. Knepley   Output Parameter:
1725*f6feae9bSMatthew G. Knepley . fvNew - A clone of the `PetscFV`
1726*f6feae9bSMatthew G. Knepley 
1727*f6feae9bSMatthew G. Knepley   Level: advanced
1728*f6feae9bSMatthew G. Knepley 
1729*f6feae9bSMatthew G. Knepley   Notes:
1730*f6feae9bSMatthew G. Knepley   This is typically used to change the number of components.
1731*f6feae9bSMatthew G. Knepley 
1732*f6feae9bSMatthew G. Knepley .seealso: `PetscFV`, `PetscFVType`, `PetscFVCreate()`, `PetscFVSetType()`
1733*f6feae9bSMatthew G. Knepley @*/
1734*f6feae9bSMatthew G. Knepley PetscErrorCode PetscFVClone(PetscFV fv, PetscFV *fvNew)
1735*f6feae9bSMatthew G. Knepley {
1736*f6feae9bSMatthew G. Knepley   PetscDualSpace  Q;
1737*f6feae9bSMatthew G. Knepley   DM              K;
1738*f6feae9bSMatthew G. Knepley   PetscQuadrature q;
1739*f6feae9bSMatthew G. Knepley   PetscInt        Nc, cdim;
1740*f6feae9bSMatthew G. Knepley 
1741*f6feae9bSMatthew G. Knepley   PetscFunctionBegin;
1742*f6feae9bSMatthew G. Knepley   PetscCall(PetscFVGetDualSpace(fv, &Q));
1743*f6feae9bSMatthew G. Knepley   PetscCall(PetscFVGetQuadrature(fv, &q));
1744*f6feae9bSMatthew G. Knepley   PetscCall(PetscDualSpaceGetDM(Q, &K));
1745*f6feae9bSMatthew G. Knepley 
1746*f6feae9bSMatthew G. Knepley   PetscCall(PetscFVCreate(PetscObjectComm((PetscObject)fv), fvNew));
1747*f6feae9bSMatthew G. Knepley   PetscCall(PetscFVSetDualSpace(*fvNew, Q));
1748*f6feae9bSMatthew G. Knepley   PetscCall(PetscFVGetNumComponents(fv, &Nc));
1749*f6feae9bSMatthew G. Knepley   PetscCall(PetscFVSetNumComponents(*fvNew, Nc));
1750*f6feae9bSMatthew G. Knepley   PetscCall(PetscFVGetSpatialDimension(fv, &cdim));
1751*f6feae9bSMatthew G. Knepley   PetscCall(PetscFVSetSpatialDimension(*fvNew, cdim));
1752*f6feae9bSMatthew G. Knepley   PetscCall(PetscFVSetQuadrature(*fvNew, q));
1753*f6feae9bSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1754*f6feae9bSMatthew G. Knepley }
1755*f6feae9bSMatthew G. Knepley 
1756*f6feae9bSMatthew G. Knepley /*@
1757a4e35b19SJacob Faibussowitsch   PetscFVRefine - Create a "refined" `PetscFV` object that refines the reference cell into
1758a4e35b19SJacob Faibussowitsch   smaller copies.
1759c0ce001eSMatthew G. Knepley 
1760c0ce001eSMatthew G. Knepley   Input Parameter:
1761dce8aebaSBarry Smith . fv - The initial `PetscFV`
1762c0ce001eSMatthew G. Knepley 
1763c0ce001eSMatthew G. Knepley   Output Parameter:
1764dce8aebaSBarry Smith . fvRef - The refined `PetscFV`
1765c0ce001eSMatthew G. Knepley 
176688f5f89eSMatthew G. Knepley   Level: advanced
1767c0ce001eSMatthew G. Knepley 
1768a4e35b19SJacob Faibussowitsch   Notes:
1769a4e35b19SJacob Faibussowitsch   This is typically used to generate a preconditioner for a high order method from a lower order method on a
1770a4e35b19SJacob Faibussowitsch   refined mesh having the same number of dofs (but more sparsity). It is also used to create an
1771a4e35b19SJacob Faibussowitsch   interpolation between regularly refined meshes.
1772a4e35b19SJacob Faibussowitsch 
1773dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVCreate()`, `PetscFVSetType()`
1774c0ce001eSMatthew G. Knepley @*/
1775d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVRefine(PetscFV fv, PetscFV *fvRef)
1776d71ae5a4SJacob Faibussowitsch {
1777c0ce001eSMatthew G. Knepley   PetscDualSpace  Q, Qref;
1778c0ce001eSMatthew G. Knepley   DM              K, Kref;
1779c0ce001eSMatthew G. Knepley   PetscQuadrature q, qref;
1780412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
1781012bc364SMatthew G. Knepley   DMPlexTransform tr;
1782c0ce001eSMatthew G. Knepley   PetscReal      *v0;
1783c0ce001eSMatthew G. Knepley   PetscReal      *jac, *invjac;
1784c0ce001eSMatthew G. Knepley   PetscInt        numComp, numSubelements, s;
1785c0ce001eSMatthew G. Knepley 
1786c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
17879566063dSJacob Faibussowitsch   PetscCall(PetscFVGetDualSpace(fv, &Q));
17889566063dSJacob Faibussowitsch   PetscCall(PetscFVGetQuadrature(fv, &q));
17899566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceGetDM(Q, &K));
1790c0ce001eSMatthew G. Knepley   /* Create dual space */
17919566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDuplicate(Q, &Qref));
17929566063dSJacob Faibussowitsch   PetscCall(DMRefine(K, PetscObjectComm((PetscObject)fv), &Kref));
17939566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetDM(Qref, Kref));
17949566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&Kref));
17959566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetUp(Qref));
1796c0ce001eSMatthew G. Knepley   /* Create volume */
17979566063dSJacob Faibussowitsch   PetscCall(PetscFVCreate(PetscObjectComm((PetscObject)fv), fvRef));
17989566063dSJacob Faibussowitsch   PetscCall(PetscFVSetDualSpace(*fvRef, Qref));
17999566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fv, &numComp));
18009566063dSJacob Faibussowitsch   PetscCall(PetscFVSetNumComponents(*fvRef, numComp));
18019566063dSJacob Faibussowitsch   PetscCall(PetscFVSetUp(*fvRef));
1802c0ce001eSMatthew G. Knepley   /* Create quadrature */
18039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(K, 0, &ct));
18049566063dSJacob Faibussowitsch   PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
18059566063dSJacob Faibussowitsch   PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
18069566063dSJacob Faibussowitsch   PetscCall(DMPlexRefineRegularGetAffineTransforms(tr, ct, &numSubelements, &v0, &jac, &invjac));
18079566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureExpandComposite(q, numSubelements, v0, jac, &qref));
18089566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSimpleSetDimension(Qref, numSubelements));
1809c0ce001eSMatthew G. Knepley   for (s = 0; s < numSubelements; ++s) {
1810c0ce001eSMatthew G. Knepley     PetscQuadrature  qs;
1811c0ce001eSMatthew G. Knepley     const PetscReal *points, *weights;
1812c0ce001eSMatthew G. Knepley     PetscReal       *p, *w;
1813c0ce001eSMatthew G. Knepley     PetscInt         dim, Nc, npoints, np;
1814c0ce001eSMatthew G. Knepley 
18159566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, &qs));
18169566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureGetData(q, &dim, &Nc, &npoints, &points, &weights));
1817c0ce001eSMatthew G. Knepley     np = npoints / numSubelements;
18189566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(np * dim, &p));
18199566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(np * Nc, &w));
18209566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(p, &points[s * np * dim], np * dim));
18219566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(w, &weights[s * np * Nc], np * Nc));
18229566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureSetData(qs, dim, Nc, np, p, w));
18239566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSimpleSetFunctional(Qref, s, qs));
18249566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureDestroy(&qs));
1825c0ce001eSMatthew G. Knepley   }
18269566063dSJacob Faibussowitsch   PetscCall(PetscFVSetQuadrature(*fvRef, qref));
18279566063dSJacob Faibussowitsch   PetscCall(DMPlexTransformDestroy(&tr));
18289566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&qref));
18299566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDestroy(&Qref));
18303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1831c0ce001eSMatthew G. Knepley }
1832c0ce001eSMatthew G. Knepley 
1833d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVDestroy_Upwind(PetscFV fvm)
1834d71ae5a4SJacob Faibussowitsch {
1835c0ce001eSMatthew G. Knepley   PetscFV_Upwind *b = (PetscFV_Upwind *)fvm->data;
1836c0ce001eSMatthew G. Knepley 
1837c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
18389566063dSJacob Faibussowitsch   PetscCall(PetscFree(b));
18393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1840c0ce001eSMatthew G. Knepley }
1841c0ce001eSMatthew G. Knepley 
1842d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVView_Upwind_Ascii(PetscFV fv, PetscViewer viewer)
1843d71ae5a4SJacob Faibussowitsch {
1844c0ce001eSMatthew G. Knepley   PetscInt          Nc, c;
1845c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
1846c0ce001eSMatthew G. Knepley 
1847c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
18489566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fv, &Nc));
18499566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
18509566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Upwind Finite Volume:\n"));
185163a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  num components: %" PetscInt_FMT "\n", Nc));
1852c0ce001eSMatthew G. Knepley   for (c = 0; c < Nc; c++) {
185348a46eb9SPierre Jolivet     if (fv->componentNames[c]) PetscCall(PetscViewerASCIIPrintf(viewer, "    component %" PetscInt_FMT ": %s\n", c, fv->componentNames[c]));
1854c0ce001eSMatthew G. Knepley   }
18553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1856c0ce001eSMatthew G. Knepley }
1857c0ce001eSMatthew G. Knepley 
1858d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVView_Upwind(PetscFV fv, PetscViewer viewer)
1859d71ae5a4SJacob Faibussowitsch {
1860c0ce001eSMatthew G. Knepley   PetscBool iascii;
1861c0ce001eSMatthew G. Knepley 
1862c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1863c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 1);
1864c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
18669566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscFVView_Upwind_Ascii(fv, viewer));
18673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1868c0ce001eSMatthew G. Knepley }
1869c0ce001eSMatthew G. Knepley 
1870d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVSetUp_Upwind(PetscFV fvm)
1871d71ae5a4SJacob Faibussowitsch {
1872c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
18733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1874c0ce001eSMatthew G. Knepley }
1875c0ce001eSMatthew G. Knepley 
1876c0ce001eSMatthew G. Knepley /*
1877c0ce001eSMatthew G. Knepley   neighborVol[f*2+0] contains the left  geom
1878c0ce001eSMatthew G. Knepley   neighborVol[f*2+1] contains the right geom
1879c0ce001eSMatthew G. Knepley */
1880d71ae5a4SJacob 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[])
1881d71ae5a4SJacob Faibussowitsch {
1882c0ce001eSMatthew G. Knepley   void (*riemann)(PetscInt, PetscInt, const PetscReal[], const PetscReal[], const PetscScalar[], const PetscScalar[], PetscInt, const PetscScalar[], PetscScalar[], void *);
1883c0ce001eSMatthew G. Knepley   void              *rctx;
1884c0ce001eSMatthew G. Knepley   PetscScalar       *flux = fvm->fluxWork;
1885c0ce001eSMatthew G. Knepley   const PetscScalar *constants;
1886c0ce001eSMatthew G. Knepley   PetscInt           dim, numConstants, pdim, totDim, Nc, off, f, d;
1887c0ce001eSMatthew G. Knepley 
1888c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
18899566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(prob, &Nc));
18909566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
18919566063dSJacob Faibussowitsch   PetscCall(PetscDSGetFieldOffset(prob, field, &off));
18929566063dSJacob Faibussowitsch   PetscCall(PetscDSGetRiemannSolver(prob, field, &riemann));
18939566063dSJacob Faibussowitsch   PetscCall(PetscDSGetContext(prob, field, &rctx));
18949566063dSJacob Faibussowitsch   PetscCall(PetscDSGetConstants(prob, &numConstants, &constants));
18959566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
18969566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fvm, &pdim));
1897c0ce001eSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
1898c0ce001eSMatthew G. Knepley     (*riemann)(dim, pdim, fgeom[f].centroid, fgeom[f].normal, &uL[f * Nc], &uR[f * Nc], numConstants, constants, flux, rctx);
1899c0ce001eSMatthew G. Knepley     for (d = 0; d < pdim; ++d) {
1900c0ce001eSMatthew G. Knepley       fluxL[f * totDim + off + d] = flux[d] / neighborVol[f * 2 + 0];
1901c0ce001eSMatthew G. Knepley       fluxR[f * totDim + off + d] = flux[d] / neighborVol[f * 2 + 1];
1902c0ce001eSMatthew G. Knepley     }
1903c0ce001eSMatthew G. Knepley   }
19043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1905c0ce001eSMatthew G. Knepley }
1906c0ce001eSMatthew G. Knepley 
1907d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVInitialize_Upwind(PetscFV fvm)
1908d71ae5a4SJacob Faibussowitsch {
1909c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1910c0ce001eSMatthew G. Knepley   fvm->ops->setfromoptions       = NULL;
1911c0ce001eSMatthew G. Knepley   fvm->ops->setup                = PetscFVSetUp_Upwind;
1912c0ce001eSMatthew G. Knepley   fvm->ops->view                 = PetscFVView_Upwind;
1913c0ce001eSMatthew G. Knepley   fvm->ops->destroy              = PetscFVDestroy_Upwind;
1914c0ce001eSMatthew G. Knepley   fvm->ops->integraterhsfunction = PetscFVIntegrateRHSFunction_Upwind;
19153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1916c0ce001eSMatthew G. Knepley }
1917c0ce001eSMatthew G. Knepley 
1918c0ce001eSMatthew G. Knepley /*MC
1919dce8aebaSBarry Smith   PETSCFVUPWIND = "upwind" - A `PetscFV` implementation
1920c0ce001eSMatthew G. Knepley 
1921c0ce001eSMatthew G. Knepley   Level: intermediate
1922c0ce001eSMatthew G. Knepley 
1923dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVCreate()`, `PetscFVSetType()`
1924c0ce001eSMatthew G. Knepley M*/
1925c0ce001eSMatthew G. Knepley 
1926d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscFVCreate_Upwind(PetscFV fvm)
1927d71ae5a4SJacob Faibussowitsch {
1928c0ce001eSMatthew G. Knepley   PetscFV_Upwind *b;
1929c0ce001eSMatthew G. Knepley 
1930c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1931c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
19324dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
1933c0ce001eSMatthew G. Knepley   fvm->data = b;
1934c0ce001eSMatthew G. Knepley 
19359566063dSJacob Faibussowitsch   PetscCall(PetscFVInitialize_Upwind(fvm));
19363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1937c0ce001eSMatthew G. Knepley }
1938c0ce001eSMatthew G. Knepley 
1939c0ce001eSMatthew G. Knepley #include <petscblaslapack.h>
1940c0ce001eSMatthew G. Knepley 
1941d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVDestroy_LeastSquares(PetscFV fvm)
1942d71ae5a4SJacob Faibussowitsch {
1943c0ce001eSMatthew G. Knepley   PetscFV_LeastSquares *ls = (PetscFV_LeastSquares *)fvm->data;
1944c0ce001eSMatthew G. Knepley 
1945c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
19469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fvm, "PetscFVLeastSquaresSetMaxFaces_C", NULL));
19479566063dSJacob Faibussowitsch   PetscCall(PetscFree4(ls->B, ls->Binv, ls->tau, ls->work));
19489566063dSJacob Faibussowitsch   PetscCall(PetscFree(ls));
19493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1950c0ce001eSMatthew G. Knepley }
1951c0ce001eSMatthew G. Knepley 
1952d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVView_LeastSquares_Ascii(PetscFV fv, PetscViewer viewer)
1953d71ae5a4SJacob Faibussowitsch {
1954c0ce001eSMatthew G. Knepley   PetscInt          Nc, c;
1955c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
1956c0ce001eSMatthew G. Knepley 
1957c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
19589566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fv, &Nc));
19599566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
19609566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Finite Volume with Least Squares Reconstruction:\n"));
196163a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  num components: %" PetscInt_FMT "\n", Nc));
1962c0ce001eSMatthew G. Knepley   for (c = 0; c < Nc; c++) {
196348a46eb9SPierre Jolivet     if (fv->componentNames[c]) PetscCall(PetscViewerASCIIPrintf(viewer, "    component %" PetscInt_FMT ": %s\n", c, fv->componentNames[c]));
1964c0ce001eSMatthew G. Knepley   }
19653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1966c0ce001eSMatthew G. Knepley }
1967c0ce001eSMatthew G. Knepley 
1968d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVView_LeastSquares(PetscFV fv, PetscViewer viewer)
1969d71ae5a4SJacob Faibussowitsch {
1970c0ce001eSMatthew G. Knepley   PetscBool iascii;
1971c0ce001eSMatthew G. Knepley 
1972c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1973c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 1);
1974c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19759566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
19769566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscFVView_LeastSquares_Ascii(fv, viewer));
19773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1978c0ce001eSMatthew G. Knepley }
1979c0ce001eSMatthew G. Knepley 
1980d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVSetUp_LeastSquares(PetscFV fvm)
1981d71ae5a4SJacob Faibussowitsch {
1982c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
19833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1984c0ce001eSMatthew G. Knepley }
1985c0ce001eSMatthew G. Knepley 
1986c0ce001eSMatthew G. Knepley /* Overwrites A. Can only handle full-rank problems with m>=n */
1987d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVLeastSquaresPseudoInverse_Static(PetscInt m, PetscInt mstride, PetscInt n, PetscScalar *A, PetscScalar *Ainv, PetscScalar *tau, PetscInt worksize, PetscScalar *work)
1988d71ae5a4SJacob Faibussowitsch {
1989c0ce001eSMatthew G. Knepley   PetscBool    debug = PETSC_FALSE;
1990c0ce001eSMatthew G. Knepley   PetscBLASInt M, N, K, lda, ldb, ldwork, info;
1991c0ce001eSMatthew G. Knepley   PetscScalar *R, *Q, *Aback, Alpha;
1992c0ce001eSMatthew G. Knepley 
1993c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1994c0ce001eSMatthew G. Knepley   if (debug) {
19959566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m * n, &Aback));
19969566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(Aback, A, m * n));
1997c0ce001eSMatthew G. Knepley   }
1998c0ce001eSMatthew G. Knepley 
19999566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &M));
20009566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(n, &N));
20019566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(mstride, &lda));
20029566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(worksize, &ldwork));
20039566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
2004792fecdfSBarry Smith   PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&M, &N, A, &lda, tau, work, &ldwork, &info));
20059566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
200628b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "xGEQRF error");
2007c0ce001eSMatthew G. Knepley   R = A; /* Upper triangular part of A now contains R, the rest contains the elementary reflectors */
2008c0ce001eSMatthew G. Knepley 
2009c0ce001eSMatthew G. Knepley   /* Extract an explicit representation of Q */
2010c0ce001eSMatthew G. Knepley   Q = Ainv;
20119566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(Q, A, mstride * n));
2012c0ce001eSMatthew G. Knepley   K = N; /* full rank */
2013792fecdfSBarry Smith   PetscCallBLAS("LAPACKorgqr", LAPACKorgqr_(&M, &N, &K, Q, &lda, tau, work, &ldwork, &info));
201428b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "xORGQR/xUNGQR error");
2015c0ce001eSMatthew G. Knepley 
2016c0ce001eSMatthew G. Knepley   /* Compute A^{-T} = (R^{-1} Q^T)^T = Q R^{-T} */
2017c0ce001eSMatthew G. Knepley   Alpha = 1.0;
2018c0ce001eSMatthew G. Knepley   ldb   = lda;
2019c0ce001eSMatthew G. Knepley   BLAStrsm_("Right", "Upper", "ConjugateTranspose", "NotUnitTriangular", &M, &N, &Alpha, R, &lda, Q, &ldb);
2020c0ce001eSMatthew G. Knepley   /* Ainv is Q, overwritten with inverse */
2021c0ce001eSMatthew G. Knepley 
2022c0ce001eSMatthew G. Knepley   if (debug) { /* Check that pseudo-inverse worked */
2023c0ce001eSMatthew G. Knepley     PetscScalar  Beta = 0.0;
2024c0ce001eSMatthew G. Knepley     PetscBLASInt ldc;
2025c0ce001eSMatthew G. Knepley     K   = N;
2026c0ce001eSMatthew G. Knepley     ldc = N;
2027c0ce001eSMatthew G. Knepley     BLASgemm_("ConjugateTranspose", "Normal", &N, &K, &M, &Alpha, Ainv, &lda, Aback, &ldb, &Beta, work, &ldc);
20289566063dSJacob Faibussowitsch     PetscCall(PetscScalarView(n * n, work, PETSC_VIEWER_STDOUT_SELF));
20299566063dSJacob Faibussowitsch     PetscCall(PetscFree(Aback));
2030c0ce001eSMatthew G. Knepley   }
20313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2032c0ce001eSMatthew G. Knepley }
2033c0ce001eSMatthew G. Knepley 
2034c0ce001eSMatthew G. Knepley /* Overwrites A. Can handle degenerate problems and m<n. */
2035d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVLeastSquaresPseudoInverseSVD_Static(PetscInt m, PetscInt mstride, PetscInt n, PetscScalar *A, PetscScalar *Ainv, PetscScalar *tau, PetscInt worksize, PetscScalar *work)
2036d71ae5a4SJacob Faibussowitsch {
20376bb27163SBarry Smith   PetscScalar *Brhs;
2038c0ce001eSMatthew G. Knepley   PetscScalar *tmpwork;
2039c0ce001eSMatthew G. Knepley   PetscReal    rcond;
2040c0ce001eSMatthew G. Knepley #if defined(PETSC_USE_COMPLEX)
2041c0ce001eSMatthew G. Knepley   PetscInt   rworkSize;
2042c0ce001eSMatthew G. Knepley   PetscReal *rwork;
2043c0ce001eSMatthew G. Knepley #endif
2044c0ce001eSMatthew G. Knepley   PetscInt     i, j, maxmn;
2045c0ce001eSMatthew G. Knepley   PetscBLASInt M, N, lda, ldb, ldwork;
2046c0ce001eSMatthew G. Knepley   PetscBLASInt nrhs, irank, info;
2047c0ce001eSMatthew G. Knepley 
2048c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2049c0ce001eSMatthew G. Knepley   /* initialize to identity */
2050736d4f42SpierreXVI   tmpwork = work;
2051736d4f42SpierreXVI   Brhs    = Ainv;
2052c0ce001eSMatthew G. Knepley   maxmn   = PetscMax(m, n);
2053c0ce001eSMatthew G. Knepley   for (j = 0; j < maxmn; j++) {
2054c0ce001eSMatthew G. Knepley     for (i = 0; i < maxmn; i++) Brhs[i + j * maxmn] = 1.0 * (i == j);
2055c0ce001eSMatthew G. Knepley   }
2056c0ce001eSMatthew G. Knepley 
20579566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &M));
20589566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(n, &N));
20599566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(mstride, &lda));
20609566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(maxmn, &ldb));
20619566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(worksize, &ldwork));
2062c0ce001eSMatthew G. Knepley   rcond = -1;
2063c0ce001eSMatthew G. Knepley   nrhs  = M;
2064c0ce001eSMatthew G. Knepley #if defined(PETSC_USE_COMPLEX)
2065c0ce001eSMatthew G. Knepley   rworkSize = 5 * PetscMin(M, N);
20669566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(rworkSize, &rwork));
20676bb27163SBarry Smith   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
2068792fecdfSBarry Smith   PetscCallBLAS("LAPACKgelss", LAPACKgelss_(&M, &N, &nrhs, A, &lda, Brhs, &ldb, (PetscReal *)tau, &rcond, &irank, tmpwork, &ldwork, rwork, &info));
20699566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
20709566063dSJacob Faibussowitsch   PetscCall(PetscFree(rwork));
2071c0ce001eSMatthew G. Knepley #else
2072c0ce001eSMatthew G. Knepley   nrhs = M;
20736bb27163SBarry Smith   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
2074792fecdfSBarry Smith   PetscCallBLAS("LAPACKgelss", LAPACKgelss_(&M, &N, &nrhs, A, &lda, Brhs, &ldb, (PetscReal *)tau, &rcond, &irank, tmpwork, &ldwork, &info));
20759566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
2076c0ce001eSMatthew G. Knepley #endif
207728b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "xGELSS error");
2078c0ce001eSMatthew G. Knepley   /* The following check should be turned into a diagnostic as soon as someone wants to do this intentionally */
207908401ef6SPierre 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");
20803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2081c0ce001eSMatthew G. Knepley }
2082c0ce001eSMatthew G. Knepley 
2083c0ce001eSMatthew G. Knepley #if 0
2084c0ce001eSMatthew G. Knepley static PetscErrorCode PetscFVLeastSquaresDebugCell_Static(PetscFV fvm, PetscInt cell, DM dm, DM dmFace, PetscScalar *fgeom, DM dmCell, PetscScalar *cgeom)
2085c0ce001eSMatthew G. Knepley {
2086c0ce001eSMatthew G. Knepley   PetscReal       grad[2] = {0, 0};
2087c0ce001eSMatthew G. Knepley   const PetscInt *faces;
2088c0ce001eSMatthew G. Knepley   PetscInt        numFaces, f;
2089c0ce001eSMatthew G. Knepley 
2090c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
20919566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, cell, &numFaces));
20929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, cell, &faces));
2093c0ce001eSMatthew G. Knepley   for (f = 0; f < numFaces; ++f) {
2094c0ce001eSMatthew G. Knepley     const PetscInt *fcells;
2095c0ce001eSMatthew G. Knepley     const CellGeom *cg1;
2096c0ce001eSMatthew G. Knepley     const FaceGeom *fg;
2097c0ce001eSMatthew G. Knepley 
20989566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, faces[f], &fcells));
20999566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmFace, faces[f], fgeom, &fg));
2100c0ce001eSMatthew G. Knepley     for (i = 0; i < 2; ++i) {
2101c0ce001eSMatthew G. Knepley       PetscScalar du;
2102c0ce001eSMatthew G. Knepley 
2103c0ce001eSMatthew G. Knepley       if (fcells[i] == c) continue;
21049566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, fcells[i], cgeom, &cg1));
2105c0ce001eSMatthew G. Knepley       du   = cg1->centroid[0] + 3*cg1->centroid[1] - (cg->centroid[0] + 3*cg->centroid[1]);
2106c0ce001eSMatthew G. Knepley       grad[0] += fg->grad[!i][0] * du;
2107c0ce001eSMatthew G. Knepley       grad[1] += fg->grad[!i][1] * du;
2108c0ce001eSMatthew G. Knepley     }
2109c0ce001eSMatthew G. Knepley   }
21109566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "cell[%d] grad (%g, %g)\n", cell, grad[0], grad[1]));
21113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2112c0ce001eSMatthew G. Knepley }
2113c0ce001eSMatthew G. Knepley #endif
2114c0ce001eSMatthew G. Knepley 
2115c0ce001eSMatthew G. Knepley /*
2116c0ce001eSMatthew G. Knepley   PetscFVComputeGradient - Compute the gradient reconstruction matrix for a given cell
2117c0ce001eSMatthew G. Knepley 
2118c0ce001eSMatthew G. Knepley   Input Parameters:
2119dce8aebaSBarry Smith + fvm      - The `PetscFV` object
2120c0ce001eSMatthew G. Knepley . numFaces - The number of cell faces which are not constrained
2121c0ce001eSMatthew G. Knepley . dx       - The vector from the cell centroid to the neighboring cell centroid for each face
2122c0ce001eSMatthew G. Knepley 
2123c0ce001eSMatthew G. Knepley   Level: developer
2124c0ce001eSMatthew G. Knepley 
2125dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVCreate()`
2126c0ce001eSMatthew G. Knepley */
2127d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVComputeGradient_LeastSquares(PetscFV fvm, PetscInt numFaces, const PetscScalar dx[], PetscScalar grad[])
2128d71ae5a4SJacob Faibussowitsch {
2129c0ce001eSMatthew G. Knepley   PetscFV_LeastSquares *ls       = (PetscFV_LeastSquares *)fvm->data;
2130c0ce001eSMatthew G. Knepley   const PetscBool       useSVD   = PETSC_TRUE;
2131c0ce001eSMatthew G. Knepley   const PetscInt        maxFaces = ls->maxFaces;
2132c0ce001eSMatthew G. Knepley   PetscInt              dim, f, d;
2133c0ce001eSMatthew G. Knepley 
2134c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2135c0ce001eSMatthew G. Knepley   if (numFaces > maxFaces) {
213608401ef6SPierre Jolivet     PetscCheck(maxFaces >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Reconstruction has not been initialized, call PetscFVLeastSquaresSetMaxFaces()");
213763a3b9bcSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input faces %" PetscInt_FMT " > %" PetscInt_FMT " maxfaces", numFaces, maxFaces);
2138c0ce001eSMatthew G. Knepley   }
21399566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
2140c0ce001eSMatthew G. Knepley   for (f = 0; f < numFaces; ++f) {
2141c0ce001eSMatthew G. Knepley     for (d = 0; d < dim; ++d) ls->B[d * maxFaces + f] = dx[f * dim + d];
2142c0ce001eSMatthew G. Knepley   }
2143c0ce001eSMatthew G. Knepley   /* Overwrites B with garbage, returns Binv in row-major format */
2144736d4f42SpierreXVI   if (useSVD) {
2145736d4f42SpierreXVI     PetscInt maxmn = PetscMax(numFaces, dim);
21469566063dSJacob Faibussowitsch     PetscCall(PetscFVLeastSquaresPseudoInverseSVD_Static(numFaces, maxFaces, dim, ls->B, ls->Binv, ls->tau, ls->workSize, ls->work));
2147736d4f42SpierreXVI     /* Binv shaped in column-major, coldim=maxmn.*/
2148736d4f42SpierreXVI     for (f = 0; f < numFaces; ++f) {
2149736d4f42SpierreXVI       for (d = 0; d < dim; ++d) grad[f * dim + d] = ls->Binv[d + maxmn * f];
2150736d4f42SpierreXVI     }
2151736d4f42SpierreXVI   } else {
21529566063dSJacob Faibussowitsch     PetscCall(PetscFVLeastSquaresPseudoInverse_Static(numFaces, maxFaces, dim, ls->B, ls->Binv, ls->tau, ls->workSize, ls->work));
2153736d4f42SpierreXVI     /* Binv shaped in row-major, rowdim=maxFaces.*/
2154c0ce001eSMatthew G. Knepley     for (f = 0; f < numFaces; ++f) {
2155c0ce001eSMatthew G. Knepley       for (d = 0; d < dim; ++d) grad[f * dim + d] = ls->Binv[d * maxFaces + f];
2156c0ce001eSMatthew G. Knepley     }
2157736d4f42SpierreXVI   }
21583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2159c0ce001eSMatthew G. Knepley }
2160c0ce001eSMatthew G. Knepley 
2161c0ce001eSMatthew G. Knepley /*
2162c0ce001eSMatthew G. Knepley   neighborVol[f*2+0] contains the left  geom
2163c0ce001eSMatthew G. Knepley   neighborVol[f*2+1] contains the right geom
2164c0ce001eSMatthew G. Knepley */
2165d71ae5a4SJacob 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[])
2166d71ae5a4SJacob Faibussowitsch {
2167c0ce001eSMatthew G. Knepley   void (*riemann)(PetscInt, PetscInt, const PetscReal[], const PetscReal[], const PetscScalar[], const PetscScalar[], PetscInt, const PetscScalar[], PetscScalar[], void *);
2168c0ce001eSMatthew G. Knepley   void              *rctx;
2169c0ce001eSMatthew G. Knepley   PetscScalar       *flux = fvm->fluxWork;
2170c0ce001eSMatthew G. Knepley   const PetscScalar *constants;
2171c0ce001eSMatthew G. Knepley   PetscInt           dim, numConstants, pdim, Nc, totDim, off, f, d;
2172c0ce001eSMatthew G. Knepley 
2173c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
21749566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(prob, &Nc));
21759566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
21769566063dSJacob Faibussowitsch   PetscCall(PetscDSGetFieldOffset(prob, field, &off));
21779566063dSJacob Faibussowitsch   PetscCall(PetscDSGetRiemannSolver(prob, field, &riemann));
21789566063dSJacob Faibussowitsch   PetscCall(PetscDSGetContext(prob, field, &rctx));
21799566063dSJacob Faibussowitsch   PetscCall(PetscDSGetConstants(prob, &numConstants, &constants));
21809566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
21819566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fvm, &pdim));
2182c0ce001eSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
2183c0ce001eSMatthew G. Knepley     (*riemann)(dim, pdim, fgeom[f].centroid, fgeom[f].normal, &uL[f * Nc], &uR[f * Nc], numConstants, constants, flux, rctx);
2184c0ce001eSMatthew G. Knepley     for (d = 0; d < pdim; ++d) {
2185c0ce001eSMatthew G. Knepley       fluxL[f * totDim + off + d] = flux[d] / neighborVol[f * 2 + 0];
2186c0ce001eSMatthew G. Knepley       fluxR[f * totDim + off + d] = flux[d] / neighborVol[f * 2 + 1];
2187c0ce001eSMatthew G. Knepley     }
2188c0ce001eSMatthew G. Knepley   }
21893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2190c0ce001eSMatthew G. Knepley }
2191c0ce001eSMatthew G. Knepley 
2192d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVLeastSquaresSetMaxFaces_LS(PetscFV fvm, PetscInt maxFaces)
2193d71ae5a4SJacob Faibussowitsch {
2194c0ce001eSMatthew G. Knepley   PetscFV_LeastSquares *ls = (PetscFV_LeastSquares *)fvm->data;
2195736d4f42SpierreXVI   PetscInt              dim, m, n, nrhs, minmn, maxmn;
2196c0ce001eSMatthew G. Knepley 
2197c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2198c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
21999566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
22009566063dSJacob Faibussowitsch   PetscCall(PetscFree4(ls->B, ls->Binv, ls->tau, ls->work));
2201c0ce001eSMatthew G. Knepley   ls->maxFaces = maxFaces;
2202c0ce001eSMatthew G. Knepley   m            = ls->maxFaces;
2203c0ce001eSMatthew G. Knepley   n            = dim;
2204c0ce001eSMatthew G. Knepley   nrhs         = ls->maxFaces;
2205736d4f42SpierreXVI   minmn        = PetscMin(m, n);
2206736d4f42SpierreXVI   maxmn        = PetscMax(m, n);
2207736d4f42SpierreXVI   ls->workSize = 3 * minmn + PetscMax(2 * minmn, PetscMax(maxmn, nrhs)); /* required by LAPACK */
22089566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(m * n, &ls->B, maxmn * maxmn, &ls->Binv, minmn, &ls->tau, ls->workSize, &ls->work));
22093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2210c0ce001eSMatthew G. Knepley }
2211c0ce001eSMatthew G. Knepley 
221266976f2fSJacob Faibussowitsch static PetscErrorCode PetscFVInitialize_LeastSquares(PetscFV fvm)
2213d71ae5a4SJacob Faibussowitsch {
2214c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2215c0ce001eSMatthew G. Knepley   fvm->ops->setfromoptions       = NULL;
2216c0ce001eSMatthew G. Knepley   fvm->ops->setup                = PetscFVSetUp_LeastSquares;
2217c0ce001eSMatthew G. Knepley   fvm->ops->view                 = PetscFVView_LeastSquares;
2218c0ce001eSMatthew G. Knepley   fvm->ops->destroy              = PetscFVDestroy_LeastSquares;
2219c0ce001eSMatthew G. Knepley   fvm->ops->computegradient      = PetscFVComputeGradient_LeastSquares;
2220c0ce001eSMatthew G. Knepley   fvm->ops->integraterhsfunction = PetscFVIntegrateRHSFunction_LeastSquares;
22213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2222c0ce001eSMatthew G. Knepley }
2223c0ce001eSMatthew G. Knepley 
2224c0ce001eSMatthew G. Knepley /*MC
2225dce8aebaSBarry Smith   PETSCFVLEASTSQUARES = "leastsquares" - A `PetscFV` implementation
2226c0ce001eSMatthew G. Knepley 
2227c0ce001eSMatthew G. Knepley   Level: intermediate
2228c0ce001eSMatthew G. Knepley 
2229dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVCreate()`, `PetscFVSetType()`
2230c0ce001eSMatthew G. Knepley M*/
2231c0ce001eSMatthew G. Knepley 
2232d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscFVCreate_LeastSquares(PetscFV fvm)
2233d71ae5a4SJacob Faibussowitsch {
2234c0ce001eSMatthew G. Knepley   PetscFV_LeastSquares *ls;
2235c0ce001eSMatthew G. Knepley 
2236c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2237c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
22384dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&ls));
2239c0ce001eSMatthew G. Knepley   fvm->data = ls;
2240c0ce001eSMatthew G. Knepley 
2241c0ce001eSMatthew G. Knepley   ls->maxFaces = -1;
2242c0ce001eSMatthew G. Knepley   ls->workSize = -1;
2243c0ce001eSMatthew G. Knepley   ls->B        = NULL;
2244c0ce001eSMatthew G. Knepley   ls->Binv     = NULL;
2245c0ce001eSMatthew G. Knepley   ls->tau      = NULL;
2246c0ce001eSMatthew G. Knepley   ls->work     = NULL;
2247c0ce001eSMatthew G. Knepley 
22489566063dSJacob Faibussowitsch   PetscCall(PetscFVSetComputeGradients(fvm, PETSC_TRUE));
22499566063dSJacob Faibussowitsch   PetscCall(PetscFVInitialize_LeastSquares(fvm));
22509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fvm, "PetscFVLeastSquaresSetMaxFaces_C", PetscFVLeastSquaresSetMaxFaces_LS));
22513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2252c0ce001eSMatthew G. Knepley }
2253c0ce001eSMatthew G. Knepley 
2254c0ce001eSMatthew G. Knepley /*@
2255c0ce001eSMatthew G. Knepley   PetscFVLeastSquaresSetMaxFaces - Set the maximum number of cell faces for gradient reconstruction
2256c0ce001eSMatthew G. Knepley 
225720f4b53cSBarry Smith   Not Collective
2258c0ce001eSMatthew G. Knepley 
225960225df5SJacob Faibussowitsch   Input Parameters:
2260dce8aebaSBarry Smith + fvm      - The `PetscFV` object
2261c0ce001eSMatthew G. Knepley - maxFaces - The maximum number of cell faces
2262c0ce001eSMatthew G. Knepley 
2263c0ce001eSMatthew G. Knepley   Level: intermediate
2264c0ce001eSMatthew G. Knepley 
2265dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVCreate()`, `PETSCFVLEASTSQUARES`, `PetscFVComputeGradient()`
2266c0ce001eSMatthew G. Knepley @*/
2267d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVLeastSquaresSetMaxFaces(PetscFV fvm, PetscInt maxFaces)
2268d71ae5a4SJacob Faibussowitsch {
2269c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2270c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
2271cac4c232SBarry Smith   PetscTryMethod(fvm, "PetscFVLeastSquaresSetMaxFaces_C", (PetscFV, PetscInt), (fvm, maxFaces));
22723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2273c0ce001eSMatthew G. Knepley }
2274