xref: /petsc/src/dm/dt/fv/interface/fv.c (revision a4e35b1925eceef64945ea472b84f2bf06a67b5e)
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 
1156dce8aebaSBarry Smith .seealso: `PetscFVSet`, `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:
1268*a4e35b19SJacob 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 
1673*a4e35b19SJacob Faibussowitsch   Output Parameter:
1674*a4e35b19SJacob Faibussowitsch . grad - the gradient
1675*a4e35b19SJacob 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 /*@
1720*a4e35b19SJacob Faibussowitsch   PetscFVRefine - Create a "refined" `PetscFV` object that refines the reference cell into
1721*a4e35b19SJacob 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 
1731*a4e35b19SJacob Faibussowitsch   Notes:
1732*a4e35b19SJacob Faibussowitsch   This is typically used to generate a preconditioner for a high order method from a lower order method on a
1733*a4e35b19SJacob Faibussowitsch   refined mesh having the same number of dofs (but more sparsity). It is also used to create an
1734*a4e35b19SJacob Faibussowitsch   interpolation between regularly refined meshes.
1735*a4e35b19SJacob 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 
2175d71ae5a4SJacob Faibussowitsch 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