xref: /petsc/src/dm/dt/fv/interface/fv.c (revision 1d27aa22b2f6148b2c4e3f06a75e0638d6493e09)
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 
87c0ce001eSMatthew G. Knepley   if (lim->ops->destroy) {
88dbbe0bcdSBarry Smith     PetscUseTypeMethod(lim, destroy);
89c0ce001eSMatthew G. Knepley     lim->ops->destroy = NULL;
90c0ce001eSMatthew G. Knepley   }
919566063dSJacob Faibussowitsch   PetscCall((*r)(lim));
929566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)lim, name));
933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
94c0ce001eSMatthew G. Knepley }
95c0ce001eSMatthew G. Knepley 
96c0ce001eSMatthew G. Knepley /*@C
97dce8aebaSBarry Smith   PetscLimiterGetType - Gets the `PetscLimiterType` name (as a string) from the `PetscLimiter`.
98c0ce001eSMatthew G. Knepley 
99c0ce001eSMatthew G. Knepley   Not Collective
100c0ce001eSMatthew G. Knepley 
101c0ce001eSMatthew G. Knepley   Input Parameter:
102dce8aebaSBarry Smith . lim - The `PetscLimiter`
103c0ce001eSMatthew G. Knepley 
104c0ce001eSMatthew G. Knepley   Output Parameter:
105dce8aebaSBarry Smith . name - The `PetscLimiterType`
106c0ce001eSMatthew G. Knepley 
107c0ce001eSMatthew G. Knepley   Level: intermediate
108c0ce001eSMatthew G. Knepley 
109dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterSetType()`, `PetscLimiterCreate()`
110c0ce001eSMatthew G. Knepley @*/
111d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterGetType(PetscLimiter lim, PetscLimiterType *name)
112d71ae5a4SJacob Faibussowitsch {
113c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
114c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
1154f572ea9SToby Isaac   PetscAssertPointer(name, 2);
1169566063dSJacob Faibussowitsch   PetscCall(PetscLimiterRegisterAll());
117c0ce001eSMatthew G. Knepley   *name = ((PetscObject)lim)->type_name;
1183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
119c0ce001eSMatthew G. Knepley }
120c0ce001eSMatthew G. Knepley 
121c0ce001eSMatthew G. Knepley /*@C
122dce8aebaSBarry Smith   PetscLimiterViewFromOptions - View a `PetscLimiter` based on values in the options database
123fe2efc57SMark 
12420f4b53cSBarry Smith   Collective
125fe2efc57SMark 
126fe2efc57SMark   Input Parameters:
127dce8aebaSBarry Smith + A    - the `PetscLimiter` object to view
128dce8aebaSBarry Smith . obj  - Optional object that provides the options prefix to use
129dce8aebaSBarry Smith - name - command line option name
130fe2efc57SMark 
131fe2efc57SMark   Level: intermediate
132dce8aebaSBarry Smith 
133dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterView()`, `PetscObjectViewFromOptions()`, `PetscLimiterCreate()`
134fe2efc57SMark @*/
135d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterViewFromOptions(PetscLimiter A, PetscObject obj, const char name[])
136d71ae5a4SJacob Faibussowitsch {
137fe2efc57SMark   PetscFunctionBegin;
138fe2efc57SMark   PetscValidHeaderSpecific(A, PETSCLIMITER_CLASSID, 1);
1399566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
141fe2efc57SMark }
142fe2efc57SMark 
143fe2efc57SMark /*@C
144dce8aebaSBarry Smith   PetscLimiterView - Views a `PetscLimiter`
145c0ce001eSMatthew G. Knepley 
14620f4b53cSBarry Smith   Collective
147c0ce001eSMatthew G. Knepley 
148d8d19677SJose E. Roman   Input Parameters:
149dce8aebaSBarry Smith + lim - the `PetscLimiter` object to view
150c0ce001eSMatthew G. Knepley - v   - the viewer
151c0ce001eSMatthew G. Knepley 
15288f5f89eSMatthew G. Knepley   Level: beginner
153c0ce001eSMatthew G. Knepley 
154dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscViewer`, `PetscLimiterDestroy()`, `PetscLimiterViewFromOptions()`
155c0ce001eSMatthew G. Knepley @*/
156d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterView(PetscLimiter lim, PetscViewer v)
157d71ae5a4SJacob Faibussowitsch {
158c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
159c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
1609566063dSJacob Faibussowitsch   if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)lim), &v));
161dbbe0bcdSBarry Smith   PetscTryTypeMethod(lim, view, v);
1623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
163c0ce001eSMatthew G. Knepley }
164c0ce001eSMatthew G. Knepley 
165c0ce001eSMatthew G. Knepley /*@
166dce8aebaSBarry Smith   PetscLimiterSetFromOptions - sets parameters in a `PetscLimiter` from the options database
167c0ce001eSMatthew G. Knepley 
16820f4b53cSBarry Smith   Collective
169c0ce001eSMatthew G. Knepley 
170c0ce001eSMatthew G. Knepley   Input Parameter:
171dce8aebaSBarry Smith . lim - the `PetscLimiter` object to set options for
172c0ce001eSMatthew G. Knepley 
17388f5f89eSMatthew G. Knepley   Level: intermediate
174c0ce001eSMatthew G. Knepley 
175dce8aebaSBarry Smith .seealso: `PetscLimiter`, ``PetscLimiterView()`
176c0ce001eSMatthew G. Knepley @*/
177d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterSetFromOptions(PetscLimiter lim)
178d71ae5a4SJacob Faibussowitsch {
179c0ce001eSMatthew G. Knepley   const char *defaultType;
180c0ce001eSMatthew G. Knepley   char        name[256];
181c0ce001eSMatthew G. Knepley   PetscBool   flg;
182c0ce001eSMatthew G. Knepley 
183c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
184c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
185c0ce001eSMatthew G. Knepley   if (!((PetscObject)lim)->type_name) defaultType = PETSCLIMITERSIN;
186c0ce001eSMatthew G. Knepley   else defaultType = ((PetscObject)lim)->type_name;
1879566063dSJacob Faibussowitsch   PetscCall(PetscLimiterRegisterAll());
188c0ce001eSMatthew G. Knepley 
189d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)lim);
1909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-petsclimiter_type", "Finite volume slope limiter", "PetscLimiterSetType", PetscLimiterList, defaultType, name, 256, &flg));
191c0ce001eSMatthew G. Knepley   if (flg) {
1929566063dSJacob Faibussowitsch     PetscCall(PetscLimiterSetType(lim, name));
193c0ce001eSMatthew G. Knepley   } else if (!((PetscObject)lim)->type_name) {
1949566063dSJacob Faibussowitsch     PetscCall(PetscLimiterSetType(lim, defaultType));
195c0ce001eSMatthew G. Knepley   }
196dbbe0bcdSBarry Smith   PetscTryTypeMethod(lim, setfromoptions);
197c0ce001eSMatthew G. Knepley   /* process any options handlers added with PetscObjectAddOptionsHandler() */
198dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)lim, PetscOptionsObject));
199d0609cedSBarry Smith   PetscOptionsEnd();
2009566063dSJacob Faibussowitsch   PetscCall(PetscLimiterViewFromOptions(lim, NULL, "-petsclimiter_view"));
2013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
202c0ce001eSMatthew G. Knepley }
203c0ce001eSMatthew G. Knepley 
204c0ce001eSMatthew G. Knepley /*@C
205dce8aebaSBarry Smith   PetscLimiterSetUp - Construct data structures for the `PetscLimiter`
206c0ce001eSMatthew G. Knepley 
20720f4b53cSBarry Smith   Collective
208c0ce001eSMatthew G. Knepley 
209c0ce001eSMatthew G. Knepley   Input Parameter:
210dce8aebaSBarry Smith . lim - the `PetscLimiter` object to setup
211c0ce001eSMatthew G. Knepley 
21288f5f89eSMatthew G. Knepley   Level: intermediate
213c0ce001eSMatthew G. Knepley 
214dce8aebaSBarry Smith .seealso: `PetscLimiter`, ``PetscLimiterView()`, `PetscLimiterDestroy()`
215c0ce001eSMatthew G. Knepley @*/
216d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterSetUp(PetscLimiter lim)
217d71ae5a4SJacob Faibussowitsch {
218c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
219c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
220dbbe0bcdSBarry Smith   PetscTryTypeMethod(lim, setup);
2213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
222c0ce001eSMatthew G. Knepley }
223c0ce001eSMatthew G. Knepley 
224c0ce001eSMatthew G. Knepley /*@
225dce8aebaSBarry Smith   PetscLimiterDestroy - Destroys a `PetscLimiter` object
226c0ce001eSMatthew G. Knepley 
22720f4b53cSBarry Smith   Collective
228c0ce001eSMatthew G. Knepley 
229c0ce001eSMatthew G. Knepley   Input Parameter:
230dce8aebaSBarry Smith . lim - the `PetscLimiter` object to destroy
231c0ce001eSMatthew G. Knepley 
23288f5f89eSMatthew G. Knepley   Level: beginner
233c0ce001eSMatthew G. Knepley 
234dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterView()`
235c0ce001eSMatthew G. Knepley @*/
236d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterDestroy(PetscLimiter *lim)
237d71ae5a4SJacob Faibussowitsch {
238c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2393ba16761SJacob Faibussowitsch   if (!*lim) PetscFunctionReturn(PETSC_SUCCESS);
240c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific((*lim), PETSCLIMITER_CLASSID, 1);
241c0ce001eSMatthew G. Knepley 
2429371c9d4SSatish Balay   if (--((PetscObject)(*lim))->refct > 0) {
2439371c9d4SSatish Balay     *lim = NULL;
2443ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2459371c9d4SSatish Balay   }
246c0ce001eSMatthew G. Knepley   ((PetscObject)(*lim))->refct = 0;
247c0ce001eSMatthew G. Knepley 
248dbbe0bcdSBarry Smith   PetscTryTypeMethod((*lim), destroy);
2499566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(lim));
2503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
251c0ce001eSMatthew G. Knepley }
252c0ce001eSMatthew G. Knepley 
253c0ce001eSMatthew G. Knepley /*@
254dce8aebaSBarry Smith   PetscLimiterCreate - Creates an empty `PetscLimiter` object. The type can then be set with `PetscLimiterSetType()`.
255c0ce001eSMatthew G. Knepley 
256c0ce001eSMatthew G. Knepley   Collective
257c0ce001eSMatthew G. Knepley 
258c0ce001eSMatthew G. Knepley   Input Parameter:
259dce8aebaSBarry Smith . comm - The communicator for the `PetscLimiter` object
260c0ce001eSMatthew G. Knepley 
261c0ce001eSMatthew G. Knepley   Output Parameter:
262dce8aebaSBarry Smith . lim - The `PetscLimiter` object
263c0ce001eSMatthew G. Knepley 
264c0ce001eSMatthew G. Knepley   Level: beginner
265c0ce001eSMatthew G. Knepley 
26660225df5SJacob Faibussowitsch .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterSetType()`, `PETSCLIMITERSIN`
267c0ce001eSMatthew G. Knepley @*/
268d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterCreate(MPI_Comm comm, PetscLimiter *lim)
269d71ae5a4SJacob Faibussowitsch {
270c0ce001eSMatthew G. Knepley   PetscLimiter l;
271c0ce001eSMatthew G. Knepley 
272c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2734f572ea9SToby Isaac   PetscAssertPointer(lim, 2);
2749566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(LimiterCitation, &Limitercite));
275c0ce001eSMatthew G. Knepley   *lim = NULL;
2769566063dSJacob Faibussowitsch   PetscCall(PetscFVInitializePackage());
277c0ce001eSMatthew G. Knepley 
2789566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(l, PETSCLIMITER_CLASSID, "PetscLimiter", "Finite Volume Slope Limiter", "PetscLimiter", comm, PetscLimiterDestroy, PetscLimiterView));
279c0ce001eSMatthew G. Knepley 
280c0ce001eSMatthew G. Knepley   *lim = l;
2813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
282c0ce001eSMatthew G. Knepley }
283c0ce001eSMatthew G. Knepley 
28488f5f89eSMatthew G. Knepley /*@
28588f5f89eSMatthew G. Knepley   PetscLimiterLimit - Limit the flux
28688f5f89eSMatthew G. Knepley 
28788f5f89eSMatthew G. Knepley   Input Parameters:
288dce8aebaSBarry Smith + lim  - The `PetscLimiter`
28988f5f89eSMatthew G. Knepley - flim - The input field
29088f5f89eSMatthew G. Knepley 
29188f5f89eSMatthew G. Knepley   Output Parameter:
29288f5f89eSMatthew G. Knepley . phi - The limited field
29388f5f89eSMatthew G. Knepley 
29488f5f89eSMatthew G. Knepley   Level: beginner
29588f5f89eSMatthew G. Knepley 
296dce8aebaSBarry Smith   Note:
297dce8aebaSBarry Smith   Limiters given in symmetric form following Berger, Aftosmis, and Murman 2005
298dce8aebaSBarry Smith .vb
299dce8aebaSBarry Smith  The classical flux-limited formulation is psi(r) where
300dce8aebaSBarry Smith 
301dce8aebaSBarry Smith  r = (u[0] - u[-1]) / (u[1] - u[0])
302dce8aebaSBarry Smith 
303dce8aebaSBarry Smith  The second order TVD region is bounded by
304dce8aebaSBarry Smith 
305dce8aebaSBarry Smith  psi_minmod(r) = min(r,1)      and        psi_superbee(r) = min(2, 2r, max(1,r))
306dce8aebaSBarry Smith 
307dce8aebaSBarry Smith  where all limiters are implicitly clipped to be non-negative. A more convenient slope-limited form is psi(r) =
308dce8aebaSBarry Smith  phi(r)(r+1)/2 in which the reconstructed interface values are
309dce8aebaSBarry Smith 
310dce8aebaSBarry Smith  u(v) = u[0] + phi(r) (grad u)[0] v
311dce8aebaSBarry Smith 
312dce8aebaSBarry Smith  where v is the vector from centroid to quadrature point. In these variables, the usual limiters become
313dce8aebaSBarry Smith 
314dce8aebaSBarry 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))
315dce8aebaSBarry Smith 
316dce8aebaSBarry Smith  For a nicer symmetric formulation, rewrite in terms of
317dce8aebaSBarry Smith 
318dce8aebaSBarry Smith  f = (u[0] - u[-1]) / (u[1] - u[-1])
319dce8aebaSBarry Smith 
320dce8aebaSBarry Smith  where r(f) = f/(1-f). Not that r(1-f) = (1-f)/f = 1/r(f) so the symmetry condition
321dce8aebaSBarry Smith 
322dce8aebaSBarry Smith  phi(r) = phi(1/r)
323dce8aebaSBarry Smith 
324dce8aebaSBarry Smith  becomes
325dce8aebaSBarry Smith 
326dce8aebaSBarry Smith  w(f) = w(1-f).
327dce8aebaSBarry Smith 
328dce8aebaSBarry Smith  The limiters below implement this final form w(f). The reference methods are
329dce8aebaSBarry Smith 
330dce8aebaSBarry Smith  w_minmod(f) = 2 min(f,(1-f))             w_superbee(r) = 4 min((1-f), f)
331dce8aebaSBarry Smith .ve
332dce8aebaSBarry Smith 
333dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterSetType()`, `PetscLimiterCreate()`
33488f5f89eSMatthew G. Knepley @*/
335d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterLimit(PetscLimiter lim, PetscReal flim, PetscReal *phi)
336d71ae5a4SJacob Faibussowitsch {
337c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
338c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
3394f572ea9SToby Isaac   PetscAssertPointer(phi, 3);
340dbbe0bcdSBarry Smith   PetscUseTypeMethod(lim, limit, flim, phi);
3413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
342c0ce001eSMatthew G. Knepley }
343c0ce001eSMatthew G. Knepley 
344d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterDestroy_Sin(PetscLimiter lim)
345d71ae5a4SJacob Faibussowitsch {
346c0ce001eSMatthew G. Knepley   PetscLimiter_Sin *l = (PetscLimiter_Sin *)lim->data;
347c0ce001eSMatthew G. Knepley 
348c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
3499566063dSJacob Faibussowitsch   PetscCall(PetscFree(l));
3503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
351c0ce001eSMatthew G. Knepley }
352c0ce001eSMatthew G. Knepley 
353d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_Sin_Ascii(PetscLimiter lim, PetscViewer viewer)
354d71ae5a4SJacob Faibussowitsch {
355c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
356c0ce001eSMatthew G. Knepley 
357c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
3589566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
3599566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Sin Slope Limiter:\n"));
3603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
361c0ce001eSMatthew G. Knepley }
362c0ce001eSMatthew G. Knepley 
363d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_Sin(PetscLimiter lim, PetscViewer viewer)
364d71ae5a4SJacob Faibussowitsch {
365c0ce001eSMatthew G. Knepley   PetscBool iascii;
366c0ce001eSMatthew G. Knepley 
367c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
368c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
369c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
3709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
3719566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscLimiterView_Sin_Ascii(lim, viewer));
3723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
373c0ce001eSMatthew G. Knepley }
374c0ce001eSMatthew G. Knepley 
375d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterLimit_Sin(PetscLimiter lim, PetscReal f, PetscReal *phi)
376d71ae5a4SJacob Faibussowitsch {
377c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
378c0ce001eSMatthew G. Knepley   *phi = PetscSinReal(PETSC_PI * PetscMax(0, PetscMin(f, 1)));
3793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
380c0ce001eSMatthew G. Knepley }
381c0ce001eSMatthew G. Knepley 
382d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterInitialize_Sin(PetscLimiter lim)
383d71ae5a4SJacob Faibussowitsch {
384c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
385c0ce001eSMatthew G. Knepley   lim->ops->view    = PetscLimiterView_Sin;
386c0ce001eSMatthew G. Knepley   lim->ops->destroy = PetscLimiterDestroy_Sin;
387c0ce001eSMatthew G. Knepley   lim->ops->limit   = PetscLimiterLimit_Sin;
3883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
389c0ce001eSMatthew G. Knepley }
390c0ce001eSMatthew G. Knepley 
391c0ce001eSMatthew G. Knepley /*MC
392dce8aebaSBarry Smith   PETSCLIMITERSIN = "sin" - A `PetscLimiter` implementation
393c0ce001eSMatthew G. Knepley 
394c0ce001eSMatthew G. Knepley   Level: intermediate
395c0ce001eSMatthew G. Knepley 
396dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterCreate()`, `PetscLimiterSetType()`
397c0ce001eSMatthew G. Knepley M*/
398c0ce001eSMatthew G. Knepley 
399d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscLimiterCreate_Sin(PetscLimiter lim)
400d71ae5a4SJacob Faibussowitsch {
401c0ce001eSMatthew G. Knepley   PetscLimiter_Sin *l;
402c0ce001eSMatthew G. Knepley 
403c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
404c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
4054dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&l));
406c0ce001eSMatthew G. Knepley   lim->data = l;
407c0ce001eSMatthew G. Knepley 
4089566063dSJacob Faibussowitsch   PetscCall(PetscLimiterInitialize_Sin(lim));
4093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
410c0ce001eSMatthew G. Knepley }
411c0ce001eSMatthew G. Knepley 
412d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterDestroy_Zero(PetscLimiter lim)
413d71ae5a4SJacob Faibussowitsch {
414c0ce001eSMatthew G. Knepley   PetscLimiter_Zero *l = (PetscLimiter_Zero *)lim->data;
415c0ce001eSMatthew G. Knepley 
416c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
4179566063dSJacob Faibussowitsch   PetscCall(PetscFree(l));
4183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
419c0ce001eSMatthew G. Knepley }
420c0ce001eSMatthew G. Knepley 
421d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_Zero_Ascii(PetscLimiter lim, PetscViewer viewer)
422d71ae5a4SJacob Faibussowitsch {
423c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
424c0ce001eSMatthew G. Knepley 
425c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
4269566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
4279566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Zero Slope Limiter:\n"));
4283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
429c0ce001eSMatthew G. Knepley }
430c0ce001eSMatthew G. Knepley 
431d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_Zero(PetscLimiter lim, PetscViewer viewer)
432d71ae5a4SJacob Faibussowitsch {
433c0ce001eSMatthew G. Knepley   PetscBool iascii;
434c0ce001eSMatthew G. Knepley 
435c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
436c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
437c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
4389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4399566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscLimiterView_Zero_Ascii(lim, viewer));
4403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
441c0ce001eSMatthew G. Knepley }
442c0ce001eSMatthew G. Knepley 
443d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterLimit_Zero(PetscLimiter lim, PetscReal f, PetscReal *phi)
444d71ae5a4SJacob Faibussowitsch {
445c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
446c0ce001eSMatthew G. Knepley   *phi = 0.0;
4473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
448c0ce001eSMatthew G. Knepley }
449c0ce001eSMatthew G. Knepley 
450d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterInitialize_Zero(PetscLimiter lim)
451d71ae5a4SJacob Faibussowitsch {
452c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
453c0ce001eSMatthew G. Knepley   lim->ops->view    = PetscLimiterView_Zero;
454c0ce001eSMatthew G. Knepley   lim->ops->destroy = PetscLimiterDestroy_Zero;
455c0ce001eSMatthew G. Knepley   lim->ops->limit   = PetscLimiterLimit_Zero;
4563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
457c0ce001eSMatthew G. Knepley }
458c0ce001eSMatthew G. Knepley 
459c0ce001eSMatthew G. Knepley /*MC
460dce8aebaSBarry Smith   PETSCLIMITERZERO = "zero" - A simple `PetscLimiter` implementation
461c0ce001eSMatthew G. Knepley 
462c0ce001eSMatthew G. Knepley   Level: intermediate
463c0ce001eSMatthew G. Knepley 
464dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterCreate()`, `PetscLimiterSetType()`
465c0ce001eSMatthew G. Knepley M*/
466c0ce001eSMatthew G. Knepley 
467d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscLimiterCreate_Zero(PetscLimiter lim)
468d71ae5a4SJacob Faibussowitsch {
469c0ce001eSMatthew G. Knepley   PetscLimiter_Zero *l;
470c0ce001eSMatthew G. Knepley 
471c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
472c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
4734dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&l));
474c0ce001eSMatthew G. Knepley   lim->data = l;
475c0ce001eSMatthew G. Knepley 
4769566063dSJacob Faibussowitsch   PetscCall(PetscLimiterInitialize_Zero(lim));
4773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
478c0ce001eSMatthew G. Knepley }
479c0ce001eSMatthew G. Knepley 
480d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterDestroy_None(PetscLimiter lim)
481d71ae5a4SJacob Faibussowitsch {
482c0ce001eSMatthew G. Knepley   PetscLimiter_None *l = (PetscLimiter_None *)lim->data;
483c0ce001eSMatthew G. Knepley 
484c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
4859566063dSJacob Faibussowitsch   PetscCall(PetscFree(l));
4863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
487c0ce001eSMatthew G. Knepley }
488c0ce001eSMatthew G. Knepley 
489d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_None_Ascii(PetscLimiter lim, PetscViewer viewer)
490d71ae5a4SJacob Faibussowitsch {
491c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
492c0ce001eSMatthew G. Knepley 
493c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
4949566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
4959566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "None Slope Limiter:\n"));
4963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
497c0ce001eSMatthew G. Knepley }
498c0ce001eSMatthew G. Knepley 
499d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_None(PetscLimiter lim, PetscViewer viewer)
500d71ae5a4SJacob Faibussowitsch {
501c0ce001eSMatthew G. Knepley   PetscBool iascii;
502c0ce001eSMatthew G. Knepley 
503c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
504c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
505c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
5069566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
5079566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscLimiterView_None_Ascii(lim, viewer));
5083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
509c0ce001eSMatthew G. Knepley }
510c0ce001eSMatthew G. Knepley 
511d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterLimit_None(PetscLimiter lim, PetscReal f, PetscReal *phi)
512d71ae5a4SJacob Faibussowitsch {
513c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
514c0ce001eSMatthew G. Knepley   *phi = 1.0;
5153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
516c0ce001eSMatthew G. Knepley }
517c0ce001eSMatthew G. Knepley 
518d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterInitialize_None(PetscLimiter lim)
519d71ae5a4SJacob Faibussowitsch {
520c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
521c0ce001eSMatthew G. Knepley   lim->ops->view    = PetscLimiterView_None;
522c0ce001eSMatthew G. Knepley   lim->ops->destroy = PetscLimiterDestroy_None;
523c0ce001eSMatthew G. Knepley   lim->ops->limit   = PetscLimiterLimit_None;
5243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
525c0ce001eSMatthew G. Knepley }
526c0ce001eSMatthew G. Knepley 
527c0ce001eSMatthew G. Knepley /*MC
528dce8aebaSBarry Smith   PETSCLIMITERNONE = "none" - A trivial `PetscLimiter` implementation
529c0ce001eSMatthew G. Knepley 
530c0ce001eSMatthew G. Knepley   Level: intermediate
531c0ce001eSMatthew G. Knepley 
532dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterCreate()`, `PetscLimiterSetType()`
533c0ce001eSMatthew G. Knepley M*/
534c0ce001eSMatthew G. Knepley 
535d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscLimiterCreate_None(PetscLimiter lim)
536d71ae5a4SJacob Faibussowitsch {
537c0ce001eSMatthew G. Knepley   PetscLimiter_None *l;
538c0ce001eSMatthew G. Knepley 
539c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
540c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
5414dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&l));
542c0ce001eSMatthew G. Knepley   lim->data = l;
543c0ce001eSMatthew G. Knepley 
5449566063dSJacob Faibussowitsch   PetscCall(PetscLimiterInitialize_None(lim));
5453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
546c0ce001eSMatthew G. Knepley }
547c0ce001eSMatthew G. Knepley 
548d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterDestroy_Minmod(PetscLimiter lim)
549d71ae5a4SJacob Faibussowitsch {
550c0ce001eSMatthew G. Knepley   PetscLimiter_Minmod *l = (PetscLimiter_Minmod *)lim->data;
551c0ce001eSMatthew G. Knepley 
552c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
5539566063dSJacob Faibussowitsch   PetscCall(PetscFree(l));
5543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
555c0ce001eSMatthew G. Knepley }
556c0ce001eSMatthew G. Knepley 
557d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_Minmod_Ascii(PetscLimiter lim, PetscViewer viewer)
558d71ae5a4SJacob Faibussowitsch {
559c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
560c0ce001eSMatthew G. Knepley 
561c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
5629566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
5639566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Minmod Slope Limiter:\n"));
5643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
565c0ce001eSMatthew G. Knepley }
566c0ce001eSMatthew G. Knepley 
567d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_Minmod(PetscLimiter lim, PetscViewer viewer)
568d71ae5a4SJacob Faibussowitsch {
569c0ce001eSMatthew G. Knepley   PetscBool iascii;
570c0ce001eSMatthew G. Knepley 
571c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
572c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
573c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
5749566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
5759566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscLimiterView_Minmod_Ascii(lim, viewer));
5763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
577c0ce001eSMatthew G. Knepley }
578c0ce001eSMatthew G. Knepley 
579d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterLimit_Minmod(PetscLimiter lim, PetscReal f, PetscReal *phi)
580d71ae5a4SJacob Faibussowitsch {
581c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
582c0ce001eSMatthew G. Knepley   *phi = 2 * PetscMax(0, PetscMin(f, 1 - f));
5833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
584c0ce001eSMatthew G. Knepley }
585c0ce001eSMatthew G. Knepley 
586d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterInitialize_Minmod(PetscLimiter lim)
587d71ae5a4SJacob Faibussowitsch {
588c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
589c0ce001eSMatthew G. Knepley   lim->ops->view    = PetscLimiterView_Minmod;
590c0ce001eSMatthew G. Knepley   lim->ops->destroy = PetscLimiterDestroy_Minmod;
591c0ce001eSMatthew G. Knepley   lim->ops->limit   = PetscLimiterLimit_Minmod;
5923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
593c0ce001eSMatthew G. Knepley }
594c0ce001eSMatthew G. Knepley 
595c0ce001eSMatthew G. Knepley /*MC
596dce8aebaSBarry Smith   PETSCLIMITERMINMOD = "minmod" - A `PetscLimiter` implementation
597c0ce001eSMatthew G. Knepley 
598c0ce001eSMatthew G. Knepley   Level: intermediate
599c0ce001eSMatthew G. Knepley 
600dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterCreate()`, `PetscLimiterSetType()`
601c0ce001eSMatthew G. Knepley M*/
602c0ce001eSMatthew G. Knepley 
603d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscLimiterCreate_Minmod(PetscLimiter lim)
604d71ae5a4SJacob Faibussowitsch {
605c0ce001eSMatthew G. Knepley   PetscLimiter_Minmod *l;
606c0ce001eSMatthew G. Knepley 
607c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
608c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
6094dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&l));
610c0ce001eSMatthew G. Knepley   lim->data = l;
611c0ce001eSMatthew G. Knepley 
6129566063dSJacob Faibussowitsch   PetscCall(PetscLimiterInitialize_Minmod(lim));
6133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
614c0ce001eSMatthew G. Knepley }
615c0ce001eSMatthew G. Knepley 
616d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterDestroy_VanLeer(PetscLimiter lim)
617d71ae5a4SJacob Faibussowitsch {
618c0ce001eSMatthew G. Knepley   PetscLimiter_VanLeer *l = (PetscLimiter_VanLeer *)lim->data;
619c0ce001eSMatthew G. Knepley 
620c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
6219566063dSJacob Faibussowitsch   PetscCall(PetscFree(l));
6223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
623c0ce001eSMatthew G. Knepley }
624c0ce001eSMatthew G. Knepley 
625d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_VanLeer_Ascii(PetscLimiter lim, PetscViewer viewer)
626d71ae5a4SJacob Faibussowitsch {
627c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
628c0ce001eSMatthew G. Knepley 
629c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
6309566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6319566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Van Leer Slope Limiter:\n"));
6323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
633c0ce001eSMatthew G. Knepley }
634c0ce001eSMatthew G. Knepley 
635d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_VanLeer(PetscLimiter lim, PetscViewer viewer)
636d71ae5a4SJacob Faibussowitsch {
637c0ce001eSMatthew G. Knepley   PetscBool iascii;
638c0ce001eSMatthew G. Knepley 
639c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
640c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
641c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
6429566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
6439566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscLimiterView_VanLeer_Ascii(lim, viewer));
6443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
645c0ce001eSMatthew G. Knepley }
646c0ce001eSMatthew G. Knepley 
647d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterLimit_VanLeer(PetscLimiter lim, PetscReal f, PetscReal *phi)
648d71ae5a4SJacob Faibussowitsch {
649c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
650c0ce001eSMatthew G. Knepley   *phi = PetscMax(0, 4 * f * (1 - f));
6513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
652c0ce001eSMatthew G. Knepley }
653c0ce001eSMatthew G. Knepley 
654d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterInitialize_VanLeer(PetscLimiter lim)
655d71ae5a4SJacob Faibussowitsch {
656c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
657c0ce001eSMatthew G. Knepley   lim->ops->view    = PetscLimiterView_VanLeer;
658c0ce001eSMatthew G. Knepley   lim->ops->destroy = PetscLimiterDestroy_VanLeer;
659c0ce001eSMatthew G. Knepley   lim->ops->limit   = PetscLimiterLimit_VanLeer;
6603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
661c0ce001eSMatthew G. Knepley }
662c0ce001eSMatthew G. Knepley 
663c0ce001eSMatthew G. Knepley /*MC
664dce8aebaSBarry Smith   PETSCLIMITERVANLEER = "vanleer" - A `PetscLimiter` implementation
665c0ce001eSMatthew G. Knepley 
666c0ce001eSMatthew G. Knepley   Level: intermediate
667c0ce001eSMatthew G. Knepley 
668dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterCreate()`, `PetscLimiterSetType()`
669c0ce001eSMatthew G. Knepley M*/
670c0ce001eSMatthew G. Knepley 
671d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscLimiterCreate_VanLeer(PetscLimiter lim)
672d71ae5a4SJacob Faibussowitsch {
673c0ce001eSMatthew G. Knepley   PetscLimiter_VanLeer *l;
674c0ce001eSMatthew G. Knepley 
675c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
676c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
6774dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&l));
678c0ce001eSMatthew G. Knepley   lim->data = l;
679c0ce001eSMatthew G. Knepley 
6809566063dSJacob Faibussowitsch   PetscCall(PetscLimiterInitialize_VanLeer(lim));
6813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
682c0ce001eSMatthew G. Knepley }
683c0ce001eSMatthew G. Knepley 
684d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterDestroy_VanAlbada(PetscLimiter lim)
685d71ae5a4SJacob Faibussowitsch {
686c0ce001eSMatthew G. Knepley   PetscLimiter_VanAlbada *l = (PetscLimiter_VanAlbada *)lim->data;
687c0ce001eSMatthew G. Knepley 
688c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
6899566063dSJacob Faibussowitsch   PetscCall(PetscFree(l));
6903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
691c0ce001eSMatthew G. Knepley }
692c0ce001eSMatthew G. Knepley 
693d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_VanAlbada_Ascii(PetscLimiter lim, PetscViewer viewer)
694d71ae5a4SJacob Faibussowitsch {
695c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
696c0ce001eSMatthew G. Knepley 
697c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
6989566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6999566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Van Albada Slope Limiter:\n"));
7003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
701c0ce001eSMatthew G. Knepley }
702c0ce001eSMatthew G. Knepley 
703d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_VanAlbada(PetscLimiter lim, PetscViewer viewer)
704d71ae5a4SJacob Faibussowitsch {
705c0ce001eSMatthew G. Knepley   PetscBool iascii;
706c0ce001eSMatthew G. Knepley 
707c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
708c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
709c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
7109566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
7119566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscLimiterView_VanAlbada_Ascii(lim, viewer));
7123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
713c0ce001eSMatthew G. Knepley }
714c0ce001eSMatthew G. Knepley 
715d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterLimit_VanAlbada(PetscLimiter lim, PetscReal f, PetscReal *phi)
716d71ae5a4SJacob Faibussowitsch {
717c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
718c0ce001eSMatthew G. Knepley   *phi = PetscMax(0, 2 * f * (1 - f) / (PetscSqr(f) + PetscSqr(1 - f)));
7193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
720c0ce001eSMatthew G. Knepley }
721c0ce001eSMatthew G. Knepley 
722d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterInitialize_VanAlbada(PetscLimiter lim)
723d71ae5a4SJacob Faibussowitsch {
724c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
725c0ce001eSMatthew G. Knepley   lim->ops->view    = PetscLimiterView_VanAlbada;
726c0ce001eSMatthew G. Knepley   lim->ops->destroy = PetscLimiterDestroy_VanAlbada;
727c0ce001eSMatthew G. Knepley   lim->ops->limit   = PetscLimiterLimit_VanAlbada;
7283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
729c0ce001eSMatthew G. Knepley }
730c0ce001eSMatthew G. Knepley 
731c0ce001eSMatthew G. Knepley /*MC
732dce8aebaSBarry Smith   PETSCLIMITERVANALBADA = "vanalbada" - A PetscLimiter implementation
733c0ce001eSMatthew G. Knepley 
734c0ce001eSMatthew G. Knepley   Level: intermediate
735c0ce001eSMatthew G. Knepley 
736dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterCreate()`, `PetscLimiterSetType()`
737c0ce001eSMatthew G. Knepley M*/
738c0ce001eSMatthew G. Knepley 
739d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscLimiterCreate_VanAlbada(PetscLimiter lim)
740d71ae5a4SJacob Faibussowitsch {
741c0ce001eSMatthew G. Knepley   PetscLimiter_VanAlbada *l;
742c0ce001eSMatthew G. Knepley 
743c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
744c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
7454dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&l));
746c0ce001eSMatthew G. Knepley   lim->data = l;
747c0ce001eSMatthew G. Knepley 
7489566063dSJacob Faibussowitsch   PetscCall(PetscLimiterInitialize_VanAlbada(lim));
7493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
750c0ce001eSMatthew G. Knepley }
751c0ce001eSMatthew G. Knepley 
752d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterDestroy_Superbee(PetscLimiter lim)
753d71ae5a4SJacob Faibussowitsch {
754c0ce001eSMatthew G. Knepley   PetscLimiter_Superbee *l = (PetscLimiter_Superbee *)lim->data;
755c0ce001eSMatthew G. Knepley 
756c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
7579566063dSJacob Faibussowitsch   PetscCall(PetscFree(l));
7583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
759c0ce001eSMatthew G. Knepley }
760c0ce001eSMatthew G. Knepley 
761d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_Superbee_Ascii(PetscLimiter lim, PetscViewer viewer)
762d71ae5a4SJacob Faibussowitsch {
763c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
764c0ce001eSMatthew G. Knepley 
765c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
7669566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
7679566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Superbee Slope Limiter:\n"));
7683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
769c0ce001eSMatthew G. Knepley }
770c0ce001eSMatthew G. Knepley 
771d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_Superbee(PetscLimiter lim, PetscViewer viewer)
772d71ae5a4SJacob Faibussowitsch {
773c0ce001eSMatthew G. Knepley   PetscBool iascii;
774c0ce001eSMatthew G. Knepley 
775c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
776c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
777c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
7789566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
7799566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscLimiterView_Superbee_Ascii(lim, viewer));
7803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
781c0ce001eSMatthew G. Knepley }
782c0ce001eSMatthew G. Knepley 
783d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterLimit_Superbee(PetscLimiter lim, PetscReal f, PetscReal *phi)
784d71ae5a4SJacob Faibussowitsch {
785c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
786c0ce001eSMatthew G. Knepley   *phi = 4 * PetscMax(0, PetscMin(f, 1 - f));
7873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
788c0ce001eSMatthew G. Knepley }
789c0ce001eSMatthew G. Knepley 
790d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterInitialize_Superbee(PetscLimiter lim)
791d71ae5a4SJacob Faibussowitsch {
792c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
793c0ce001eSMatthew G. Knepley   lim->ops->view    = PetscLimiterView_Superbee;
794c0ce001eSMatthew G. Knepley   lim->ops->destroy = PetscLimiterDestroy_Superbee;
795c0ce001eSMatthew G. Knepley   lim->ops->limit   = PetscLimiterLimit_Superbee;
7963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
797c0ce001eSMatthew G. Knepley }
798c0ce001eSMatthew G. Knepley 
799c0ce001eSMatthew G. Knepley /*MC
800dce8aebaSBarry Smith   PETSCLIMITERSUPERBEE = "superbee" - A `PetscLimiter` implementation
801c0ce001eSMatthew G. Knepley 
802c0ce001eSMatthew G. Knepley   Level: intermediate
803c0ce001eSMatthew G. Knepley 
804dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterCreate()`, `PetscLimiterSetType()`
805c0ce001eSMatthew G. Knepley M*/
806c0ce001eSMatthew G. Knepley 
807d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscLimiterCreate_Superbee(PetscLimiter lim)
808d71ae5a4SJacob Faibussowitsch {
809c0ce001eSMatthew G. Knepley   PetscLimiter_Superbee *l;
810c0ce001eSMatthew G. Knepley 
811c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
812c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
8134dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&l));
814c0ce001eSMatthew G. Knepley   lim->data = l;
815c0ce001eSMatthew G. Knepley 
8169566063dSJacob Faibussowitsch   PetscCall(PetscLimiterInitialize_Superbee(lim));
8173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
818c0ce001eSMatthew G. Knepley }
819c0ce001eSMatthew G. Knepley 
820d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterDestroy_MC(PetscLimiter lim)
821d71ae5a4SJacob Faibussowitsch {
822c0ce001eSMatthew G. Knepley   PetscLimiter_MC *l = (PetscLimiter_MC *)lim->data;
823c0ce001eSMatthew G. Knepley 
824c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
8259566063dSJacob Faibussowitsch   PetscCall(PetscFree(l));
8263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
827c0ce001eSMatthew G. Knepley }
828c0ce001eSMatthew G. Knepley 
829d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_MC_Ascii(PetscLimiter lim, PetscViewer viewer)
830d71ae5a4SJacob Faibussowitsch {
831c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
832c0ce001eSMatthew G. Knepley 
833c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
8349566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
8359566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "MC Slope Limiter:\n"));
8363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
837c0ce001eSMatthew G. Knepley }
838c0ce001eSMatthew G. Knepley 
839d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterView_MC(PetscLimiter lim, PetscViewer viewer)
840d71ae5a4SJacob Faibussowitsch {
841c0ce001eSMatthew G. Knepley   PetscBool iascii;
842c0ce001eSMatthew G. Knepley 
843c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
844c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
845c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
8469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
8479566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscLimiterView_MC_Ascii(lim, viewer));
8483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
849c0ce001eSMatthew G. Knepley }
850c0ce001eSMatthew G. Knepley 
851c0ce001eSMatthew G. Knepley /* aka Barth-Jespersen */
852d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterLimit_MC(PetscLimiter lim, PetscReal f, PetscReal *phi)
853d71ae5a4SJacob Faibussowitsch {
854c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
855c0ce001eSMatthew G. Knepley   *phi = PetscMin(1, 4 * PetscMax(0, PetscMin(f, 1 - f)));
8563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
857c0ce001eSMatthew G. Knepley }
858c0ce001eSMatthew G. Knepley 
859d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLimiterInitialize_MC(PetscLimiter lim)
860d71ae5a4SJacob Faibussowitsch {
861c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
862c0ce001eSMatthew G. Knepley   lim->ops->view    = PetscLimiterView_MC;
863c0ce001eSMatthew G. Knepley   lim->ops->destroy = PetscLimiterDestroy_MC;
864c0ce001eSMatthew G. Knepley   lim->ops->limit   = PetscLimiterLimit_MC;
8653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
866c0ce001eSMatthew G. Knepley }
867c0ce001eSMatthew G. Knepley 
868c0ce001eSMatthew G. Knepley /*MC
869dce8aebaSBarry Smith   PETSCLIMITERMC = "mc" - A `PetscLimiter` implementation
870c0ce001eSMatthew G. Knepley 
871c0ce001eSMatthew G. Knepley   Level: intermediate
872c0ce001eSMatthew G. Knepley 
873dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterType`, `PetscLimiterCreate()`, `PetscLimiterSetType()`
874c0ce001eSMatthew G. Knepley M*/
875c0ce001eSMatthew G. Knepley 
876d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscLimiterCreate_MC(PetscLimiter lim)
877d71ae5a4SJacob Faibussowitsch {
878c0ce001eSMatthew G. Knepley   PetscLimiter_MC *l;
879c0ce001eSMatthew G. Knepley 
880c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
881c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 1);
8824dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&l));
883c0ce001eSMatthew G. Knepley   lim->data = l;
884c0ce001eSMatthew G. Knepley 
8859566063dSJacob Faibussowitsch   PetscCall(PetscLimiterInitialize_MC(lim));
8863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
887c0ce001eSMatthew G. Knepley }
888c0ce001eSMatthew G. Knepley 
889c0ce001eSMatthew G. Knepley PetscClassId PETSCFV_CLASSID = 0;
890c0ce001eSMatthew G. Knepley 
891c0ce001eSMatthew G. Knepley PetscFunctionList PetscFVList              = NULL;
892c0ce001eSMatthew G. Knepley PetscBool         PetscFVRegisterAllCalled = PETSC_FALSE;
893c0ce001eSMatthew G. Knepley 
894c0ce001eSMatthew G. Knepley /*@C
895dce8aebaSBarry Smith   PetscFVRegister - Adds a new `PetscFV` implementation
896c0ce001eSMatthew G. Knepley 
897c0ce001eSMatthew G. Knepley   Not Collective
898c0ce001eSMatthew G. Knepley 
899c0ce001eSMatthew G. Knepley   Input Parameters:
9002fe279fdSBarry Smith + sname    - The name of a new user-defined creation routine
9012fe279fdSBarry Smith - function - The creation routine itself
902c0ce001eSMatthew G. Knepley 
90360225df5SJacob Faibussowitsch   Example Usage:
904c0ce001eSMatthew G. Knepley .vb
905c0ce001eSMatthew G. Knepley     PetscFVRegister("my_fv", MyPetscFVCreate);
906c0ce001eSMatthew G. Knepley .ve
907c0ce001eSMatthew G. Knepley 
908c0ce001eSMatthew G. Knepley   Then, your PetscFV type can be chosen with the procedural interface via
909c0ce001eSMatthew G. Knepley .vb
910c0ce001eSMatthew G. Knepley     PetscFVCreate(MPI_Comm, PetscFV *);
911c0ce001eSMatthew G. Knepley     PetscFVSetType(PetscFV, "my_fv");
912c0ce001eSMatthew G. Knepley .ve
913c0ce001eSMatthew G. Knepley   or at runtime via the option
914c0ce001eSMatthew G. Knepley .vb
915c0ce001eSMatthew G. Knepley     -petscfv_type my_fv
916c0ce001eSMatthew G. Knepley .ve
917c0ce001eSMatthew G. Knepley 
918c0ce001eSMatthew G. Knepley   Level: advanced
919c0ce001eSMatthew G. Knepley 
920dce8aebaSBarry Smith   Note:
921dce8aebaSBarry Smith   `PetscFVRegister()` may be called multiple times to add several user-defined PetscFVs
922c0ce001eSMatthew G. Knepley 
923dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVRegisterAll()`, `PetscFVRegisterDestroy()`
924c0ce001eSMatthew G. Knepley @*/
925d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVRegister(const char sname[], PetscErrorCode (*function)(PetscFV))
926d71ae5a4SJacob Faibussowitsch {
927c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
9289566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&PetscFVList, sname, function));
9293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
930c0ce001eSMatthew G. Knepley }
931c0ce001eSMatthew G. Knepley 
932c0ce001eSMatthew G. Knepley /*@C
933dce8aebaSBarry Smith   PetscFVSetType - Builds a particular `PetscFV`
934c0ce001eSMatthew G. Knepley 
93520f4b53cSBarry Smith   Collective
936c0ce001eSMatthew G. Knepley 
937c0ce001eSMatthew G. Knepley   Input Parameters:
938dce8aebaSBarry Smith + fvm  - The `PetscFV` object
939dce8aebaSBarry Smith - name - The type of FVM space
940c0ce001eSMatthew G. Knepley 
941c0ce001eSMatthew G. Knepley   Options Database Key:
942dce8aebaSBarry Smith . -petscfv_type <type> - Sets the `PetscFVType`; use -help for a list of available types
943c0ce001eSMatthew G. Knepley 
944c0ce001eSMatthew G. Knepley   Level: intermediate
945c0ce001eSMatthew G. Knepley 
946dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVGetType()`, `PetscFVCreate()`
947c0ce001eSMatthew G. Knepley @*/
948d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetType(PetscFV fvm, PetscFVType name)
949d71ae5a4SJacob Faibussowitsch {
950c0ce001eSMatthew G. Knepley   PetscErrorCode (*r)(PetscFV);
951c0ce001eSMatthew G. Knepley   PetscBool match;
952c0ce001eSMatthew G. Knepley 
953c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
954c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
9559566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)fvm, name, &match));
9563ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
957c0ce001eSMatthew G. Knepley 
9589566063dSJacob Faibussowitsch   PetscCall(PetscFVRegisterAll());
9599566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(PetscFVList, name, &r));
96028b400f6SJacob Faibussowitsch   PetscCheck(r, PetscObjectComm((PetscObject)fvm), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscFV type: %s", name);
961c0ce001eSMatthew G. Knepley 
962dbbe0bcdSBarry Smith   PetscTryTypeMethod(fvm, destroy);
963c0ce001eSMatthew G. Knepley   fvm->ops->destroy = NULL;
964dbbe0bcdSBarry Smith 
9659566063dSJacob Faibussowitsch   PetscCall((*r)(fvm));
9669566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)fvm, name));
9673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
968c0ce001eSMatthew G. Knepley }
969c0ce001eSMatthew G. Knepley 
970c0ce001eSMatthew G. Knepley /*@C
971dce8aebaSBarry Smith   PetscFVGetType - Gets the `PetscFVType` (as a string) from a `PetscFV`.
972c0ce001eSMatthew G. Knepley 
973c0ce001eSMatthew G. Knepley   Not Collective
974c0ce001eSMatthew G. Knepley 
975c0ce001eSMatthew G. Knepley   Input Parameter:
976dce8aebaSBarry Smith . fvm - The `PetscFV`
977c0ce001eSMatthew G. Knepley 
978c0ce001eSMatthew G. Knepley   Output Parameter:
979dce8aebaSBarry Smith . name - The `PetscFVType` name
980c0ce001eSMatthew G. Knepley 
981c0ce001eSMatthew G. Knepley   Level: intermediate
982c0ce001eSMatthew G. Knepley 
983dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVSetType()`, `PetscFVCreate()`
984c0ce001eSMatthew G. Knepley @*/
985d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetType(PetscFV fvm, PetscFVType *name)
986d71ae5a4SJacob Faibussowitsch {
987c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
988c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
9894f572ea9SToby Isaac   PetscAssertPointer(name, 2);
9909566063dSJacob Faibussowitsch   PetscCall(PetscFVRegisterAll());
991c0ce001eSMatthew G. Knepley   *name = ((PetscObject)fvm)->type_name;
9923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
993c0ce001eSMatthew G. Knepley }
994c0ce001eSMatthew G. Knepley 
995c0ce001eSMatthew G. Knepley /*@C
996dce8aebaSBarry Smith   PetscFVViewFromOptions - View a `PetscFV` based on values in the options database
997fe2efc57SMark 
99820f4b53cSBarry Smith   Collective
999fe2efc57SMark 
1000fe2efc57SMark   Input Parameters:
1001dce8aebaSBarry Smith + A    - the `PetscFV` object
1002dce8aebaSBarry Smith . obj  - Optional object that provides the options prefix
1003dce8aebaSBarry Smith - name - command line option name
1004fe2efc57SMark 
1005fe2efc57SMark   Level: intermediate
1006dce8aebaSBarry Smith 
1007dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVView()`, `PetscObjectViewFromOptions()`, `PetscFVCreate()`
1008fe2efc57SMark @*/
1009d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVViewFromOptions(PetscFV A, PetscObject obj, const char name[])
1010d71ae5a4SJacob Faibussowitsch {
1011fe2efc57SMark   PetscFunctionBegin;
1012fe2efc57SMark   PetscValidHeaderSpecific(A, PETSCFV_CLASSID, 1);
10139566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
10143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1015fe2efc57SMark }
1016fe2efc57SMark 
1017fe2efc57SMark /*@C
1018dce8aebaSBarry Smith   PetscFVView - Views a `PetscFV`
1019c0ce001eSMatthew G. Knepley 
102020f4b53cSBarry Smith   Collective
1021c0ce001eSMatthew G. Knepley 
1022d8d19677SJose E. Roman   Input Parameters:
1023dce8aebaSBarry Smith + fvm - the `PetscFV` object to view
1024c0ce001eSMatthew G. Knepley - v   - the viewer
1025c0ce001eSMatthew G. Knepley 
102688f5f89eSMatthew G. Knepley   Level: beginner
1027c0ce001eSMatthew G. Knepley 
1028dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscViewer`, `PetscFVDestroy()`
1029c0ce001eSMatthew G. Knepley @*/
1030d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVView(PetscFV fvm, PetscViewer v)
1031d71ae5a4SJacob Faibussowitsch {
1032c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1033c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
10349566063dSJacob Faibussowitsch   if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)fvm), &v));
1035dbbe0bcdSBarry Smith   PetscTryTypeMethod(fvm, view, v);
10363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1037c0ce001eSMatthew G. Knepley }
1038c0ce001eSMatthew G. Knepley 
1039c0ce001eSMatthew G. Knepley /*@
1040dce8aebaSBarry Smith   PetscFVSetFromOptions - sets parameters in a `PetscFV` from the options database
1041c0ce001eSMatthew G. Knepley 
104220f4b53cSBarry Smith   Collective
1043c0ce001eSMatthew G. Knepley 
1044c0ce001eSMatthew G. Knepley   Input Parameter:
1045dce8aebaSBarry Smith . fvm - the `PetscFV` object to set options for
1046c0ce001eSMatthew G. Knepley 
1047c0ce001eSMatthew G. Knepley   Options Database Key:
1048c0ce001eSMatthew G. Knepley . -petscfv_compute_gradients <bool> - Determines whether cell gradients are calculated
1049c0ce001eSMatthew G. Knepley 
105088f5f89eSMatthew G. Knepley   Level: intermediate
1051c0ce001eSMatthew G. Knepley 
1052dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVView()`
1053c0ce001eSMatthew G. Knepley @*/
1054d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetFromOptions(PetscFV fvm)
1055d71ae5a4SJacob Faibussowitsch {
1056c0ce001eSMatthew G. Knepley   const char *defaultType;
1057c0ce001eSMatthew G. Knepley   char        name[256];
1058c0ce001eSMatthew G. Knepley   PetscBool   flg;
1059c0ce001eSMatthew G. Knepley 
1060c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1061c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1062c0ce001eSMatthew G. Knepley   if (!((PetscObject)fvm)->type_name) defaultType = PETSCFVUPWIND;
1063c0ce001eSMatthew G. Knepley   else defaultType = ((PetscObject)fvm)->type_name;
10649566063dSJacob Faibussowitsch   PetscCall(PetscFVRegisterAll());
1065c0ce001eSMatthew G. Knepley 
1066d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)fvm);
10679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-petscfv_type", "Finite volume discretization", "PetscFVSetType", PetscFVList, defaultType, name, 256, &flg));
1068c0ce001eSMatthew G. Knepley   if (flg) {
10699566063dSJacob Faibussowitsch     PetscCall(PetscFVSetType(fvm, name));
1070c0ce001eSMatthew G. Knepley   } else if (!((PetscObject)fvm)->type_name) {
10719566063dSJacob Faibussowitsch     PetscCall(PetscFVSetType(fvm, defaultType));
1072c0ce001eSMatthew G. Knepley   }
10739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-petscfv_compute_gradients", "Compute cell gradients", "PetscFVSetComputeGradients", fvm->computeGradients, &fvm->computeGradients, NULL));
1074dbbe0bcdSBarry Smith   PetscTryTypeMethod(fvm, setfromoptions);
1075c0ce001eSMatthew G. Knepley   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1076dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)fvm, PetscOptionsObject));
10779566063dSJacob Faibussowitsch   PetscCall(PetscLimiterSetFromOptions(fvm->limiter));
1078d0609cedSBarry Smith   PetscOptionsEnd();
10799566063dSJacob Faibussowitsch   PetscCall(PetscFVViewFromOptions(fvm, NULL, "-petscfv_view"));
10803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1081c0ce001eSMatthew G. Knepley }
1082c0ce001eSMatthew G. Knepley 
1083c0ce001eSMatthew G. Knepley /*@
1084dce8aebaSBarry Smith   PetscFVSetUp - Setup the data structures for the `PetscFV` based on the `PetscFVType` provided by `PetscFVSetType()`
1085c0ce001eSMatthew G. Knepley 
108620f4b53cSBarry Smith   Collective
1087c0ce001eSMatthew G. Knepley 
1088c0ce001eSMatthew G. Knepley   Input Parameter:
1089dce8aebaSBarry Smith . fvm - the `PetscFV` object to setup
1090c0ce001eSMatthew G. Knepley 
109188f5f89eSMatthew G. Knepley   Level: intermediate
1092c0ce001eSMatthew G. Knepley 
1093dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVView()`, `PetscFVDestroy()`
1094c0ce001eSMatthew G. Knepley @*/
1095d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetUp(PetscFV fvm)
1096d71ae5a4SJacob Faibussowitsch {
1097c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1098c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
10999566063dSJacob Faibussowitsch   PetscCall(PetscLimiterSetUp(fvm->limiter));
1100dbbe0bcdSBarry Smith   PetscTryTypeMethod(fvm, setup);
11013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1102c0ce001eSMatthew G. Knepley }
1103c0ce001eSMatthew G. Knepley 
1104c0ce001eSMatthew G. Knepley /*@
1105dce8aebaSBarry Smith   PetscFVDestroy - Destroys a `PetscFV` object
1106c0ce001eSMatthew G. Knepley 
110720f4b53cSBarry Smith   Collective
1108c0ce001eSMatthew G. Knepley 
1109c0ce001eSMatthew G. Knepley   Input Parameter:
1110dce8aebaSBarry Smith . fvm - the `PetscFV` object to destroy
1111c0ce001eSMatthew G. Knepley 
111288f5f89eSMatthew G. Knepley   Level: beginner
1113c0ce001eSMatthew G. Knepley 
1114dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVCreate()`, `PetscFVView()`
1115c0ce001eSMatthew G. Knepley @*/
1116d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVDestroy(PetscFV *fvm)
1117d71ae5a4SJacob Faibussowitsch {
1118c0ce001eSMatthew G. Knepley   PetscInt i;
1119c0ce001eSMatthew G. Knepley 
1120c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
11213ba16761SJacob Faibussowitsch   if (!*fvm) PetscFunctionReturn(PETSC_SUCCESS);
1122c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific((*fvm), PETSCFV_CLASSID, 1);
1123c0ce001eSMatthew G. Knepley 
11249371c9d4SSatish Balay   if (--((PetscObject)(*fvm))->refct > 0) {
11259371c9d4SSatish Balay     *fvm = NULL;
11263ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
11279371c9d4SSatish Balay   }
1128c0ce001eSMatthew G. Knepley   ((PetscObject)(*fvm))->refct = 0;
1129c0ce001eSMatthew G. Knepley 
113048a46eb9SPierre Jolivet   for (i = 0; i < (*fvm)->numComponents; i++) PetscCall(PetscFree((*fvm)->componentNames[i]));
11319566063dSJacob Faibussowitsch   PetscCall(PetscFree((*fvm)->componentNames));
11329566063dSJacob Faibussowitsch   PetscCall(PetscLimiterDestroy(&(*fvm)->limiter));
11339566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDestroy(&(*fvm)->dualSpace));
11349566063dSJacob Faibussowitsch   PetscCall(PetscFree((*fvm)->fluxWork));
11359566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&(*fvm)->quadrature));
11369566063dSJacob Faibussowitsch   PetscCall(PetscTabulationDestroy(&(*fvm)->T));
1137c0ce001eSMatthew G. Knepley 
1138dbbe0bcdSBarry Smith   PetscTryTypeMethod((*fvm), destroy);
11399566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(fvm));
11403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1141c0ce001eSMatthew G. Knepley }
1142c0ce001eSMatthew G. Knepley 
1143c0ce001eSMatthew G. Knepley /*@
1144dce8aebaSBarry Smith   PetscFVCreate - Creates an empty `PetscFV` object. The type can then be set with `PetscFVSetType()`.
1145c0ce001eSMatthew G. Knepley 
1146c0ce001eSMatthew G. Knepley   Collective
1147c0ce001eSMatthew G. Knepley 
1148c0ce001eSMatthew G. Knepley   Input Parameter:
1149dce8aebaSBarry Smith . comm - The communicator for the `PetscFV` object
1150c0ce001eSMatthew G. Knepley 
1151c0ce001eSMatthew G. Knepley   Output Parameter:
1152dce8aebaSBarry Smith . fvm - The `PetscFV` object
1153c0ce001eSMatthew G. Knepley 
1154c0ce001eSMatthew G. Knepley   Level: beginner
1155c0ce001eSMatthew G. Knepley 
1156*1d27aa22SBarry Smith .seealso: `PetscFVSetUp()`, `PetscFVSetType()`, `PETSCFVUPWIND`, `PetscFVDestroy()`
1157c0ce001eSMatthew G. Knepley @*/
1158d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVCreate(MPI_Comm comm, PetscFV *fvm)
1159d71ae5a4SJacob Faibussowitsch {
1160c0ce001eSMatthew G. Knepley   PetscFV f;
1161c0ce001eSMatthew G. Knepley 
1162c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
11634f572ea9SToby Isaac   PetscAssertPointer(fvm, 2);
1164c0ce001eSMatthew G. Knepley   *fvm = NULL;
11659566063dSJacob Faibussowitsch   PetscCall(PetscFVInitializePackage());
1166c0ce001eSMatthew G. Knepley 
11679566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(f, PETSCFV_CLASSID, "PetscFV", "Finite Volume", "PetscFV", comm, PetscFVDestroy, PetscFVView));
11689566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(f->ops, sizeof(struct _PetscFVOps)));
1169c0ce001eSMatthew G. Knepley 
11709566063dSJacob Faibussowitsch   PetscCall(PetscLimiterCreate(comm, &f->limiter));
1171c0ce001eSMatthew G. Knepley   f->numComponents    = 1;
1172c0ce001eSMatthew G. Knepley   f->dim              = 0;
1173c0ce001eSMatthew G. Knepley   f->computeGradients = PETSC_FALSE;
1174c0ce001eSMatthew G. Knepley   f->fluxWork         = NULL;
11759566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(f->numComponents, &f->componentNames));
1176c0ce001eSMatthew G. Knepley 
1177c0ce001eSMatthew G. Knepley   *fvm = f;
11783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1179c0ce001eSMatthew G. Knepley }
1180c0ce001eSMatthew G. Knepley 
1181c0ce001eSMatthew G. Knepley /*@
1182dce8aebaSBarry Smith   PetscFVSetLimiter - Set the `PetscLimiter` to the `PetscFV`
1183c0ce001eSMatthew G. Knepley 
118420f4b53cSBarry Smith   Logically Collective
1185c0ce001eSMatthew G. Knepley 
1186c0ce001eSMatthew G. Knepley   Input Parameters:
1187dce8aebaSBarry Smith + fvm - the `PetscFV` object
1188dce8aebaSBarry Smith - lim - The `PetscLimiter`
1189c0ce001eSMatthew G. Knepley 
119088f5f89eSMatthew G. Knepley   Level: intermediate
1191c0ce001eSMatthew G. Knepley 
1192dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscLimiter`, `PetscFVGetLimiter()`
1193c0ce001eSMatthew G. Knepley @*/
1194d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetLimiter(PetscFV fvm, PetscLimiter lim)
1195d71ae5a4SJacob Faibussowitsch {
1196c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1197c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1198c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(lim, PETSCLIMITER_CLASSID, 2);
11999566063dSJacob Faibussowitsch   PetscCall(PetscLimiterDestroy(&fvm->limiter));
12009566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)lim));
1201c0ce001eSMatthew G. Knepley   fvm->limiter = lim;
12023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1203c0ce001eSMatthew G. Knepley }
1204c0ce001eSMatthew G. Knepley 
1205c0ce001eSMatthew G. Knepley /*@
1206dce8aebaSBarry Smith   PetscFVGetLimiter - Get the `PetscLimiter` object from the `PetscFV`
1207c0ce001eSMatthew G. Knepley 
120820f4b53cSBarry Smith   Not Collective
1209c0ce001eSMatthew G. Knepley 
1210c0ce001eSMatthew G. Knepley   Input Parameter:
1211dce8aebaSBarry Smith . fvm - the `PetscFV` object
1212c0ce001eSMatthew G. Knepley 
1213c0ce001eSMatthew G. Knepley   Output Parameter:
1214dce8aebaSBarry Smith . lim - The `PetscLimiter`
1215c0ce001eSMatthew G. Knepley 
121688f5f89eSMatthew G. Knepley   Level: intermediate
1217c0ce001eSMatthew G. Knepley 
1218dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscLimiter`, `PetscFVSetLimiter()`
1219c0ce001eSMatthew G. Knepley @*/
1220d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetLimiter(PetscFV fvm, PetscLimiter *lim)
1221d71ae5a4SJacob Faibussowitsch {
1222c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1223c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
12244f572ea9SToby Isaac   PetscAssertPointer(lim, 2);
1225c0ce001eSMatthew G. Knepley   *lim = fvm->limiter;
12263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1227c0ce001eSMatthew G. Knepley }
1228c0ce001eSMatthew G. Knepley 
1229c0ce001eSMatthew G. Knepley /*@
1230dce8aebaSBarry Smith   PetscFVSetNumComponents - Set the number of field components in a `PetscFV`
1231c0ce001eSMatthew G. Knepley 
123220f4b53cSBarry Smith   Logically Collective
1233c0ce001eSMatthew G. Knepley 
1234c0ce001eSMatthew G. Knepley   Input Parameters:
1235dce8aebaSBarry Smith + fvm  - the `PetscFV` object
1236c0ce001eSMatthew G. Knepley - comp - The number of components
1237c0ce001eSMatthew G. Knepley 
123888f5f89eSMatthew G. Knepley   Level: intermediate
1239c0ce001eSMatthew G. Knepley 
1240dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVGetNumComponents()`
1241c0ce001eSMatthew G. Knepley @*/
1242d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetNumComponents(PetscFV fvm, PetscInt comp)
1243d71ae5a4SJacob Faibussowitsch {
1244c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1245c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1246c0ce001eSMatthew G. Knepley   if (fvm->numComponents != comp) {
1247c0ce001eSMatthew G. Knepley     PetscInt i;
1248c0ce001eSMatthew G. Knepley 
124948a46eb9SPierre Jolivet     for (i = 0; i < fvm->numComponents; i++) PetscCall(PetscFree(fvm->componentNames[i]));
12509566063dSJacob Faibussowitsch     PetscCall(PetscFree(fvm->componentNames));
12519566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(comp, &fvm->componentNames));
1252c0ce001eSMatthew G. Knepley   }
1253c0ce001eSMatthew G. Knepley   fvm->numComponents = comp;
12549566063dSJacob Faibussowitsch   PetscCall(PetscFree(fvm->fluxWork));
12559566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(comp, &fvm->fluxWork));
12563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1257c0ce001eSMatthew G. Knepley }
1258c0ce001eSMatthew G. Knepley 
1259c0ce001eSMatthew G. Knepley /*@
1260dce8aebaSBarry Smith   PetscFVGetNumComponents - Get the number of field components in a `PetscFV`
1261c0ce001eSMatthew G. Knepley 
126220f4b53cSBarry Smith   Not Collective
1263c0ce001eSMatthew G. Knepley 
1264c0ce001eSMatthew G. Knepley   Input Parameter:
1265dce8aebaSBarry Smith . fvm - the `PetscFV` object
1266c0ce001eSMatthew G. Knepley 
1267c0ce001eSMatthew G. Knepley   Output Parameter:
1268a4e35b19SJacob Faibussowitsch . comp - The number of components
1269c0ce001eSMatthew G. Knepley 
127088f5f89eSMatthew G. Knepley   Level: intermediate
1271c0ce001eSMatthew G. Knepley 
1272dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVSetNumComponents()`, `PetscFVSetComponentName()`
1273c0ce001eSMatthew G. Knepley @*/
1274d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetNumComponents(PetscFV fvm, PetscInt *comp)
1275d71ae5a4SJacob Faibussowitsch {
1276c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1277c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
12784f572ea9SToby Isaac   PetscAssertPointer(comp, 2);
1279c0ce001eSMatthew G. Knepley   *comp = fvm->numComponents;
12803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1281c0ce001eSMatthew G. Knepley }
1282c0ce001eSMatthew G. Knepley 
1283c0ce001eSMatthew G. Knepley /*@C
1284dce8aebaSBarry Smith   PetscFVSetComponentName - Set the name of a component (used in output and viewing) in a `PetscFV`
1285c0ce001eSMatthew G. Knepley 
128620f4b53cSBarry Smith   Logically Collective
1287dce8aebaSBarry Smith 
1288c0ce001eSMatthew G. Knepley   Input Parameters:
1289dce8aebaSBarry Smith + fvm  - the `PetscFV` object
1290c0ce001eSMatthew G. Knepley . comp - the component number
1291c0ce001eSMatthew G. Knepley - name - the component name
1292c0ce001eSMatthew G. Knepley 
129388f5f89eSMatthew G. Knepley   Level: intermediate
1294c0ce001eSMatthew G. Knepley 
1295dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVGetComponentName()`
1296c0ce001eSMatthew G. Knepley @*/
1297d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetComponentName(PetscFV fvm, PetscInt comp, const char *name)
1298d71ae5a4SJacob Faibussowitsch {
1299c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
13009566063dSJacob Faibussowitsch   PetscCall(PetscFree(fvm->componentNames[comp]));
13019566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(name, &fvm->componentNames[comp]));
13023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1303c0ce001eSMatthew G. Knepley }
1304c0ce001eSMatthew G. Knepley 
1305c0ce001eSMatthew G. Knepley /*@C
1306dce8aebaSBarry Smith   PetscFVGetComponentName - Get the name of a component (used in output and viewing) in a `PetscFV`
1307c0ce001eSMatthew G. Knepley 
130820f4b53cSBarry Smith   Logically Collective
130960225df5SJacob Faibussowitsch 
1310c0ce001eSMatthew G. Knepley   Input Parameters:
1311dce8aebaSBarry Smith + fvm  - the `PetscFV` object
1312c0ce001eSMatthew G. Knepley - comp - the component number
1313c0ce001eSMatthew G. Knepley 
1314c0ce001eSMatthew G. Knepley   Output Parameter:
1315c0ce001eSMatthew G. Knepley . name - the component name
1316c0ce001eSMatthew G. Knepley 
131788f5f89eSMatthew G. Knepley   Level: intermediate
1318c0ce001eSMatthew G. Knepley 
1319dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVSetComponentName()`
1320c0ce001eSMatthew G. Knepley @*/
1321d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetComponentName(PetscFV fvm, PetscInt comp, const char **name)
1322d71ae5a4SJacob Faibussowitsch {
1323c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1324c0ce001eSMatthew G. Knepley   *name = fvm->componentNames[comp];
13253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1326c0ce001eSMatthew G. Knepley }
1327c0ce001eSMatthew G. Knepley 
1328c0ce001eSMatthew G. Knepley /*@
1329dce8aebaSBarry Smith   PetscFVSetSpatialDimension - Set the spatial dimension of a `PetscFV`
1330c0ce001eSMatthew G. Knepley 
133120f4b53cSBarry Smith   Logically Collective
1332c0ce001eSMatthew G. Knepley 
1333c0ce001eSMatthew G. Knepley   Input Parameters:
1334dce8aebaSBarry Smith + fvm - the `PetscFV` object
1335c0ce001eSMatthew G. Knepley - dim - The spatial dimension
1336c0ce001eSMatthew G. Knepley 
133788f5f89eSMatthew G. Knepley   Level: intermediate
1338c0ce001eSMatthew G. Knepley 
1339dce8aebaSBarry Smith .seealso: `PetscFV`, ``PetscFVGetSpatialDimension()`
1340c0ce001eSMatthew G. Knepley @*/
1341d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetSpatialDimension(PetscFV fvm, PetscInt dim)
1342d71ae5a4SJacob Faibussowitsch {
1343c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1344c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1345c0ce001eSMatthew G. Knepley   fvm->dim = dim;
13463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1347c0ce001eSMatthew G. Knepley }
1348c0ce001eSMatthew G. Knepley 
1349c0ce001eSMatthew G. Knepley /*@
1350dce8aebaSBarry Smith   PetscFVGetSpatialDimension - Get the spatial dimension of a `PetscFV`
1351c0ce001eSMatthew G. Knepley 
135220f4b53cSBarry Smith   Not Collective
1353c0ce001eSMatthew G. Knepley 
1354c0ce001eSMatthew G. Knepley   Input Parameter:
1355dce8aebaSBarry Smith . fvm - the `PetscFV` object
1356c0ce001eSMatthew G. Knepley 
1357c0ce001eSMatthew G. Knepley   Output Parameter:
1358c0ce001eSMatthew G. Knepley . dim - The spatial dimension
1359c0ce001eSMatthew G. Knepley 
136088f5f89eSMatthew G. Knepley   Level: intermediate
1361c0ce001eSMatthew G. Knepley 
1362dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVSetSpatialDimension()`
1363c0ce001eSMatthew G. Knepley @*/
1364d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetSpatialDimension(PetscFV fvm, PetscInt *dim)
1365d71ae5a4SJacob Faibussowitsch {
1366c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1367c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
13684f572ea9SToby Isaac   PetscAssertPointer(dim, 2);
1369c0ce001eSMatthew G. Knepley   *dim = fvm->dim;
13703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1371c0ce001eSMatthew G. Knepley }
1372c0ce001eSMatthew G. Knepley 
1373c0ce001eSMatthew G. Knepley /*@
1374dce8aebaSBarry Smith   PetscFVSetComputeGradients - Toggle computation of cell gradients on a `PetscFV`
1375c0ce001eSMatthew G. Knepley 
137620f4b53cSBarry Smith   Logically Collective
1377c0ce001eSMatthew G. Knepley 
1378c0ce001eSMatthew G. Knepley   Input Parameters:
1379dce8aebaSBarry Smith + fvm              - the `PetscFV` object
1380c0ce001eSMatthew G. Knepley - computeGradients - Flag to compute cell gradients
1381c0ce001eSMatthew G. Knepley 
138288f5f89eSMatthew G. Knepley   Level: intermediate
1383c0ce001eSMatthew G. Knepley 
1384dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVGetComputeGradients()`
1385c0ce001eSMatthew G. Knepley @*/
1386d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetComputeGradients(PetscFV fvm, PetscBool computeGradients)
1387d71ae5a4SJacob Faibussowitsch {
1388c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1389c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1390c0ce001eSMatthew G. Knepley   fvm->computeGradients = computeGradients;
13913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1392c0ce001eSMatthew G. Knepley }
1393c0ce001eSMatthew G. Knepley 
1394c0ce001eSMatthew G. Knepley /*@
1395dce8aebaSBarry Smith   PetscFVGetComputeGradients - Return flag for computation of cell gradients on a `PetscFV`
1396c0ce001eSMatthew G. Knepley 
139720f4b53cSBarry Smith   Not Collective
1398c0ce001eSMatthew G. Knepley 
1399c0ce001eSMatthew G. Knepley   Input Parameter:
1400dce8aebaSBarry Smith . fvm - the `PetscFV` object
1401c0ce001eSMatthew G. Knepley 
1402c0ce001eSMatthew G. Knepley   Output Parameter:
1403c0ce001eSMatthew G. Knepley . computeGradients - Flag to compute cell gradients
1404c0ce001eSMatthew G. Knepley 
140588f5f89eSMatthew G. Knepley   Level: intermediate
1406c0ce001eSMatthew G. Knepley 
1407dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVSetComputeGradients()`
1408c0ce001eSMatthew G. Knepley @*/
1409d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetComputeGradients(PetscFV fvm, PetscBool *computeGradients)
1410d71ae5a4SJacob Faibussowitsch {
1411c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1412c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
14134f572ea9SToby Isaac   PetscAssertPointer(computeGradients, 2);
1414c0ce001eSMatthew G. Knepley   *computeGradients = fvm->computeGradients;
14153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1416c0ce001eSMatthew G. Knepley }
1417c0ce001eSMatthew G. Knepley 
1418c0ce001eSMatthew G. Knepley /*@
1419dce8aebaSBarry Smith   PetscFVSetQuadrature - Set the `PetscQuadrature` object for a `PetscFV`
1420c0ce001eSMatthew G. Knepley 
142120f4b53cSBarry Smith   Logically Collective
1422c0ce001eSMatthew G. Knepley 
1423c0ce001eSMatthew G. Knepley   Input Parameters:
1424dce8aebaSBarry Smith + fvm - the `PetscFV` object
1425dce8aebaSBarry Smith - q   - The `PetscQuadrature`
1426c0ce001eSMatthew G. Knepley 
142788f5f89eSMatthew G. Knepley   Level: intermediate
1428c0ce001eSMatthew G. Knepley 
1429dce8aebaSBarry Smith .seealso: `PetscQuadrature`, `PetscFV`, `PetscFVGetQuadrature()`
1430c0ce001eSMatthew G. Knepley @*/
1431d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetQuadrature(PetscFV fvm, PetscQuadrature q)
1432d71ae5a4SJacob Faibussowitsch {
1433c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1434c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
14359566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&fvm->quadrature));
14369566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)q));
1437c0ce001eSMatthew G. Knepley   fvm->quadrature = q;
14383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1439c0ce001eSMatthew G. Knepley }
1440c0ce001eSMatthew G. Knepley 
1441c0ce001eSMatthew G. Knepley /*@
1442dce8aebaSBarry Smith   PetscFVGetQuadrature - Get the `PetscQuadrature` from a `PetscFV`
1443c0ce001eSMatthew G. Knepley 
144420f4b53cSBarry Smith   Not Collective
1445c0ce001eSMatthew G. Knepley 
1446c0ce001eSMatthew G. Knepley   Input Parameter:
1447dce8aebaSBarry Smith . fvm - the `PetscFV` object
1448c0ce001eSMatthew G. Knepley 
1449c0ce001eSMatthew G. Knepley   Output Parameter:
145060225df5SJacob Faibussowitsch . q - The `PetscQuadrature`
1451c0ce001eSMatthew G. Knepley 
145288f5f89eSMatthew G. Knepley   Level: intermediate
1453c0ce001eSMatthew G. Knepley 
1454dce8aebaSBarry Smith .seealso: `PetscQuadrature`, `PetscFV`, `PetscFVSetQuadrature()`
1455c0ce001eSMatthew G. Knepley @*/
1456d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetQuadrature(PetscFV fvm, PetscQuadrature *q)
1457d71ae5a4SJacob Faibussowitsch {
1458c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1459c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
14604f572ea9SToby Isaac   PetscAssertPointer(q, 2);
1461c0ce001eSMatthew G. Knepley   if (!fvm->quadrature) {
1462c0ce001eSMatthew G. Knepley     /* Create default 1-point quadrature */
1463c0ce001eSMatthew G. Knepley     PetscReal *points, *weights;
1464c0ce001eSMatthew G. Knepley 
14659566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, &fvm->quadrature));
14669566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(fvm->dim, &points));
14679566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(1, &weights));
1468c0ce001eSMatthew G. Knepley     weights[0] = 1.0;
14699566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureSetData(fvm->quadrature, fvm->dim, 1, 1, points, weights));
1470c0ce001eSMatthew G. Knepley   }
1471c0ce001eSMatthew G. Knepley   *q = fvm->quadrature;
14723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1473c0ce001eSMatthew G. Knepley }
1474c0ce001eSMatthew G. Knepley 
1475c0ce001eSMatthew G. Knepley /*@
1476dce8aebaSBarry Smith   PetscFVGetDualSpace - Returns the `PetscDualSpace` used to define the inner product on a `PetscFV`
1477c0ce001eSMatthew G. Knepley 
147820f4b53cSBarry Smith   Not Collective
1479c0ce001eSMatthew G. Knepley 
1480c0ce001eSMatthew G. Knepley   Input Parameter:
1481dce8aebaSBarry Smith . fvm - The `PetscFV` object
1482c0ce001eSMatthew G. Knepley 
1483c0ce001eSMatthew G. Knepley   Output Parameter:
148420f4b53cSBarry Smith . sp - The `PetscDualSpace` object
1485c0ce001eSMatthew G. Knepley 
148688f5f89eSMatthew G. Knepley   Level: intermediate
1487c0ce001eSMatthew G. Knepley 
148860225df5SJacob Faibussowitsch   Developer Notes:
1489dce8aebaSBarry Smith   There is overlap between the methods of `PetscFE` and `PetscFV`, they should probably share a common parent class
1490dce8aebaSBarry Smith 
1491dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscFV`, `PetscFVCreate()`
1492c0ce001eSMatthew G. Knepley @*/
1493d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetDualSpace(PetscFV fvm, PetscDualSpace *sp)
1494d71ae5a4SJacob Faibussowitsch {
1495c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1496c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
14974f572ea9SToby Isaac   PetscAssertPointer(sp, 2);
1498c0ce001eSMatthew G. Knepley   if (!fvm->dualSpace) {
1499c0ce001eSMatthew G. Knepley     DM       K;
1500c0ce001eSMatthew G. Knepley     PetscInt dim, Nc, c;
1501c0ce001eSMatthew G. Knepley 
15029566063dSJacob Faibussowitsch     PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
15039566063dSJacob Faibussowitsch     PetscCall(PetscFVGetNumComponents(fvm, &Nc));
15049566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceCreate(PetscObjectComm((PetscObject)fvm), &fvm->dualSpace));
15059566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSetType(fvm->dualSpace, PETSCDUALSPACESIMPLE));
15069566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, PETSC_FALSE), &K));
15079566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSetNumComponents(fvm->dualSpace, Nc));
15089566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSetDM(fvm->dualSpace, K));
15099566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&K));
15109566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSimpleSetDimension(fvm->dualSpace, Nc));
1511c0ce001eSMatthew G. Knepley     /* Should we be using PetscFVGetQuadrature() here? */
1512c0ce001eSMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
1513c0ce001eSMatthew G. Knepley       PetscQuadrature qc;
1514c0ce001eSMatthew G. Knepley       PetscReal      *points, *weights;
1515c0ce001eSMatthew G. Knepley 
15169566063dSJacob Faibussowitsch       PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, &qc));
15179566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(dim, &points));
15189566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(Nc, &weights));
1519c0ce001eSMatthew G. Knepley       weights[c] = 1.0;
15209566063dSJacob Faibussowitsch       PetscCall(PetscQuadratureSetData(qc, dim, Nc, 1, points, weights));
15219566063dSJacob Faibussowitsch       PetscCall(PetscDualSpaceSimpleSetFunctional(fvm->dualSpace, c, qc));
15229566063dSJacob Faibussowitsch       PetscCall(PetscQuadratureDestroy(&qc));
1523c0ce001eSMatthew G. Knepley     }
15249566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSetUp(fvm->dualSpace));
1525c0ce001eSMatthew G. Knepley   }
1526c0ce001eSMatthew G. Knepley   *sp = fvm->dualSpace;
15273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1528c0ce001eSMatthew G. Knepley }
1529c0ce001eSMatthew G. Knepley 
1530c0ce001eSMatthew G. Knepley /*@
1531dce8aebaSBarry Smith   PetscFVSetDualSpace - Sets the `PetscDualSpace` used to define the inner product
1532c0ce001eSMatthew G. Knepley 
153320f4b53cSBarry Smith   Not Collective
1534c0ce001eSMatthew G. Knepley 
1535c0ce001eSMatthew G. Knepley   Input Parameters:
1536dce8aebaSBarry Smith + fvm - The `PetscFV` object
1537dce8aebaSBarry Smith - sp  - The `PetscDualSpace` object
1538c0ce001eSMatthew G. Knepley 
1539c0ce001eSMatthew G. Knepley   Level: intermediate
1540c0ce001eSMatthew G. Knepley 
1541dce8aebaSBarry Smith   Note:
1542dce8aebaSBarry Smith   A simple dual space is provided automatically, and the user typically will not need to override it.
1543c0ce001eSMatthew G. Knepley 
1544dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscFV`, `PetscFVCreate()`
1545c0ce001eSMatthew G. Knepley @*/
1546d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetDualSpace(PetscFV fvm, PetscDualSpace sp)
1547d71ae5a4SJacob Faibussowitsch {
1548c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1549c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1550c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 2);
15519566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDestroy(&fvm->dualSpace));
1552c0ce001eSMatthew G. Knepley   fvm->dualSpace = sp;
15539566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fvm->dualSpace));
15543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1555c0ce001eSMatthew G. Knepley }
1556c0ce001eSMatthew G. Knepley 
155788f5f89eSMatthew G. Knepley /*@C
1558ef0bb6c7SMatthew G. Knepley   PetscFVGetCellTabulation - Returns the tabulation of the basis functions at the quadrature points
155988f5f89eSMatthew G. Knepley 
156020f4b53cSBarry Smith   Not Collective
156188f5f89eSMatthew G. Knepley 
156288f5f89eSMatthew G. Knepley   Input Parameter:
1563dce8aebaSBarry Smith . fvm - The `PetscFV` object
156488f5f89eSMatthew G. Knepley 
1565ef0bb6c7SMatthew G. Knepley   Output Parameter:
1566a5b23f4aSJose E. Roman . T - The basis function values and derivatives at quadrature points
156788f5f89eSMatthew G. Knepley 
156888f5f89eSMatthew G. Knepley   Level: intermediate
156988f5f89eSMatthew G. Knepley 
1570dce8aebaSBarry Smith   Note:
1571dce8aebaSBarry Smith .vb
1572dce8aebaSBarry Smith   T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
1573dce8aebaSBarry 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
1574dce8aebaSBarry 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
1575dce8aebaSBarry Smith .ve
1576dce8aebaSBarry Smith 
1577dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscTabulation`, `PetscFEGetCellTabulation()`, `PetscFVCreateTabulation()`, `PetscFVGetQuadrature()`, `PetscQuadratureGetData()`
157888f5f89eSMatthew G. Knepley @*/
1579d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetCellTabulation(PetscFV fvm, PetscTabulation *T)
1580d71ae5a4SJacob Faibussowitsch {
1581c0ce001eSMatthew G. Knepley   PetscInt         npoints;
1582c0ce001eSMatthew G. Knepley   const PetscReal *points;
1583c0ce001eSMatthew G. Knepley 
1584c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1585c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
15864f572ea9SToby Isaac   PetscAssertPointer(T, 2);
15879566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureGetData(fvm->quadrature, NULL, NULL, &npoints, &points, NULL));
15889566063dSJacob Faibussowitsch   if (!fvm->T) PetscCall(PetscFVCreateTabulation(fvm, 1, npoints, points, 1, &fvm->T));
1589ef0bb6c7SMatthew G. Knepley   *T = fvm->T;
15903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1591c0ce001eSMatthew G. Knepley }
1592c0ce001eSMatthew G. Knepley 
159388f5f89eSMatthew G. Knepley /*@C
1594ef0bb6c7SMatthew G. Knepley   PetscFVCreateTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided.
159588f5f89eSMatthew G. Knepley 
159620f4b53cSBarry Smith   Not Collective
159788f5f89eSMatthew G. Knepley 
159888f5f89eSMatthew G. Knepley   Input Parameters:
1599dce8aebaSBarry Smith + fvm     - The `PetscFV` object
1600ef0bb6c7SMatthew G. Knepley . nrepl   - The number of replicas
1601ef0bb6c7SMatthew G. Knepley . npoints - The number of tabulation points in a replica
1602ef0bb6c7SMatthew G. Knepley . points  - The tabulation point coordinates
1603ef0bb6c7SMatthew G. Knepley - K       - The order of derivative to tabulate
160488f5f89eSMatthew G. Knepley 
1605ef0bb6c7SMatthew G. Knepley   Output Parameter:
1606a5b23f4aSJose E. Roman . T - The basis function values and derivative at tabulation points
160788f5f89eSMatthew G. Knepley 
160888f5f89eSMatthew G. Knepley   Level: intermediate
160988f5f89eSMatthew G. Knepley 
1610dce8aebaSBarry Smith   Note:
1611dce8aebaSBarry Smith .vb
1612dce8aebaSBarry Smith   T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
1613dce8aebaSBarry 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
1614dce8aebaSBarry 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
1615dce8aebaSBarry Smith .ve
1616dce8aebaSBarry Smith 
1617dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscTabulation`, `PetscFECreateTabulation()`, `PetscTabulationDestroy()`, `PetscFEGetCellTabulation()`
161888f5f89eSMatthew G. Knepley @*/
1619d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVCreateTabulation(PetscFV fvm, PetscInt nrepl, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation *T)
1620d71ae5a4SJacob Faibussowitsch {
1621c0ce001eSMatthew G. Knepley   PetscInt pdim = 1; /* Dimension of approximation space P */
1622ef0bb6c7SMatthew G. Knepley   PetscInt cdim;     /* Spatial dimension */
1623ef0bb6c7SMatthew G. Knepley   PetscInt Nc;       /* Field components */
1624ef0bb6c7SMatthew G. Knepley   PetscInt k, p, d, c, e;
1625c0ce001eSMatthew G. Knepley 
1626c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1627ef0bb6c7SMatthew G. Knepley   if (!npoints || K < 0) {
1628ef0bb6c7SMatthew G. Knepley     *T = NULL;
16293ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1630c0ce001eSMatthew G. Knepley   }
1631c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
16324f572ea9SToby Isaac   PetscAssertPointer(points, 4);
16334f572ea9SToby Isaac   PetscAssertPointer(T, 6);
16349566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &cdim));
16359566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fvm, &Nc));
16369566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1, T));
1637ef0bb6c7SMatthew G. Knepley   (*T)->K    = !cdim ? 0 : K;
1638ef0bb6c7SMatthew G. Knepley   (*T)->Nr   = nrepl;
1639ef0bb6c7SMatthew G. Knepley   (*T)->Np   = npoints;
1640ef0bb6c7SMatthew G. Knepley   (*T)->Nb   = pdim;
1641ef0bb6c7SMatthew G. Knepley   (*T)->Nc   = Nc;
1642ef0bb6c7SMatthew G. Knepley   (*T)->cdim = cdim;
16439566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*T)->K + 1, &(*T)->T));
164448a46eb9SPierre Jolivet   for (k = 0; k <= (*T)->K; ++k) PetscCall(PetscMalloc1(nrepl * npoints * pdim * Nc * PetscPowInt(cdim, k), &(*T)->T[k]));
16459371c9d4SSatish Balay   if (K >= 0) {
16469371c9d4SSatish Balay     for (p = 0; p < nrepl * npoints; ++p)
16479371c9d4SSatish Balay       for (d = 0; d < pdim; ++d)
16489371c9d4SSatish Balay         for (c = 0; c < Nc; ++c) (*T)->T[0][(p * pdim + d) * Nc + c] = 1.0;
1649ef0bb6c7SMatthew G. Knepley   }
16509371c9d4SSatish Balay   if (K >= 1) {
16519371c9d4SSatish Balay     for (p = 0; p < nrepl * npoints; ++p)
16529371c9d4SSatish Balay       for (d = 0; d < pdim; ++d)
16539371c9d4SSatish Balay         for (c = 0; c < Nc; ++c)
16549371c9d4SSatish Balay           for (e = 0; e < cdim; ++e) (*T)->T[1][((p * pdim + d) * Nc + c) * cdim + e] = 0.0;
16559371c9d4SSatish Balay   }
16569371c9d4SSatish Balay   if (K >= 2) {
16579371c9d4SSatish Balay     for (p = 0; p < nrepl * npoints; ++p)
16589371c9d4SSatish Balay       for (d = 0; d < pdim; ++d)
16599371c9d4SSatish Balay         for (c = 0; c < Nc; ++c)
16609371c9d4SSatish Balay           for (e = 0; e < cdim * cdim; ++e) (*T)->T[2][((p * pdim + d) * Nc + c) * cdim * cdim + e] = 0.0;
16619371c9d4SSatish Balay   }
16623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1663c0ce001eSMatthew G. Knepley }
1664c0ce001eSMatthew G. Knepley 
1665c0ce001eSMatthew G. Knepley /*@C
1666c0ce001eSMatthew G. Knepley   PetscFVComputeGradient - Compute the gradient reconstruction matrix for a given cell
1667c0ce001eSMatthew G. Knepley 
1668c0ce001eSMatthew G. Knepley   Input Parameters:
1669dce8aebaSBarry Smith + fvm      - The `PetscFV` object
1670c0ce001eSMatthew G. Knepley . numFaces - The number of cell faces which are not constrained
1671c0ce001eSMatthew G. Knepley - dx       - The vector from the cell centroid to the neighboring cell centroid for each face
1672c0ce001eSMatthew G. Knepley 
1673a4e35b19SJacob Faibussowitsch   Output Parameter:
1674a4e35b19SJacob Faibussowitsch . grad - the gradient
1675a4e35b19SJacob Faibussowitsch 
167688f5f89eSMatthew G. Knepley   Level: advanced
1677c0ce001eSMatthew G. Knepley 
1678dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVCreate()`
1679c0ce001eSMatthew G. Knepley @*/
1680d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVComputeGradient(PetscFV fvm, PetscInt numFaces, PetscScalar dx[], PetscScalar grad[])
1681d71ae5a4SJacob Faibussowitsch {
1682c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1683c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1684dbbe0bcdSBarry Smith   PetscTryTypeMethod(fvm, computegradient, numFaces, dx, grad);
16853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1686c0ce001eSMatthew G. Knepley }
1687c0ce001eSMatthew G. Knepley 
168888f5f89eSMatthew G. Knepley /*@C
1689c0ce001eSMatthew G. Knepley   PetscFVIntegrateRHSFunction - Produce the cell residual vector for a chunk of elements by quadrature integration
1690c0ce001eSMatthew G. Knepley 
169120f4b53cSBarry Smith   Not Collective
1692c0ce001eSMatthew G. Knepley 
1693c0ce001eSMatthew G. Knepley   Input Parameters:
1694dce8aebaSBarry Smith + fvm         - The `PetscFV` object for the field being integrated
1695da81f932SPierre Jolivet . prob        - The `PetscDS` specifying the discretizations and continuum functions
1696c0ce001eSMatthew G. Knepley . field       - The field being integrated
1697c0ce001eSMatthew G. Knepley . Nf          - The number of faces in the chunk
1698c0ce001eSMatthew G. Knepley . fgeom       - The face geometry for each face in the chunk
1699c0ce001eSMatthew G. Knepley . neighborVol - The volume for each pair of cells in the chunk
1700c0ce001eSMatthew G. Knepley . uL          - The state from the cell on the left
1701c0ce001eSMatthew G. Knepley - uR          - The state from the cell on the right
1702c0ce001eSMatthew G. Knepley 
1703d8d19677SJose E. Roman   Output Parameters:
1704c0ce001eSMatthew G. Knepley + fluxL - the left fluxes for each face
1705c0ce001eSMatthew G. Knepley - fluxR - the right fluxes for each face
170688f5f89eSMatthew G. Knepley 
170788f5f89eSMatthew G. Knepley   Level: developer
170888f5f89eSMatthew G. Knepley 
1709dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscDS`, `PetscFVFaceGeom`, `PetscFVCreate()`
171088f5f89eSMatthew G. Knepley @*/
1711d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVIntegrateRHSFunction(PetscFV fvm, PetscDS prob, PetscInt field, PetscInt Nf, PetscFVFaceGeom *fgeom, PetscReal *neighborVol, PetscScalar uL[], PetscScalar uR[], PetscScalar fluxL[], PetscScalar fluxR[])
1712d71ae5a4SJacob Faibussowitsch {
1713c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1714c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1715dbbe0bcdSBarry Smith   PetscTryTypeMethod(fvm, integraterhsfunction, prob, field, Nf, fgeom, neighborVol, uL, uR, fluxL, fluxR);
17163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1717c0ce001eSMatthew G. Knepley }
1718c0ce001eSMatthew G. Knepley 
1719c0ce001eSMatthew G. Knepley /*@
1720a4e35b19SJacob Faibussowitsch   PetscFVRefine - Create a "refined" `PetscFV` object that refines the reference cell into
1721a4e35b19SJacob Faibussowitsch   smaller copies.
1722c0ce001eSMatthew G. Knepley 
1723c0ce001eSMatthew G. Knepley   Input Parameter:
1724dce8aebaSBarry Smith . fv - The initial `PetscFV`
1725c0ce001eSMatthew G. Knepley 
1726c0ce001eSMatthew G. Knepley   Output Parameter:
1727dce8aebaSBarry Smith . fvRef - The refined `PetscFV`
1728c0ce001eSMatthew G. Knepley 
172988f5f89eSMatthew G. Knepley   Level: advanced
1730c0ce001eSMatthew G. Knepley 
1731a4e35b19SJacob Faibussowitsch   Notes:
1732a4e35b19SJacob Faibussowitsch   This is typically used to generate a preconditioner for a high order method from a lower order method on a
1733a4e35b19SJacob Faibussowitsch   refined mesh having the same number of dofs (but more sparsity). It is also used to create an
1734a4e35b19SJacob Faibussowitsch   interpolation between regularly refined meshes.
1735a4e35b19SJacob Faibussowitsch 
1736dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVCreate()`, `PetscFVSetType()`
1737c0ce001eSMatthew G. Knepley @*/
1738d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVRefine(PetscFV fv, PetscFV *fvRef)
1739d71ae5a4SJacob Faibussowitsch {
1740c0ce001eSMatthew G. Knepley   PetscDualSpace  Q, Qref;
1741c0ce001eSMatthew G. Knepley   DM              K, Kref;
1742c0ce001eSMatthew G. Knepley   PetscQuadrature q, qref;
1743412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
1744012bc364SMatthew G. Knepley   DMPlexTransform tr;
1745c0ce001eSMatthew G. Knepley   PetscReal      *v0;
1746c0ce001eSMatthew G. Knepley   PetscReal      *jac, *invjac;
1747c0ce001eSMatthew G. Knepley   PetscInt        numComp, numSubelements, s;
1748c0ce001eSMatthew G. Knepley 
1749c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
17509566063dSJacob Faibussowitsch   PetscCall(PetscFVGetDualSpace(fv, &Q));
17519566063dSJacob Faibussowitsch   PetscCall(PetscFVGetQuadrature(fv, &q));
17529566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceGetDM(Q, &K));
1753c0ce001eSMatthew G. Knepley   /* Create dual space */
17549566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDuplicate(Q, &Qref));
17559566063dSJacob Faibussowitsch   PetscCall(DMRefine(K, PetscObjectComm((PetscObject)fv), &Kref));
17569566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetDM(Qref, Kref));
17579566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&Kref));
17589566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetUp(Qref));
1759c0ce001eSMatthew G. Knepley   /* Create volume */
17609566063dSJacob Faibussowitsch   PetscCall(PetscFVCreate(PetscObjectComm((PetscObject)fv), fvRef));
17619566063dSJacob Faibussowitsch   PetscCall(PetscFVSetDualSpace(*fvRef, Qref));
17629566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fv, &numComp));
17639566063dSJacob Faibussowitsch   PetscCall(PetscFVSetNumComponents(*fvRef, numComp));
17649566063dSJacob Faibussowitsch   PetscCall(PetscFVSetUp(*fvRef));
1765c0ce001eSMatthew G. Knepley   /* Create quadrature */
17669566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(K, 0, &ct));
17679566063dSJacob Faibussowitsch   PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
17689566063dSJacob Faibussowitsch   PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
17699566063dSJacob Faibussowitsch   PetscCall(DMPlexRefineRegularGetAffineTransforms(tr, ct, &numSubelements, &v0, &jac, &invjac));
17709566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureExpandComposite(q, numSubelements, v0, jac, &qref));
17719566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSimpleSetDimension(Qref, numSubelements));
1772c0ce001eSMatthew G. Knepley   for (s = 0; s < numSubelements; ++s) {
1773c0ce001eSMatthew G. Knepley     PetscQuadrature  qs;
1774c0ce001eSMatthew G. Knepley     const PetscReal *points, *weights;
1775c0ce001eSMatthew G. Knepley     PetscReal       *p, *w;
1776c0ce001eSMatthew G. Knepley     PetscInt         dim, Nc, npoints, np;
1777c0ce001eSMatthew G. Knepley 
17789566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, &qs));
17799566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureGetData(q, &dim, &Nc, &npoints, &points, &weights));
1780c0ce001eSMatthew G. Knepley     np = npoints / numSubelements;
17819566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(np * dim, &p));
17829566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(np * Nc, &w));
17839566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(p, &points[s * np * dim], np * dim));
17849566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(w, &weights[s * np * Nc], np * Nc));
17859566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureSetData(qs, dim, Nc, np, p, w));
17869566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSimpleSetFunctional(Qref, s, qs));
17879566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureDestroy(&qs));
1788c0ce001eSMatthew G. Knepley   }
17899566063dSJacob Faibussowitsch   PetscCall(PetscFVSetQuadrature(*fvRef, qref));
17909566063dSJacob Faibussowitsch   PetscCall(DMPlexTransformDestroy(&tr));
17919566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&qref));
17929566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDestroy(&Qref));
17933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1794c0ce001eSMatthew G. Knepley }
1795c0ce001eSMatthew G. Knepley 
1796d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVDestroy_Upwind(PetscFV fvm)
1797d71ae5a4SJacob Faibussowitsch {
1798c0ce001eSMatthew G. Knepley   PetscFV_Upwind *b = (PetscFV_Upwind *)fvm->data;
1799c0ce001eSMatthew G. Knepley 
1800c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
18019566063dSJacob Faibussowitsch   PetscCall(PetscFree(b));
18023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1803c0ce001eSMatthew G. Knepley }
1804c0ce001eSMatthew G. Knepley 
1805d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVView_Upwind_Ascii(PetscFV fv, PetscViewer viewer)
1806d71ae5a4SJacob Faibussowitsch {
1807c0ce001eSMatthew G. Knepley   PetscInt          Nc, c;
1808c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
1809c0ce001eSMatthew G. Knepley 
1810c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
18119566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fv, &Nc));
18129566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
18139566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Upwind Finite Volume:\n"));
181463a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  num components: %" PetscInt_FMT "\n", Nc));
1815c0ce001eSMatthew G. Knepley   for (c = 0; c < Nc; c++) {
181648a46eb9SPierre Jolivet     if (fv->componentNames[c]) PetscCall(PetscViewerASCIIPrintf(viewer, "    component %" PetscInt_FMT ": %s\n", c, fv->componentNames[c]));
1817c0ce001eSMatthew G. Knepley   }
18183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1819c0ce001eSMatthew G. Knepley }
1820c0ce001eSMatthew G. Knepley 
1821d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVView_Upwind(PetscFV fv, PetscViewer viewer)
1822d71ae5a4SJacob Faibussowitsch {
1823c0ce001eSMatthew G. Knepley   PetscBool iascii;
1824c0ce001eSMatthew G. Knepley 
1825c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1826c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 1);
1827c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18289566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
18299566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscFVView_Upwind_Ascii(fv, viewer));
18303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1831c0ce001eSMatthew G. Knepley }
1832c0ce001eSMatthew G. Knepley 
1833d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVSetUp_Upwind(PetscFV fvm)
1834d71ae5a4SJacob Faibussowitsch {
1835c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
18363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1837c0ce001eSMatthew G. Knepley }
1838c0ce001eSMatthew G. Knepley 
1839c0ce001eSMatthew G. Knepley /*
1840c0ce001eSMatthew G. Knepley   neighborVol[f*2+0] contains the left  geom
1841c0ce001eSMatthew G. Knepley   neighborVol[f*2+1] contains the right geom
1842c0ce001eSMatthew G. Knepley */
1843d71ae5a4SJacob 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[])
1844d71ae5a4SJacob Faibussowitsch {
1845c0ce001eSMatthew G. Knepley   void (*riemann)(PetscInt, PetscInt, const PetscReal[], const PetscReal[], const PetscScalar[], const PetscScalar[], PetscInt, const PetscScalar[], PetscScalar[], void *);
1846c0ce001eSMatthew G. Knepley   void              *rctx;
1847c0ce001eSMatthew G. Knepley   PetscScalar       *flux = fvm->fluxWork;
1848c0ce001eSMatthew G. Knepley   const PetscScalar *constants;
1849c0ce001eSMatthew G. Knepley   PetscInt           dim, numConstants, pdim, totDim, Nc, off, f, d;
1850c0ce001eSMatthew G. Knepley 
1851c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
18529566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(prob, &Nc));
18539566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
18549566063dSJacob Faibussowitsch   PetscCall(PetscDSGetFieldOffset(prob, field, &off));
18559566063dSJacob Faibussowitsch   PetscCall(PetscDSGetRiemannSolver(prob, field, &riemann));
18569566063dSJacob Faibussowitsch   PetscCall(PetscDSGetContext(prob, field, &rctx));
18579566063dSJacob Faibussowitsch   PetscCall(PetscDSGetConstants(prob, &numConstants, &constants));
18589566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
18599566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fvm, &pdim));
1860c0ce001eSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
1861c0ce001eSMatthew G. Knepley     (*riemann)(dim, pdim, fgeom[f].centroid, fgeom[f].normal, &uL[f * Nc], &uR[f * Nc], numConstants, constants, flux, rctx);
1862c0ce001eSMatthew G. Knepley     for (d = 0; d < pdim; ++d) {
1863c0ce001eSMatthew G. Knepley       fluxL[f * totDim + off + d] = flux[d] / neighborVol[f * 2 + 0];
1864c0ce001eSMatthew G. Knepley       fluxR[f * totDim + off + d] = flux[d] / neighborVol[f * 2 + 1];
1865c0ce001eSMatthew G. Knepley     }
1866c0ce001eSMatthew G. Knepley   }
18673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1868c0ce001eSMatthew G. Knepley }
1869c0ce001eSMatthew G. Knepley 
1870d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVInitialize_Upwind(PetscFV fvm)
1871d71ae5a4SJacob Faibussowitsch {
1872c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1873c0ce001eSMatthew G. Knepley   fvm->ops->setfromoptions       = NULL;
1874c0ce001eSMatthew G. Knepley   fvm->ops->setup                = PetscFVSetUp_Upwind;
1875c0ce001eSMatthew G. Knepley   fvm->ops->view                 = PetscFVView_Upwind;
1876c0ce001eSMatthew G. Knepley   fvm->ops->destroy              = PetscFVDestroy_Upwind;
1877c0ce001eSMatthew G. Knepley   fvm->ops->integraterhsfunction = PetscFVIntegrateRHSFunction_Upwind;
18783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1879c0ce001eSMatthew G. Knepley }
1880c0ce001eSMatthew G. Knepley 
1881c0ce001eSMatthew G. Knepley /*MC
1882dce8aebaSBarry Smith   PETSCFVUPWIND = "upwind" - A `PetscFV` implementation
1883c0ce001eSMatthew G. Knepley 
1884c0ce001eSMatthew G. Knepley   Level: intermediate
1885c0ce001eSMatthew G. Knepley 
1886dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVCreate()`, `PetscFVSetType()`
1887c0ce001eSMatthew G. Knepley M*/
1888c0ce001eSMatthew G. Knepley 
1889d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscFVCreate_Upwind(PetscFV fvm)
1890d71ae5a4SJacob Faibussowitsch {
1891c0ce001eSMatthew G. Knepley   PetscFV_Upwind *b;
1892c0ce001eSMatthew G. Knepley 
1893c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1894c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
18954dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
1896c0ce001eSMatthew G. Knepley   fvm->data = b;
1897c0ce001eSMatthew G. Knepley 
18989566063dSJacob Faibussowitsch   PetscCall(PetscFVInitialize_Upwind(fvm));
18993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1900c0ce001eSMatthew G. Knepley }
1901c0ce001eSMatthew G. Knepley 
1902c0ce001eSMatthew G. Knepley #include <petscblaslapack.h>
1903c0ce001eSMatthew G. Knepley 
1904d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVDestroy_LeastSquares(PetscFV fvm)
1905d71ae5a4SJacob Faibussowitsch {
1906c0ce001eSMatthew G. Knepley   PetscFV_LeastSquares *ls = (PetscFV_LeastSquares *)fvm->data;
1907c0ce001eSMatthew G. Knepley 
1908c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
19099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fvm, "PetscFVLeastSquaresSetMaxFaces_C", NULL));
19109566063dSJacob Faibussowitsch   PetscCall(PetscFree4(ls->B, ls->Binv, ls->tau, ls->work));
19119566063dSJacob Faibussowitsch   PetscCall(PetscFree(ls));
19123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1913c0ce001eSMatthew G. Knepley }
1914c0ce001eSMatthew G. Knepley 
1915d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVView_LeastSquares_Ascii(PetscFV fv, PetscViewer viewer)
1916d71ae5a4SJacob Faibussowitsch {
1917c0ce001eSMatthew G. Knepley   PetscInt          Nc, c;
1918c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
1919c0ce001eSMatthew G. Knepley 
1920c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
19219566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fv, &Nc));
19229566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
19239566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Finite Volume with Least Squares Reconstruction:\n"));
192463a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  num components: %" PetscInt_FMT "\n", Nc));
1925c0ce001eSMatthew G. Knepley   for (c = 0; c < Nc; c++) {
192648a46eb9SPierre Jolivet     if (fv->componentNames[c]) PetscCall(PetscViewerASCIIPrintf(viewer, "    component %" PetscInt_FMT ": %s\n", c, fv->componentNames[c]));
1927c0ce001eSMatthew G. Knepley   }
19283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1929c0ce001eSMatthew G. Knepley }
1930c0ce001eSMatthew G. Knepley 
1931d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVView_LeastSquares(PetscFV fv, PetscViewer viewer)
1932d71ae5a4SJacob Faibussowitsch {
1933c0ce001eSMatthew G. Knepley   PetscBool iascii;
1934c0ce001eSMatthew G. Knepley 
1935c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1936c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 1);
1937c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
19399566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscFVView_LeastSquares_Ascii(fv, viewer));
19403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1941c0ce001eSMatthew G. Knepley }
1942c0ce001eSMatthew G. Knepley 
1943d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVSetUp_LeastSquares(PetscFV fvm)
1944d71ae5a4SJacob Faibussowitsch {
1945c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
19463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1947c0ce001eSMatthew G. Knepley }
1948c0ce001eSMatthew G. Knepley 
1949c0ce001eSMatthew G. Knepley /* Overwrites A. Can only handle full-rank problems with m>=n */
1950d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVLeastSquaresPseudoInverse_Static(PetscInt m, PetscInt mstride, PetscInt n, PetscScalar *A, PetscScalar *Ainv, PetscScalar *tau, PetscInt worksize, PetscScalar *work)
1951d71ae5a4SJacob Faibussowitsch {
1952c0ce001eSMatthew G. Knepley   PetscBool    debug = PETSC_FALSE;
1953c0ce001eSMatthew G. Knepley   PetscBLASInt M, N, K, lda, ldb, ldwork, info;
1954c0ce001eSMatthew G. Knepley   PetscScalar *R, *Q, *Aback, Alpha;
1955c0ce001eSMatthew G. Knepley 
1956c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1957c0ce001eSMatthew G. Knepley   if (debug) {
19589566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m * n, &Aback));
19599566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(Aback, A, m * n));
1960c0ce001eSMatthew G. Knepley   }
1961c0ce001eSMatthew G. Knepley 
19629566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &M));
19639566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(n, &N));
19649566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(mstride, &lda));
19659566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(worksize, &ldwork));
19669566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
1967792fecdfSBarry Smith   PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&M, &N, A, &lda, tau, work, &ldwork, &info));
19689566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
196928b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "xGEQRF error");
1970c0ce001eSMatthew G. Knepley   R = A; /* Upper triangular part of A now contains R, the rest contains the elementary reflectors */
1971c0ce001eSMatthew G. Knepley 
1972c0ce001eSMatthew G. Knepley   /* Extract an explicit representation of Q */
1973c0ce001eSMatthew G. Knepley   Q = Ainv;
19749566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(Q, A, mstride * n));
1975c0ce001eSMatthew G. Knepley   K = N; /* full rank */
1976792fecdfSBarry Smith   PetscCallBLAS("LAPACKorgqr", LAPACKorgqr_(&M, &N, &K, Q, &lda, tau, work, &ldwork, &info));
197728b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "xORGQR/xUNGQR error");
1978c0ce001eSMatthew G. Knepley 
1979c0ce001eSMatthew G. Knepley   /* Compute A^{-T} = (R^{-1} Q^T)^T = Q R^{-T} */
1980c0ce001eSMatthew G. Knepley   Alpha = 1.0;
1981c0ce001eSMatthew G. Knepley   ldb   = lda;
1982c0ce001eSMatthew G. Knepley   BLAStrsm_("Right", "Upper", "ConjugateTranspose", "NotUnitTriangular", &M, &N, &Alpha, R, &lda, Q, &ldb);
1983c0ce001eSMatthew G. Knepley   /* Ainv is Q, overwritten with inverse */
1984c0ce001eSMatthew G. Knepley 
1985c0ce001eSMatthew G. Knepley   if (debug) { /* Check that pseudo-inverse worked */
1986c0ce001eSMatthew G. Knepley     PetscScalar  Beta = 0.0;
1987c0ce001eSMatthew G. Knepley     PetscBLASInt ldc;
1988c0ce001eSMatthew G. Knepley     K   = N;
1989c0ce001eSMatthew G. Knepley     ldc = N;
1990c0ce001eSMatthew G. Knepley     BLASgemm_("ConjugateTranspose", "Normal", &N, &K, &M, &Alpha, Ainv, &lda, Aback, &ldb, &Beta, work, &ldc);
19919566063dSJacob Faibussowitsch     PetscCall(PetscScalarView(n * n, work, PETSC_VIEWER_STDOUT_SELF));
19929566063dSJacob Faibussowitsch     PetscCall(PetscFree(Aback));
1993c0ce001eSMatthew G. Knepley   }
19943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1995c0ce001eSMatthew G. Knepley }
1996c0ce001eSMatthew G. Knepley 
1997c0ce001eSMatthew G. Knepley /* Overwrites A. Can handle degenerate problems and m<n. */
1998d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVLeastSquaresPseudoInverseSVD_Static(PetscInt m, PetscInt mstride, PetscInt n, PetscScalar *A, PetscScalar *Ainv, PetscScalar *tau, PetscInt worksize, PetscScalar *work)
1999d71ae5a4SJacob Faibussowitsch {
20006bb27163SBarry Smith   PetscScalar *Brhs;
2001c0ce001eSMatthew G. Knepley   PetscScalar *tmpwork;
2002c0ce001eSMatthew G. Knepley   PetscReal    rcond;
2003c0ce001eSMatthew G. Knepley #if defined(PETSC_USE_COMPLEX)
2004c0ce001eSMatthew G. Knepley   PetscInt   rworkSize;
2005c0ce001eSMatthew G. Knepley   PetscReal *rwork;
2006c0ce001eSMatthew G. Knepley #endif
2007c0ce001eSMatthew G. Knepley   PetscInt     i, j, maxmn;
2008c0ce001eSMatthew G. Knepley   PetscBLASInt M, N, lda, ldb, ldwork;
2009c0ce001eSMatthew G. Knepley   PetscBLASInt nrhs, irank, info;
2010c0ce001eSMatthew G. Knepley 
2011c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2012c0ce001eSMatthew G. Knepley   /* initialize to identity */
2013736d4f42SpierreXVI   tmpwork = work;
2014736d4f42SpierreXVI   Brhs    = Ainv;
2015c0ce001eSMatthew G. Knepley   maxmn   = PetscMax(m, n);
2016c0ce001eSMatthew G. Knepley   for (j = 0; j < maxmn; j++) {
2017c0ce001eSMatthew G. Knepley     for (i = 0; i < maxmn; i++) Brhs[i + j * maxmn] = 1.0 * (i == j);
2018c0ce001eSMatthew G. Knepley   }
2019c0ce001eSMatthew G. Knepley 
20209566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &M));
20219566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(n, &N));
20229566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(mstride, &lda));
20239566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(maxmn, &ldb));
20249566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(worksize, &ldwork));
2025c0ce001eSMatthew G. Knepley   rcond = -1;
2026c0ce001eSMatthew G. Knepley   nrhs  = M;
2027c0ce001eSMatthew G. Knepley #if defined(PETSC_USE_COMPLEX)
2028c0ce001eSMatthew G. Knepley   rworkSize = 5 * PetscMin(M, N);
20299566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(rworkSize, &rwork));
20306bb27163SBarry Smith   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
2031792fecdfSBarry Smith   PetscCallBLAS("LAPACKgelss", LAPACKgelss_(&M, &N, &nrhs, A, &lda, Brhs, &ldb, (PetscReal *)tau, &rcond, &irank, tmpwork, &ldwork, rwork, &info));
20329566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
20339566063dSJacob Faibussowitsch   PetscCall(PetscFree(rwork));
2034c0ce001eSMatthew G. Knepley #else
2035c0ce001eSMatthew G. Knepley   nrhs = M;
20366bb27163SBarry Smith   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
2037792fecdfSBarry Smith   PetscCallBLAS("LAPACKgelss", LAPACKgelss_(&M, &N, &nrhs, A, &lda, Brhs, &ldb, (PetscReal *)tau, &rcond, &irank, tmpwork, &ldwork, &info));
20389566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
2039c0ce001eSMatthew G. Knepley #endif
204028b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "xGELSS error");
2041c0ce001eSMatthew G. Knepley   /* The following check should be turned into a diagnostic as soon as someone wants to do this intentionally */
204208401ef6SPierre 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");
20433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2044c0ce001eSMatthew G. Knepley }
2045c0ce001eSMatthew G. Knepley 
2046c0ce001eSMatthew G. Knepley #if 0
2047c0ce001eSMatthew G. Knepley static PetscErrorCode PetscFVLeastSquaresDebugCell_Static(PetscFV fvm, PetscInt cell, DM dm, DM dmFace, PetscScalar *fgeom, DM dmCell, PetscScalar *cgeom)
2048c0ce001eSMatthew G. Knepley {
2049c0ce001eSMatthew G. Knepley   PetscReal       grad[2] = {0, 0};
2050c0ce001eSMatthew G. Knepley   const PetscInt *faces;
2051c0ce001eSMatthew G. Knepley   PetscInt        numFaces, f;
2052c0ce001eSMatthew G. Knepley 
2053c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
20549566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, cell, &numFaces));
20559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, cell, &faces));
2056c0ce001eSMatthew G. Knepley   for (f = 0; f < numFaces; ++f) {
2057c0ce001eSMatthew G. Knepley     const PetscInt *fcells;
2058c0ce001eSMatthew G. Knepley     const CellGeom *cg1;
2059c0ce001eSMatthew G. Knepley     const FaceGeom *fg;
2060c0ce001eSMatthew G. Knepley 
20619566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, faces[f], &fcells));
20629566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmFace, faces[f], fgeom, &fg));
2063c0ce001eSMatthew G. Knepley     for (i = 0; i < 2; ++i) {
2064c0ce001eSMatthew G. Knepley       PetscScalar du;
2065c0ce001eSMatthew G. Knepley 
2066c0ce001eSMatthew G. Knepley       if (fcells[i] == c) continue;
20679566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, fcells[i], cgeom, &cg1));
2068c0ce001eSMatthew G. Knepley       du   = cg1->centroid[0] + 3*cg1->centroid[1] - (cg->centroid[0] + 3*cg->centroid[1]);
2069c0ce001eSMatthew G. Knepley       grad[0] += fg->grad[!i][0] * du;
2070c0ce001eSMatthew G. Knepley       grad[1] += fg->grad[!i][1] * du;
2071c0ce001eSMatthew G. Knepley     }
2072c0ce001eSMatthew G. Knepley   }
20739566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "cell[%d] grad (%g, %g)\n", cell, grad[0], grad[1]));
20743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2075c0ce001eSMatthew G. Knepley }
2076c0ce001eSMatthew G. Knepley #endif
2077c0ce001eSMatthew G. Knepley 
2078c0ce001eSMatthew G. Knepley /*
2079c0ce001eSMatthew G. Knepley   PetscFVComputeGradient - Compute the gradient reconstruction matrix for a given cell
2080c0ce001eSMatthew G. Knepley 
2081c0ce001eSMatthew G. Knepley   Input Parameters:
2082dce8aebaSBarry Smith + fvm      - The `PetscFV` object
2083c0ce001eSMatthew G. Knepley . numFaces - The number of cell faces which are not constrained
2084c0ce001eSMatthew G. Knepley . dx       - The vector from the cell centroid to the neighboring cell centroid for each face
2085c0ce001eSMatthew G. Knepley 
2086c0ce001eSMatthew G. Knepley   Level: developer
2087c0ce001eSMatthew G. Knepley 
2088dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVCreate()`
2089c0ce001eSMatthew G. Knepley */
2090d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVComputeGradient_LeastSquares(PetscFV fvm, PetscInt numFaces, const PetscScalar dx[], PetscScalar grad[])
2091d71ae5a4SJacob Faibussowitsch {
2092c0ce001eSMatthew G. Knepley   PetscFV_LeastSquares *ls       = (PetscFV_LeastSquares *)fvm->data;
2093c0ce001eSMatthew G. Knepley   const PetscBool       useSVD   = PETSC_TRUE;
2094c0ce001eSMatthew G. Knepley   const PetscInt        maxFaces = ls->maxFaces;
2095c0ce001eSMatthew G. Knepley   PetscInt              dim, f, d;
2096c0ce001eSMatthew G. Knepley 
2097c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2098c0ce001eSMatthew G. Knepley   if (numFaces > maxFaces) {
209908401ef6SPierre Jolivet     PetscCheck(maxFaces >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Reconstruction has not been initialized, call PetscFVLeastSquaresSetMaxFaces()");
210063a3b9bcSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input faces %" PetscInt_FMT " > %" PetscInt_FMT " maxfaces", numFaces, maxFaces);
2101c0ce001eSMatthew G. Knepley   }
21029566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
2103c0ce001eSMatthew G. Knepley   for (f = 0; f < numFaces; ++f) {
2104c0ce001eSMatthew G. Knepley     for (d = 0; d < dim; ++d) ls->B[d * maxFaces + f] = dx[f * dim + d];
2105c0ce001eSMatthew G. Knepley   }
2106c0ce001eSMatthew G. Knepley   /* Overwrites B with garbage, returns Binv in row-major format */
2107736d4f42SpierreXVI   if (useSVD) {
2108736d4f42SpierreXVI     PetscInt maxmn = PetscMax(numFaces, dim);
21099566063dSJacob Faibussowitsch     PetscCall(PetscFVLeastSquaresPseudoInverseSVD_Static(numFaces, maxFaces, dim, ls->B, ls->Binv, ls->tau, ls->workSize, ls->work));
2110736d4f42SpierreXVI     /* Binv shaped in column-major, coldim=maxmn.*/
2111736d4f42SpierreXVI     for (f = 0; f < numFaces; ++f) {
2112736d4f42SpierreXVI       for (d = 0; d < dim; ++d) grad[f * dim + d] = ls->Binv[d + maxmn * f];
2113736d4f42SpierreXVI     }
2114736d4f42SpierreXVI   } else {
21159566063dSJacob Faibussowitsch     PetscCall(PetscFVLeastSquaresPseudoInverse_Static(numFaces, maxFaces, dim, ls->B, ls->Binv, ls->tau, ls->workSize, ls->work));
2116736d4f42SpierreXVI     /* Binv shaped in row-major, rowdim=maxFaces.*/
2117c0ce001eSMatthew G. Knepley     for (f = 0; f < numFaces; ++f) {
2118c0ce001eSMatthew G. Knepley       for (d = 0; d < dim; ++d) grad[f * dim + d] = ls->Binv[d * maxFaces + f];
2119c0ce001eSMatthew G. Knepley     }
2120736d4f42SpierreXVI   }
21213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2122c0ce001eSMatthew G. Knepley }
2123c0ce001eSMatthew G. Knepley 
2124c0ce001eSMatthew G. Knepley /*
2125c0ce001eSMatthew G. Knepley   neighborVol[f*2+0] contains the left  geom
2126c0ce001eSMatthew G. Knepley   neighborVol[f*2+1] contains the right geom
2127c0ce001eSMatthew G. Knepley */
2128d71ae5a4SJacob 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[])
2129d71ae5a4SJacob Faibussowitsch {
2130c0ce001eSMatthew G. Knepley   void (*riemann)(PetscInt, PetscInt, const PetscReal[], const PetscReal[], const PetscScalar[], const PetscScalar[], PetscInt, const PetscScalar[], PetscScalar[], void *);
2131c0ce001eSMatthew G. Knepley   void              *rctx;
2132c0ce001eSMatthew G. Knepley   PetscScalar       *flux = fvm->fluxWork;
2133c0ce001eSMatthew G. Knepley   const PetscScalar *constants;
2134c0ce001eSMatthew G. Knepley   PetscInt           dim, numConstants, pdim, Nc, totDim, off, f, d;
2135c0ce001eSMatthew G. Knepley 
2136c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
21379566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(prob, &Nc));
21389566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
21399566063dSJacob Faibussowitsch   PetscCall(PetscDSGetFieldOffset(prob, field, &off));
21409566063dSJacob Faibussowitsch   PetscCall(PetscDSGetRiemannSolver(prob, field, &riemann));
21419566063dSJacob Faibussowitsch   PetscCall(PetscDSGetContext(prob, field, &rctx));
21429566063dSJacob Faibussowitsch   PetscCall(PetscDSGetConstants(prob, &numConstants, &constants));
21439566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
21449566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fvm, &pdim));
2145c0ce001eSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
2146c0ce001eSMatthew G. Knepley     (*riemann)(dim, pdim, fgeom[f].centroid, fgeom[f].normal, &uL[f * Nc], &uR[f * Nc], numConstants, constants, flux, rctx);
2147c0ce001eSMatthew G. Knepley     for (d = 0; d < pdim; ++d) {
2148c0ce001eSMatthew G. Knepley       fluxL[f * totDim + off + d] = flux[d] / neighborVol[f * 2 + 0];
2149c0ce001eSMatthew G. Knepley       fluxR[f * totDim + off + d] = flux[d] / neighborVol[f * 2 + 1];
2150c0ce001eSMatthew G. Knepley     }
2151c0ce001eSMatthew G. Knepley   }
21523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2153c0ce001eSMatthew G. Knepley }
2154c0ce001eSMatthew G. Knepley 
2155d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVLeastSquaresSetMaxFaces_LS(PetscFV fvm, PetscInt maxFaces)
2156d71ae5a4SJacob Faibussowitsch {
2157c0ce001eSMatthew G. Knepley   PetscFV_LeastSquares *ls = (PetscFV_LeastSquares *)fvm->data;
2158736d4f42SpierreXVI   PetscInt              dim, m, n, nrhs, minmn, maxmn;
2159c0ce001eSMatthew G. Knepley 
2160c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2161c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
21629566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
21639566063dSJacob Faibussowitsch   PetscCall(PetscFree4(ls->B, ls->Binv, ls->tau, ls->work));
2164c0ce001eSMatthew G. Knepley   ls->maxFaces = maxFaces;
2165c0ce001eSMatthew G. Knepley   m            = ls->maxFaces;
2166c0ce001eSMatthew G. Knepley   n            = dim;
2167c0ce001eSMatthew G. Knepley   nrhs         = ls->maxFaces;
2168736d4f42SpierreXVI   minmn        = PetscMin(m, n);
2169736d4f42SpierreXVI   maxmn        = PetscMax(m, n);
2170736d4f42SpierreXVI   ls->workSize = 3 * minmn + PetscMax(2 * minmn, PetscMax(maxmn, nrhs)); /* required by LAPACK */
21719566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(m * n, &ls->B, maxmn * maxmn, &ls->Binv, minmn, &ls->tau, ls->workSize, &ls->work));
21723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2173c0ce001eSMatthew G. Knepley }
2174c0ce001eSMatthew G. Knepley 
217566976f2fSJacob Faibussowitsch static PetscErrorCode PetscFVInitialize_LeastSquares(PetscFV fvm)
2176d71ae5a4SJacob Faibussowitsch {
2177c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2178c0ce001eSMatthew G. Knepley   fvm->ops->setfromoptions       = NULL;
2179c0ce001eSMatthew G. Knepley   fvm->ops->setup                = PetscFVSetUp_LeastSquares;
2180c0ce001eSMatthew G. Knepley   fvm->ops->view                 = PetscFVView_LeastSquares;
2181c0ce001eSMatthew G. Knepley   fvm->ops->destroy              = PetscFVDestroy_LeastSquares;
2182c0ce001eSMatthew G. Knepley   fvm->ops->computegradient      = PetscFVComputeGradient_LeastSquares;
2183c0ce001eSMatthew G. Knepley   fvm->ops->integraterhsfunction = PetscFVIntegrateRHSFunction_LeastSquares;
21843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2185c0ce001eSMatthew G. Knepley }
2186c0ce001eSMatthew G. Knepley 
2187c0ce001eSMatthew G. Knepley /*MC
2188dce8aebaSBarry Smith   PETSCFVLEASTSQUARES = "leastsquares" - A `PetscFV` implementation
2189c0ce001eSMatthew G. Knepley 
2190c0ce001eSMatthew G. Knepley   Level: intermediate
2191c0ce001eSMatthew G. Knepley 
2192dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVCreate()`, `PetscFVSetType()`
2193c0ce001eSMatthew G. Knepley M*/
2194c0ce001eSMatthew G. Knepley 
2195d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscFVCreate_LeastSquares(PetscFV fvm)
2196d71ae5a4SJacob Faibussowitsch {
2197c0ce001eSMatthew G. Knepley   PetscFV_LeastSquares *ls;
2198c0ce001eSMatthew G. Knepley 
2199c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2200c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
22014dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&ls));
2202c0ce001eSMatthew G. Knepley   fvm->data = ls;
2203c0ce001eSMatthew G. Knepley 
2204c0ce001eSMatthew G. Knepley   ls->maxFaces = -1;
2205c0ce001eSMatthew G. Knepley   ls->workSize = -1;
2206c0ce001eSMatthew G. Knepley   ls->B        = NULL;
2207c0ce001eSMatthew G. Knepley   ls->Binv     = NULL;
2208c0ce001eSMatthew G. Knepley   ls->tau      = NULL;
2209c0ce001eSMatthew G. Knepley   ls->work     = NULL;
2210c0ce001eSMatthew G. Knepley 
22119566063dSJacob Faibussowitsch   PetscCall(PetscFVSetComputeGradients(fvm, PETSC_TRUE));
22129566063dSJacob Faibussowitsch   PetscCall(PetscFVInitialize_LeastSquares(fvm));
22139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fvm, "PetscFVLeastSquaresSetMaxFaces_C", PetscFVLeastSquaresSetMaxFaces_LS));
22143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2215c0ce001eSMatthew G. Knepley }
2216c0ce001eSMatthew G. Knepley 
2217c0ce001eSMatthew G. Knepley /*@
2218c0ce001eSMatthew G. Knepley   PetscFVLeastSquaresSetMaxFaces - Set the maximum number of cell faces for gradient reconstruction
2219c0ce001eSMatthew G. Knepley 
222020f4b53cSBarry Smith   Not Collective
2221c0ce001eSMatthew G. Knepley 
222260225df5SJacob Faibussowitsch   Input Parameters:
2223dce8aebaSBarry Smith + fvm      - The `PetscFV` object
2224c0ce001eSMatthew G. Knepley - maxFaces - The maximum number of cell faces
2225c0ce001eSMatthew G. Knepley 
2226c0ce001eSMatthew G. Knepley   Level: intermediate
2227c0ce001eSMatthew G. Knepley 
2228dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVCreate()`, `PETSCFVLEASTSQUARES`, `PetscFVComputeGradient()`
2229c0ce001eSMatthew G. Knepley @*/
2230d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVLeastSquaresSetMaxFaces(PetscFV fvm, PetscInt maxFaces)
2231d71ae5a4SJacob Faibussowitsch {
2232c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2233c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
2234cac4c232SBarry Smith   PetscTryMethod(fvm, "PetscFVLeastSquaresSetMaxFaces_C", (PetscFV, PetscInt), (fvm, maxFaces));
22353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2236c0ce001eSMatthew G. Knepley }
2237