xref: /libCEED/interface/ceed-fortran.c (revision c9c2c07970382857cc7b4a28d359710237b91a3e)
1 // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
2 // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3 //
4 // SPDX-License-Identifier: BSD-2-Clause
5 //
6 // This file is part of CEED:  http://github.com/ceed
7 
8 // Fortran interface
9 #include <ceed/ceed.h>
10 #include <ceed/backend.h>
11 #include <ceed-impl.h>
12 #include <ceed-fortran-name.h>
13 #include <stdbool.h>
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <string.h>
17 
18 #define FORTRAN_REQUEST_IMMEDIATE -1
19 #define FORTRAN_REQUEST_ORDERED -2
20 #define FORTRAN_NULL -3
21 #define FORTRAN_STRIDES_BACKEND -4
22 #define FORTRAN_VECTOR_ACTIVE -5
23 #define FORTRAN_VECTOR_NONE -6
24 #define FORTRAN_ELEMRESTRICTION_NONE -7
25 #define FORTRAN_BASIS_COLLOCATED -8
26 #define FORTRAN_QFUNCTION_NONE -9
27 
28 static Ceed *Ceed_dict = NULL;
29 static int Ceed_count = 0;
30 static int Ceed_n = 0;
31 static int Ceed_count_max = 0;
32 
33 // This test should actually be for the gfortran version, but we don't currently
34 // have a configure system to determine that (TODO).  At present, this will use
35 // the smaller integer when run with clang+gfortran=8, for example.  (That is
36 // sketchy, but will likely work for users that don't have huge character
37 // strings.)
38 #if __GNUC__ >= 8
39 typedef size_t fortran_charlen_t;
40 #else
41 typedef int fortran_charlen_t;
42 #endif
43 
44 #define Splice(a, b) a ## b
45 
46 // Fortran strings are generally unterminated and the length is passed as an
47 // extra argument after all the normal arguments.  Some compilers (I only know
48 // of Windows) place the length argument immediately after the string parameter
49 // (TODO).
50 //
51 // We can't just NULL-terminate the string in-place because that could overwrite
52 // other strings or attempt to write to read-only memory.  This macro allocates
53 // a string to hold the null-terminated version of the string that C expects.
54 #define FIX_STRING(stringname)                                          \
55   char Splice(stringname, _c)[1024];                                    \
56   if (Splice(stringname, _len) > 1023)                                  \
57     *err = CeedError(NULL, 1, "Fortran string length too long %zd", (size_t)Splice(stringname, _len)); \
58   strncpy(Splice(stringname, _c), stringname, Splice(stringname, _len)); \
59   Splice(stringname, _c)[Splice(stringname, _len)] = 0;                 \
60 
61 // -----------------------------------------------------------------------------
62 // Ceed
63 // -----------------------------------------------------------------------------
64 #define fCeedInit FORTRAN_NAME(ceedinit,CEEDINIT)
65 CEED_EXTERN void fCeedInit(const char *resource, int *ceed, int *err,
66                            fortran_charlen_t resource_len) {
67   FIX_STRING(resource);
68   if (Ceed_count == Ceed_count_max) {
69     Ceed_count_max += Ceed_count_max/2 + 1;
70     CeedRealloc(Ceed_count_max, &Ceed_dict);
71   }
72 
73   Ceed *ceed_ = &Ceed_dict[Ceed_count];
74   *err = CeedInit(resource_c, ceed_);
75 
76   if (*err == 0) {
77     *ceed = Ceed_count++;
78     Ceed_n++;
79   }
80 }
81 
82 #define fCeedIsDeterministic \
83     FORTRAN_NAME(ceedisdeterministic,CEEDISDETERMINISTIC)
84 CEED_EXTERN void fCeedIsDeterministic(int *ceed, int *is_deterministic,
85                                       int *err) {
86   *err = CeedIsDeterministic(Ceed_dict[*ceed], (bool *)is_deterministic);
87 }
88 
89 #define fCeedGetPreferredMemType \
90     FORTRAN_NAME(ceedgetpreferredmemtype,CEEDGETPREFERREDMEMTYPE)
91 CEED_EXTERN void fCeedGetPreferredMemType(int *ceed, int *type, int *err) {
92   *err = CeedGetPreferredMemType(Ceed_dict[*ceed], (CeedMemType *)type);
93 }
94 
95 #define fCeedView FORTRAN_NAME(ceedview,CEEDVIEW)
96 CEED_EXTERN void fCeedView(int *ceed, int *err) {
97   *err = CeedView(Ceed_dict[*ceed], stdout);
98 }
99 
100 #define fCeedDestroy FORTRAN_NAME(ceeddestroy,CEEDDESTROY)
101 CEED_EXTERN void fCeedDestroy(int *ceed, int *err) {
102   if (*ceed == FORTRAN_NULL) return;
103   *err = CeedDestroy(&Ceed_dict[*ceed]);
104 
105   if (*err == 0) {
106     *ceed = FORTRAN_NULL;
107     Ceed_n--;
108     if (Ceed_n == 0) {
109       CeedFree(&Ceed_dict);
110       Ceed_count = 0;
111       Ceed_count_max = 0;
112     }
113   }
114 }
115 
116 // -----------------------------------------------------------------------------
117 // CeedVector
118 // -----------------------------------------------------------------------------
119 static CeedVector *CeedVector_dict = NULL;
120 static int CeedVector_count = 0;
121 static int CeedVector_n = 0;
122 static int CeedVector_count_max = 0;
123 
124 #define fCeedVectorCreate FORTRAN_NAME(ceedvectorcreate,CEEDVECTORCREATE)
125 CEED_EXTERN void fCeedVectorCreate(int *ceed, int *length, int *vec, int *err) {
126   if (CeedVector_count == CeedVector_count_max) {
127     CeedVector_count_max += CeedVector_count_max/2 + 1;
128     CeedRealloc(CeedVector_count_max, &CeedVector_dict);
129   }
130 
131   CeedVector *vec_ = &CeedVector_dict[CeedVector_count];
132   *err = CeedVectorCreate(Ceed_dict[*ceed], *length, vec_);
133 
134   if (*err == 0) {
135     *vec = CeedVector_count++;
136     CeedVector_n++;
137   }
138 }
139 
140 #define fCeedVectorSetArray FORTRAN_NAME(ceedvectorsetarray,CEEDVECTORSETARRAY)
141 CEED_EXTERN void fCeedVectorSetArray(int *vec, int *memtype, int *copymode,
142                                      CeedScalar *array, int64_t *offset, int *err) {
143   *err = CeedVectorSetArray(CeedVector_dict[*vec], (CeedMemType)*memtype,
144                             (CeedCopyMode)*copymode,
145                             (CeedScalar *)(array + *offset));
146 }
147 
148 #define fCeedVectorTakeArray FORTRAN_NAME(ceedvectortakearray,CEEDVECTORTAKEARRAY)
149 CEED_EXTERN void fCeedVectorTakeArray(int *vec, int *memtype, CeedScalar *array,
150                                       int64_t *offset, int *err) {
151   CeedScalar *b;
152   CeedVector vec_ = CeedVector_dict[*vec];
153   *err = CeedVectorTakeArray(vec_, (CeedMemType)*memtype, &b);
154   *offset = b - array;
155 }
156 
157 #define fCeedVectorSyncArray FORTRAN_NAME(ceedvectorsyncarray,CEEDVECTORSYNCARRAY)
158 CEED_EXTERN void fCeedVectorSyncArray(int *vec, int *memtype, int *err) {
159   *err = CeedVectorSyncArray(CeedVector_dict[*vec], (CeedMemType)*memtype);
160 }
161 
162 #define fCeedVectorSetValue FORTRAN_NAME(ceedvectorsetvalue,CEEDVECTORSETVALUE)
163 CEED_EXTERN void fCeedVectorSetValue(int *vec, CeedScalar *value, int *err) {
164   *err = CeedVectorSetValue(CeedVector_dict[*vec], *value);
165 }
166 
167 #define fCeedVectorGetArray FORTRAN_NAME(ceedvectorgetarray,CEEDVECTORGETARRAY)
168 CEED_EXTERN void fCeedVectorGetArray(int *vec, int *memtype, CeedScalar *array,
169                                      int64_t *offset, int *err) {
170   CeedScalar *b;
171   CeedVector vec_ = CeedVector_dict[*vec];
172   *err = CeedVectorGetArray(vec_, (CeedMemType)*memtype, &b);
173   *offset = b - array;
174 }
175 
176 #define fCeedVectorGetArrayRead \
177     FORTRAN_NAME(ceedvectorgetarrayread,CEEDVECTORGETARRAYREAD)
178 CEED_EXTERN void fCeedVectorGetArrayRead(int *vec, int *memtype,
179     CeedScalar *array,
180     int64_t *offset, int *err) {
181   const CeedScalar *b;
182   CeedVector vec_ = CeedVector_dict[*vec];
183   *err = CeedVectorGetArrayRead(vec_, (CeedMemType)*memtype, &b);
184   *offset = b - array;
185 }
186 
187 #define fCeedVectorGetArrayWrite \
188     FORTRAN_NAME(ceedvectorgetarraywrite,CEEDVECTORGETARRAYWRITE)
189 CEED_EXTERN void fCeedVectorGetArrayWrite(int *vec, int *memtype,
190     CeedScalar *array,
191     int64_t *offset, int *err) {
192   CeedScalar *b;
193   CeedVector vec_ = CeedVector_dict[*vec];
194   *err = CeedVectorGetArrayWrite(vec_, (CeedMemType)*memtype, &b);
195   *offset = b - array;
196 }
197 
198 #define fCeedVectorRestoreArray \
199     FORTRAN_NAME(ceedvectorrestorearray,CEEDVECTORRESTOREARRAY)
200 CEED_EXTERN void fCeedVectorRestoreArray(int *vec, CeedScalar *array,
201     int64_t *offset, int *err) {
202   CeedScalar *offsetArray = array + *offset;
203   *err = CeedVectorRestoreArray(CeedVector_dict[*vec], &offsetArray);
204   *offset = 0;
205 }
206 
207 #define fCeedVectorRestoreArrayRead \
208     FORTRAN_NAME(ceedvectorrestorearrayread,CEEDVECTORRESTOREARRAYREAD)
209 CEED_EXTERN void fCeedVectorRestoreArrayRead(int *vec, const CeedScalar *array,
210     int64_t *offset, int *err) {
211   *err = CeedVectorRestoreArrayRead(CeedVector_dict[*vec], &array);
212   *offset = 0;
213 }
214 
215 #define fCeedVectorNorm \
216     FORTRAN_NAME(ceedvectornorm,CEEDVECTORNORM)
217 CEED_EXTERN void fCeedVectorNorm(int *vec, int *type, CeedScalar *norm,
218                                  int *err) {
219   *err = CeedVectorNorm(CeedVector_dict[*vec], (CeedNormType)*type, norm);
220 }
221 
222 #define fCeedVectorReciprocal \
223     FORTRAN_NAME(ceedvectorreciprocal,CEEDVECTORRECIPROCAL)
224 CEED_EXTERN void fCeedVectorReciprocal(int *vec, int *err) {
225   *err = CeedVectorReciprocal(CeedVector_dict[*vec]);
226 }
227 
228 #define fCeedVectorView FORTRAN_NAME(ceedvectorview,CEEDVECTORVIEW)
229 CEED_EXTERN void fCeedVectorView(int *vec, int *err) {
230   *err = CeedVectorView(CeedVector_dict[*vec], "%12.8f", stdout);
231 }
232 
233 #define fCeedVectorDestroy FORTRAN_NAME(ceedvectordestroy,CEEDVECTORDESTROY)
234 CEED_EXTERN void fCeedVectorDestroy(int *vec, int *err) {
235   if (*vec == FORTRAN_NULL) return;
236   *err = CeedVectorDestroy(&CeedVector_dict[*vec]);
237 
238   if (*err == 0) {
239     *vec = FORTRAN_NULL;
240     CeedVector_n--;
241     if (CeedVector_n == 0) {
242       CeedFree(&CeedVector_dict);
243       CeedVector_count = 0;
244       CeedVector_count_max = 0;
245     }
246   }
247 }
248 
249 // -----------------------------------------------------------------------------
250 // CeedElemRestriction
251 // -----------------------------------------------------------------------------
252 static CeedElemRestriction *CeedElemRestriction_dict = NULL;
253 static int CeedElemRestriction_count = 0;
254 static int CeedElemRestriction_n = 0;
255 static int CeedElemRestriction_count_max = 0;
256 
257 #define fCeedElemRestrictionCreate \
258     FORTRAN_NAME(ceedelemrestrictioncreate, CEEDELEMRESTRICTIONCREATE)
259 CEED_EXTERN void fCeedElemRestrictionCreate(int *ceed, int *nelements,
260     int *esize,
261     int *num_comp, int *comp_stride, int *lsize,
262     int *memtype, int *copymode, const int *offsets,
263     int *elemrestriction, int *err) {
264   if (CeedElemRestriction_count == CeedElemRestriction_count_max) {
265     CeedElemRestriction_count_max += CeedElemRestriction_count_max/2 + 1;
266     CeedRealloc(CeedElemRestriction_count_max, &CeedElemRestriction_dict);
267   }
268 
269   const int *offsets_ = offsets;
270 
271   CeedElemRestriction *elemrestriction_ =
272     &CeedElemRestriction_dict[CeedElemRestriction_count];
273   *err = CeedElemRestrictionCreate(Ceed_dict[*ceed], *nelements, *esize,
274                                    *num_comp, *comp_stride, *lsize,
275                                    (CeedMemType)*memtype,
276                                    (CeedCopyMode)*copymode, offsets_,
277                                    elemrestriction_);
278 
279   if (*err == 0) {
280     *elemrestriction = CeedElemRestriction_count++;
281     CeedElemRestriction_n++;
282   }
283 }
284 
285 #define fCeedElemRestrictionCreateStrided \
286     FORTRAN_NAME(ceedelemrestrictioncreatestrided, CEEDELEMRESTRICTIONCREATESTRIDED)
287 CEED_EXTERN void fCeedElemRestrictionCreateStrided(int *ceed, int *nelements,
288     int *esize,
289     int *num_comp, int *lsize, int *strides,
290     int *elemrestriction, int *err) {
291   if (CeedElemRestriction_count == CeedElemRestriction_count_max) {
292     CeedElemRestriction_count_max += CeedElemRestriction_count_max/2 + 1;
293     CeedRealloc(CeedElemRestriction_count_max, &CeedElemRestriction_dict);
294   }
295 
296   CeedElemRestriction *elemrestriction_ =
297     &CeedElemRestriction_dict[CeedElemRestriction_count];
298   *err = CeedElemRestrictionCreateStrided(Ceed_dict[*ceed], *nelements, *esize,
299                                           *num_comp, *lsize,
300                                           *strides == FORTRAN_STRIDES_BACKEND ?
301                                           CEED_STRIDES_BACKEND : strides,
302                                           elemrestriction_);
303   if (*err == 0) {
304     *elemrestriction = CeedElemRestriction_count++;
305     CeedElemRestriction_n++;
306   }
307 }
308 
309 #define fCeedElemRestrictionCreateBlocked \
310     FORTRAN_NAME(ceedelemrestrictioncreateblocked,CEEDELEMRESTRICTIONCREATEBLOCKED)
311 CEED_EXTERN void fCeedElemRestrictionCreateBlocked(int *ceed, int *nelements,
312     int *esize,
313     int *blocksize, int *num_comp,
314     int *comp_stride, int *lsize,
315     int *mtype, int *cmode,
316     int *blkindices, int *elemrestriction,
317     int *err) {
318 
319   if (CeedElemRestriction_count == CeedElemRestriction_count_max) {
320     CeedElemRestriction_count_max += CeedElemRestriction_count_max/2 + 1;
321     CeedRealloc(CeedElemRestriction_count_max, &CeedElemRestriction_dict);
322   }
323 
324   CeedElemRestriction *elemrestriction_ =
325     &CeedElemRestriction_dict[CeedElemRestriction_count];
326   *err = CeedElemRestrictionCreateBlocked(Ceed_dict[*ceed],
327                                           *nelements, *esize, *blocksize,
328                                           *num_comp, *comp_stride, *lsize,
329                                           (CeedMemType)*mtype,
330                                           (CeedCopyMode)*cmode, blkindices,
331                                           elemrestriction_);
332 
333   if (*err == 0) {
334     *elemrestriction = CeedElemRestriction_count++;
335     CeedElemRestriction_n++;
336   }
337 }
338 
339 #define fCeedElemRestrictionCreateBlockedStrided \
340     FORTRAN_NAME(ceedelemrestrictioncreateblockedstrided, CEEDELEMRESTRICTIONCREATEBLOCKEDSTRIDED)
341 CEED_EXTERN void fCeedElemRestrictionCreateBlockedStrided(int *ceed,
342     int *nelements,
343     int *esize, int *blk_size, int *num_comp, int *lsize, int *strides,
344     int *elemrestriction, int *err) {
345   if (CeedElemRestriction_count == CeedElemRestriction_count_max) {
346     CeedElemRestriction_count_max += CeedElemRestriction_count_max/2 + 1;
347     CeedRealloc(CeedElemRestriction_count_max, &CeedElemRestriction_dict);
348   }
349 
350   CeedElemRestriction *elemrestriction_ =
351     &CeedElemRestriction_dict[CeedElemRestriction_count];
352   *err = CeedElemRestrictionCreateBlockedStrided(Ceed_dict[*ceed], *nelements,
353          *esize, *blk_size, *num_comp, *lsize, strides, elemrestriction_);
354   if (*err == 0) {
355     *elemrestriction = CeedElemRestriction_count++;
356     CeedElemRestriction_n++;
357   }
358 }
359 
360 static CeedRequest *CeedRequest_dict = NULL;
361 static int CeedRequest_count = 0;
362 static int CeedRequest_n = 0;
363 static int CeedRequest_count_max = 0;
364 
365 #define fCeedElemRestrictionApply \
366     FORTRAN_NAME(ceedelemrestrictionapply,CEEDELEMRESTRICTIONAPPLY)
367 CEED_EXTERN void fCeedElemRestrictionApply(int *elemr, int *tmode, int *uvec,
368     int *ruvec,
369     int *rqst, int *err) {
370   int createRequest = 1;
371   // Check if input is CEED_REQUEST_ORDERED(-2) or CEED_REQUEST_IMMEDIATE(-1)
372   if (*rqst == FORTRAN_REQUEST_IMMEDIATE || *rqst == FORTRAN_REQUEST_ORDERED)
373     createRequest = 0;
374 
375   if (createRequest && CeedRequest_count == CeedRequest_count_max) {
376     CeedRequest_count_max += CeedRequest_count_max/2 + 1;
377     CeedRealloc(CeedRequest_count_max, &CeedRequest_dict);
378   }
379 
380   CeedRequest *rqst_;
381   if      (*rqst == FORTRAN_REQUEST_IMMEDIATE) rqst_ = CEED_REQUEST_IMMEDIATE;
382   else if (*rqst == FORTRAN_REQUEST_ORDERED  ) rqst_ = CEED_REQUEST_ORDERED;
383   else rqst_ = &CeedRequest_dict[CeedRequest_count];
384 
385   *err = CeedElemRestrictionApply(CeedElemRestriction_dict[*elemr],
386                                   (CeedTransposeMode)*tmode,
387                                   CeedVector_dict[*uvec],
388                                   CeedVector_dict[*ruvec], rqst_);
389 
390   if (*err == 0 && createRequest) {
391     *rqst = CeedRequest_count++;
392     CeedRequest_n++;
393   }
394 }
395 
396 #define fCeedElemRestrictionApplyBlock \
397     FORTRAN_NAME(ceedelemrestrictionapplyblock,CEEDELEMRESTRICTIONAPPLYBLOCK)
398 CEED_EXTERN void fCeedElemRestrictionApplyBlock(int *elemr, int *block,
399     int *tmode,
400     int *uvec, int *ruvec, int *rqst, int *err) {
401   int createRequest = 1;
402   // Check if input is CEED_REQUEST_ORDERED(-2) or CEED_REQUEST_IMMEDIATE(-1)
403   if (*rqst == FORTRAN_REQUEST_IMMEDIATE || *rqst == FORTRAN_REQUEST_ORDERED)
404     createRequest = 0;
405 
406   if (createRequest && CeedRequest_count == CeedRequest_count_max) {
407     CeedRequest_count_max += CeedRequest_count_max/2 + 1;
408     CeedRealloc(CeedRequest_count_max, &CeedRequest_dict);
409   }
410 
411   CeedRequest *rqst_;
412   if      (*rqst == FORTRAN_REQUEST_IMMEDIATE) rqst_ = CEED_REQUEST_IMMEDIATE;
413   else if (*rqst == FORTRAN_REQUEST_ORDERED  ) rqst_ = CEED_REQUEST_ORDERED;
414   else rqst_ = &CeedRequest_dict[CeedRequest_count];
415 
416   *err = CeedElemRestrictionApplyBlock(CeedElemRestriction_dict[*elemr], *block,
417                                        (CeedTransposeMode)*tmode, CeedVector_dict[*uvec],
418                                        CeedVector_dict[*ruvec], rqst_);
419 
420   if (*err == 0 && createRequest) {
421     *rqst = CeedRequest_count++;
422     CeedRequest_n++;
423   }
424 }
425 
426 #define fCeedElemRestrictionGetMultiplicity \
427     FORTRAN_NAME(ceedelemrestrictiongetmultiplicity,CEEDELEMRESTRICTIONGETMULTIPLICITY)
428 CEED_EXTERN void fCeedElemRestrictionGetMultiplicity(int *elemr, int *mult,
429     int *err) {
430   *err = CeedElemRestrictionGetMultiplicity(CeedElemRestriction_dict[*elemr],
431          CeedVector_dict[*mult]);
432 }
433 
434 #define fCeedElemRestrictionGetELayout \
435     FORTRAN_NAME(ceedelemrestrictiongetelayout,CEEDELEMRESTRICTIONGETELAYOUT)
436 CEED_EXTERN void fCeedElemRestrictionGetELayout(int *elemr, int *layout,
437     int *err) {
438   CeedInt layout_c[3];
439   *err = CeedElemRestrictionGetELayout(CeedElemRestriction_dict[*elemr],
440                                        &layout_c);
441   for (int i=0; i<3; i++)
442     layout[i] = layout_c[i];
443 }
444 
445 #define fCeedElemRestrictionView \
446     FORTRAN_NAME(ceedelemrestrictionview,CEEDELEMRESTRICTIONVIEW)
447 CEED_EXTERN void fCeedElemRestrictionView(int *elemr, int *err) {
448   *err = CeedElemRestrictionView(CeedElemRestriction_dict[*elemr], stdout);
449 }
450 
451 #define fCeedRequestWait FORTRAN_NAME(ceedrequestwait, CEEDREQUESTWAIT)
452 CEED_EXTERN void fCeedRequestWait(int *rqst, int *err) {
453   // TODO Uncomment this once CeedRequestWait is implemented
454   //*err = CeedRequestWait(&CeedRequest_dict[*rqst]);
455 
456   if (*err == 0) {
457     CeedRequest_n--;
458     if (CeedRequest_n == 0) {
459       CeedFree(&CeedRequest_dict);
460       CeedRequest_count = 0;
461       CeedRequest_count_max = 0;
462     }
463   }
464 }
465 
466 #define fCeedElemRestrictionDestroy \
467     FORTRAN_NAME(ceedelemrestrictiondestroy,CEEDELEMRESTRICTIONDESTROY)
468 CEED_EXTERN void fCeedElemRestrictionDestroy(int *elem, int *err) {
469   if (*elem == FORTRAN_NULL) return;
470   *err = CeedElemRestrictionDestroy(&CeedElemRestriction_dict[*elem]);
471 
472   if (*err == 0) {
473     *elem = FORTRAN_NULL;
474     CeedElemRestriction_n--;
475     if (CeedElemRestriction_n == 0) {
476       CeedFree(&CeedElemRestriction_dict);
477       CeedElemRestriction_count = 0;
478       CeedElemRestriction_count_max = 0;
479     }
480   }
481 }
482 
483 // -----------------------------------------------------------------------------
484 // CeedBasis
485 // -----------------------------------------------------------------------------
486 static CeedBasis *CeedBasis_dict = NULL;
487 static int CeedBasis_count = 0;
488 static int CeedBasis_n = 0;
489 static int CeedBasis_count_max = 0;
490 
491 #define fCeedBasisCreateTensorH1Lagrange \
492     FORTRAN_NAME(ceedbasiscreatetensorh1lagrange, CEEDBASISCREATETENSORH1LAGRANGE)
493 CEED_EXTERN void fCeedBasisCreateTensorH1Lagrange(int *ceed, int *dim,
494     int *num_comp, int *P, int *Q, int *quadmode,
495     int *basis, int *err) {
496   if (CeedBasis_count == CeedBasis_count_max) {
497     CeedBasis_count_max += CeedBasis_count_max/2 + 1;
498     CeedRealloc(CeedBasis_count_max, &CeedBasis_dict);
499   }
500 
501   *err = CeedBasisCreateTensorH1Lagrange(Ceed_dict[*ceed], *dim, *num_comp, *P,
502                                          *Q,
503                                          (CeedQuadMode)*quadmode,
504                                          &CeedBasis_dict[CeedBasis_count]);
505 
506   if (*err == 0) {
507     *basis = CeedBasis_count++;
508     CeedBasis_n++;
509   }
510 }
511 
512 #define fCeedBasisCreateTensorH1 \
513     FORTRAN_NAME(ceedbasiscreatetensorh1, CEEDBASISCREATETENSORH1)
514 CEED_EXTERN void fCeedBasisCreateTensorH1(int *ceed, int *dim, int *num_comp,
515     int *P_1d,
516     int *Q_1d, const CeedScalar *interp_1d,
517     const CeedScalar *grad_1d,
518     const CeedScalar *q_ref_1d,
519     const CeedScalar *q_weight_1d, int *basis,
520     int *err) {
521   if (CeedBasis_count == CeedBasis_count_max) {
522     CeedBasis_count_max += CeedBasis_count_max/2 + 1;
523     CeedRealloc(CeedBasis_count_max, &CeedBasis_dict);
524   }
525 
526   *err = CeedBasisCreateTensorH1(Ceed_dict[*ceed], *dim, *num_comp, *P_1d, *Q_1d,
527                                  interp_1d, grad_1d, q_ref_1d, q_weight_1d,
528                                  &CeedBasis_dict[CeedBasis_count]);
529 
530   if (*err == 0) {
531     *basis = CeedBasis_count++;
532     CeedBasis_n++;
533   }
534 }
535 
536 #define fCeedBasisCreateH1 \
537     FORTRAN_NAME(ceedbasiscreateh1, CEEDBASISCREATEH1)
538 CEED_EXTERN void fCeedBasisCreateH1(int *ceed, int *topo, int *num_comp,
539                                     int *nnodes,
540                                     int *nqpts, const CeedScalar *interp,
541                                     const CeedScalar *grad, const CeedScalar *qref,
542                                     const CeedScalar *qweight, int *basis, int *err) {
543   if (CeedBasis_count == CeedBasis_count_max) {
544     CeedBasis_count_max += CeedBasis_count_max/2 + 1;
545     CeedRealloc(CeedBasis_count_max, &CeedBasis_dict);
546   }
547 
548   *err = CeedBasisCreateH1(Ceed_dict[*ceed], (CeedElemTopology)*topo, *num_comp,
549                            *nnodes, *nqpts, interp, grad, qref, qweight,
550                            &CeedBasis_dict[CeedBasis_count]);
551 
552   if (*err == 0) {
553     *basis = CeedBasis_count++;
554     CeedBasis_n++;
555   }
556 }
557 
558 #define fCeedBasisView FORTRAN_NAME(ceedbasisview, CEEDBASISVIEW)
559 CEED_EXTERN void fCeedBasisView(int *basis, int *err) {
560   *err = CeedBasisView(CeedBasis_dict[*basis], stdout);
561 }
562 
563 #define fCeedQRFactorization \
564     FORTRAN_NAME(ceedqrfactorization, CEEDQRFACTORIZATION)
565 CEED_EXTERN void fCeedQRFactorization(int *ceed, CeedScalar *mat,
566                                       CeedScalar *tau, int *m,
567                                       int *n, int *err) {
568   *err = CeedQRFactorization(Ceed_dict[*ceed], mat, tau, *m, *n);
569 }
570 
571 #define fCeedHouseholderApplyQ \
572     FORTRAN_NAME(ceedhouseholderapplyq, CEEDHOUSEHOLDERAPPLYQ)
573 CEED_EXTERN void fCeedHouseholderApplyQ(CeedScalar *A, CeedScalar *Q,
574                                         CeedScalar *tau,
575                                         int *t_mode,
576                                         int *m, int *n, int *k, int *row, int *col, int *err) {
577   *err = CeedHouseholderApplyQ(A, Q, tau, (CeedTransposeMode)*t_mode, *m, *n, *k,
578                                *row, *col);
579 }
580 
581 #define fCeedSymmetricSchurDecomposition \
582     FORTRAN_NAME(ceedsymmetricschurdecomposition, CEEDSYMMETRICSCHURDECOMPOSITION)
583 CEED_EXTERN void fCeedSymmetricSchurDecomposition(int *ceed, CeedScalar *mat,
584     CeedScalar *lambda, int *n, int *err) {
585   *err = CeedSymmetricSchurDecomposition(Ceed_dict[*ceed], mat, lambda, *n);
586 }
587 
588 #define fCeedSimultaneousDiagonalization \
589     FORTRAN_NAME(ceedsimultaneousdiagonalization, CEEDSIMULTANEOUSDIAGONALIZATION)
590 CEED_EXTERN void fCeedSimultaneousDiagonalization(int *ceed, CeedScalar *matA,
591     CeedScalar *matB, CeedScalar *x,
592     CeedScalar *lambda, int *n, int *err) {
593   *err = CeedSimultaneousDiagonalization(Ceed_dict[*ceed], matA, matB, x,
594                                          lambda, *n);
595 }
596 
597 #define fCeedBasisGetCollocatedGrad \
598     FORTRAN_NAME(ceedbasisgetcollocatedgrad, CEEDBASISGETCOLLOCATEDGRAD)
599 CEED_EXTERN void fCeedBasisGetCollocatedGrad(int *basis,
600     CeedScalar *colo_grad_1d,
601     int *err) {
602   *err = CeedBasisGetCollocatedGrad(CeedBasis_dict[*basis], colo_grad_1d);
603 }
604 
605 #define fCeedBasisApply FORTRAN_NAME(ceedbasisapply, CEEDBASISAPPLY)
606 CEED_EXTERN void fCeedBasisApply(int *basis, int *num_elem, int *tmode,
607                                  int *eval_mode,
608                                  int *u, int *v, int *err) {
609   *err = CeedBasisApply(CeedBasis_dict[*basis], *num_elem,
610                         (CeedTransposeMode)*tmode,
611                         (CeedEvalMode)*eval_mode,
612                         *u == FORTRAN_VECTOR_NONE ? CEED_VECTOR_NONE : CeedVector_dict[*u],
613                         CeedVector_dict[*v]);
614 }
615 
616 #define fCeedBasisGetNumNodes \
617     FORTRAN_NAME(ceedbasisgetnumnodes, CEEDBASISGETNUMNODES)
618 CEED_EXTERN void fCeedBasisGetNumNodes(int *basis, int *P, int *err) {
619   *err = CeedBasisGetNumNodes(CeedBasis_dict[*basis], P);
620 }
621 
622 #define fCeedBasisGetNumQuadraturePoints \
623     FORTRAN_NAME(ceedbasisgetnumquadraturepoints, CEEDBASISGETNUMQUADRATUREPOINTS)
624 CEED_EXTERN void fCeedBasisGetNumQuadraturePoints(int *basis, int *Q,
625     int *err) {
626   *err = CeedBasisGetNumQuadraturePoints(CeedBasis_dict[*basis], Q);
627 }
628 
629 #define fCeedBasisGetInterp1D \
630     FORTRAN_NAME(ceedbasisgetinterp1d, CEEDBASISGETINTERP1D)
631 CEED_EXTERN void fCeedBasisGetInterp1D(int *basis, CeedScalar *interp_1d,
632                                        int64_t *offset,
633                                        int *err) {
634   const CeedScalar *interp1d_;
635   CeedBasis basis_ = CeedBasis_dict[*basis];
636   *err = CeedBasisGetInterp1D(basis_, &interp1d_);
637   *offset = interp1d_ - interp_1d;
638 }
639 
640 #define fCeedBasisGetGrad1D \
641     FORTRAN_NAME(ceedbasisgetgrad1d, CEEDBASISGETGRAD1D)
642 CEED_EXTERN void fCeedBasisGetGrad1D(int *basis, CeedScalar *grad_1d,
643                                      int64_t *offset,
644                                      int *err) {
645   const CeedScalar *grad1d_;
646   CeedBasis basis_ = CeedBasis_dict[*basis];
647   *err = CeedBasisGetGrad1D(basis_, &grad1d_);
648   *offset = grad1d_ - grad_1d;
649 }
650 
651 #define fCeedBasisGetQRef \
652     FORTRAN_NAME(ceedbasisgetqref, CEEDBASISGETQREF)
653 CEED_EXTERN void fCeedBasisGetQRef(int *basis, CeedScalar *q_ref,
654                                    int64_t *offset,
655                                    int *err) {
656   const CeedScalar *qref_;
657   CeedBasis basis_ = CeedBasis_dict[*basis];
658   *err = CeedBasisGetQRef(basis_, &qref_);
659   *offset = qref_ - q_ref;
660 }
661 
662 #define fCeedBasisDestroy FORTRAN_NAME(ceedbasisdestroy,CEEDBASISDESTROY)
663 CEED_EXTERN void fCeedBasisDestroy(int *basis, int *err) {
664   if (*basis == FORTRAN_NULL) return;
665   *err = CeedBasisDestroy(&CeedBasis_dict[*basis]);
666 
667   if (*err == 0) {
668     *basis = FORTRAN_NULL;
669     CeedBasis_n--;
670     if (CeedBasis_n == 0) {
671       CeedFree(&CeedBasis_dict);
672       CeedBasis_count = 0;
673       CeedBasis_count_max = 0;
674     }
675   }
676 }
677 
678 #define fCeedGaussQuadrature FORTRAN_NAME(ceedgaussquadrature, CEEDGAUSSQUADRATURE)
679 CEED_EXTERN void fCeedGaussQuadrature(int *Q, CeedScalar *q_ref_1d,
680                                       CeedScalar *q_weight_1d,
681                                       int *err) {
682   *err = CeedGaussQuadrature(*Q, q_ref_1d, q_weight_1d);
683 }
684 
685 #define fCeedLobattoQuadrature \
686     FORTRAN_NAME(ceedlobattoquadrature, CEEDLOBATTOQUADRATURE)
687 CEED_EXTERN void fCeedLobattoQuadrature(int *Q, CeedScalar *q_ref_1d,
688                                         CeedScalar *q_weight_1d,
689                                         int *err) {
690   *err = CeedLobattoQuadrature(*Q, q_ref_1d, q_weight_1d);
691 }
692 
693 // -----------------------------------------------------------------------------
694 // CeedQFunctionContext
695 // -----------------------------------------------------------------------------
696 static CeedQFunctionContext *CeedQFunctionContext_dict = NULL;
697 static int CeedQFunctionContext_count = 0;
698 static int CeedQFunctionContext_n = 0;
699 static int CeedQFunctionContext_count_max = 0;
700 
701 #define fCeedQFunctionContextCreate \
702     FORTRAN_NAME(ceedqfunctioncontextcreate,CEEDQFUNCTIONCONTEXTCREATE)
703 CEED_EXTERN void fCeedQFunctionContextCreate(int *ceed, int *ctx, int *err) {
704   if (CeedQFunctionContext_count == CeedQFunctionContext_count_max) {
705     CeedQFunctionContext_count_max += CeedQFunctionContext_count_max/2 + 1;
706     CeedRealloc(CeedQFunctionContext_count_max, &CeedQFunctionContext_dict);
707   }
708 
709   CeedQFunctionContext *ctx_ =
710     &CeedQFunctionContext_dict[CeedQFunctionContext_count];
711 
712   *err = CeedQFunctionContextCreate(Ceed_dict[*ceed], ctx_);
713   if (*err) return;
714   *ctx = CeedQFunctionContext_count++;
715   CeedQFunctionContext_n++;
716 }
717 
718 #define fCeedQFunctionContextSetData \
719     FORTRAN_NAME(ceedqfunctioncontextsetdata,CEEDQFUNCTIONCONTEXTSETDATA)
720 CEED_EXTERN void fCeedQFunctionContextSetData(int *ctx, int *memtype,
721     int *copymode,
722     CeedInt *n,
723     CeedScalar *data, int64_t *offset, int *err) {
724   size_t ctx_size = ((size_t) *n)*sizeof(CeedScalar);
725   *err = CeedQFunctionContextSetData(CeedQFunctionContext_dict[*ctx],
726                                      (CeedMemType)*memtype,
727                                      (CeedCopyMode)*copymode, ctx_size,
728                                      data + *offset);
729 }
730 
731 #define fCeedQFunctionContextGetData \
732     FORTRAN_NAME(ceedqfunctioncontextgetdata,CEEDQFUNCTIONCONTEXTGETDATA)
733 CEED_EXTERN void fCeedQFunctionContextGetData(int *ctx, int *memtype,
734     CeedScalar *data,
735     int64_t *offset, int *err) {
736   CeedScalar *b;
737   CeedQFunctionContext ctx_ = CeedQFunctionContext_dict[*ctx];
738   *err = CeedQFunctionContextGetData(ctx_, (CeedMemType)*memtype, &b);
739   *offset = b - data;
740 }
741 
742 #define fCeedQFunctionContextRestoreData \
743     FORTRAN_NAME(ceedqfunctioncontextrestoredata,CEEDQFUNCTIONCONTEXTRESTOREDATA)
744 CEED_EXTERN void fCeedQFunctionContextRestoreData(int *ctx, CeedScalar *data,
745     int64_t *offset, int *err) {
746   *err = CeedQFunctionContextRestoreData(CeedQFunctionContext_dict[*ctx],
747                                          (void **)&data);
748   *offset = 0;
749 }
750 
751 #define fCeedQFunctionContextView \
752     FORTRAN_NAME(ceedqfunctioncontextview,CEEDQFUNCTIONCONTEXTVIEW)
753 CEED_EXTERN void fCeedQFunctionContextView(int *ctx, int *err) {
754   *err = CeedQFunctionContextView(CeedQFunctionContext_dict[*ctx], stdout);
755 }
756 
757 #define fCeedQFunctionContextDestroy \
758     FORTRAN_NAME(ceedqfunctioncontextdestroy,CEEDQFUNCTIONCONTEXTDESTROY)
759 CEED_EXTERN void fCeedQFunctionContextDestroy(int *ctx, int *err) {
760   if (*ctx == FORTRAN_NULL) return;
761   *err = CeedQFunctionContextDestroy(&CeedQFunctionContext_dict[*ctx]);
762 
763   if (*err == 0) {
764     *ctx = FORTRAN_NULL;
765     CeedQFunctionContext_n--;
766     if (CeedQFunctionContext_n == 0) {
767       CeedFree(&CeedQFunctionContext_dict);
768       CeedQFunctionContext_count = 0;
769       CeedQFunctionContext_count_max = 0;
770     }
771   }
772 }
773 
774 // -----------------------------------------------------------------------------
775 // CeedQFunction
776 // -----------------------------------------------------------------------------
777 static CeedQFunction *CeedQFunction_dict = NULL;
778 static int CeedQFunction_count = 0;
779 static int CeedQFunction_n = 0;
780 static int CeedQFunction_count_max = 0;
781 
782 static int CeedQFunctionFortranStub(void *ctx, int nq,
783                                     const CeedScalar *const *u,
784                                     CeedScalar *const *v) {
785   CeedFortranContext fctx = ctx;
786   CeedQFunctionContext inner_ctx = fctx->inner_ctx;
787   int ierr;
788 
789   CeedScalar *ctx_ = NULL;
790   // Note: Device backends are generating their own kernels from
791   //         single source files, so only Host backends need to
792   //         use this Fortran stub.
793   if (inner_ctx) {
794     ierr = CeedQFunctionContextGetData(inner_ctx, CEED_MEM_HOST, &ctx_);
795     CeedChk(ierr);
796   }
797 
798   fctx->f((void *)ctx_,&nq,u[0],u[1],u[2],u[3],u[4],u[5],u[6],
799           u[7],u[8],u[9],u[10],u[11],u[12],u[13],u[14],u[15],
800           v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],
801           v[10],v[11],v[12],v[13],v[14],v[15],&ierr);
802 
803   if (inner_ctx) {
804     ierr = CeedQFunctionContextRestoreData(inner_ctx, (void *)&ctx_);
805     CeedChk(ierr);
806   }
807 
808   return ierr;
809 }
810 
811 #define fCeedQFunctionCreateInterior \
812     FORTRAN_NAME(ceedqfunctioncreateinterior, CEEDQFUNCTIONCREATEINTERIOR)
813 CEED_EXTERN void fCeedQFunctionCreateInterior(int *ceed, int *vec_length,
814     void (*f)(void *ctx, int *nq,
815               const CeedScalar *u,const CeedScalar *u1,
816               const CeedScalar *u2,const CeedScalar *u3,
817               const CeedScalar *u4,const CeedScalar *u5,
818               const CeedScalar *u6,const CeedScalar *u7,
819               const CeedScalar *u8,const CeedScalar *u9,
820               const CeedScalar *u10,const CeedScalar *u11,
821               const CeedScalar *u12,const CeedScalar *u13,
822               const CeedScalar *u14,const CeedScalar *u15,
823               CeedScalar *v,CeedScalar *v1,CeedScalar *v2,
824               CeedScalar *v3,CeedScalar *v4,
825               CeedScalar *v5,CeedScalar *v6,
826               CeedScalar *v7,CeedScalar *v8,
827               CeedScalar *v9,CeedScalar *v10,
828               CeedScalar *v11,CeedScalar *v12,
829               CeedScalar *v13,CeedScalar *v14,
830               CeedScalar *v15,int *err),
831     const char *source, int *qf, int *err,
832     fortran_charlen_t source_len) {
833   FIX_STRING(source);
834   if (CeedQFunction_count == CeedQFunction_count_max) {
835     CeedQFunction_count_max += CeedQFunction_count_max/2 + 1;
836     CeedRealloc(CeedQFunction_count_max, &CeedQFunction_dict);
837   }
838 
839   CeedQFunction *qf_ = &CeedQFunction_dict[CeedQFunction_count];
840   *err = CeedQFunctionCreateInterior(Ceed_dict[*ceed], *vec_length,
841                                      CeedQFunctionFortranStub, source_c, qf_);
842 
843   if (*err == 0) {
844     *qf = CeedQFunction_count++;
845     CeedQFunction_n++;
846   }
847 
848   CeedFortranContext fctxdata;
849   *err = CeedCalloc(1, &fctxdata);
850   if (*err) return;
851   fctxdata->f = f; fctxdata->inner_ctx = NULL;
852   CeedQFunctionContext fctx;
853   *err = CeedQFunctionContextCreate(Ceed_dict[*ceed], &fctx);
854   if (*err) return;
855   *err = CeedQFunctionContextSetData(fctx, CEED_MEM_HOST, CEED_OWN_POINTER,
856                                      sizeof(*fctxdata), fctxdata);
857   if (*err) return;
858   *err = CeedQFunctionSetContext(*qf_, fctx);
859   if (*err) return;
860   CeedQFunctionContextDestroy(&fctx);
861   if (*err) return;
862 
863   *err = CeedQFunctionSetFortranStatus(*qf_, true);
864 }
865 
866 #define fCeedQFunctionCreateInteriorByName \
867     FORTRAN_NAME(ceedqfunctioncreateinteriorbyname, CEEDQFUNCTIONCREATEINTERIORBYNAME)
868 CEED_EXTERN void fCeedQFunctionCreateInteriorByName(int *ceed, const char *name,
869     int *qf,
870     int *err, fortran_charlen_t name_len) {
871   FIX_STRING(name);
872   if (CeedQFunction_count == CeedQFunction_count_max) {
873     CeedQFunction_count_max += CeedQFunction_count_max/2 + 1;
874     CeedRealloc(CeedQFunction_count_max, &CeedQFunction_dict);
875   }
876 
877   CeedQFunction *qf_ = &CeedQFunction_dict[CeedQFunction_count];
878   *err = CeedQFunctionCreateInteriorByName(Ceed_dict[*ceed], name_c, qf_);
879 
880   if (*err == 0) {
881     *qf = CeedQFunction_count++;
882     CeedQFunction_n++;
883   }
884 }
885 
886 #define fCeedQFunctionCreateIdentity \
887     FORTRAN_NAME(ceedqfunctioncreateidentity, CEEDQFUNCTIONCREATEIDENTITY)
888 CEED_EXTERN void fCeedQFunctionCreateIdentity(int *ceed, int *size, int *inmode,
889     int *outmode, int *qf, int *err) {
890   if (CeedQFunction_count == CeedQFunction_count_max) {
891     CeedQFunction_count_max += CeedQFunction_count_max/2 + 1;
892     CeedRealloc(CeedQFunction_count_max, &CeedQFunction_dict);
893   }
894 
895   CeedQFunction *qf_ = &CeedQFunction_dict[CeedQFunction_count];
896   *err = CeedQFunctionCreateIdentity(Ceed_dict[*ceed], *size,
897                                      (CeedEvalMode)*inmode,
898                                      (CeedEvalMode)*outmode, qf_);
899 
900   if (*err == 0) {
901     *qf = CeedQFunction_count++;
902     CeedQFunction_n++;
903   }
904 }
905 
906 #define fCeedQFunctionAddInput \
907     FORTRAN_NAME(ceedqfunctionaddinput,CEEDQFUNCTIONADDINPUT)
908 CEED_EXTERN void fCeedQFunctionAddInput(int *qf, const char *field_name,
909                                         CeedInt *num_comp, CeedEvalMode *eval_mode, int *err,
910                                         fortran_charlen_t field_name_len) {
911   FIX_STRING(field_name);
912   CeedQFunction qf_ = CeedQFunction_dict[*qf];
913 
914   *err = CeedQFunctionAddInput(qf_, field_name_c, *num_comp, *eval_mode);
915 }
916 
917 #define fCeedQFunctionAddOutput \
918     FORTRAN_NAME(ceedqfunctionaddoutput,CEEDQFUNCTIONADDOUTPUT)
919 CEED_EXTERN void fCeedQFunctionAddOutput(int *qf, const char *field_name,
920     CeedInt *num_comp, CeedEvalMode *eval_mode, int *err,
921     fortran_charlen_t field_name_len) {
922   FIX_STRING(field_name);
923   CeedQFunction qf_ = CeedQFunction_dict[*qf];
924 
925   *err = CeedQFunctionAddOutput(qf_, field_name_c, *num_comp, *eval_mode);
926 }
927 
928 #define fCeedQFunctionSetContext \
929     FORTRAN_NAME(ceedqfunctionsetcontext,CEEDQFUNCTIONSETCONTEXT)
930 CEED_EXTERN void fCeedQFunctionSetContext(int *qf, int *ctx, int *err) {
931   CeedQFunction qf_ = CeedQFunction_dict[*qf];
932   CeedQFunctionContext ctx_ = CeedQFunctionContext_dict[*ctx];
933 
934   CeedQFunctionContext fctx;
935   *err = CeedQFunctionGetContext(qf_, &fctx);
936   if (*err) return;
937   CeedFortranContext fctxdata;
938   *err = CeedQFunctionContextGetData(fctx, CEED_MEM_HOST, &fctxdata);
939   if (*err) return;
940   fctxdata->inner_ctx = ctx_;
941   *err = CeedQFunctionContextRestoreData(fctx, (void **)&fctxdata);
942 }
943 
944 #define fCeedQFunctionView \
945     FORTRAN_NAME(ceedqfunctionview,CEEDQFUNCTIONVIEW)
946 CEED_EXTERN void fCeedQFunctionView(int *qf, int *err) {
947   CeedQFunction qf_ = CeedQFunction_dict[*qf];
948 
949   *err = CeedQFunctionView(qf_, stdout);
950 }
951 
952 #define fCeedQFunctionApply \
953     FORTRAN_NAME(ceedqfunctionapply,CEEDQFUNCTIONAPPLY)
954 //TODO Need Fixing, double pointer
955 CEED_EXTERN void fCeedQFunctionApply(int *qf, int *Q,
956                                      int *u, int *u1, int *u2, int *u3,
957                                      int *u4, int *u5, int *u6, int *u7,
958                                      int *u8, int *u9, int *u10, int *u11,
959                                      int *u12, int *u13, int *u14, int *u15,
960                                      int *v, int *v1, int *v2, int *v3,
961                                      int *v4, int *v5, int *v6, int *v7,
962                                      int *v8, int *v9, int *v10, int *v11,
963                                      int *v12, int *v13, int *v14, int *v15, int *err) {
964   CeedQFunction qf_ = CeedQFunction_dict[*qf];
965   CeedVector *in;
966   *err = CeedCalloc(CEED_FIELD_MAX, &in);
967   if (*err) return;
968   in[0] = *u==FORTRAN_NULL?NULL:CeedVector_dict[*u];
969   in[1] = *u1==FORTRAN_NULL?NULL:CeedVector_dict[*u1];
970   in[2] = *u2==FORTRAN_NULL?NULL:CeedVector_dict[*u2];
971   in[3] = *u3==FORTRAN_NULL?NULL:CeedVector_dict[*u3];
972   in[4] = *u4==FORTRAN_NULL?NULL:CeedVector_dict[*u4];
973   in[5] = *u5==FORTRAN_NULL?NULL:CeedVector_dict[*u5];
974   in[6] = *u6==FORTRAN_NULL?NULL:CeedVector_dict[*u6];
975   in[7] = *u7==FORTRAN_NULL?NULL:CeedVector_dict[*u7];
976   in[8] = *u8==FORTRAN_NULL?NULL:CeedVector_dict[*u8];
977   in[9] = *u9==FORTRAN_NULL?NULL:CeedVector_dict[*u9];
978   in[10] = *u10==FORTRAN_NULL?NULL:CeedVector_dict[*u10];
979   in[11] = *u11==FORTRAN_NULL?NULL:CeedVector_dict[*u11];
980   in[12] = *u12==FORTRAN_NULL?NULL:CeedVector_dict[*u12];
981   in[13] = *u13==FORTRAN_NULL?NULL:CeedVector_dict[*u13];
982   in[14] = *u14==FORTRAN_NULL?NULL:CeedVector_dict[*u14];
983   in[15] = *u15==FORTRAN_NULL?NULL:CeedVector_dict[*u15];
984   CeedVector *out;
985   *err = CeedCalloc(CEED_FIELD_MAX, &out);
986   if (*err) return;
987   out[0] = *v==FORTRAN_NULL?NULL:CeedVector_dict[*v];
988   out[1] = *v1==FORTRAN_NULL?NULL:CeedVector_dict[*v1];
989   out[2] = *v2==FORTRAN_NULL?NULL:CeedVector_dict[*v2];
990   out[3] = *v3==FORTRAN_NULL?NULL:CeedVector_dict[*v3];
991   out[4] = *v4==FORTRAN_NULL?NULL:CeedVector_dict[*v4];
992   out[5] = *v5==FORTRAN_NULL?NULL:CeedVector_dict[*v5];
993   out[6] = *v6==FORTRAN_NULL?NULL:CeedVector_dict[*v6];
994   out[7] = *v7==FORTRAN_NULL?NULL:CeedVector_dict[*v7];
995   out[8] = *v8==FORTRAN_NULL?NULL:CeedVector_dict[*v8];
996   out[9] = *v9==FORTRAN_NULL?NULL:CeedVector_dict[*v9];
997   out[10] = *v10==FORTRAN_NULL?NULL:CeedVector_dict[*v10];
998   out[11] = *v11==FORTRAN_NULL?NULL:CeedVector_dict[*v11];
999   out[12] = *v12==FORTRAN_NULL?NULL:CeedVector_dict[*v12];
1000   out[13] = *v13==FORTRAN_NULL?NULL:CeedVector_dict[*v13];
1001   out[14] = *v14==FORTRAN_NULL?NULL:CeedVector_dict[*v14];
1002   out[15] = *v15==FORTRAN_NULL?NULL:CeedVector_dict[*v15];
1003   *err = CeedQFunctionApply(qf_, *Q, in, out);
1004   if (*err) return;
1005 
1006   *err = CeedFree(&in);
1007   if (*err) return;
1008   *err = CeedFree(&out);
1009 }
1010 
1011 #define fCeedQFunctionDestroy \
1012     FORTRAN_NAME(ceedqfunctiondestroy,CEEDQFUNCTIONDESTROY)
1013 CEED_EXTERN void fCeedQFunctionDestroy(int *qf, int *err) {
1014   if (*qf == FORTRAN_NULL) return;
1015 
1016   *err = CeedQFunctionDestroy(&CeedQFunction_dict[*qf]);
1017   if (*err == 0) {
1018     *qf = FORTRAN_NULL;
1019     CeedQFunction_n--;
1020     if (CeedQFunction_n == 0) {
1021       *err = CeedFree(&CeedQFunction_dict);
1022       CeedQFunction_count = 0;
1023       CeedQFunction_count_max = 0;
1024     }
1025   }
1026 }
1027 
1028 // -----------------------------------------------------------------------------
1029 // CeedOperator
1030 // -----------------------------------------------------------------------------
1031 static CeedOperator *CeedOperator_dict = NULL;
1032 static int CeedOperator_count = 0;
1033 static int CeedOperator_n = 0;
1034 static int CeedOperator_count_max = 0;
1035 
1036 #define fCeedOperatorCreate \
1037     FORTRAN_NAME(ceedoperatorcreate, CEEDOPERATORCREATE)
1038 CEED_EXTERN void fCeedOperatorCreate(int *ceed,
1039                                      int *qf, int *dqf, int *dqfT, int *op, int *err) {
1040   if (CeedOperator_count == CeedOperator_count_max) {
1041     CeedOperator_count_max += CeedOperator_count_max/2 + 1;
1042     CeedRealloc(CeedOperator_count_max, &CeedOperator_dict);
1043   }
1044 
1045   CeedOperator *op_ = &CeedOperator_dict[CeedOperator_count];
1046 
1047   CeedQFunction dqf_  = CEED_QFUNCTION_NONE, dqfT_ = CEED_QFUNCTION_NONE;
1048   if (*dqf  != FORTRAN_QFUNCTION_NONE) dqf_  = CeedQFunction_dict[*dqf ];
1049   if (*dqfT != FORTRAN_QFUNCTION_NONE) dqfT_ = CeedQFunction_dict[*dqfT];
1050 
1051   *err = CeedOperatorCreate(Ceed_dict[*ceed], CeedQFunction_dict[*qf], dqf_,
1052                             dqfT_, op_);
1053   if (*err) return;
1054   *op = CeedOperator_count++;
1055   CeedOperator_n++;
1056 }
1057 
1058 #define fCeedCompositeOperatorCreate \
1059     FORTRAN_NAME(ceedcompositeoperatorcreate, CEEDCOMPOSITEOPERATORCREATE)
1060 CEED_EXTERN void fCeedCompositeOperatorCreate(int *ceed, int *op, int *err) {
1061   if (CeedOperator_count == CeedOperator_count_max) {
1062     CeedOperator_count_max += CeedOperator_count_max/2 + 1;
1063     CeedRealloc(CeedOperator_count_max, &CeedOperator_dict);
1064   }
1065 
1066   CeedOperator *op_ = &CeedOperator_dict[CeedOperator_count];
1067 
1068   *err = CeedCompositeOperatorCreate(Ceed_dict[*ceed], op_);
1069   if (*err) return;
1070   *op = CeedOperator_count++;
1071   CeedOperator_n++;
1072 }
1073 
1074 #define fCeedOperatorSetField \
1075     FORTRAN_NAME(ceedoperatorsetfield,CEEDOPERATORSETFIELD)
1076 CEED_EXTERN void fCeedOperatorSetField(int *op, const char *field_name, int *r,
1077                                        int *b, int *v, int *err,
1078                                        fortran_charlen_t field_name_len) {
1079   FIX_STRING(field_name);
1080   CeedElemRestriction r_;
1081   CeedBasis b_;
1082   CeedVector v_;
1083 
1084   CeedOperator op_ = CeedOperator_dict[*op];
1085 
1086   if (*r == FORTRAN_NULL) {
1087     r_ = NULL;
1088   } else if (*r == FORTRAN_ELEMRESTRICTION_NONE) {
1089     r_ = CEED_ELEMRESTRICTION_NONE;
1090   } else {
1091     r_ = CeedElemRestriction_dict[*r];
1092   }
1093 
1094   if (*b == FORTRAN_NULL) {
1095     b_ = NULL;
1096   } else if (*b == FORTRAN_BASIS_COLLOCATED) {
1097     b_ = CEED_BASIS_COLLOCATED;
1098   } else {
1099     b_ = CeedBasis_dict[*b];
1100   }
1101   if (*v == FORTRAN_NULL) {
1102     v_ = NULL;
1103   } else if (*v == FORTRAN_VECTOR_ACTIVE) {
1104     v_ = CEED_VECTOR_ACTIVE;
1105   } else if (*v == FORTRAN_VECTOR_NONE) {
1106     v_ = CEED_VECTOR_NONE;
1107   } else {
1108     v_ = CeedVector_dict[*v];
1109   }
1110 
1111   *err = CeedOperatorSetField(op_, field_name_c, r_, b_, v_);
1112 }
1113 
1114 #define fCeedCompositeOperatorAddSub \
1115     FORTRAN_NAME(ceedcompositeoperatoraddsub, CEEDCOMPOSITEOPERATORADDSUB)
1116 CEED_EXTERN void fCeedCompositeOperatorAddSub(int *compositeop, int *subop,
1117     int *err) {
1118   CeedOperator compositeop_ = CeedOperator_dict[*compositeop];
1119   CeedOperator subop_ = CeedOperator_dict[*subop];
1120 
1121   *err = CeedCompositeOperatorAddSub(compositeop_, subop_);
1122 }
1123 
1124 #define fCeedOperatorSetName \
1125     FORTRAN_NAME(ceedoperatorsetname, CEEDOPERATORSETNAME)
1126 CEED_EXTERN void fCeedOperatorSetName(int *op, const char *name, int *err,
1127                                       fortran_charlen_t name_len) {
1128   FIX_STRING(name);
1129   CeedOperator op_ = CeedOperator_dict[*op];
1130 
1131   *err = CeedOperatorSetName(op_, name_c);
1132 }
1133 
1134 #define fCeedOperatorLinearAssembleQFunction \
1135     FORTRAN_NAME(ceedoperatorlinearassembleqfunction, CEEDOPERATORLINEARASSEMBLEQFUNCTION)
1136 CEED_EXTERN void fCeedOperatorLinearAssembleQFunction(int *op,
1137     int *assembledvec,
1138     int *assembledrstr, int *rqst, int *err) {
1139   // Vector
1140   if (CeedVector_count == CeedVector_count_max) {
1141     CeedVector_count_max += CeedVector_count_max/2 + 1;
1142     CeedRealloc(CeedVector_count_max, &CeedVector_dict);
1143   }
1144   CeedVector *assembledvec_ = &CeedVector_dict[CeedVector_count];
1145 
1146   // Restriction
1147   if (CeedElemRestriction_count == CeedElemRestriction_count_max) {
1148     CeedElemRestriction_count_max += CeedElemRestriction_count_max/2 + 1;
1149     CeedRealloc(CeedElemRestriction_count_max, &CeedElemRestriction_dict);
1150   }
1151   CeedElemRestriction *rstr_ =
1152     &CeedElemRestriction_dict[CeedElemRestriction_count];
1153 
1154   int createRequest = 1;
1155   // Check if input is CEED_REQUEST_ORDERED(-2) or CEED_REQUEST_IMMEDIATE(-1)
1156   if (*rqst == -1 || *rqst == -2) {
1157     createRequest = 0;
1158   }
1159 
1160   if (createRequest && CeedRequest_count == CeedRequest_count_max) {
1161     CeedRequest_count_max += CeedRequest_count_max/2 + 1;
1162     CeedRealloc(CeedRequest_count_max, &CeedRequest_dict);
1163   }
1164 
1165   CeedRequest *rqst_;
1166   if (*rqst == -1) rqst_ = CEED_REQUEST_IMMEDIATE;
1167   else if (*rqst == -2) rqst_ = CEED_REQUEST_ORDERED;
1168   else rqst_ = &CeedRequest_dict[CeedRequest_count];
1169 
1170   *err = CeedOperatorLinearAssembleQFunction(CeedOperator_dict[*op],
1171          assembledvec_, rstr_, rqst_);
1172   if (*err) return;
1173   if (createRequest) {
1174     *rqst = CeedRequest_count++;
1175     CeedRequest_n++;
1176   }
1177 
1178   if (*err == 0) {
1179     *assembledrstr = CeedElemRestriction_count++;
1180     CeedElemRestriction_n++;
1181     *assembledvec = CeedVector_count++;
1182     CeedVector_n++;
1183   }
1184 }
1185 
1186 #define fCeedOperatorLinearAssembleDiagonal \
1187     FORTRAN_NAME(ceedoperatorlinearassemblediagonal, CEEDOPERATORLINEARASSEMBLEDIAGONAL)
1188 CEED_EXTERN void fCeedOperatorLinearAssembleDiagonal(int *op, int *assembledvec,
1189     int *rqst, int *err) {
1190   int createRequest = 1;
1191   // Check if input is CEED_REQUEST_ORDERED(-2) or CEED_REQUEST_IMMEDIATE(-1)
1192   if (*rqst == -1 || *rqst == -2) {
1193     createRequest = 0;
1194   }
1195 
1196   if (createRequest && CeedRequest_count == CeedRequest_count_max) {
1197     CeedRequest_count_max += CeedRequest_count_max/2 + 1;
1198     CeedRealloc(CeedRequest_count_max, &CeedRequest_dict);
1199   }
1200 
1201   CeedRequest *rqst_;
1202   if (*rqst == -1) rqst_ = CEED_REQUEST_IMMEDIATE;
1203   else if (*rqst == -2) rqst_ = CEED_REQUEST_ORDERED;
1204   else rqst_ = &CeedRequest_dict[CeedRequest_count];
1205 
1206   *err = CeedOperatorLinearAssembleDiagonal(CeedOperator_dict[*op],
1207          CeedVector_dict[*assembledvec], rqst_);
1208   if (*err) return;
1209   if (createRequest) {
1210     *rqst = CeedRequest_count++;
1211     CeedRequest_n++;
1212   }
1213 }
1214 
1215 #define fCeedOperatorMultigridLevelCreate \
1216     FORTRAN_NAME(ceedoperatormultigridlevelcreate, CEEDOPERATORMULTIGRIDLEVELCREATE)
1217 CEED_EXTERN void fCeedOperatorMultigridLevelCreate(int *opFine, int *pMultFine,
1218     int *rstrCoarse, int *basisCoarse, int *opCoarse,
1219     int *opProlong, int *opRestrict, int *err) {
1220   // Operators
1221   CeedOperator opCoarse_, opProlong_, opRestrict_;
1222 
1223   // C interface call
1224   *err = CeedOperatorMultigridLevelCreate(
1225            CeedOperator_dict[*opFine], CeedVector_dict[*pMultFine],
1226            CeedElemRestriction_dict[*rstrCoarse],
1227            CeedBasis_dict[*basisCoarse],
1228            &opCoarse_, &opProlong_, &opRestrict_);
1229 
1230   if (*err) return;
1231   while (CeedOperator_count + 2 >= CeedOperator_count_max) {
1232     CeedOperator_count_max += CeedOperator_count_max/2 + 1;
1233   }
1234   CeedRealloc(CeedOperator_count_max, &CeedOperator_dict);
1235   CeedOperator_dict[CeedOperator_count] = opCoarse_;
1236   *opCoarse = CeedOperator_count++;
1237   CeedOperator_dict[CeedOperator_count] = opProlong_;
1238   *opProlong = CeedOperator_count++;
1239   CeedOperator_dict[CeedOperator_count] = opRestrict_;
1240   *opRestrict = CeedOperator_count++;
1241   CeedOperator_n += 3;
1242 }
1243 
1244 #define fCeedOperatorMultigridLevelCreateTensorH1 \
1245     FORTRAN_NAME(ceedoperatormultigridlevelcreatetensorh1, CEEDOPERATORMULTIGRIDLEVELCREATETENSORH1)
1246 CEED_EXTERN void fCeedOperatorMultigridLevelCreateTensorH1(int *opFine,
1247     int *pMultFine,
1248     int *rstrCoarse, int *basisCoarse, const CeedScalar *interpCtoF,
1249     int *opCoarse, int *opProlong, int *opRestrict, int *err) {
1250   // Operators
1251   CeedOperator opCoarse_, opProlong_, opRestrict_;
1252 
1253   // C interface call
1254   *err = CeedOperatorMultigridLevelCreateTensorH1(
1255            CeedOperator_dict[*opFine], CeedVector_dict[*pMultFine],
1256            CeedElemRestriction_dict[*rstrCoarse], CeedBasis_dict[*basisCoarse],
1257            interpCtoF, &opCoarse_, &opProlong_, &opRestrict_);
1258 
1259   if (*err) return;
1260   while (CeedOperator_count + 2 >= CeedOperator_count_max) {
1261     CeedOperator_count_max += CeedOperator_count_max/2 + 1;
1262   }
1263   CeedRealloc(CeedOperator_count_max, &CeedOperator_dict);
1264   CeedOperator_dict[CeedOperator_count] = opCoarse_;
1265   *opCoarse = CeedOperator_count++;
1266   CeedOperator_dict[CeedOperator_count] = opProlong_;
1267   *opProlong = CeedOperator_count++;
1268   CeedOperator_dict[CeedOperator_count] = opRestrict_;
1269   *opRestrict = CeedOperator_count++;
1270   CeedOperator_n += 3;
1271 }
1272 
1273 #define fCeedOperatorMultigridLevelCreateH1 \
1274     FORTRAN_NAME(ceedoperatormultigridlevelcreateh1, CEEDOPERATORMULTIGRIDLEVELCREATEH1)
1275 CEED_EXTERN void fCeedOperatorMultigridLevelCreateH1(int *opFine,
1276     int *pMultFine,
1277     int *rstrCoarse, int *basisCoarse, const CeedScalar *interpCtoF,
1278     int *opCoarse, int *opProlong, int *opRestrict, int *err) {
1279   // Operators
1280   CeedOperator opCoarse_, opProlong_, opRestrict_;
1281 
1282   // C interface call
1283   *err = CeedOperatorMultigridLevelCreateH1(
1284            CeedOperator_dict[*opFine], CeedVector_dict[*pMultFine],
1285            CeedElemRestriction_dict[*rstrCoarse], CeedBasis_dict[*basisCoarse],
1286            interpCtoF, &opCoarse_, &opProlong_, &opRestrict_);
1287 
1288   if (*err) return;
1289   while (CeedOperator_count + 2 >= CeedOperator_count_max) {
1290     CeedOperator_count_max += CeedOperator_count_max/2 + 1;
1291   }
1292   CeedRealloc(CeedOperator_count_max, &CeedOperator_dict);
1293   CeedOperator_dict[CeedOperator_count] = opCoarse_;
1294   *opCoarse = CeedOperator_count++;
1295   CeedOperator_dict[CeedOperator_count] = opProlong_;
1296   *opProlong = CeedOperator_count++;
1297   CeedOperator_dict[CeedOperator_count] = opRestrict_;
1298   *opRestrict = CeedOperator_count++;
1299   CeedOperator_n += 3;
1300 }
1301 
1302 #define fCeedOperatorView \
1303     FORTRAN_NAME(ceedoperatorview,CEEDOPERATORVIEW)
1304 CEED_EXTERN void fCeedOperatorView(int *op, int *err) {
1305   CeedOperator op_ = CeedOperator_dict[*op];
1306 
1307   *err = CeedOperatorView(op_, stdout);
1308 }
1309 
1310 #define fCeedOperatorCreateFDMElementInverse \
1311     FORTRAN_NAME(ceedoperatorcreatefdmelementinverse, CEEDOPERATORCREATEFDMELEMENTINVERSE)
1312 CEED_EXTERN void fCeedOperatorCreateFDMElementInverse(int *op, int *fdminv,
1313     int *rqst, int *err) {
1314   // Operator
1315   if (CeedOperator_count == CeedOperator_count_max) {
1316     CeedOperator_count_max += CeedOperator_count_max/2 + 1;
1317     CeedRealloc(CeedOperator_count_max, &CeedOperator_dict);
1318   }
1319   CeedOperator *fdminv_ =
1320     &CeedOperator_dict[CeedOperator_count];
1321 
1322   int createRequest = 1;
1323   // Check if input is CEED_REQUEST_ORDERED(-2) or CEED_REQUEST_IMMEDIATE(-1)
1324   if (*rqst == -1 || *rqst == -2) {
1325     createRequest = 0;
1326   }
1327 
1328   if (createRequest && CeedRequest_count == CeedRequest_count_max) {
1329     CeedRequest_count_max += CeedRequest_count_max/2 + 1;
1330     CeedRealloc(CeedRequest_count_max, &CeedRequest_dict);
1331   }
1332 
1333   CeedRequest *rqst_;
1334   if (*rqst == -1) rqst_ = CEED_REQUEST_IMMEDIATE;
1335   else if (*rqst == -2) rqst_ = CEED_REQUEST_ORDERED;
1336   else rqst_ = &CeedRequest_dict[CeedRequest_count];
1337 
1338   *err = CeedOperatorCreateFDMElementInverse(CeedOperator_dict[*op],
1339          fdminv_, rqst_);
1340   if (*err) return;
1341   if (createRequest) {
1342     *rqst = CeedRequest_count++;
1343     CeedRequest_n++;
1344   }
1345 
1346   if (*err == 0) {
1347     *fdminv = CeedOperator_count++;
1348     CeedOperator_n++;
1349   }
1350 }
1351 
1352 #define fCeedOperatorApply FORTRAN_NAME(ceedoperatorapply, CEEDOPERATORAPPLY)
1353 CEED_EXTERN void fCeedOperatorApply(int *op, int *ustatevec,
1354                                     int *resvec, int *rqst, int *err) {
1355   CeedVector ustatevec_ = (*ustatevec == FORTRAN_NULL) ?
1356                           NULL : (*ustatevec == FORTRAN_VECTOR_NONE ?
1357                                   CEED_VECTOR_NONE : CeedVector_dict[*ustatevec]);
1358   CeedVector resvec_ = (*resvec == FORTRAN_NULL) ?
1359                        NULL : (*resvec == FORTRAN_VECTOR_NONE ?
1360                                CEED_VECTOR_NONE : CeedVector_dict[*resvec]);
1361 
1362   int createRequest = 1;
1363   // Check if input is CEED_REQUEST_ORDERED(-2) or CEED_REQUEST_IMMEDIATE(-1)
1364   if (*rqst == -1 || *rqst == -2) {
1365     createRequest = 0;
1366   }
1367 
1368   if (createRequest && CeedRequest_count == CeedRequest_count_max) {
1369     CeedRequest_count_max += CeedRequest_count_max/2 + 1;
1370     CeedRealloc(CeedRequest_count_max, &CeedRequest_dict);
1371   }
1372 
1373   CeedRequest *rqst_;
1374   if (*rqst == -1) rqst_ = CEED_REQUEST_IMMEDIATE;
1375   else if (*rqst == -2) rqst_ = CEED_REQUEST_ORDERED;
1376   else rqst_ = &CeedRequest_dict[CeedRequest_count];
1377 
1378   *err = CeedOperatorApply(CeedOperator_dict[*op],
1379                            ustatevec_, resvec_, rqst_);
1380   if (*err) return;
1381   if (createRequest) {
1382     *rqst = CeedRequest_count++;
1383     CeedRequest_n++;
1384   }
1385 }
1386 
1387 #define fCeedOperatorApplyAdd FORTRAN_NAME(ceedoperatorapplyadd, CEEDOPERATORAPPLYADD)
1388 CEED_EXTERN void fCeedOperatorApplyAdd(int *op, int *ustatevec,
1389                                        int *resvec, int *rqst, int *err) {
1390   CeedVector ustatevec_ = *ustatevec == FORTRAN_NULL
1391                           ? NULL : CeedVector_dict[*ustatevec];
1392   CeedVector resvec_ = *resvec == FORTRAN_NULL
1393                        ? NULL : CeedVector_dict[*resvec];
1394 
1395   int createRequest = 1;
1396   // Check if input is CEED_REQUEST_ORDERED(-2) or CEED_REQUEST_IMMEDIATE(-1)
1397   if (*rqst == -1 || *rqst == -2) {
1398     createRequest = 0;
1399   }
1400 
1401   if (createRequest && CeedRequest_count == CeedRequest_count_max) {
1402     CeedRequest_count_max += CeedRequest_count_max/2 + 1;
1403     CeedRealloc(CeedRequest_count_max, &CeedRequest_dict);
1404   }
1405 
1406   CeedRequest *rqst_;
1407   if (*rqst == -1) rqst_ = CEED_REQUEST_IMMEDIATE;
1408   else if (*rqst == -2) rqst_ = CEED_REQUEST_ORDERED;
1409   else rqst_ = &CeedRequest_dict[CeedRequest_count];
1410 
1411   *err = CeedOperatorApplyAdd(CeedOperator_dict[*op],
1412                               ustatevec_, resvec_, rqst_);
1413   if (*err) return;
1414   if (createRequest) {
1415     *rqst = CeedRequest_count++;
1416     CeedRequest_n++;
1417   }
1418 }
1419 
1420 #define fCeedOperatorApplyJacobian \
1421     FORTRAN_NAME(ceedoperatorapplyjacobian, CEEDOPERATORAPPLYJACOBIAN)
1422 CEED_EXTERN void fCeedOperatorApplyJacobian(int *op, int *qdatavec,
1423     int *ustatevec,
1424     int *dustatevec, int *dresvec, int *rqst,
1425     int *err) {
1426 // TODO Uncomment this when CeedOperatorApplyJacobian is implemented
1427 //  *err = CeedOperatorApplyJacobian(CeedOperator_dict[*op], CeedVector_dict[*qdatavec],
1428 //             CeedVector_dict[*ustatevec], CeedVector_dict[*dustatevec],
1429 //             CeedVector_dict[*dresvec], &CeedRequest_dict[*rqst]);
1430 }
1431 
1432 #define fCeedOperatorDestroy \
1433     FORTRAN_NAME(ceedoperatordestroy, CEEDOPERATORDESTROY)
1434 CEED_EXTERN void fCeedOperatorDestroy(int *op, int *err) {
1435   if (*op == FORTRAN_NULL) return;
1436   *err = CeedOperatorDestroy(&CeedOperator_dict[*op]);
1437   if (*err == 0) {
1438     *op = FORTRAN_NULL;
1439     CeedOperator_n--;
1440     if (CeedOperator_n == 0) {
1441       *err = CeedFree(&CeedOperator_dict);
1442       CeedOperator_count = 0;
1443       CeedOperator_count_max = 0;
1444     }
1445   }
1446 }
1447 
1448 // -----------------------------------------------------------------------------
1449