xref: /petsc/src/dm/dt/fv/interface/fv.c (revision dce8aeba1c9b69b19f651c53d8a6b674bd7e9cbd)
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
20*dce8aebaSBarry Smith   PetscLimiterRegister - Adds a new `PetscLimiter` implementation
21c0ce001eSMatthew G. Knepley 
22c0ce001eSMatthew G. Knepley   Not Collective
23c0ce001eSMatthew G. Knepley 
24c0ce001eSMatthew G. Knepley   Input Parameters:
25c0ce001eSMatthew G. Knepley + name        - The name of a new user-defined creation routine
26c0ce001eSMatthew G. Knepley - create_func - The creation routine itself
27c0ce001eSMatthew G. Knepley 
28c0ce001eSMatthew G. Knepley   Sample usage:
29c0ce001eSMatthew G. Knepley .vb
30c0ce001eSMatthew G. Knepley     PetscLimiterRegister("my_lim", MyPetscLimiterCreate);
31c0ce001eSMatthew G. Knepley .ve
32c0ce001eSMatthew G. Knepley 
33*dce8aebaSBarry 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 
45*dce8aebaSBarry Smith   Note:
46*dce8aebaSBarry Smith   `PetscLimiterRegister()` may be called multiple times to add several user-defined PetscLimiters
47c0ce001eSMatthew G. Knepley 
48*dce8aebaSBarry 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));
54c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
55c0ce001eSMatthew G. Knepley }
56c0ce001eSMatthew G. Knepley 
57c0ce001eSMatthew G. Knepley /*@C
58*dce8aebaSBarry Smith   PetscLimiterSetType - Builds a `PetscLimiter` for a given `PetscLimiterType`
59c0ce001eSMatthew G. Knepley 
60c0ce001eSMatthew G. Knepley   Collective on lim
61c0ce001eSMatthew G. Knepley 
62c0ce001eSMatthew G. Knepley   Input Parameters:
63*dce8aebaSBarry 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 
71*dce8aebaSBarry 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));
81c0ce001eSMatthew G. Knepley   if (match) PetscFunctionReturn(0);
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));
93c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
94c0ce001eSMatthew G. Knepley }
95c0ce001eSMatthew G. Knepley 
96c0ce001eSMatthew G. Knepley /*@C
97*dce8aebaSBarry 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:
102*dce8aebaSBarry Smith . lim  - The `PetscLimiter`
103c0ce001eSMatthew G. Knepley 
104c0ce001eSMatthew G. Knepley   Output Parameter:
105*dce8aebaSBarry Smith . name - The `PetscLimiterType`
106c0ce001eSMatthew G. Knepley 
107c0ce001eSMatthew G. Knepley   Level: intermediate
108c0ce001eSMatthew G. Knepley 
109*dce8aebaSBarry 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);
115c0ce001eSMatthew G. Knepley   PetscValidPointer(name, 2);
1169566063dSJacob Faibussowitsch   PetscCall(PetscLimiterRegisterAll());
117c0ce001eSMatthew G. Knepley   *name = ((PetscObject)lim)->type_name;
118c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
119c0ce001eSMatthew G. Knepley }
120c0ce001eSMatthew G. Knepley 
121c0ce001eSMatthew G. Knepley /*@C
122*dce8aebaSBarry Smith    PetscLimiterViewFromOptions - View a `PetscLimiter` based on values in the options database
123fe2efc57SMark 
124*dce8aebaSBarry Smith    Collective on A
125fe2efc57SMark 
126fe2efc57SMark    Input Parameters:
127*dce8aebaSBarry Smith +  A - the `PetscLimiter` object to view
128*dce8aebaSBarry Smith .  obj - Optional object that provides the options prefix to use
129*dce8aebaSBarry Smith -  name - command line option name
130fe2efc57SMark 
131fe2efc57SMark    Level: intermediate
132*dce8aebaSBarry Smith 
133*dce8aebaSBarry 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));
140fe2efc57SMark   PetscFunctionReturn(0);
141fe2efc57SMark }
142fe2efc57SMark 
143fe2efc57SMark /*@C
144*dce8aebaSBarry Smith   PetscLimiterView - Views a `PetscLimiter`
145c0ce001eSMatthew G. Knepley 
146c0ce001eSMatthew G. Knepley   Collective on lim
147c0ce001eSMatthew G. Knepley 
148d8d19677SJose E. Roman   Input Parameters:
149*dce8aebaSBarry Smith + lim - the `PetscLimiter` object to view
150c0ce001eSMatthew G. Knepley - v   - the viewer
151c0ce001eSMatthew G. Knepley 
15288f5f89eSMatthew G. Knepley   Level: beginner
153c0ce001eSMatthew G. Knepley 
154*dce8aebaSBarry 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);
162c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
163c0ce001eSMatthew G. Knepley }
164c0ce001eSMatthew G. Knepley 
165c0ce001eSMatthew G. Knepley /*@
166*dce8aebaSBarry Smith   PetscLimiterSetFromOptions - sets parameters in a `PetscLimiter` from the options database
167c0ce001eSMatthew G. Knepley 
168c0ce001eSMatthew G. Knepley   Collective on lim
169c0ce001eSMatthew G. Knepley 
170c0ce001eSMatthew G. Knepley   Input Parameter:
171*dce8aebaSBarry Smith . lim - the `PetscLimiter` object to set options for
172c0ce001eSMatthew G. Knepley 
17388f5f89eSMatthew G. Knepley   Level: intermediate
174c0ce001eSMatthew G. Knepley 
175*dce8aebaSBarry 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"));
201c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
202c0ce001eSMatthew G. Knepley }
203c0ce001eSMatthew G. Knepley 
204c0ce001eSMatthew G. Knepley /*@C
205*dce8aebaSBarry Smith   PetscLimiterSetUp - Construct data structures for the `PetscLimiter`
206c0ce001eSMatthew G. Knepley 
207c0ce001eSMatthew G. Knepley   Collective on lim
208c0ce001eSMatthew G. Knepley 
209c0ce001eSMatthew G. Knepley   Input Parameter:
210*dce8aebaSBarry Smith . lim - the `PetscLimiter` object to setup
211c0ce001eSMatthew G. Knepley 
21288f5f89eSMatthew G. Knepley   Level: intermediate
213c0ce001eSMatthew G. Knepley 
214*dce8aebaSBarry 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);
221c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
222c0ce001eSMatthew G. Knepley }
223c0ce001eSMatthew G. Knepley 
224c0ce001eSMatthew G. Knepley /*@
225*dce8aebaSBarry Smith   PetscLimiterDestroy - Destroys a `PetscLimiter` object
226c0ce001eSMatthew G. Knepley 
227c0ce001eSMatthew G. Knepley   Collective on lim
228c0ce001eSMatthew G. Knepley 
229c0ce001eSMatthew G. Knepley   Input Parameter:
230*dce8aebaSBarry Smith . lim - the `PetscLimiter` object to destroy
231c0ce001eSMatthew G. Knepley 
23288f5f89eSMatthew G. Knepley   Level: beginner
233c0ce001eSMatthew G. Knepley 
234*dce8aebaSBarry Smith .seealso: `PetscLimiter`, `PetscLimiterView()`
235c0ce001eSMatthew G. Knepley @*/
236d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscLimiterDestroy(PetscLimiter *lim)
237d71ae5a4SJacob Faibussowitsch {
238c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
239c0ce001eSMatthew G. Knepley   if (!*lim) PetscFunctionReturn(0);
240c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific((*lim), PETSCLIMITER_CLASSID, 1);
241c0ce001eSMatthew G. Knepley 
2429371c9d4SSatish Balay   if (--((PetscObject)(*lim))->refct > 0) {
2439371c9d4SSatish Balay     *lim = NULL;
2449371c9d4SSatish Balay     PetscFunctionReturn(0);
2459371c9d4SSatish Balay   }
246c0ce001eSMatthew G. Knepley   ((PetscObject)(*lim))->refct = 0;
247c0ce001eSMatthew G. Knepley 
248dbbe0bcdSBarry Smith   PetscTryTypeMethod((*lim), destroy);
2499566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(lim));
250c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
251c0ce001eSMatthew G. Knepley }
252c0ce001eSMatthew G. Knepley 
253c0ce001eSMatthew G. Knepley /*@
254*dce8aebaSBarry 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:
259*dce8aebaSBarry Smith . comm - The communicator for the `PetscLimiter` object
260c0ce001eSMatthew G. Knepley 
261c0ce001eSMatthew G. Knepley   Output Parameter:
262*dce8aebaSBarry Smith . lim - The `PetscLimiter` object
263c0ce001eSMatthew G. Knepley 
264c0ce001eSMatthew G. Knepley   Level: beginner
265c0ce001eSMatthew G. Knepley 
266*dce8aebaSBarry Smith .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;
273c0ce001eSMatthew G. Knepley   PetscValidPointer(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;
281c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
282c0ce001eSMatthew G. Knepley }
283c0ce001eSMatthew G. Knepley 
28488f5f89eSMatthew G. Knepley /*@
28588f5f89eSMatthew G. Knepley   PetscLimiterLimit - Limit the flux
28688f5f89eSMatthew G. Knepley 
28788f5f89eSMatthew G. Knepley   Input Parameters:
288*dce8aebaSBarry 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 
296*dce8aebaSBarry Smith   Note:
297*dce8aebaSBarry Smith   Limiters given in symmetric form following Berger, Aftosmis, and Murman 2005
298*dce8aebaSBarry Smith .vb
299*dce8aebaSBarry Smith  The classical flux-limited formulation is psi(r) where
300*dce8aebaSBarry Smith 
301*dce8aebaSBarry Smith  r = (u[0] - u[-1]) / (u[1] - u[0])
302*dce8aebaSBarry Smith 
303*dce8aebaSBarry Smith  The second order TVD region is bounded by
304*dce8aebaSBarry Smith 
305*dce8aebaSBarry Smith  psi_minmod(r) = min(r,1)      and        psi_superbee(r) = min(2, 2r, max(1,r))
306*dce8aebaSBarry Smith 
307*dce8aebaSBarry Smith  where all limiters are implicitly clipped to be non-negative. A more convenient slope-limited form is psi(r) =
308*dce8aebaSBarry Smith  phi(r)(r+1)/2 in which the reconstructed interface values are
309*dce8aebaSBarry Smith 
310*dce8aebaSBarry Smith  u(v) = u[0] + phi(r) (grad u)[0] v
311*dce8aebaSBarry Smith 
312*dce8aebaSBarry Smith  where v is the vector from centroid to quadrature point. In these variables, the usual limiters become
313*dce8aebaSBarry Smith 
314*dce8aebaSBarry 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))
315*dce8aebaSBarry Smith 
316*dce8aebaSBarry Smith  For a nicer symmetric formulation, rewrite in terms of
317*dce8aebaSBarry Smith 
318*dce8aebaSBarry Smith  f = (u[0] - u[-1]) / (u[1] - u[-1])
319*dce8aebaSBarry Smith 
320*dce8aebaSBarry Smith  where r(f) = f/(1-f). Not that r(1-f) = (1-f)/f = 1/r(f) so the symmetry condition
321*dce8aebaSBarry Smith 
322*dce8aebaSBarry Smith  phi(r) = phi(1/r)
323*dce8aebaSBarry Smith 
324*dce8aebaSBarry Smith  becomes
325*dce8aebaSBarry Smith 
326*dce8aebaSBarry Smith  w(f) = w(1-f).
327*dce8aebaSBarry Smith 
328*dce8aebaSBarry Smith  The limiters below implement this final form w(f). The reference methods are
329*dce8aebaSBarry Smith 
330*dce8aebaSBarry Smith  w_minmod(f) = 2 min(f,(1-f))             w_superbee(r) = 4 min((1-f), f)
331*dce8aebaSBarry Smith .ve
332*dce8aebaSBarry Smith 
333*dce8aebaSBarry 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);
339dadcf809SJacob Faibussowitsch   PetscValidRealPointer(phi, 3);
340dbbe0bcdSBarry Smith   PetscUseTypeMethod(lim, limit, flim, phi);
341c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
350c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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"));
360c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
372c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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)));
379c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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;
388c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
389c0ce001eSMatthew G. Knepley }
390c0ce001eSMatthew G. Knepley 
391c0ce001eSMatthew G. Knepley /*MC
392*dce8aebaSBarry Smith   PETSCLIMITERSIN = "sin" - A `PetscLimiter` implementation
393c0ce001eSMatthew G. Knepley 
394c0ce001eSMatthew G. Knepley   Level: intermediate
395c0ce001eSMatthew G. Knepley 
396*dce8aebaSBarry 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));
409c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
418c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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"));
428c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
440c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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;
447c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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;
456c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
457c0ce001eSMatthew G. Knepley }
458c0ce001eSMatthew G. Knepley 
459c0ce001eSMatthew G. Knepley /*MC
460*dce8aebaSBarry Smith   PETSCLIMITERZERO = "zero" - A simple `PetscLimiter` implementation
461c0ce001eSMatthew G. Knepley 
462c0ce001eSMatthew G. Knepley   Level: intermediate
463c0ce001eSMatthew G. Knepley 
464*dce8aebaSBarry 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));
477c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
486c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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"));
496c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
508c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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;
515c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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;
524c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
525c0ce001eSMatthew G. Knepley }
526c0ce001eSMatthew G. Knepley 
527c0ce001eSMatthew G. Knepley /*MC
528*dce8aebaSBarry Smith   PETSCLIMITERNONE = "none" - A trivial `PetscLimiter` implementation
529c0ce001eSMatthew G. Knepley 
530c0ce001eSMatthew G. Knepley   Level: intermediate
531c0ce001eSMatthew G. Knepley 
532*dce8aebaSBarry 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));
545c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
554c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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"));
564c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
576c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
583c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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;
592c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
593c0ce001eSMatthew G. Knepley }
594c0ce001eSMatthew G. Knepley 
595c0ce001eSMatthew G. Knepley /*MC
596*dce8aebaSBarry Smith   PETSCLIMITERMINMOD = "minmod" - A `PetscLimiter` implementation
597c0ce001eSMatthew G. Knepley 
598c0ce001eSMatthew G. Knepley   Level: intermediate
599c0ce001eSMatthew G. Knepley 
600*dce8aebaSBarry 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));
613c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
622c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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"));
632c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
644c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
651c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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;
660c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
661c0ce001eSMatthew G. Knepley }
662c0ce001eSMatthew G. Knepley 
663c0ce001eSMatthew G. Knepley /*MC
664*dce8aebaSBarry Smith   PETSCLIMITERVANLEER = "vanleer" - A `PetscLimiter` implementation
665c0ce001eSMatthew G. Knepley 
666c0ce001eSMatthew G. Knepley   Level: intermediate
667c0ce001eSMatthew G. Knepley 
668*dce8aebaSBarry 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));
681c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
690c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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"));
700c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
712c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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)));
719c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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;
728c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
729c0ce001eSMatthew G. Knepley }
730c0ce001eSMatthew G. Knepley 
731c0ce001eSMatthew G. Knepley /*MC
732*dce8aebaSBarry Smith   PETSCLIMITERVANALBADA = "vanalbada" - A PetscLimiter implementation
733c0ce001eSMatthew G. Knepley 
734c0ce001eSMatthew G. Knepley   Level: intermediate
735c0ce001eSMatthew G. Knepley 
736*dce8aebaSBarry 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));
749c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
758c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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"));
768c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
780c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
787c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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;
796c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
797c0ce001eSMatthew G. Knepley }
798c0ce001eSMatthew G. Knepley 
799c0ce001eSMatthew G. Knepley /*MC
800*dce8aebaSBarry Smith   PETSCLIMITERSUPERBEE = "superbee" - A `PetscLimiter` implementation
801c0ce001eSMatthew G. Knepley 
802c0ce001eSMatthew G. Knepley   Level: intermediate
803c0ce001eSMatthew G. Knepley 
804*dce8aebaSBarry 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));
817c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
826c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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"));
836c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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));
848c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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)));
856c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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;
865c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
866c0ce001eSMatthew G. Knepley }
867c0ce001eSMatthew G. Knepley 
868c0ce001eSMatthew G. Knepley /*MC
869*dce8aebaSBarry Smith   PETSCLIMITERMC = "mc" - A `PetscLimiter` implementation
870c0ce001eSMatthew G. Knepley 
871c0ce001eSMatthew G. Knepley   Level: intermediate
872c0ce001eSMatthew G. Knepley 
873*dce8aebaSBarry 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));
886c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
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
895*dce8aebaSBarry Smith   PetscFVRegister - Adds a new `PetscFV` implementation
896c0ce001eSMatthew G. Knepley 
897c0ce001eSMatthew G. Knepley   Not Collective
898c0ce001eSMatthew G. Knepley 
899c0ce001eSMatthew G. Knepley   Input Parameters:
900c0ce001eSMatthew G. Knepley + name        - The name of a new user-defined creation routine
901c0ce001eSMatthew G. Knepley - create_func - The creation routine itself
902c0ce001eSMatthew G. Knepley 
903c0ce001eSMatthew G. Knepley   Sample 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 
920*dce8aebaSBarry Smith   Note:
921*dce8aebaSBarry Smith   `PetscFVRegister()` may be called multiple times to add several user-defined PetscFVs
922c0ce001eSMatthew G. Knepley 
923*dce8aebaSBarry 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));
929c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
930c0ce001eSMatthew G. Knepley }
931c0ce001eSMatthew G. Knepley 
932c0ce001eSMatthew G. Knepley /*@C
933*dce8aebaSBarry Smith   PetscFVSetType - Builds a particular `PetscFV`
934c0ce001eSMatthew G. Knepley 
935c0ce001eSMatthew G. Knepley   Collective on fvm
936c0ce001eSMatthew G. Knepley 
937c0ce001eSMatthew G. Knepley   Input Parameters:
938*dce8aebaSBarry Smith + fvm  - The `PetscFV` object
939*dce8aebaSBarry Smith - name - The type of FVM space
940c0ce001eSMatthew G. Knepley 
941c0ce001eSMatthew G. Knepley   Options Database Key:
942*dce8aebaSBarry 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 
946*dce8aebaSBarry 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));
956c0ce001eSMatthew G. Knepley   if (match) PetscFunctionReturn(0);
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));
967c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
968c0ce001eSMatthew G. Knepley }
969c0ce001eSMatthew G. Knepley 
970c0ce001eSMatthew G. Knepley /*@C
971*dce8aebaSBarry 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:
976*dce8aebaSBarry Smith . fvm  - The `PetscFV`
977c0ce001eSMatthew G. Knepley 
978c0ce001eSMatthew G. Knepley   Output Parameter:
979*dce8aebaSBarry Smith . name - The `PetscFVType` name
980c0ce001eSMatthew G. Knepley 
981c0ce001eSMatthew G. Knepley   Level: intermediate
982c0ce001eSMatthew G. Knepley 
983*dce8aebaSBarry 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);
989c0ce001eSMatthew G. Knepley   PetscValidPointer(name, 2);
9909566063dSJacob Faibussowitsch   PetscCall(PetscFVRegisterAll());
991c0ce001eSMatthew G. Knepley   *name = ((PetscObject)fvm)->type_name;
992c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
993c0ce001eSMatthew G. Knepley }
994c0ce001eSMatthew G. Knepley 
995c0ce001eSMatthew G. Knepley /*@C
996*dce8aebaSBarry Smith    PetscFVViewFromOptions - View a `PetscFV` based on values in the options database
997fe2efc57SMark 
998*dce8aebaSBarry Smith    Collective on A
999fe2efc57SMark 
1000fe2efc57SMark    Input Parameters:
1001*dce8aebaSBarry Smith +  A - the `PetscFV` object
1002*dce8aebaSBarry Smith .  obj - Optional object that provides the options prefix
1003*dce8aebaSBarry Smith -  name - command line option name
1004fe2efc57SMark 
1005fe2efc57SMark    Level: intermediate
1006*dce8aebaSBarry Smith 
1007*dce8aebaSBarry 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));
1014fe2efc57SMark   PetscFunctionReturn(0);
1015fe2efc57SMark }
1016fe2efc57SMark 
1017fe2efc57SMark /*@C
1018*dce8aebaSBarry Smith   PetscFVView - Views a `PetscFV`
1019c0ce001eSMatthew G. Knepley 
1020c0ce001eSMatthew G. Knepley   Collective on fvm
1021c0ce001eSMatthew G. Knepley 
1022d8d19677SJose E. Roman   Input Parameters:
1023*dce8aebaSBarry Smith + fvm - the `PetscFV` object to view
1024c0ce001eSMatthew G. Knepley - v   - the viewer
1025c0ce001eSMatthew G. Knepley 
102688f5f89eSMatthew G. Knepley   Level: beginner
1027c0ce001eSMatthew G. Knepley 
1028*dce8aebaSBarry 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);
1036c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1037c0ce001eSMatthew G. Knepley }
1038c0ce001eSMatthew G. Knepley 
1039c0ce001eSMatthew G. Knepley /*@
1040*dce8aebaSBarry Smith   PetscFVSetFromOptions - sets parameters in a `PetscFV` from the options database
1041c0ce001eSMatthew G. Knepley 
1042c0ce001eSMatthew G. Knepley   Collective on fvm
1043c0ce001eSMatthew G. Knepley 
1044c0ce001eSMatthew G. Knepley   Input Parameter:
1045*dce8aebaSBarry 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 
1052*dce8aebaSBarry 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"));
1080c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1081c0ce001eSMatthew G. Knepley }
1082c0ce001eSMatthew G. Knepley 
1083c0ce001eSMatthew G. Knepley /*@
1084*dce8aebaSBarry Smith   PetscFVSetUp - Setup the data structures for the `PetscFV` based on the `PetscFVType` provided by `PetscFVSetType()`
1085c0ce001eSMatthew G. Knepley 
1086c0ce001eSMatthew G. Knepley   Collective on fvm
1087c0ce001eSMatthew G. Knepley 
1088c0ce001eSMatthew G. Knepley   Input Parameter:
1089*dce8aebaSBarry Smith . fvm - the `PetscFV` object to setup
1090c0ce001eSMatthew G. Knepley 
109188f5f89eSMatthew G. Knepley   Level: intermediate
1092c0ce001eSMatthew G. Knepley 
1093*dce8aebaSBarry 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);
1101c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1102c0ce001eSMatthew G. Knepley }
1103c0ce001eSMatthew G. Knepley 
1104c0ce001eSMatthew G. Knepley /*@
1105*dce8aebaSBarry Smith   PetscFVDestroy - Destroys a `PetscFV` object
1106c0ce001eSMatthew G. Knepley 
1107c0ce001eSMatthew G. Knepley   Collective on fvm
1108c0ce001eSMatthew G. Knepley 
1109c0ce001eSMatthew G. Knepley   Input Parameter:
1110*dce8aebaSBarry Smith . fvm - the `PetscFV` object to destroy
1111c0ce001eSMatthew G. Knepley 
111288f5f89eSMatthew G. Knepley   Level: beginner
1113c0ce001eSMatthew G. Knepley 
1114*dce8aebaSBarry 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;
1121c0ce001eSMatthew G. Knepley   if (!*fvm) PetscFunctionReturn(0);
1122c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific((*fvm), PETSCFV_CLASSID, 1);
1123c0ce001eSMatthew G. Knepley 
11249371c9d4SSatish Balay   if (--((PetscObject)(*fvm))->refct > 0) {
11259371c9d4SSatish Balay     *fvm = NULL;
11269371c9d4SSatish Balay     PetscFunctionReturn(0);
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));
1140c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1141c0ce001eSMatthew G. Knepley }
1142c0ce001eSMatthew G. Knepley 
1143c0ce001eSMatthew G. Knepley /*@
1144*dce8aebaSBarry 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:
1149*dce8aebaSBarry Smith . comm - The communicator for the `PetscFV` object
1150c0ce001eSMatthew G. Knepley 
1151c0ce001eSMatthew G. Knepley   Output Parameter:
1152*dce8aebaSBarry Smith . fvm - The `PetscFV` object
1153c0ce001eSMatthew G. Knepley 
1154c0ce001eSMatthew G. Knepley   Level: beginner
1155c0ce001eSMatthew G. Knepley 
1156*dce8aebaSBarry 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;
1163c0ce001eSMatthew G. Knepley   PetscValidPointer(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;
1178c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1179c0ce001eSMatthew G. Knepley }
1180c0ce001eSMatthew G. Knepley 
1181c0ce001eSMatthew G. Knepley /*@
1182*dce8aebaSBarry Smith   PetscFVSetLimiter - Set the `PetscLimiter` to the `PetscFV`
1183c0ce001eSMatthew G. Knepley 
1184c0ce001eSMatthew G. Knepley   Logically collective on fvm
1185c0ce001eSMatthew G. Knepley 
1186c0ce001eSMatthew G. Knepley   Input Parameters:
1187*dce8aebaSBarry Smith + fvm - the `PetscFV` object
1188*dce8aebaSBarry Smith - lim - The `PetscLimiter`
1189c0ce001eSMatthew G. Knepley 
119088f5f89eSMatthew G. Knepley   Level: intermediate
1191c0ce001eSMatthew G. Knepley 
1192*dce8aebaSBarry 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;
1202c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1203c0ce001eSMatthew G. Knepley }
1204c0ce001eSMatthew G. Knepley 
1205c0ce001eSMatthew G. Knepley /*@
1206*dce8aebaSBarry Smith   PetscFVGetLimiter - Get the `PetscLimiter` object from the `PetscFV`
1207c0ce001eSMatthew G. Knepley 
1208c0ce001eSMatthew G. Knepley   Not collective
1209c0ce001eSMatthew G. Knepley 
1210c0ce001eSMatthew G. Knepley   Input Parameter:
1211*dce8aebaSBarry Smith . fvm - the `PetscFV` object
1212c0ce001eSMatthew G. Knepley 
1213c0ce001eSMatthew G. Knepley   Output Parameter:
1214*dce8aebaSBarry Smith . lim - The `PetscLimiter`
1215c0ce001eSMatthew G. Knepley 
121688f5f89eSMatthew G. Knepley   Level: intermediate
1217c0ce001eSMatthew G. Knepley 
1218*dce8aebaSBarry 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);
1224c0ce001eSMatthew G. Knepley   PetscValidPointer(lim, 2);
1225c0ce001eSMatthew G. Knepley   *lim = fvm->limiter;
1226c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1227c0ce001eSMatthew G. Knepley }
1228c0ce001eSMatthew G. Knepley 
1229c0ce001eSMatthew G. Knepley /*@
1230*dce8aebaSBarry Smith   PetscFVSetNumComponents - Set the number of field components in a `PetscFV`
1231c0ce001eSMatthew G. Knepley 
1232c0ce001eSMatthew G. Knepley   Logically collective on fvm
1233c0ce001eSMatthew G. Knepley 
1234c0ce001eSMatthew G. Knepley   Input Parameters:
1235*dce8aebaSBarry Smith + fvm - the `PetscFV` object
1236c0ce001eSMatthew G. Knepley - comp - The number of components
1237c0ce001eSMatthew G. Knepley 
123888f5f89eSMatthew G. Knepley   Level: intermediate
1239c0ce001eSMatthew G. Knepley 
1240*dce8aebaSBarry 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));
1256c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1257c0ce001eSMatthew G. Knepley }
1258c0ce001eSMatthew G. Knepley 
1259c0ce001eSMatthew G. Knepley /*@
1260*dce8aebaSBarry Smith   PetscFVGetNumComponents - Get the number of field components in a `PetscFV`
1261c0ce001eSMatthew G. Knepley 
1262c0ce001eSMatthew G. Knepley   Not collective
1263c0ce001eSMatthew G. Knepley 
1264c0ce001eSMatthew G. Knepley   Input Parameter:
1265*dce8aebaSBarry Smith . fvm - the `PetscFV` object
1266c0ce001eSMatthew G. Knepley 
1267c0ce001eSMatthew G. Knepley   Output Parameter:
1268c0ce001eSMatthew G. Knepley , comp - The number of components
1269c0ce001eSMatthew G. Knepley 
127088f5f89eSMatthew G. Knepley   Level: intermediate
1271c0ce001eSMatthew G. Knepley 
1272*dce8aebaSBarry 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);
1278dadcf809SJacob Faibussowitsch   PetscValidIntPointer(comp, 2);
1279c0ce001eSMatthew G. Knepley   *comp = fvm->numComponents;
1280c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1281c0ce001eSMatthew G. Knepley }
1282c0ce001eSMatthew G. Knepley 
1283c0ce001eSMatthew G. Knepley /*@C
1284*dce8aebaSBarry Smith   PetscFVSetComponentName - Set the name of a component (used in output and viewing) in a `PetscFV`
1285c0ce001eSMatthew G. Knepley 
1286c0ce001eSMatthew G. Knepley   Logically collective on fvm
1287*dce8aebaSBarry Smith 
1288c0ce001eSMatthew G. Knepley   Input Parameters:
1289*dce8aebaSBarry 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 
1295*dce8aebaSBarry 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]));
1302c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1303c0ce001eSMatthew G. Knepley }
1304c0ce001eSMatthew G. Knepley 
1305c0ce001eSMatthew G. Knepley /*@C
1306*dce8aebaSBarry Smith   PetscFVGetComponentName - Get the name of a component (used in output and viewing) in a `PetscFV`
1307c0ce001eSMatthew G. Knepley 
1308c0ce001eSMatthew G. Knepley   Logically collective on fvm
1309c0ce001eSMatthew G. Knepley   Input Parameters:
1310*dce8aebaSBarry Smith + fvm - the `PetscFV` object
1311c0ce001eSMatthew G. Knepley - comp - the component number
1312c0ce001eSMatthew G. Knepley 
1313c0ce001eSMatthew G. Knepley   Output Parameter:
1314c0ce001eSMatthew G. Knepley . name - the component name
1315c0ce001eSMatthew G. Knepley 
131688f5f89eSMatthew G. Knepley   Level: intermediate
1317c0ce001eSMatthew G. Knepley 
1318*dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVSetComponentName()`
1319c0ce001eSMatthew G. Knepley @*/
1320d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetComponentName(PetscFV fvm, PetscInt comp, const char **name)
1321d71ae5a4SJacob Faibussowitsch {
1322c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1323c0ce001eSMatthew G. Knepley   *name = fvm->componentNames[comp];
1324c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1325c0ce001eSMatthew G. Knepley }
1326c0ce001eSMatthew G. Knepley 
1327c0ce001eSMatthew G. Knepley /*@
1328*dce8aebaSBarry Smith   PetscFVSetSpatialDimension - Set the spatial dimension of a `PetscFV`
1329c0ce001eSMatthew G. Knepley 
1330c0ce001eSMatthew G. Knepley   Logically collective on fvm
1331c0ce001eSMatthew G. Knepley 
1332c0ce001eSMatthew G. Knepley   Input Parameters:
1333*dce8aebaSBarry Smith + fvm - the `PetscFV` object
1334c0ce001eSMatthew G. Knepley - dim - The spatial dimension
1335c0ce001eSMatthew G. Knepley 
133688f5f89eSMatthew G. Knepley   Level: intermediate
1337c0ce001eSMatthew G. Knepley 
1338*dce8aebaSBarry Smith .seealso: `PetscFV`, ``PetscFVGetSpatialDimension()`
1339c0ce001eSMatthew G. Knepley @*/
1340d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetSpatialDimension(PetscFV fvm, PetscInt dim)
1341d71ae5a4SJacob Faibussowitsch {
1342c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1343c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1344c0ce001eSMatthew G. Knepley   fvm->dim = dim;
1345c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1346c0ce001eSMatthew G. Knepley }
1347c0ce001eSMatthew G. Knepley 
1348c0ce001eSMatthew G. Knepley /*@
1349*dce8aebaSBarry Smith   PetscFVGetSpatialDimension - Get the spatial dimension of a `PetscFV`
1350c0ce001eSMatthew G. Knepley 
1351c0ce001eSMatthew G. Knepley   Logically collective on fvm
1352c0ce001eSMatthew G. Knepley 
1353c0ce001eSMatthew G. Knepley   Input Parameter:
1354*dce8aebaSBarry Smith . fvm - the `PetscFV` object
1355c0ce001eSMatthew G. Knepley 
1356c0ce001eSMatthew G. Knepley   Output Parameter:
1357c0ce001eSMatthew G. Knepley . dim - The spatial dimension
1358c0ce001eSMatthew G. Knepley 
135988f5f89eSMatthew G. Knepley   Level: intermediate
1360c0ce001eSMatthew G. Knepley 
1361*dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVSetSpatialDimension()`
1362c0ce001eSMatthew G. Knepley @*/
1363d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetSpatialDimension(PetscFV fvm, PetscInt *dim)
1364d71ae5a4SJacob Faibussowitsch {
1365c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1366c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1367dadcf809SJacob Faibussowitsch   PetscValidIntPointer(dim, 2);
1368c0ce001eSMatthew G. Knepley   *dim = fvm->dim;
1369c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1370c0ce001eSMatthew G. Knepley }
1371c0ce001eSMatthew G. Knepley 
1372c0ce001eSMatthew G. Knepley /*@
1373*dce8aebaSBarry Smith  PetscFVSetComputeGradients - Toggle computation of cell gradients on a `PetscFV`
1374c0ce001eSMatthew G. Knepley 
1375c0ce001eSMatthew G. Knepley   Logically collective on fvm
1376c0ce001eSMatthew G. Knepley 
1377c0ce001eSMatthew G. Knepley   Input Parameters:
1378*dce8aebaSBarry Smith + fvm - the `PetscFV` object
1379c0ce001eSMatthew G. Knepley - computeGradients - Flag to compute cell gradients
1380c0ce001eSMatthew G. Knepley 
138188f5f89eSMatthew G. Knepley   Level: intermediate
1382c0ce001eSMatthew G. Knepley 
1383*dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVGetComputeGradients()`
1384c0ce001eSMatthew G. Knepley @*/
1385d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetComputeGradients(PetscFV fvm, PetscBool computeGradients)
1386d71ae5a4SJacob Faibussowitsch {
1387c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1388c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1389c0ce001eSMatthew G. Knepley   fvm->computeGradients = computeGradients;
1390c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1391c0ce001eSMatthew G. Knepley }
1392c0ce001eSMatthew G. Knepley 
1393c0ce001eSMatthew G. Knepley /*@
1394*dce8aebaSBarry Smith   PetscFVGetComputeGradients - Return flag for computation of cell gradients on a `PetscFV`
1395c0ce001eSMatthew G. Knepley 
1396c0ce001eSMatthew G. Knepley   Not collective
1397c0ce001eSMatthew G. Knepley 
1398c0ce001eSMatthew G. Knepley   Input Parameter:
1399*dce8aebaSBarry Smith . fvm - the `PetscFV` object
1400c0ce001eSMatthew G. Knepley 
1401c0ce001eSMatthew G. Knepley   Output Parameter:
1402c0ce001eSMatthew G. Knepley . computeGradients - Flag to compute cell gradients
1403c0ce001eSMatthew G. Knepley 
140488f5f89eSMatthew G. Knepley   Level: intermediate
1405c0ce001eSMatthew G. Knepley 
1406*dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVSetComputeGradients()`
1407c0ce001eSMatthew G. Knepley @*/
1408d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetComputeGradients(PetscFV fvm, PetscBool *computeGradients)
1409d71ae5a4SJacob Faibussowitsch {
1410c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1411c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1412dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(computeGradients, 2);
1413c0ce001eSMatthew G. Knepley   *computeGradients = fvm->computeGradients;
1414c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1415c0ce001eSMatthew G. Knepley }
1416c0ce001eSMatthew G. Knepley 
1417c0ce001eSMatthew G. Knepley /*@
1418*dce8aebaSBarry Smith   PetscFVSetQuadrature - Set the `PetscQuadrature` object for a `PetscFV`
1419c0ce001eSMatthew G. Knepley 
1420c0ce001eSMatthew G. Knepley   Logically collective on fvm
1421c0ce001eSMatthew G. Knepley 
1422c0ce001eSMatthew G. Knepley   Input Parameters:
1423*dce8aebaSBarry Smith + fvm - the `PetscFV` object
1424*dce8aebaSBarry Smith - q - The `PetscQuadrature`
1425c0ce001eSMatthew G. Knepley 
142688f5f89eSMatthew G. Knepley   Level: intermediate
1427c0ce001eSMatthew G. Knepley 
1428*dce8aebaSBarry Smith .seealso: `PetscQuadrature`, `PetscFV`, `PetscFVGetQuadrature()`
1429c0ce001eSMatthew G. Knepley @*/
1430d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetQuadrature(PetscFV fvm, PetscQuadrature q)
1431d71ae5a4SJacob Faibussowitsch {
1432c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1433c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
14349566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&fvm->quadrature));
14359566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)q));
1436c0ce001eSMatthew G. Knepley   fvm->quadrature = q;
1437c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1438c0ce001eSMatthew G. Knepley }
1439c0ce001eSMatthew G. Knepley 
1440c0ce001eSMatthew G. Knepley /*@
1441*dce8aebaSBarry Smith   PetscFVGetQuadrature - Get the `PetscQuadrature` from a `PetscFV`
1442c0ce001eSMatthew G. Knepley 
1443c0ce001eSMatthew G. Knepley   Not collective
1444c0ce001eSMatthew G. Knepley 
1445c0ce001eSMatthew G. Knepley   Input Parameter:
1446*dce8aebaSBarry Smith . fvm - the `PetscFV` object
1447c0ce001eSMatthew G. Knepley 
1448c0ce001eSMatthew G. Knepley   Output Parameter:
1449*dce8aebaSBarry Smith . lim - The `PetscQuadrature`
1450c0ce001eSMatthew G. Knepley 
145188f5f89eSMatthew G. Knepley   Level: intermediate
1452c0ce001eSMatthew G. Knepley 
1453*dce8aebaSBarry Smith .seealso: `PetscQuadrature`, `PetscFV`, `PetscFVSetQuadrature()`
1454c0ce001eSMatthew G. Knepley @*/
1455d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetQuadrature(PetscFV fvm, PetscQuadrature *q)
1456d71ae5a4SJacob Faibussowitsch {
1457c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1458c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1459c0ce001eSMatthew G. Knepley   PetscValidPointer(q, 2);
1460c0ce001eSMatthew G. Knepley   if (!fvm->quadrature) {
1461c0ce001eSMatthew G. Knepley     /* Create default 1-point quadrature */
1462c0ce001eSMatthew G. Knepley     PetscReal *points, *weights;
1463c0ce001eSMatthew G. Knepley 
14649566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, &fvm->quadrature));
14659566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(fvm->dim, &points));
14669566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(1, &weights));
1467c0ce001eSMatthew G. Knepley     weights[0] = 1.0;
14689566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureSetData(fvm->quadrature, fvm->dim, 1, 1, points, weights));
1469c0ce001eSMatthew G. Knepley   }
1470c0ce001eSMatthew G. Knepley   *q = fvm->quadrature;
1471c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1472c0ce001eSMatthew G. Knepley }
1473c0ce001eSMatthew G. Knepley 
1474c0ce001eSMatthew G. Knepley /*@
1475*dce8aebaSBarry Smith   PetscFVGetDualSpace - Returns the `PetscDualSpace` used to define the inner product on a `PetscFV`
1476c0ce001eSMatthew G. Knepley 
1477c0ce001eSMatthew G. Knepley   Not collective
1478c0ce001eSMatthew G. Knepley 
1479c0ce001eSMatthew G. Knepley   Input Parameter:
1480*dce8aebaSBarry Smith . fvm - The `PetscFV` object
1481c0ce001eSMatthew G. Knepley 
1482c0ce001eSMatthew G. Knepley   Output Parameter:
1483c0ce001eSMatthew G. Knepley . sp - The PetscDualSpace object
1484c0ce001eSMatthew G. Knepley 
148588f5f89eSMatthew G. Knepley   Level: intermediate
1486c0ce001eSMatthew G. Knepley 
1487*dce8aebaSBarry Smith   Developer Note:
1488*dce8aebaSBarry Smith   There is overlap between the methods of `PetscFE` and `PetscFV`, they should probably share a common parent class
1489*dce8aebaSBarry Smith 
1490*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscFV`, `PetscFVCreate()`
1491c0ce001eSMatthew G. Knepley @*/
1492d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetDualSpace(PetscFV fvm, PetscDualSpace *sp)
1493d71ae5a4SJacob Faibussowitsch {
1494c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1495c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1496c0ce001eSMatthew G. Knepley   PetscValidPointer(sp, 2);
1497c0ce001eSMatthew G. Knepley   if (!fvm->dualSpace) {
1498c0ce001eSMatthew G. Knepley     DM       K;
1499c0ce001eSMatthew G. Knepley     PetscInt dim, Nc, c;
1500c0ce001eSMatthew G. Knepley 
15019566063dSJacob Faibussowitsch     PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
15029566063dSJacob Faibussowitsch     PetscCall(PetscFVGetNumComponents(fvm, &Nc));
15039566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceCreate(PetscObjectComm((PetscObject)fvm), &fvm->dualSpace));
15049566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSetType(fvm->dualSpace, PETSCDUALSPACESIMPLE));
15059566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, PETSC_FALSE), &K));
15069566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSetNumComponents(fvm->dualSpace, Nc));
15079566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSetDM(fvm->dualSpace, K));
15089566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&K));
15099566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSimpleSetDimension(fvm->dualSpace, Nc));
1510c0ce001eSMatthew G. Knepley     /* Should we be using PetscFVGetQuadrature() here? */
1511c0ce001eSMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
1512c0ce001eSMatthew G. Knepley       PetscQuadrature qc;
1513c0ce001eSMatthew G. Knepley       PetscReal      *points, *weights;
1514c0ce001eSMatthew G. Knepley 
15159566063dSJacob Faibussowitsch       PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, &qc));
15169566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(dim, &points));
15179566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(Nc, &weights));
1518c0ce001eSMatthew G. Knepley       weights[c] = 1.0;
15199566063dSJacob Faibussowitsch       PetscCall(PetscQuadratureSetData(qc, dim, Nc, 1, points, weights));
15209566063dSJacob Faibussowitsch       PetscCall(PetscDualSpaceSimpleSetFunctional(fvm->dualSpace, c, qc));
15219566063dSJacob Faibussowitsch       PetscCall(PetscQuadratureDestroy(&qc));
1522c0ce001eSMatthew G. Knepley     }
15239566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSetUp(fvm->dualSpace));
1524c0ce001eSMatthew G. Knepley   }
1525c0ce001eSMatthew G. Knepley   *sp = fvm->dualSpace;
1526c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1527c0ce001eSMatthew G. Knepley }
1528c0ce001eSMatthew G. Knepley 
1529c0ce001eSMatthew G. Knepley /*@
1530*dce8aebaSBarry Smith   PetscFVSetDualSpace - Sets the `PetscDualSpace` used to define the inner product
1531c0ce001eSMatthew G. Knepley 
1532c0ce001eSMatthew G. Knepley   Not collective
1533c0ce001eSMatthew G. Knepley 
1534c0ce001eSMatthew G. Knepley   Input Parameters:
1535*dce8aebaSBarry Smith + fvm - The `PetscFV` object
1536*dce8aebaSBarry Smith - sp  - The `PetscDualSpace` object
1537c0ce001eSMatthew G. Knepley 
1538c0ce001eSMatthew G. Knepley   Level: intermediate
1539c0ce001eSMatthew G. Knepley 
1540*dce8aebaSBarry Smith   Note:
1541*dce8aebaSBarry Smith   A simple dual space is provided automatically, and the user typically will not need to override it.
1542c0ce001eSMatthew G. Knepley 
1543*dce8aebaSBarry Smith .seealso: `PetscDualSpace`, `PetscFV`, `PetscFVCreate()`
1544c0ce001eSMatthew G. Knepley @*/
1545d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVSetDualSpace(PetscFV fvm, PetscDualSpace sp)
1546d71ae5a4SJacob Faibussowitsch {
1547c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1548c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1549c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 2);
15509566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDestroy(&fvm->dualSpace));
1551c0ce001eSMatthew G. Knepley   fvm->dualSpace = sp;
15529566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fvm->dualSpace));
1553c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1554c0ce001eSMatthew G. Knepley }
1555c0ce001eSMatthew G. Knepley 
155688f5f89eSMatthew G. Knepley /*@C
1557ef0bb6c7SMatthew G. Knepley   PetscFVGetCellTabulation - Returns the tabulation of the basis functions at the quadrature points
155888f5f89eSMatthew G. Knepley 
155988f5f89eSMatthew G. Knepley   Not collective
156088f5f89eSMatthew G. Knepley 
156188f5f89eSMatthew G. Knepley   Input Parameter:
1562*dce8aebaSBarry Smith . fvm - The `PetscFV` object
156388f5f89eSMatthew G. Knepley 
1564ef0bb6c7SMatthew G. Knepley   Output Parameter:
1565a5b23f4aSJose E. Roman . T - The basis function values and derivatives at quadrature points
156688f5f89eSMatthew G. Knepley 
156788f5f89eSMatthew G. Knepley   Level: intermediate
156888f5f89eSMatthew G. Knepley 
1569*dce8aebaSBarry Smith   Note:
1570*dce8aebaSBarry Smith .vb
1571*dce8aebaSBarry Smith   T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
1572*dce8aebaSBarry 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
1573*dce8aebaSBarry 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
1574*dce8aebaSBarry Smith .ve
1575*dce8aebaSBarry Smith 
1576*dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscTabulation`, `PetscFEGetCellTabulation()`, `PetscFVCreateTabulation()`, `PetscFVGetQuadrature()`, `PetscQuadratureGetData()`
157788f5f89eSMatthew G. Knepley @*/
1578d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVGetCellTabulation(PetscFV fvm, PetscTabulation *T)
1579d71ae5a4SJacob Faibussowitsch {
1580c0ce001eSMatthew G. Knepley   PetscInt         npoints;
1581c0ce001eSMatthew G. Knepley   const PetscReal *points;
1582c0ce001eSMatthew G. Knepley 
1583c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1584c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1585ef0bb6c7SMatthew G. Knepley   PetscValidPointer(T, 2);
15869566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureGetData(fvm->quadrature, NULL, NULL, &npoints, &points, NULL));
15879566063dSJacob Faibussowitsch   if (!fvm->T) PetscCall(PetscFVCreateTabulation(fvm, 1, npoints, points, 1, &fvm->T));
1588ef0bb6c7SMatthew G. Knepley   *T = fvm->T;
1589c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1590c0ce001eSMatthew G. Knepley }
1591c0ce001eSMatthew G. Knepley 
159288f5f89eSMatthew G. Knepley /*@C
1593ef0bb6c7SMatthew G. Knepley   PetscFVCreateTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided.
159488f5f89eSMatthew G. Knepley 
159588f5f89eSMatthew G. Knepley   Not collective
159688f5f89eSMatthew G. Knepley 
159788f5f89eSMatthew G. Knepley   Input Parameters:
1598*dce8aebaSBarry Smith + fvm     - The `PetscFV` object
1599ef0bb6c7SMatthew G. Knepley . nrepl   - The number of replicas
1600ef0bb6c7SMatthew G. Knepley . npoints - The number of tabulation points in a replica
1601ef0bb6c7SMatthew G. Knepley . points  - The tabulation point coordinates
1602ef0bb6c7SMatthew G. Knepley - K       - The order of derivative to tabulate
160388f5f89eSMatthew G. Knepley 
1604ef0bb6c7SMatthew G. Knepley   Output Parameter:
1605a5b23f4aSJose E. Roman . T - The basis function values and derivative at tabulation points
160688f5f89eSMatthew G. Knepley 
160788f5f89eSMatthew G. Knepley   Level: intermediate
160888f5f89eSMatthew G. Knepley 
1609*dce8aebaSBarry Smith   Note:
1610*dce8aebaSBarry Smith .vb
1611*dce8aebaSBarry Smith   T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
1612*dce8aebaSBarry 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
1613*dce8aebaSBarry 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
1614*dce8aebaSBarry Smith .ve
1615*dce8aebaSBarry Smith 
1616*dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscTabulation`, `PetscFECreateTabulation()`, `PetscTabulationDestroy()`, `PetscFEGetCellTabulation()`
161788f5f89eSMatthew G. Knepley @*/
1618d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVCreateTabulation(PetscFV fvm, PetscInt nrepl, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation *T)
1619d71ae5a4SJacob Faibussowitsch {
1620c0ce001eSMatthew G. Knepley   PetscInt pdim = 1; /* Dimension of approximation space P */
1621ef0bb6c7SMatthew G. Knepley   PetscInt cdim;     /* Spatial dimension */
1622ef0bb6c7SMatthew G. Knepley   PetscInt Nc;       /* Field components */
1623ef0bb6c7SMatthew G. Knepley   PetscInt k, p, d, c, e;
1624c0ce001eSMatthew G. Knepley 
1625c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1626ef0bb6c7SMatthew G. Knepley   if (!npoints || K < 0) {
1627ef0bb6c7SMatthew G. Knepley     *T = NULL;
1628c0ce001eSMatthew G. Knepley     PetscFunctionReturn(0);
1629c0ce001eSMatthew G. Knepley   }
1630c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1631dadcf809SJacob Faibussowitsch   PetscValidRealPointer(points, 4);
163240a2aa30SMatthew G. Knepley   PetscValidPointer(T, 6);
16339566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &cdim));
16349566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fvm, &Nc));
16359566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1, T));
1636ef0bb6c7SMatthew G. Knepley   (*T)->K    = !cdim ? 0 : K;
1637ef0bb6c7SMatthew G. Knepley   (*T)->Nr   = nrepl;
1638ef0bb6c7SMatthew G. Knepley   (*T)->Np   = npoints;
1639ef0bb6c7SMatthew G. Knepley   (*T)->Nb   = pdim;
1640ef0bb6c7SMatthew G. Knepley   (*T)->Nc   = Nc;
1641ef0bb6c7SMatthew G. Knepley   (*T)->cdim = cdim;
16429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((*T)->K + 1, &(*T)->T));
164348a46eb9SPierre Jolivet   for (k = 0; k <= (*T)->K; ++k) PetscCall(PetscMalloc1(nrepl * npoints * pdim * Nc * PetscPowInt(cdim, k), &(*T)->T[k]));
16449371c9d4SSatish Balay   if (K >= 0) {
16459371c9d4SSatish Balay     for (p = 0; p < nrepl * npoints; ++p)
16469371c9d4SSatish Balay       for (d = 0; d < pdim; ++d)
16479371c9d4SSatish Balay         for (c = 0; c < Nc; ++c) (*T)->T[0][(p * pdim + d) * Nc + c] = 1.0;
1648ef0bb6c7SMatthew G. Knepley   }
16499371c9d4SSatish Balay   if (K >= 1) {
16509371c9d4SSatish Balay     for (p = 0; p < nrepl * npoints; ++p)
16519371c9d4SSatish Balay       for (d = 0; d < pdim; ++d)
16529371c9d4SSatish Balay         for (c = 0; c < Nc; ++c)
16539371c9d4SSatish Balay           for (e = 0; e < cdim; ++e) (*T)->T[1][((p * pdim + d) * Nc + c) * cdim + e] = 0.0;
16549371c9d4SSatish Balay   }
16559371c9d4SSatish Balay   if (K >= 2) {
16569371c9d4SSatish Balay     for (p = 0; p < nrepl * npoints; ++p)
16579371c9d4SSatish Balay       for (d = 0; d < pdim; ++d)
16589371c9d4SSatish Balay         for (c = 0; c < Nc; ++c)
16599371c9d4SSatish Balay           for (e = 0; e < cdim * cdim; ++e) (*T)->T[2][((p * pdim + d) * Nc + c) * cdim * cdim + e] = 0.0;
16609371c9d4SSatish Balay   }
1661c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1662c0ce001eSMatthew G. Knepley }
1663c0ce001eSMatthew G. Knepley 
1664c0ce001eSMatthew G. Knepley /*@C
1665c0ce001eSMatthew G. Knepley   PetscFVComputeGradient - Compute the gradient reconstruction matrix for a given cell
1666c0ce001eSMatthew G. Knepley 
1667c0ce001eSMatthew G. Knepley   Input Parameters:
1668*dce8aebaSBarry Smith + fvm      - The `PetscFV` object
1669c0ce001eSMatthew G. Knepley . numFaces - The number of cell faces which are not constrained
1670c0ce001eSMatthew G. Knepley - dx       - The vector from the cell centroid to the neighboring cell centroid for each face
1671c0ce001eSMatthew G. Knepley 
167288f5f89eSMatthew G. Knepley   Level: advanced
1673c0ce001eSMatthew G. Knepley 
1674*dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVCreate()`
1675c0ce001eSMatthew G. Knepley @*/
1676d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVComputeGradient(PetscFV fvm, PetscInt numFaces, PetscScalar dx[], PetscScalar grad[])
1677d71ae5a4SJacob Faibussowitsch {
1678c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1679c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1680dbbe0bcdSBarry Smith   PetscTryTypeMethod(fvm, computegradient, numFaces, dx, grad);
1681c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1682c0ce001eSMatthew G. Knepley }
1683c0ce001eSMatthew G. Knepley 
168488f5f89eSMatthew G. Knepley /*@C
1685c0ce001eSMatthew G. Knepley   PetscFVIntegrateRHSFunction - Produce the cell residual vector for a chunk of elements by quadrature integration
1686c0ce001eSMatthew G. Knepley 
1687c0ce001eSMatthew G. Knepley   Not collective
1688c0ce001eSMatthew G. Knepley 
1689c0ce001eSMatthew G. Knepley   Input Parameters:
1690*dce8aebaSBarry Smith + fvm          - The `PetscFV` object for the field being integrated
1691*dce8aebaSBarry Smith . prob         - The `PetscDS` specifing the discretizations and continuum functions
1692c0ce001eSMatthew G. Knepley . field        - The field being integrated
1693c0ce001eSMatthew G. Knepley . Nf           - The number of faces in the chunk
1694c0ce001eSMatthew G. Knepley . fgeom        - The face geometry for each face in the chunk
1695c0ce001eSMatthew G. Knepley . neighborVol  - The volume for each pair of cells in the chunk
1696c0ce001eSMatthew G. Knepley . uL           - The state from the cell on the left
1697c0ce001eSMatthew G. Knepley - uR           - The state from the cell on the right
1698c0ce001eSMatthew G. Knepley 
1699d8d19677SJose E. Roman   Output Parameters:
1700c0ce001eSMatthew G. Knepley + fluxL        - the left fluxes for each face
1701c0ce001eSMatthew G. Knepley - fluxR        - the right fluxes for each face
170288f5f89eSMatthew G. Knepley 
170388f5f89eSMatthew G. Knepley   Level: developer
170488f5f89eSMatthew G. Knepley 
1705*dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscDS`, `PetscFVFaceGeom`, `PetscFVCreate()`
170688f5f89eSMatthew G. Knepley @*/
1707d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVIntegrateRHSFunction(PetscFV fvm, PetscDS prob, PetscInt field, PetscInt Nf, PetscFVFaceGeom *fgeom, PetscReal *neighborVol, PetscScalar uL[], PetscScalar uR[], PetscScalar fluxL[], PetscScalar fluxR[])
1708d71ae5a4SJacob Faibussowitsch {
1709c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1710c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
1711dbbe0bcdSBarry Smith   PetscTryTypeMethod(fvm, integraterhsfunction, prob, field, Nf, fgeom, neighborVol, uL, uR, fluxL, fluxR);
1712c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1713c0ce001eSMatthew G. Knepley }
1714c0ce001eSMatthew G. Knepley 
1715c0ce001eSMatthew G. Knepley /*@
1716*dce8aebaSBarry Smith   PetscFVRefine - Create a "refined" `PetscFV` object that refines the reference cell into smaller copies. This is typically used
1717c0ce001eSMatthew G. Knepley   to precondition a higher order method with a lower order method on a refined mesh having the same number of dofs (but more
1718c0ce001eSMatthew G. Knepley   sparsity). It is also used to create an interpolation between regularly refined meshes.
1719c0ce001eSMatthew G. Knepley 
1720c0ce001eSMatthew G. Knepley   Input Parameter:
1721*dce8aebaSBarry Smith . fv - The initial `PetscFV`
1722c0ce001eSMatthew G. Knepley 
1723c0ce001eSMatthew G. Knepley   Output Parameter:
1724*dce8aebaSBarry Smith . fvRef - The refined `PetscFV`
1725c0ce001eSMatthew G. Knepley 
172688f5f89eSMatthew G. Knepley   Level: advanced
1727c0ce001eSMatthew G. Knepley 
1728*dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVCreate()`, `PetscFVSetType()`
1729c0ce001eSMatthew G. Knepley @*/
1730d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVRefine(PetscFV fv, PetscFV *fvRef)
1731d71ae5a4SJacob Faibussowitsch {
1732c0ce001eSMatthew G. Knepley   PetscDualSpace  Q, Qref;
1733c0ce001eSMatthew G. Knepley   DM              K, Kref;
1734c0ce001eSMatthew G. Knepley   PetscQuadrature q, qref;
1735412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
1736012bc364SMatthew G. Knepley   DMPlexTransform tr;
1737c0ce001eSMatthew G. Knepley   PetscReal      *v0;
1738c0ce001eSMatthew G. Knepley   PetscReal      *jac, *invjac;
1739c0ce001eSMatthew G. Knepley   PetscInt        numComp, numSubelements, s;
1740c0ce001eSMatthew G. Knepley 
1741c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
17429566063dSJacob Faibussowitsch   PetscCall(PetscFVGetDualSpace(fv, &Q));
17439566063dSJacob Faibussowitsch   PetscCall(PetscFVGetQuadrature(fv, &q));
17449566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceGetDM(Q, &K));
1745c0ce001eSMatthew G. Knepley   /* Create dual space */
17469566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDuplicate(Q, &Qref));
17479566063dSJacob Faibussowitsch   PetscCall(DMRefine(K, PetscObjectComm((PetscObject)fv), &Kref));
17489566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetDM(Qref, Kref));
17499566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&Kref));
17509566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetUp(Qref));
1751c0ce001eSMatthew G. Knepley   /* Create volume */
17529566063dSJacob Faibussowitsch   PetscCall(PetscFVCreate(PetscObjectComm((PetscObject)fv), fvRef));
17539566063dSJacob Faibussowitsch   PetscCall(PetscFVSetDualSpace(*fvRef, Qref));
17549566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fv, &numComp));
17559566063dSJacob Faibussowitsch   PetscCall(PetscFVSetNumComponents(*fvRef, numComp));
17569566063dSJacob Faibussowitsch   PetscCall(PetscFVSetUp(*fvRef));
1757c0ce001eSMatthew G. Knepley   /* Create quadrature */
17589566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(K, 0, &ct));
17599566063dSJacob Faibussowitsch   PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
17609566063dSJacob Faibussowitsch   PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
17619566063dSJacob Faibussowitsch   PetscCall(DMPlexRefineRegularGetAffineTransforms(tr, ct, &numSubelements, &v0, &jac, &invjac));
17629566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureExpandComposite(q, numSubelements, v0, jac, &qref));
17639566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSimpleSetDimension(Qref, numSubelements));
1764c0ce001eSMatthew G. Knepley   for (s = 0; s < numSubelements; ++s) {
1765c0ce001eSMatthew G. Knepley     PetscQuadrature  qs;
1766c0ce001eSMatthew G. Knepley     const PetscReal *points, *weights;
1767c0ce001eSMatthew G. Knepley     PetscReal       *p, *w;
1768c0ce001eSMatthew G. Knepley     PetscInt         dim, Nc, npoints, np;
1769c0ce001eSMatthew G. Knepley 
17709566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, &qs));
17719566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureGetData(q, &dim, &Nc, &npoints, &points, &weights));
1772c0ce001eSMatthew G. Knepley     np = npoints / numSubelements;
17739566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(np * dim, &p));
17749566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(np * Nc, &w));
17759566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(p, &points[s * np * dim], np * dim));
17769566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(w, &weights[s * np * Nc], np * Nc));
17779566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureSetData(qs, dim, Nc, np, p, w));
17789566063dSJacob Faibussowitsch     PetscCall(PetscDualSpaceSimpleSetFunctional(Qref, s, qs));
17799566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureDestroy(&qs));
1780c0ce001eSMatthew G. Knepley   }
17819566063dSJacob Faibussowitsch   PetscCall(PetscFVSetQuadrature(*fvRef, qref));
17829566063dSJacob Faibussowitsch   PetscCall(DMPlexTransformDestroy(&tr));
17839566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&qref));
17849566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDestroy(&Qref));
1785c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1786c0ce001eSMatthew G. Knepley }
1787c0ce001eSMatthew G. Knepley 
1788d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVDestroy_Upwind(PetscFV fvm)
1789d71ae5a4SJacob Faibussowitsch {
1790c0ce001eSMatthew G. Knepley   PetscFV_Upwind *b = (PetscFV_Upwind *)fvm->data;
1791c0ce001eSMatthew G. Knepley 
1792c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
17939566063dSJacob Faibussowitsch   PetscCall(PetscFree(b));
1794c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1795c0ce001eSMatthew G. Knepley }
1796c0ce001eSMatthew G. Knepley 
1797d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVView_Upwind_Ascii(PetscFV fv, PetscViewer viewer)
1798d71ae5a4SJacob Faibussowitsch {
1799c0ce001eSMatthew G. Knepley   PetscInt          Nc, c;
1800c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
1801c0ce001eSMatthew G. Knepley 
1802c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
18039566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fv, &Nc));
18049566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
18059566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Upwind Finite Volume:\n"));
180663a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  num components: %" PetscInt_FMT "\n", Nc));
1807c0ce001eSMatthew G. Knepley   for (c = 0; c < Nc; c++) {
180848a46eb9SPierre Jolivet     if (fv->componentNames[c]) PetscCall(PetscViewerASCIIPrintf(viewer, "    component %" PetscInt_FMT ": %s\n", c, fv->componentNames[c]));
1809c0ce001eSMatthew G. Knepley   }
1810c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1811c0ce001eSMatthew G. Knepley }
1812c0ce001eSMatthew G. Knepley 
1813d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVView_Upwind(PetscFV fv, PetscViewer viewer)
1814d71ae5a4SJacob Faibussowitsch {
1815c0ce001eSMatthew G. Knepley   PetscBool iascii;
1816c0ce001eSMatthew G. Knepley 
1817c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1818c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 1);
1819c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18209566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
18219566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscFVView_Upwind_Ascii(fv, viewer));
1822c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1823c0ce001eSMatthew G. Knepley }
1824c0ce001eSMatthew G. Knepley 
1825d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVSetUp_Upwind(PetscFV fvm)
1826d71ae5a4SJacob Faibussowitsch {
1827c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1828c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1829c0ce001eSMatthew G. Knepley }
1830c0ce001eSMatthew G. Knepley 
1831c0ce001eSMatthew G. Knepley /*
1832c0ce001eSMatthew G. Knepley   neighborVol[f*2+0] contains the left  geom
1833c0ce001eSMatthew G. Knepley   neighborVol[f*2+1] contains the right geom
1834c0ce001eSMatthew G. Knepley */
1835d71ae5a4SJacob 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[])
1836d71ae5a4SJacob Faibussowitsch {
1837c0ce001eSMatthew G. Knepley   void (*riemann)(PetscInt, PetscInt, const PetscReal[], const PetscReal[], const PetscScalar[], const PetscScalar[], PetscInt, const PetscScalar[], PetscScalar[], void *);
1838c0ce001eSMatthew G. Knepley   void              *rctx;
1839c0ce001eSMatthew G. Knepley   PetscScalar       *flux = fvm->fluxWork;
1840c0ce001eSMatthew G. Knepley   const PetscScalar *constants;
1841c0ce001eSMatthew G. Knepley   PetscInt           dim, numConstants, pdim, totDim, Nc, off, f, d;
1842c0ce001eSMatthew G. Knepley 
1843c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
18449566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(prob, &Nc));
18459566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
18469566063dSJacob Faibussowitsch   PetscCall(PetscDSGetFieldOffset(prob, field, &off));
18479566063dSJacob Faibussowitsch   PetscCall(PetscDSGetRiemannSolver(prob, field, &riemann));
18489566063dSJacob Faibussowitsch   PetscCall(PetscDSGetContext(prob, field, &rctx));
18499566063dSJacob Faibussowitsch   PetscCall(PetscDSGetConstants(prob, &numConstants, &constants));
18509566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
18519566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fvm, &pdim));
1852c0ce001eSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
1853c0ce001eSMatthew G. Knepley     (*riemann)(dim, pdim, fgeom[f].centroid, fgeom[f].normal, &uL[f * Nc], &uR[f * Nc], numConstants, constants, flux, rctx);
1854c0ce001eSMatthew G. Knepley     for (d = 0; d < pdim; ++d) {
1855c0ce001eSMatthew G. Knepley       fluxL[f * totDim + off + d] = flux[d] / neighborVol[f * 2 + 0];
1856c0ce001eSMatthew G. Knepley       fluxR[f * totDim + off + d] = flux[d] / neighborVol[f * 2 + 1];
1857c0ce001eSMatthew G. Knepley     }
1858c0ce001eSMatthew G. Knepley   }
1859c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1860c0ce001eSMatthew G. Knepley }
1861c0ce001eSMatthew G. Knepley 
1862d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVInitialize_Upwind(PetscFV fvm)
1863d71ae5a4SJacob Faibussowitsch {
1864c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1865c0ce001eSMatthew G. Knepley   fvm->ops->setfromoptions       = NULL;
1866c0ce001eSMatthew G. Knepley   fvm->ops->setup                = PetscFVSetUp_Upwind;
1867c0ce001eSMatthew G. Knepley   fvm->ops->view                 = PetscFVView_Upwind;
1868c0ce001eSMatthew G. Knepley   fvm->ops->destroy              = PetscFVDestroy_Upwind;
1869c0ce001eSMatthew G. Knepley   fvm->ops->integraterhsfunction = PetscFVIntegrateRHSFunction_Upwind;
1870c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1871c0ce001eSMatthew G. Knepley }
1872c0ce001eSMatthew G. Knepley 
1873c0ce001eSMatthew G. Knepley /*MC
1874*dce8aebaSBarry Smith   PETSCFVUPWIND = "upwind" - A `PetscFV` implementation
1875c0ce001eSMatthew G. Knepley 
1876c0ce001eSMatthew G. Knepley   Level: intermediate
1877c0ce001eSMatthew G. Knepley 
1878*dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVCreate()`, `PetscFVSetType()`
1879c0ce001eSMatthew G. Knepley M*/
1880c0ce001eSMatthew G. Knepley 
1881d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscFVCreate_Upwind(PetscFV fvm)
1882d71ae5a4SJacob Faibussowitsch {
1883c0ce001eSMatthew G. Knepley   PetscFV_Upwind *b;
1884c0ce001eSMatthew G. Knepley 
1885c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1886c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
18874dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
1888c0ce001eSMatthew G. Knepley   fvm->data = b;
1889c0ce001eSMatthew G. Knepley 
18909566063dSJacob Faibussowitsch   PetscCall(PetscFVInitialize_Upwind(fvm));
1891c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1892c0ce001eSMatthew G. Knepley }
1893c0ce001eSMatthew G. Knepley 
1894c0ce001eSMatthew G. Knepley #include <petscblaslapack.h>
1895c0ce001eSMatthew G. Knepley 
1896d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVDestroy_LeastSquares(PetscFV fvm)
1897d71ae5a4SJacob Faibussowitsch {
1898c0ce001eSMatthew G. Knepley   PetscFV_LeastSquares *ls = (PetscFV_LeastSquares *)fvm->data;
1899c0ce001eSMatthew G. Knepley 
1900c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
19019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fvm, "PetscFVLeastSquaresSetMaxFaces_C", NULL));
19029566063dSJacob Faibussowitsch   PetscCall(PetscFree4(ls->B, ls->Binv, ls->tau, ls->work));
19039566063dSJacob Faibussowitsch   PetscCall(PetscFree(ls));
1904c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1905c0ce001eSMatthew G. Knepley }
1906c0ce001eSMatthew G. Knepley 
1907d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVView_LeastSquares_Ascii(PetscFV fv, PetscViewer viewer)
1908d71ae5a4SJacob Faibussowitsch {
1909c0ce001eSMatthew G. Knepley   PetscInt          Nc, c;
1910c0ce001eSMatthew G. Knepley   PetscViewerFormat format;
1911c0ce001eSMatthew G. Knepley 
1912c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
19139566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fv, &Nc));
19149566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
19159566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Finite Volume with Least Squares Reconstruction:\n"));
191663a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  num components: %" PetscInt_FMT "\n", Nc));
1917c0ce001eSMatthew G. Knepley   for (c = 0; c < Nc; c++) {
191848a46eb9SPierre Jolivet     if (fv->componentNames[c]) PetscCall(PetscViewerASCIIPrintf(viewer, "    component %" PetscInt_FMT ": %s\n", c, fv->componentNames[c]));
1919c0ce001eSMatthew G. Knepley   }
1920c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1921c0ce001eSMatthew G. Knepley }
1922c0ce001eSMatthew G. Knepley 
1923d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVView_LeastSquares(PetscFV fv, PetscViewer viewer)
1924d71ae5a4SJacob Faibussowitsch {
1925c0ce001eSMatthew G. Knepley   PetscBool iascii;
1926c0ce001eSMatthew G. Knepley 
1927c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1928c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 1);
1929c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19309566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
19319566063dSJacob Faibussowitsch   if (iascii) PetscCall(PetscFVView_LeastSquares_Ascii(fv, viewer));
1932c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1933c0ce001eSMatthew G. Knepley }
1934c0ce001eSMatthew G. Knepley 
1935d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVSetUp_LeastSquares(PetscFV fvm)
1936d71ae5a4SJacob Faibussowitsch {
1937c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1938c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1939c0ce001eSMatthew G. Knepley }
1940c0ce001eSMatthew G. Knepley 
1941c0ce001eSMatthew G. Knepley /* Overwrites A. Can only handle full-rank problems with m>=n */
1942d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVLeastSquaresPseudoInverse_Static(PetscInt m, PetscInt mstride, PetscInt n, PetscScalar *A, PetscScalar *Ainv, PetscScalar *tau, PetscInt worksize, PetscScalar *work)
1943d71ae5a4SJacob Faibussowitsch {
1944c0ce001eSMatthew G. Knepley   PetscBool    debug = PETSC_FALSE;
1945c0ce001eSMatthew G. Knepley   PetscBLASInt M, N, K, lda, ldb, ldwork, info;
1946c0ce001eSMatthew G. Knepley   PetscScalar *R, *Q, *Aback, Alpha;
1947c0ce001eSMatthew G. Knepley 
1948c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
1949c0ce001eSMatthew G. Knepley   if (debug) {
19509566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m * n, &Aback));
19519566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(Aback, A, m * n));
1952c0ce001eSMatthew G. Knepley   }
1953c0ce001eSMatthew G. Knepley 
19549566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &M));
19559566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(n, &N));
19569566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(mstride, &lda));
19579566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(worksize, &ldwork));
19589566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
1959792fecdfSBarry Smith   PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&M, &N, A, &lda, tau, work, &ldwork, &info));
19609566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
196128b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "xGEQRF error");
1962c0ce001eSMatthew G. Knepley   R = A; /* Upper triangular part of A now contains R, the rest contains the elementary reflectors */
1963c0ce001eSMatthew G. Knepley 
1964c0ce001eSMatthew G. Knepley   /* Extract an explicit representation of Q */
1965c0ce001eSMatthew G. Knepley   Q = Ainv;
19669566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(Q, A, mstride * n));
1967c0ce001eSMatthew G. Knepley   K = N; /* full rank */
1968792fecdfSBarry Smith   PetscCallBLAS("LAPACKorgqr", LAPACKorgqr_(&M, &N, &K, Q, &lda, tau, work, &ldwork, &info));
196928b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "xORGQR/xUNGQR error");
1970c0ce001eSMatthew G. Knepley 
1971c0ce001eSMatthew G. Knepley   /* Compute A^{-T} = (R^{-1} Q^T)^T = Q R^{-T} */
1972c0ce001eSMatthew G. Knepley   Alpha = 1.0;
1973c0ce001eSMatthew G. Knepley   ldb   = lda;
1974c0ce001eSMatthew G. Knepley   BLAStrsm_("Right", "Upper", "ConjugateTranspose", "NotUnitTriangular", &M, &N, &Alpha, R, &lda, Q, &ldb);
1975c0ce001eSMatthew G. Knepley   /* Ainv is Q, overwritten with inverse */
1976c0ce001eSMatthew G. Knepley 
1977c0ce001eSMatthew G. Knepley   if (debug) { /* Check that pseudo-inverse worked */
1978c0ce001eSMatthew G. Knepley     PetscScalar  Beta = 0.0;
1979c0ce001eSMatthew G. Knepley     PetscBLASInt ldc;
1980c0ce001eSMatthew G. Knepley     K   = N;
1981c0ce001eSMatthew G. Knepley     ldc = N;
1982c0ce001eSMatthew G. Knepley     BLASgemm_("ConjugateTranspose", "Normal", &N, &K, &M, &Alpha, Ainv, &lda, Aback, &ldb, &Beta, work, &ldc);
19839566063dSJacob Faibussowitsch     PetscCall(PetscScalarView(n * n, work, PETSC_VIEWER_STDOUT_SELF));
19849566063dSJacob Faibussowitsch     PetscCall(PetscFree(Aback));
1985c0ce001eSMatthew G. Knepley   }
1986c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
1987c0ce001eSMatthew G. Knepley }
1988c0ce001eSMatthew G. Knepley 
1989c0ce001eSMatthew G. Knepley /* Overwrites A. Can handle degenerate problems and m<n. */
1990d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVLeastSquaresPseudoInverseSVD_Static(PetscInt m, PetscInt mstride, PetscInt n, PetscScalar *A, PetscScalar *Ainv, PetscScalar *tau, PetscInt worksize, PetscScalar *work)
1991d71ae5a4SJacob Faibussowitsch {
19926bb27163SBarry Smith   PetscScalar *Brhs;
1993c0ce001eSMatthew G. Knepley   PetscScalar *tmpwork;
1994c0ce001eSMatthew G. Knepley   PetscReal    rcond;
1995c0ce001eSMatthew G. Knepley #if defined(PETSC_USE_COMPLEX)
1996c0ce001eSMatthew G. Knepley   PetscInt   rworkSize;
1997c0ce001eSMatthew G. Knepley   PetscReal *rwork;
1998c0ce001eSMatthew G. Knepley #endif
1999c0ce001eSMatthew G. Knepley   PetscInt     i, j, maxmn;
2000c0ce001eSMatthew G. Knepley   PetscBLASInt M, N, lda, ldb, ldwork;
2001c0ce001eSMatthew G. Knepley   PetscBLASInt nrhs, irank, info;
2002c0ce001eSMatthew G. Knepley 
2003c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2004c0ce001eSMatthew G. Knepley   /* initialize to identity */
2005736d4f42SpierreXVI   tmpwork = work;
2006736d4f42SpierreXVI   Brhs    = Ainv;
2007c0ce001eSMatthew G. Knepley   maxmn   = PetscMax(m, n);
2008c0ce001eSMatthew G. Knepley   for (j = 0; j < maxmn; j++) {
2009c0ce001eSMatthew G. Knepley     for (i = 0; i < maxmn; i++) Brhs[i + j * maxmn] = 1.0 * (i == j);
2010c0ce001eSMatthew G. Knepley   }
2011c0ce001eSMatthew G. Knepley 
20129566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &M));
20139566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(n, &N));
20149566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(mstride, &lda));
20159566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(maxmn, &ldb));
20169566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(worksize, &ldwork));
2017c0ce001eSMatthew G. Knepley   rcond = -1;
2018c0ce001eSMatthew G. Knepley   nrhs  = M;
2019c0ce001eSMatthew G. Knepley #if defined(PETSC_USE_COMPLEX)
2020c0ce001eSMatthew G. Knepley   rworkSize = 5 * PetscMin(M, N);
20219566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(rworkSize, &rwork));
20226bb27163SBarry Smith   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
2023792fecdfSBarry Smith   PetscCallBLAS("LAPACKgelss", LAPACKgelss_(&M, &N, &nrhs, A, &lda, Brhs, &ldb, (PetscReal *)tau, &rcond, &irank, tmpwork, &ldwork, rwork, &info));
20249566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
20259566063dSJacob Faibussowitsch   PetscCall(PetscFree(rwork));
2026c0ce001eSMatthew G. Knepley #else
2027c0ce001eSMatthew G. Knepley   nrhs = M;
20286bb27163SBarry Smith   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
2029792fecdfSBarry Smith   PetscCallBLAS("LAPACKgelss", LAPACKgelss_(&M, &N, &nrhs, A, &lda, Brhs, &ldb, (PetscReal *)tau, &rcond, &irank, tmpwork, &ldwork, &info));
20309566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
2031c0ce001eSMatthew G. Knepley #endif
203228b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "xGELSS error");
2033c0ce001eSMatthew G. Knepley   /* The following check should be turned into a diagnostic as soon as someone wants to do this intentionally */
203408401ef6SPierre 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");
2035c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
2036c0ce001eSMatthew G. Knepley }
2037c0ce001eSMatthew G. Knepley 
2038c0ce001eSMatthew G. Knepley #if 0
2039c0ce001eSMatthew G. Knepley static PetscErrorCode PetscFVLeastSquaresDebugCell_Static(PetscFV fvm, PetscInt cell, DM dm, DM dmFace, PetscScalar *fgeom, DM dmCell, PetscScalar *cgeom)
2040c0ce001eSMatthew G. Knepley {
2041c0ce001eSMatthew G. Knepley   PetscReal       grad[2] = {0, 0};
2042c0ce001eSMatthew G. Knepley   const PetscInt *faces;
2043c0ce001eSMatthew G. Knepley   PetscInt        numFaces, f;
2044c0ce001eSMatthew G. Knepley 
2045c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
20469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, cell, &numFaces));
20479566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, cell, &faces));
2048c0ce001eSMatthew G. Knepley   for (f = 0; f < numFaces; ++f) {
2049c0ce001eSMatthew G. Knepley     const PetscInt *fcells;
2050c0ce001eSMatthew G. Knepley     const CellGeom *cg1;
2051c0ce001eSMatthew G. Knepley     const FaceGeom *fg;
2052c0ce001eSMatthew G. Knepley 
20539566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, faces[f], &fcells));
20549566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmFace, faces[f], fgeom, &fg));
2055c0ce001eSMatthew G. Knepley     for (i = 0; i < 2; ++i) {
2056c0ce001eSMatthew G. Knepley       PetscScalar du;
2057c0ce001eSMatthew G. Knepley 
2058c0ce001eSMatthew G. Knepley       if (fcells[i] == c) continue;
20599566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, fcells[i], cgeom, &cg1));
2060c0ce001eSMatthew G. Knepley       du   = cg1->centroid[0] + 3*cg1->centroid[1] - (cg->centroid[0] + 3*cg->centroid[1]);
2061c0ce001eSMatthew G. Knepley       grad[0] += fg->grad[!i][0] * du;
2062c0ce001eSMatthew G. Knepley       grad[1] += fg->grad[!i][1] * du;
2063c0ce001eSMatthew G. Knepley     }
2064c0ce001eSMatthew G. Knepley   }
20659566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "cell[%d] grad (%g, %g)\n", cell, grad[0], grad[1]));
2066c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
2067c0ce001eSMatthew G. Knepley }
2068c0ce001eSMatthew G. Knepley #endif
2069c0ce001eSMatthew G. Knepley 
2070c0ce001eSMatthew G. Knepley /*
2071c0ce001eSMatthew G. Knepley   PetscFVComputeGradient - Compute the gradient reconstruction matrix for a given cell
2072c0ce001eSMatthew G. Knepley 
2073c0ce001eSMatthew G. Knepley   Input Parameters:
2074*dce8aebaSBarry Smith + fvm      - The `PetscFV` object
2075c0ce001eSMatthew G. Knepley . numFaces - The number of cell faces which are not constrained
2076c0ce001eSMatthew G. Knepley . dx       - The vector from the cell centroid to the neighboring cell centroid for each face
2077c0ce001eSMatthew G. Knepley 
2078c0ce001eSMatthew G. Knepley   Level: developer
2079c0ce001eSMatthew G. Knepley 
2080*dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVCreate()`
2081c0ce001eSMatthew G. Knepley */
2082d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVComputeGradient_LeastSquares(PetscFV fvm, PetscInt numFaces, const PetscScalar dx[], PetscScalar grad[])
2083d71ae5a4SJacob Faibussowitsch {
2084c0ce001eSMatthew G. Knepley   PetscFV_LeastSquares *ls       = (PetscFV_LeastSquares *)fvm->data;
2085c0ce001eSMatthew G. Knepley   const PetscBool       useSVD   = PETSC_TRUE;
2086c0ce001eSMatthew G. Knepley   const PetscInt        maxFaces = ls->maxFaces;
2087c0ce001eSMatthew G. Knepley   PetscInt              dim, f, d;
2088c0ce001eSMatthew G. Knepley 
2089c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2090c0ce001eSMatthew G. Knepley   if (numFaces > maxFaces) {
209108401ef6SPierre Jolivet     PetscCheck(maxFaces >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Reconstruction has not been initialized, call PetscFVLeastSquaresSetMaxFaces()");
209263a3b9bcSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of input faces %" PetscInt_FMT " > %" PetscInt_FMT " maxfaces", numFaces, maxFaces);
2093c0ce001eSMatthew G. Knepley   }
20949566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
2095c0ce001eSMatthew G. Knepley   for (f = 0; f < numFaces; ++f) {
2096c0ce001eSMatthew G. Knepley     for (d = 0; d < dim; ++d) ls->B[d * maxFaces + f] = dx[f * dim + d];
2097c0ce001eSMatthew G. Knepley   }
2098c0ce001eSMatthew G. Knepley   /* Overwrites B with garbage, returns Binv in row-major format */
2099736d4f42SpierreXVI   if (useSVD) {
2100736d4f42SpierreXVI     PetscInt maxmn = PetscMax(numFaces, dim);
21019566063dSJacob Faibussowitsch     PetscCall(PetscFVLeastSquaresPseudoInverseSVD_Static(numFaces, maxFaces, dim, ls->B, ls->Binv, ls->tau, ls->workSize, ls->work));
2102736d4f42SpierreXVI     /* Binv shaped in column-major, coldim=maxmn.*/
2103736d4f42SpierreXVI     for (f = 0; f < numFaces; ++f) {
2104736d4f42SpierreXVI       for (d = 0; d < dim; ++d) grad[f * dim + d] = ls->Binv[d + maxmn * f];
2105736d4f42SpierreXVI     }
2106736d4f42SpierreXVI   } else {
21079566063dSJacob Faibussowitsch     PetscCall(PetscFVLeastSquaresPseudoInverse_Static(numFaces, maxFaces, dim, ls->B, ls->Binv, ls->tau, ls->workSize, ls->work));
2108736d4f42SpierreXVI     /* Binv shaped in row-major, rowdim=maxFaces.*/
2109c0ce001eSMatthew G. Knepley     for (f = 0; f < numFaces; ++f) {
2110c0ce001eSMatthew G. Knepley       for (d = 0; d < dim; ++d) grad[f * dim + d] = ls->Binv[d * maxFaces + f];
2111c0ce001eSMatthew G. Knepley     }
2112736d4f42SpierreXVI   }
2113c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
2114c0ce001eSMatthew G. Knepley }
2115c0ce001eSMatthew G. Knepley 
2116c0ce001eSMatthew G. Knepley /*
2117c0ce001eSMatthew G. Knepley   neighborVol[f*2+0] contains the left  geom
2118c0ce001eSMatthew G. Knepley   neighborVol[f*2+1] contains the right geom
2119c0ce001eSMatthew G. Knepley */
2120d71ae5a4SJacob 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[])
2121d71ae5a4SJacob Faibussowitsch {
2122c0ce001eSMatthew G. Knepley   void (*riemann)(PetscInt, PetscInt, const PetscReal[], const PetscReal[], const PetscScalar[], const PetscScalar[], PetscInt, const PetscScalar[], PetscScalar[], void *);
2123c0ce001eSMatthew G. Knepley   void              *rctx;
2124c0ce001eSMatthew G. Knepley   PetscScalar       *flux = fvm->fluxWork;
2125c0ce001eSMatthew G. Knepley   const PetscScalar *constants;
2126c0ce001eSMatthew G. Knepley   PetscInt           dim, numConstants, pdim, Nc, totDim, off, f, d;
2127c0ce001eSMatthew G. Knepley 
2128c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
21299566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(prob, &Nc));
21309566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
21319566063dSJacob Faibussowitsch   PetscCall(PetscDSGetFieldOffset(prob, field, &off));
21329566063dSJacob Faibussowitsch   PetscCall(PetscDSGetRiemannSolver(prob, field, &riemann));
21339566063dSJacob Faibussowitsch   PetscCall(PetscDSGetContext(prob, field, &rctx));
21349566063dSJacob Faibussowitsch   PetscCall(PetscDSGetConstants(prob, &numConstants, &constants));
21359566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
21369566063dSJacob Faibussowitsch   PetscCall(PetscFVGetNumComponents(fvm, &pdim));
2137c0ce001eSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
2138c0ce001eSMatthew G. Knepley     (*riemann)(dim, pdim, fgeom[f].centroid, fgeom[f].normal, &uL[f * Nc], &uR[f * Nc], numConstants, constants, flux, rctx);
2139c0ce001eSMatthew G. Knepley     for (d = 0; d < pdim; ++d) {
2140c0ce001eSMatthew G. Knepley       fluxL[f * totDim + off + d] = flux[d] / neighborVol[f * 2 + 0];
2141c0ce001eSMatthew G. Knepley       fluxR[f * totDim + off + d] = flux[d] / neighborVol[f * 2 + 1];
2142c0ce001eSMatthew G. Knepley     }
2143c0ce001eSMatthew G. Knepley   }
2144c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
2145c0ce001eSMatthew G. Knepley }
2146c0ce001eSMatthew G. Knepley 
2147d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFVLeastSquaresSetMaxFaces_LS(PetscFV fvm, PetscInt maxFaces)
2148d71ae5a4SJacob Faibussowitsch {
2149c0ce001eSMatthew G. Knepley   PetscFV_LeastSquares *ls = (PetscFV_LeastSquares *)fvm->data;
2150736d4f42SpierreXVI   PetscInt              dim, m, n, nrhs, minmn, maxmn;
2151c0ce001eSMatthew G. Knepley 
2152c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2153c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
21549566063dSJacob Faibussowitsch   PetscCall(PetscFVGetSpatialDimension(fvm, &dim));
21559566063dSJacob Faibussowitsch   PetscCall(PetscFree4(ls->B, ls->Binv, ls->tau, ls->work));
2156c0ce001eSMatthew G. Knepley   ls->maxFaces = maxFaces;
2157c0ce001eSMatthew G. Knepley   m            = ls->maxFaces;
2158c0ce001eSMatthew G. Knepley   n            = dim;
2159c0ce001eSMatthew G. Knepley   nrhs         = ls->maxFaces;
2160736d4f42SpierreXVI   minmn        = PetscMin(m, n);
2161736d4f42SpierreXVI   maxmn        = PetscMax(m, n);
2162736d4f42SpierreXVI   ls->workSize = 3 * minmn + PetscMax(2 * minmn, PetscMax(maxmn, nrhs)); /* required by LAPACK */
21639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(m * n, &ls->B, maxmn * maxmn, &ls->Binv, minmn, &ls->tau, ls->workSize, &ls->work));
2164c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
2165c0ce001eSMatthew G. Knepley }
2166c0ce001eSMatthew G. Knepley 
2167d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVInitialize_LeastSquares(PetscFV fvm)
2168d71ae5a4SJacob Faibussowitsch {
2169c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2170c0ce001eSMatthew G. Knepley   fvm->ops->setfromoptions       = NULL;
2171c0ce001eSMatthew G. Knepley   fvm->ops->setup                = PetscFVSetUp_LeastSquares;
2172c0ce001eSMatthew G. Knepley   fvm->ops->view                 = PetscFVView_LeastSquares;
2173c0ce001eSMatthew G. Knepley   fvm->ops->destroy              = PetscFVDestroy_LeastSquares;
2174c0ce001eSMatthew G. Knepley   fvm->ops->computegradient      = PetscFVComputeGradient_LeastSquares;
2175c0ce001eSMatthew G. Knepley   fvm->ops->integraterhsfunction = PetscFVIntegrateRHSFunction_LeastSquares;
2176c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
2177c0ce001eSMatthew G. Knepley }
2178c0ce001eSMatthew G. Knepley 
2179c0ce001eSMatthew G. Knepley /*MC
2180*dce8aebaSBarry Smith   PETSCFVLEASTSQUARES = "leastsquares" - A `PetscFV` implementation
2181c0ce001eSMatthew G. Knepley 
2182c0ce001eSMatthew G. Knepley   Level: intermediate
2183c0ce001eSMatthew G. Knepley 
2184*dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVType`, `PetscFVCreate()`, `PetscFVSetType()`
2185c0ce001eSMatthew G. Knepley M*/
2186c0ce001eSMatthew G. Knepley 
2187d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscFVCreate_LeastSquares(PetscFV fvm)
2188d71ae5a4SJacob Faibussowitsch {
2189c0ce001eSMatthew G. Knepley   PetscFV_LeastSquares *ls;
2190c0ce001eSMatthew G. Knepley 
2191c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2192c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
21934dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&ls));
2194c0ce001eSMatthew G. Knepley   fvm->data = ls;
2195c0ce001eSMatthew G. Knepley 
2196c0ce001eSMatthew G. Knepley   ls->maxFaces = -1;
2197c0ce001eSMatthew G. Knepley   ls->workSize = -1;
2198c0ce001eSMatthew G. Knepley   ls->B        = NULL;
2199c0ce001eSMatthew G. Knepley   ls->Binv     = NULL;
2200c0ce001eSMatthew G. Knepley   ls->tau      = NULL;
2201c0ce001eSMatthew G. Knepley   ls->work     = NULL;
2202c0ce001eSMatthew G. Knepley 
22039566063dSJacob Faibussowitsch   PetscCall(PetscFVSetComputeGradients(fvm, PETSC_TRUE));
22049566063dSJacob Faibussowitsch   PetscCall(PetscFVInitialize_LeastSquares(fvm));
22059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fvm, "PetscFVLeastSquaresSetMaxFaces_C", PetscFVLeastSquaresSetMaxFaces_LS));
2206c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
2207c0ce001eSMatthew G. Knepley }
2208c0ce001eSMatthew G. Knepley 
2209c0ce001eSMatthew G. Knepley /*@
2210c0ce001eSMatthew G. Knepley   PetscFVLeastSquaresSetMaxFaces - Set the maximum number of cell faces for gradient reconstruction
2211c0ce001eSMatthew G. Knepley 
2212c0ce001eSMatthew G. Knepley   Not collective
2213c0ce001eSMatthew G. Knepley 
2214c0ce001eSMatthew G. Knepley   Input parameters:
2215*dce8aebaSBarry Smith + fvm      - The `PetscFV` object
2216c0ce001eSMatthew G. Knepley - maxFaces - The maximum number of cell faces
2217c0ce001eSMatthew G. Knepley 
2218c0ce001eSMatthew G. Knepley   Level: intermediate
2219c0ce001eSMatthew G. Knepley 
2220*dce8aebaSBarry Smith .seealso: `PetscFV`, `PetscFVCreate()`, `PETSCFVLEASTSQUARES`, `PetscFVComputeGradient()`
2221c0ce001eSMatthew G. Knepley @*/
2222d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFVLeastSquaresSetMaxFaces(PetscFV fvm, PetscInt maxFaces)
2223d71ae5a4SJacob Faibussowitsch {
2224c0ce001eSMatthew G. Knepley   PetscFunctionBegin;
2225c0ce001eSMatthew G. Knepley   PetscValidHeaderSpecific(fvm, PETSCFV_CLASSID, 1);
2226cac4c232SBarry Smith   PetscTryMethod(fvm, "PetscFVLeastSquaresSetMaxFaces_C", (PetscFV, PetscInt), (fvm, maxFaces));
2227c0ce001eSMatthew G. Knepley   PetscFunctionReturn(0);
2228c0ce001eSMatthew G. Knepley }
2229