xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-fortran.c (revision 3b271f31235544907a33ec634d3774cfdce1092d)
1 // Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC.
2 // Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707.
3 // All Rights reserved. See files LICENSE and NOTICE for details.
4 //
5 // This file is part of CEED, a collection of benchmarks, miniapps, software
6 // libraries and APIs for efficient high-order finite element and spectral
7 // element discretizations for exascale applications. For more information and
8 // source code availability see http://github.com/ceed.
9 //
10 // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11 // a collaborative effort of two U.S. Department of Energy organizations (Office
12 // of Science and the National Nuclear Security Administration) responsible for
13 // the planning and preparation of a capable exascale ecosystem, including
14 // software, applications, hardware, advanced system engineering and early
15 // testbed platforms, in support of the nation's exascale computing imperative.
16 
17 // Fortran interface
18 #include <ceed/ceed.h>
19 #include <ceed/backend.h>
20 #include <ceed-impl.h>
21 #include <ceed-fortran-name.h>
22 #include <stdbool.h>
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <string.h>
26 
27 #define FORTRAN_REQUEST_IMMEDIATE -1
28 #define FORTRAN_REQUEST_ORDERED -2
29 #define FORTRAN_NULL -3
30 #define FORTRAN_STRIDES_BACKEND -4
31 #define FORTRAN_VECTOR_ACTIVE -5
32 #define FORTRAN_VECTOR_NONE -6
33 #define FORTRAN_ELEMRESTRICTION_NONE -7
34 #define FORTRAN_BASIS_COLLOCATED -8
35 #define FORTRAN_QFUNCTION_NONE -9
36 
37 static Ceed *Ceed_dict = NULL;
38 static int Ceed_count = 0;
39 static int Ceed_n = 0;
40 static int Ceed_count_max = 0;
41 
42 // This test should actually be for the gfortran version, but we don't currently
43 // have a configure system to determine that (TODO).  At present, this will use
44 // the smaller integer when run with clang+gfortran=8, for example.  (That is
45 // sketchy, but will likely work for users that don't have huge character
46 // strings.)
47 #if __GNUC__ >= 8
48 typedef size_t fortran_charlen_t;
49 #else
50 typedef int fortran_charlen_t;
51 #endif
52 
53 #define Splice(a, b) a ## b
54 
55 // Fortran strings are generally unterminated and the length is passed as an
56 // extra argument after all the normal arguments.  Some compilers (I only know
57 // of Windows) place the length argument immediately after the string parameter
58 // (TODO).
59 //
60 // We can't just NULL-terminate the string in-place because that could overwrite
61 // other strings or attempt to write to read-only memory.  This macro allocates
62 // a string to hold the null-terminated version of the string that C expects.
63 #define FIX_STRING(stringname)                                          \
64   char Splice(stringname, _c)[1024];                                    \
65   if (Splice(stringname, _len) > 1023)                                  \
66     *err = CeedError(NULL, 1, "Fortran string length too long %zd", (size_t)Splice(stringname, _len)); \
67   strncpy(Splice(stringname, _c), stringname, Splice(stringname, _len)); \
68   Splice(stringname, _c)[Splice(stringname, _len)] = 0;                 \
69 
70 // -----------------------------------------------------------------------------
71 // Ceed
72 // -----------------------------------------------------------------------------
73 #define fCeedInit FORTRAN_NAME(ceedinit,CEEDINIT)
74 CEED_EXTERN void fCeedInit(const char *resource, int *ceed, int *err,
75                            fortran_charlen_t resource_len) {
76   FIX_STRING(resource);
77   if (Ceed_count == Ceed_count_max) {
78     Ceed_count_max += Ceed_count_max/2 + 1;
79     CeedRealloc(Ceed_count_max, &Ceed_dict);
80   }
81 
82   Ceed *ceed_ = &Ceed_dict[Ceed_count];
83   *err = CeedInit(resource_c, ceed_);
84 
85   if (*err == 0) {
86     *ceed = Ceed_count++;
87     Ceed_n++;
88   }
89 }
90 
91 #define fCeedIsDeterministic \
92     FORTRAN_NAME(ceedisdeterministic,CEEDISDETERMINISTIC)
93 CEED_EXTERN void fCeedIsDeterministic(int *ceed, int *is_deterministic,
94                                       int *err) {
95   *err = CeedIsDeterministic(Ceed_dict[*ceed], (bool *)is_deterministic);
96 }
97 
98 #define fCeedGetPreferredMemType \
99     FORTRAN_NAME(ceedgetpreferredmemtype,CEEDGETPREFERREDMEMTYPE)
100 CEED_EXTERN void fCeedGetPreferredMemType(int *ceed, int *type, int *err) {
101   *err = CeedGetPreferredMemType(Ceed_dict[*ceed], (CeedMemType *)type);
102 }
103 
104 #define fCeedView FORTRAN_NAME(ceedview,CEEDVIEW)
105 CEED_EXTERN void fCeedView(int *ceed, int *err) {
106   *err = CeedView(Ceed_dict[*ceed], stdout);
107 }
108 
109 #define fCeedDestroy FORTRAN_NAME(ceeddestroy,CEEDDESTROY)
110 CEED_EXTERN void fCeedDestroy(int *ceed, int *err) {
111   if (*ceed == FORTRAN_NULL) return;
112   *err = CeedDestroy(&Ceed_dict[*ceed]);
113 
114   if (*err == 0) {
115     *ceed = FORTRAN_NULL;
116     Ceed_n--;
117     if (Ceed_n == 0) {
118       CeedFree(&Ceed_dict);
119       Ceed_count = 0;
120       Ceed_count_max = 0;
121     }
122   }
123 }
124 
125 // -----------------------------------------------------------------------------
126 // CeedVector
127 // -----------------------------------------------------------------------------
128 static CeedVector *CeedVector_dict = NULL;
129 static int CeedVector_count = 0;
130 static int CeedVector_n = 0;
131 static int CeedVector_count_max = 0;
132 
133 #define fCeedVectorCreate FORTRAN_NAME(ceedvectorcreate,CEEDVECTORCREATE)
134 CEED_EXTERN void fCeedVectorCreate(int *ceed, int *length, int *vec, int *err) {
135   if (CeedVector_count == CeedVector_count_max) {
136     CeedVector_count_max += CeedVector_count_max/2 + 1;
137     CeedRealloc(CeedVector_count_max, &CeedVector_dict);
138   }
139 
140   CeedVector *vec_ = &CeedVector_dict[CeedVector_count];
141   *err = CeedVectorCreate(Ceed_dict[*ceed], *length, vec_);
142 
143   if (*err == 0) {
144     *vec = CeedVector_count++;
145     CeedVector_n++;
146   }
147 }
148 
149 #define fCeedVectorSetArray FORTRAN_NAME(ceedvectorsetarray,CEEDVECTORSETARRAY)
150 CEED_EXTERN void fCeedVectorSetArray(int *vec, int *memtype, int *copymode,
151                                      CeedScalar *array, int64_t *offset, int *err) {
152   *err = CeedVectorSetArray(CeedVector_dict[*vec], (CeedMemType)*memtype,
153                             (CeedCopyMode)*copymode,
154                             (CeedScalar *)(array + *offset));
155 }
156 
157 #define fCeedVectorTakeArray FORTRAN_NAME(ceedvectortakearray,CEEDVECTORTAKEARRAY)
158 CEED_EXTERN void fCeedVectorTakeArray(int *vec, int *memtype, CeedScalar *array,
159                                       int64_t *offset, int *err) {
160   CeedScalar *b;
161   CeedVector vec_ = CeedVector_dict[*vec];
162   *err = CeedVectorTakeArray(vec_, (CeedMemType)*memtype, &b);
163   *offset = b - array;
164 }
165 
166 #define fCeedVectorSyncArray FORTRAN_NAME(ceedvectorsyncarray,CEEDVECTORSYNCARRAY)
167 CEED_EXTERN void fCeedVectorSyncArray(int *vec, int *memtype, int *err) {
168   *err = CeedVectorSyncArray(CeedVector_dict[*vec], (CeedMemType)*memtype);
169 }
170 
171 #define fCeedVectorSetValue FORTRAN_NAME(ceedvectorsetvalue,CEEDVECTORSETVALUE)
172 CEED_EXTERN void fCeedVectorSetValue(int *vec, CeedScalar *value, int *err) {
173   *err = CeedVectorSetValue(CeedVector_dict[*vec], *value);
174 }
175 
176 #define fCeedVectorGetArray FORTRAN_NAME(ceedvectorgetarray,CEEDVECTORGETARRAY)
177 CEED_EXTERN void fCeedVectorGetArray(int *vec, int *memtype, CeedScalar *array,
178                                      int64_t *offset, int *err) {
179   CeedScalar *b;
180   CeedVector vec_ = CeedVector_dict[*vec];
181   *err = CeedVectorGetArray(vec_, (CeedMemType)*memtype, &b);
182   *offset = b - array;
183 }
184 
185 #define fCeedVectorGetArrayRead \
186     FORTRAN_NAME(ceedvectorgetarrayread,CEEDVECTORGETARRAYREAD)
187 CEED_EXTERN void fCeedVectorGetArrayRead(int *vec, int *memtype,
188     CeedScalar *array,
189     int64_t *offset, int *err) {
190   const CeedScalar *b;
191   CeedVector vec_ = CeedVector_dict[*vec];
192   *err = CeedVectorGetArrayRead(vec_, (CeedMemType)*memtype, &b);
193   *offset = b - array;
194 }
195 
196 #define fCeedVectorGetArrayWrite \
197     FORTRAN_NAME(ceedvectorgetarraywrite,CEEDVECTORGETARRAYWRITE)
198 CEED_EXTERN void fCeedVectorGetArrayWrite(int *vec, int *memtype,
199     CeedScalar *array,
200     int64_t *offset, int *err) {
201   CeedScalar *b;
202   CeedVector vec_ = CeedVector_dict[*vec];
203   *err = CeedVectorGetArrayWrite(vec_, (CeedMemType)*memtype, &b);
204   *offset = b - array;
205 }
206 
207 #define fCeedVectorRestoreArray \
208     FORTRAN_NAME(ceedvectorrestorearray,CEEDVECTORRESTOREARRAY)
209 CEED_EXTERN void fCeedVectorRestoreArray(int *vec, CeedScalar *array,
210     int64_t *offset, int *err) {
211   CeedScalar *offsetArray = array + *offset;
212   *err = CeedVectorRestoreArray(CeedVector_dict[*vec], &offsetArray);
213   *offset = 0;
214 }
215 
216 #define fCeedVectorRestoreArrayRead \
217     FORTRAN_NAME(ceedvectorrestorearrayread,CEEDVECTORRESTOREARRAYREAD)
218 CEED_EXTERN void fCeedVectorRestoreArrayRead(int *vec, const CeedScalar *array,
219     int64_t *offset, int *err) {
220   *err = CeedVectorRestoreArrayRead(CeedVector_dict[*vec], &array);
221   *offset = 0;
222 }
223 
224 #define fCeedVectorNorm \
225     FORTRAN_NAME(ceedvectornorm,CEEDVECTORNORM)
226 CEED_EXTERN void fCeedVectorNorm(int *vec, int *type, CeedScalar *norm,
227                                  int *err) {
228   *err = CeedVectorNorm(CeedVector_dict[*vec], (CeedNormType)*type, norm);
229 }
230 
231 #define fCeedVectorReciprocal \
232     FORTRAN_NAME(ceedvectorreciprocal,CEEDVECTORRECIPROCAL)
233 CEED_EXTERN void fCeedVectorReciprocal(int *vec, int *err) {
234   *err = CeedVectorReciprocal(CeedVector_dict[*vec]);
235 }
236 
237 #define fCeedVectorView FORTRAN_NAME(ceedvectorview,CEEDVECTORVIEW)
238 CEED_EXTERN void fCeedVectorView(int *vec, int *err) {
239   *err = CeedVectorView(CeedVector_dict[*vec], "%12.8f", stdout);
240 }
241 
242 #define fCeedVectorDestroy FORTRAN_NAME(ceedvectordestroy,CEEDVECTORDESTROY)
243 CEED_EXTERN void fCeedVectorDestroy(int *vec, int *err) {
244   if (*vec == FORTRAN_NULL) return;
245   *err = CeedVectorDestroy(&CeedVector_dict[*vec]);
246 
247   if (*err == 0) {
248     *vec = FORTRAN_NULL;
249     CeedVector_n--;
250     if (CeedVector_n == 0) {
251       CeedFree(&CeedVector_dict);
252       CeedVector_count = 0;
253       CeedVector_count_max = 0;
254     }
255   }
256 }
257 
258 // -----------------------------------------------------------------------------
259 // CeedElemRestriction
260 // -----------------------------------------------------------------------------
261 static CeedElemRestriction *CeedElemRestriction_dict = NULL;
262 static int CeedElemRestriction_count = 0;
263 static int CeedElemRestriction_n = 0;
264 static int CeedElemRestriction_count_max = 0;
265 
266 #define fCeedElemRestrictionCreate \
267     FORTRAN_NAME(ceedelemrestrictioncreate, CEEDELEMRESTRICTIONCREATE)
268 CEED_EXTERN void fCeedElemRestrictionCreate(int *ceed, int *nelements,
269     int *esize,
270     int *num_comp, int *comp_stride, int *lsize,
271     int *memtype, int *copymode, const int *offsets,
272     int *elemrestriction, int *err) {
273   if (CeedElemRestriction_count == CeedElemRestriction_count_max) {
274     CeedElemRestriction_count_max += CeedElemRestriction_count_max/2 + 1;
275     CeedRealloc(CeedElemRestriction_count_max, &CeedElemRestriction_dict);
276   }
277 
278   const int *offsets_ = offsets;
279 
280   CeedElemRestriction *elemrestriction_ =
281     &CeedElemRestriction_dict[CeedElemRestriction_count];
282   *err = CeedElemRestrictionCreate(Ceed_dict[*ceed], *nelements, *esize,
283                                    *num_comp, *comp_stride, *lsize,
284                                    (CeedMemType)*memtype,
285                                    (CeedCopyMode)*copymode, offsets_,
286                                    elemrestriction_);
287 
288   if (*err == 0) {
289     *elemrestriction = CeedElemRestriction_count++;
290     CeedElemRestriction_n++;
291   }
292 }
293 
294 #define fCeedElemRestrictionCreateStrided \
295     FORTRAN_NAME(ceedelemrestrictioncreatestrided, CEEDELEMRESTRICTIONCREATESTRIDED)
296 CEED_EXTERN void fCeedElemRestrictionCreateStrided(int *ceed, int *nelements,
297     int *esize,
298     int *num_comp, int *lsize, int *strides,
299     int *elemrestriction, int *err) {
300   if (CeedElemRestriction_count == CeedElemRestriction_count_max) {
301     CeedElemRestriction_count_max += CeedElemRestriction_count_max/2 + 1;
302     CeedRealloc(CeedElemRestriction_count_max, &CeedElemRestriction_dict);
303   }
304 
305   CeedElemRestriction *elemrestriction_ =
306     &CeedElemRestriction_dict[CeedElemRestriction_count];
307   *err = CeedElemRestrictionCreateStrided(Ceed_dict[*ceed], *nelements, *esize,
308                                           *num_comp, *lsize,
309                                           *strides == FORTRAN_STRIDES_BACKEND ?
310                                           CEED_STRIDES_BACKEND : strides,
311                                           elemrestriction_);
312   if (*err == 0) {
313     *elemrestriction = CeedElemRestriction_count++;
314     CeedElemRestriction_n++;
315   }
316 }
317 
318 #define fCeedElemRestrictionCreateBlocked \
319     FORTRAN_NAME(ceedelemrestrictioncreateblocked,CEEDELEMRESTRICTIONCREATEBLOCKED)
320 CEED_EXTERN void fCeedElemRestrictionCreateBlocked(int *ceed, int *nelements,
321     int *esize,
322     int *blocksize, int *num_comp,
323     int *comp_stride, int *lsize,
324     int *mtype, int *cmode,
325     int *blkindices, int *elemrestriction,
326     int *err) {
327 
328   if (CeedElemRestriction_count == CeedElemRestriction_count_max) {
329     CeedElemRestriction_count_max += CeedElemRestriction_count_max/2 + 1;
330     CeedRealloc(CeedElemRestriction_count_max, &CeedElemRestriction_dict);
331   }
332 
333   CeedElemRestriction *elemrestriction_ =
334     &CeedElemRestriction_dict[CeedElemRestriction_count];
335   *err = CeedElemRestrictionCreateBlocked(Ceed_dict[*ceed],
336                                           *nelements, *esize, *blocksize,
337                                           *num_comp, *comp_stride, *lsize,
338                                           (CeedMemType)*mtype,
339                                           (CeedCopyMode)*cmode, blkindices,
340                                           elemrestriction_);
341 
342   if (*err == 0) {
343     *elemrestriction = CeedElemRestriction_count++;
344     CeedElemRestriction_n++;
345   }
346 }
347 
348 #define fCeedElemRestrictionCreateBlockedStrided \
349     FORTRAN_NAME(ceedelemrestrictioncreateblockedstrided, CEEDELEMRESTRICTIONCREATEBLOCKEDSTRIDED)
350 CEED_EXTERN void fCeedElemRestrictionCreateBlockedStrided(int *ceed,
351     int *nelements,
352     int *esize, int *blk_size, int *num_comp, int *lsize, int *strides,
353     int *elemrestriction, int *err) {
354   if (CeedElemRestriction_count == CeedElemRestriction_count_max) {
355     CeedElemRestriction_count_max += CeedElemRestriction_count_max/2 + 1;
356     CeedRealloc(CeedElemRestriction_count_max, &CeedElemRestriction_dict);
357   }
358 
359   CeedElemRestriction *elemrestriction_ =
360     &CeedElemRestriction_dict[CeedElemRestriction_count];
361   *err = CeedElemRestrictionCreateBlockedStrided(Ceed_dict[*ceed], *nelements,
362          *esize, *blk_size, *num_comp, *lsize, strides, elemrestriction_);
363   if (*err == 0) {
364     *elemrestriction = CeedElemRestriction_count++;
365     CeedElemRestriction_n++;
366   }
367 }
368 
369 static CeedRequest *CeedRequest_dict = NULL;
370 static int CeedRequest_count = 0;
371 static int CeedRequest_n = 0;
372 static int CeedRequest_count_max = 0;
373 
374 #define fCeedElemRestrictionApply \
375     FORTRAN_NAME(ceedelemrestrictionapply,CEEDELEMRESTRICTIONAPPLY)
376 CEED_EXTERN void fCeedElemRestrictionApply(int *elemr, int *tmode, int *uvec,
377     int *ruvec,
378     int *rqst, int *err) {
379   int createRequest = 1;
380   // Check if input is CEED_REQUEST_ORDERED(-2) or CEED_REQUEST_IMMEDIATE(-1)
381   if (*rqst == FORTRAN_REQUEST_IMMEDIATE || *rqst == FORTRAN_REQUEST_ORDERED)
382     createRequest = 0;
383 
384   if (createRequest && CeedRequest_count == CeedRequest_count_max) {
385     CeedRequest_count_max += CeedRequest_count_max/2 + 1;
386     CeedRealloc(CeedRequest_count_max, &CeedRequest_dict);
387   }
388 
389   CeedRequest *rqst_;
390   if      (*rqst == FORTRAN_REQUEST_IMMEDIATE) rqst_ = CEED_REQUEST_IMMEDIATE;
391   else if (*rqst == FORTRAN_REQUEST_ORDERED  ) rqst_ = CEED_REQUEST_ORDERED;
392   else rqst_ = &CeedRequest_dict[CeedRequest_count];
393 
394   *err = CeedElemRestrictionApply(CeedElemRestriction_dict[*elemr],
395                                   (CeedTransposeMode)*tmode,
396                                   CeedVector_dict[*uvec],
397                                   CeedVector_dict[*ruvec], rqst_);
398 
399   if (*err == 0 && createRequest) {
400     *rqst = CeedRequest_count++;
401     CeedRequest_n++;
402   }
403 }
404 
405 #define fCeedElemRestrictionApplyBlock \
406     FORTRAN_NAME(ceedelemrestrictionapplyblock,CEEDELEMRESTRICTIONAPPLYBLOCK)
407 CEED_EXTERN void fCeedElemRestrictionApplyBlock(int *elemr, int *block,
408     int *tmode,
409     int *uvec, int *ruvec, int *rqst, int *err) {
410   int createRequest = 1;
411   // Check if input is CEED_REQUEST_ORDERED(-2) or CEED_REQUEST_IMMEDIATE(-1)
412   if (*rqst == FORTRAN_REQUEST_IMMEDIATE || *rqst == FORTRAN_REQUEST_ORDERED)
413     createRequest = 0;
414 
415   if (createRequest && CeedRequest_count == CeedRequest_count_max) {
416     CeedRequest_count_max += CeedRequest_count_max/2 + 1;
417     CeedRealloc(CeedRequest_count_max, &CeedRequest_dict);
418   }
419 
420   CeedRequest *rqst_;
421   if      (*rqst == FORTRAN_REQUEST_IMMEDIATE) rqst_ = CEED_REQUEST_IMMEDIATE;
422   else if (*rqst == FORTRAN_REQUEST_ORDERED  ) rqst_ = CEED_REQUEST_ORDERED;
423   else rqst_ = &CeedRequest_dict[CeedRequest_count];
424 
425   *err = CeedElemRestrictionApplyBlock(CeedElemRestriction_dict[*elemr], *block,
426                                        (CeedTransposeMode)*tmode, CeedVector_dict[*uvec],
427                                        CeedVector_dict[*ruvec], rqst_);
428 
429   if (*err == 0 && createRequest) {
430     *rqst = CeedRequest_count++;
431     CeedRequest_n++;
432   }
433 }
434 
435 #define fCeedElemRestrictionGetMultiplicity \
436     FORTRAN_NAME(ceedelemrestrictiongetmultiplicity,CEEDELEMRESTRICTIONGETMULTIPLICITY)
437 CEED_EXTERN void fCeedElemRestrictionGetMultiplicity(int *elemr, int *mult,
438     int *err) {
439   *err = CeedElemRestrictionGetMultiplicity(CeedElemRestriction_dict[*elemr],
440          CeedVector_dict[*mult]);
441 }
442 
443 #define fCeedElemRestrictionGetELayout \
444     FORTRAN_NAME(ceedelemrestrictiongetelayout,CEEDELEMRESTRICTIONGETELAYOUT)
445 CEED_EXTERN void fCeedElemRestrictionGetELayout(int *elemr, int *layout,
446     int *err) {
447   CeedInt layout_c[3];
448   *err = CeedElemRestrictionGetELayout(CeedElemRestriction_dict[*elemr],
449                                        &layout_c);
450   for (int i=0; i<3; i++)
451     layout[i] = layout_c[i];
452 }
453 
454 #define fCeedElemRestrictionView \
455     FORTRAN_NAME(ceedelemrestrictionview,CEEDELEMRESTRICTIONVIEW)
456 CEED_EXTERN void fCeedElemRestrictionView(int *elemr, int *err) {
457   *err = CeedElemRestrictionView(CeedElemRestriction_dict[*elemr], stdout);
458 }
459 
460 #define fCeedRequestWait FORTRAN_NAME(ceedrequestwait, CEEDREQUESTWAIT)
461 CEED_EXTERN void fCeedRequestWait(int *rqst, int *err) {
462   // TODO Uncomment this once CeedRequestWait is implemented
463   //*err = CeedRequestWait(&CeedRequest_dict[*rqst]);
464 
465   if (*err == 0) {
466     CeedRequest_n--;
467     if (CeedRequest_n == 0) {
468       CeedFree(&CeedRequest_dict);
469       CeedRequest_count = 0;
470       CeedRequest_count_max = 0;
471     }
472   }
473 }
474 
475 #define fCeedElemRestrictionDestroy \
476     FORTRAN_NAME(ceedelemrestrictiondestroy,CEEDELEMRESTRICTIONDESTROY)
477 CEED_EXTERN void fCeedElemRestrictionDestroy(int *elem, int *err) {
478   if (*elem == FORTRAN_NULL) return;
479   *err = CeedElemRestrictionDestroy(&CeedElemRestriction_dict[*elem]);
480 
481   if (*err == 0) {
482     *elem = FORTRAN_NULL;
483     CeedElemRestriction_n--;
484     if (CeedElemRestriction_n == 0) {
485       CeedFree(&CeedElemRestriction_dict);
486       CeedElemRestriction_count = 0;
487       CeedElemRestriction_count_max = 0;
488     }
489   }
490 }
491 
492 // -----------------------------------------------------------------------------
493 // CeedBasis
494 // -----------------------------------------------------------------------------
495 static CeedBasis *CeedBasis_dict = NULL;
496 static int CeedBasis_count = 0;
497 static int CeedBasis_n = 0;
498 static int CeedBasis_count_max = 0;
499 
500 #define fCeedBasisCreateTensorH1Lagrange \
501     FORTRAN_NAME(ceedbasiscreatetensorh1lagrange, CEEDBASISCREATETENSORH1LAGRANGE)
502 CEED_EXTERN void fCeedBasisCreateTensorH1Lagrange(int *ceed, int *dim,
503     int *num_comp, int *P, int *Q, int *quadmode,
504     int *basis, int *err) {
505   if (CeedBasis_count == CeedBasis_count_max) {
506     CeedBasis_count_max += CeedBasis_count_max/2 + 1;
507     CeedRealloc(CeedBasis_count_max, &CeedBasis_dict);
508   }
509 
510   *err = CeedBasisCreateTensorH1Lagrange(Ceed_dict[*ceed], *dim, *num_comp, *P,
511                                          *Q,
512                                          (CeedQuadMode)*quadmode,
513                                          &CeedBasis_dict[CeedBasis_count]);
514 
515   if (*err == 0) {
516     *basis = CeedBasis_count++;
517     CeedBasis_n++;
518   }
519 }
520 
521 #define fCeedBasisCreateTensorH1 \
522     FORTRAN_NAME(ceedbasiscreatetensorh1, CEEDBASISCREATETENSORH1)
523 CEED_EXTERN void fCeedBasisCreateTensorH1(int *ceed, int *dim, int *num_comp,
524     int *P_1d,
525     int *Q_1d, const CeedScalar *interp_1d,
526     const CeedScalar *grad_1d,
527     const CeedScalar *q_ref_1d,
528     const CeedScalar *q_weight_1d, int *basis,
529     int *err) {
530   if (CeedBasis_count == CeedBasis_count_max) {
531     CeedBasis_count_max += CeedBasis_count_max/2 + 1;
532     CeedRealloc(CeedBasis_count_max, &CeedBasis_dict);
533   }
534 
535   *err = CeedBasisCreateTensorH1(Ceed_dict[*ceed], *dim, *num_comp, *P_1d, *Q_1d,
536                                  interp_1d, grad_1d, q_ref_1d, q_weight_1d,
537                                  &CeedBasis_dict[CeedBasis_count]);
538 
539   if (*err == 0) {
540     *basis = CeedBasis_count++;
541     CeedBasis_n++;
542   }
543 }
544 
545 #define fCeedBasisCreateH1 \
546     FORTRAN_NAME(ceedbasiscreateh1, CEEDBASISCREATEH1)
547 CEED_EXTERN void fCeedBasisCreateH1(int *ceed, int *topo, int *num_comp,
548                                     int *nnodes,
549                                     int *nqpts, const CeedScalar *interp,
550                                     const CeedScalar *grad, const CeedScalar *qref,
551                                     const CeedScalar *qweight, int *basis, int *err) {
552   if (CeedBasis_count == CeedBasis_count_max) {
553     CeedBasis_count_max += CeedBasis_count_max/2 + 1;
554     CeedRealloc(CeedBasis_count_max, &CeedBasis_dict);
555   }
556 
557   *err = CeedBasisCreateH1(Ceed_dict[*ceed], (CeedElemTopology)*topo, *num_comp,
558                            *nnodes, *nqpts, interp, grad, qref, qweight,
559                            &CeedBasis_dict[CeedBasis_count]);
560 
561   if (*err == 0) {
562     *basis = CeedBasis_count++;
563     CeedBasis_n++;
564   }
565 }
566 
567 #define fCeedBasisView FORTRAN_NAME(ceedbasisview, CEEDBASISVIEW)
568 CEED_EXTERN void fCeedBasisView(int *basis, int *err) {
569   *err = CeedBasisView(CeedBasis_dict[*basis], stdout);
570 }
571 
572 #define fCeedQRFactorization \
573     FORTRAN_NAME(ceedqrfactorization, CEEDQRFACTORIZATION)
574 CEED_EXTERN void fCeedQRFactorization(int *ceed, CeedScalar *mat,
575                                       CeedScalar *tau, int *m,
576                                       int *n, int *err) {
577   *err = CeedQRFactorization(Ceed_dict[*ceed], mat, tau, *m, *n);
578 }
579 
580 #define fCeedHouseholderApplyQ \
581     FORTRAN_NAME(ceedhouseholderapplyq, CEEDHOUSEHOLDERAPPLYQ)
582 CEED_EXTERN void fCeedHouseholderApplyQ(CeedScalar *A, CeedScalar *Q,
583                                         CeedScalar *tau,
584                                         int *t_mode,
585                                         int *m, int *n, int *k, int *row, int *col, int *err) {
586   *err = CeedHouseholderApplyQ(A, Q, tau, (CeedTransposeMode)*t_mode, *m, *n, *k,
587                                *row, *col);
588 }
589 
590 #define fCeedSymmetricSchurDecomposition \
591     FORTRAN_NAME(ceedsymmetricschurdecomposition, CEEDSYMMETRICSCHURDECOMPOSITION)
592 CEED_EXTERN void fCeedSymmetricSchurDecomposition(int *ceed, CeedScalar *mat,
593     CeedScalar *lambda, int *n, int *err) {
594   *err = CeedSymmetricSchurDecomposition(Ceed_dict[*ceed], mat, lambda, *n);
595 }
596 
597 #define fCeedSimultaneousDiagonalization \
598     FORTRAN_NAME(ceedsimultaneousdiagonalization, CEEDSIMULTANEOUSDIAGONALIZATION)
599 CEED_EXTERN void fCeedSimultaneousDiagonalization(int *ceed, CeedScalar *matA,
600     CeedScalar *matB, CeedScalar *x,
601     CeedScalar *lambda, int *n, int *err) {
602   *err = CeedSimultaneousDiagonalization(Ceed_dict[*ceed], matA, matB, x,
603                                          lambda, *n);
604 }
605 
606 #define fCeedBasisGetCollocatedGrad \
607     FORTRAN_NAME(ceedbasisgetcollocatedgrad, CEEDBASISGETCOLLOCATEDGRAD)
608 CEED_EXTERN void fCeedBasisGetCollocatedGrad(int *basis,
609     CeedScalar *colo_grad_1d,
610     int *err) {
611   *err = CeedBasisGetCollocatedGrad(CeedBasis_dict[*basis], colo_grad_1d);
612 }
613 
614 #define fCeedBasisApply FORTRAN_NAME(ceedbasisapply, CEEDBASISAPPLY)
615 CEED_EXTERN void fCeedBasisApply(int *basis, int *num_elem, int *tmode,
616                                  int *eval_mode,
617                                  int *u, int *v, int *err) {
618   *err = CeedBasisApply(CeedBasis_dict[*basis], *num_elem,
619                         (CeedTransposeMode)*tmode,
620                         (CeedEvalMode)*eval_mode,
621                         *u == FORTRAN_VECTOR_NONE ? CEED_VECTOR_NONE : CeedVector_dict[*u],
622                         CeedVector_dict[*v]);
623 }
624 
625 #define fCeedBasisGetNumNodes \
626     FORTRAN_NAME(ceedbasisgetnumnodes, CEEDBASISGETNUMNODES)
627 CEED_EXTERN void fCeedBasisGetNumNodes(int *basis, int *P, int *err) {
628   *err = CeedBasisGetNumNodes(CeedBasis_dict[*basis], P);
629 }
630 
631 #define fCeedBasisGetNumQuadraturePoints \
632     FORTRAN_NAME(ceedbasisgetnumquadraturepoints, CEEDBASISGETNUMQUADRATUREPOINTS)
633 CEED_EXTERN void fCeedBasisGetNumQuadraturePoints(int *basis, int *Q,
634     int *err) {
635   *err = CeedBasisGetNumQuadraturePoints(CeedBasis_dict[*basis], Q);
636 }
637 
638 #define fCeedBasisGetInterp1D \
639     FORTRAN_NAME(ceedbasisgetinterp1d, CEEDBASISGETINTERP1D)
640 CEED_EXTERN void fCeedBasisGetInterp1D(int *basis, CeedScalar *interp_1d,
641                                        int64_t *offset,
642                                        int *err) {
643   const CeedScalar *interp1d_;
644   CeedBasis basis_ = CeedBasis_dict[*basis];
645   *err = CeedBasisGetInterp1D(basis_, &interp1d_);
646   *offset = interp1d_ - interp_1d;
647 }
648 
649 #define fCeedBasisGetGrad1D \
650     FORTRAN_NAME(ceedbasisgetgrad1d, CEEDBASISGETGRAD1D)
651 CEED_EXTERN void fCeedBasisGetGrad1D(int *basis, CeedScalar *grad_1d,
652                                      int64_t *offset,
653                                      int *err) {
654   const CeedScalar *grad1d_;
655   CeedBasis basis_ = CeedBasis_dict[*basis];
656   *err = CeedBasisGetGrad1D(basis_, &grad1d_);
657   *offset = grad1d_ - grad_1d;
658 }
659 
660 #define fCeedBasisGetQRef \
661     FORTRAN_NAME(ceedbasisgetqref, CEEDBASISGETQREF)
662 CEED_EXTERN void fCeedBasisGetQRef(int *basis, CeedScalar *q_ref,
663                                    int64_t *offset,
664                                    int *err) {
665   const CeedScalar *qref_;
666   CeedBasis basis_ = CeedBasis_dict[*basis];
667   *err = CeedBasisGetQRef(basis_, &qref_);
668   *offset = qref_ - q_ref;
669 }
670 
671 #define fCeedBasisDestroy FORTRAN_NAME(ceedbasisdestroy,CEEDBASISDESTROY)
672 CEED_EXTERN void fCeedBasisDestroy(int *basis, int *err) {
673   if (*basis == FORTRAN_NULL) return;
674   *err = CeedBasisDestroy(&CeedBasis_dict[*basis]);
675 
676   if (*err == 0) {
677     *basis = FORTRAN_NULL;
678     CeedBasis_n--;
679     if (CeedBasis_n == 0) {
680       CeedFree(&CeedBasis_dict);
681       CeedBasis_count = 0;
682       CeedBasis_count_max = 0;
683     }
684   }
685 }
686 
687 #define fCeedGaussQuadrature FORTRAN_NAME(ceedgaussquadrature, CEEDGAUSSQUADRATURE)
688 CEED_EXTERN void fCeedGaussQuadrature(int *Q, CeedScalar *q_ref_1d,
689                                       CeedScalar *q_weight_1d,
690                                       int *err) {
691   *err = CeedGaussQuadrature(*Q, q_ref_1d, q_weight_1d);
692 }
693 
694 #define fCeedLobattoQuadrature \
695     FORTRAN_NAME(ceedlobattoquadrature, CEEDLOBATTOQUADRATURE)
696 CEED_EXTERN void fCeedLobattoQuadrature(int *Q, CeedScalar *q_ref_1d,
697                                         CeedScalar *q_weight_1d,
698                                         int *err) {
699   *err = CeedLobattoQuadrature(*Q, q_ref_1d, q_weight_1d);
700 }
701 
702 // -----------------------------------------------------------------------------
703 // CeedQFunctionContext
704 // -----------------------------------------------------------------------------
705 static CeedQFunctionContext *CeedQFunctionContext_dict = NULL;
706 static int CeedQFunctionContext_count = 0;
707 static int CeedQFunctionContext_n = 0;
708 static int CeedQFunctionContext_count_max = 0;
709 
710 #define fCeedQFunctionContextCreate \
711     FORTRAN_NAME(ceedqfunctioncontextcreate,CEEDQFUNCTIONCONTEXTCREATE)
712 CEED_EXTERN void fCeedQFunctionContextCreate(int *ceed, int *ctx, int *err) {
713   if (CeedQFunctionContext_count == CeedQFunctionContext_count_max) {
714     CeedQFunctionContext_count_max += CeedQFunctionContext_count_max/2 + 1;
715     CeedRealloc(CeedQFunctionContext_count_max, &CeedQFunctionContext_dict);
716   }
717 
718   CeedQFunctionContext *ctx_ =
719     &CeedQFunctionContext_dict[CeedQFunctionContext_count];
720 
721   *err = CeedQFunctionContextCreate(Ceed_dict[*ceed], ctx_);
722   if (*err) return;
723   *ctx = CeedQFunctionContext_count++;
724   CeedQFunctionContext_n++;
725 }
726 
727 #define fCeedQFunctionContextSetData \
728     FORTRAN_NAME(ceedqfunctioncontextsetdata,CEEDQFUNCTIONCONTEXTSETDATA)
729 CEED_EXTERN void fCeedQFunctionContextSetData(int *ctx, int *memtype,
730     int *copymode,
731     CeedInt *n,
732     CeedScalar *data, int64_t *offset, int *err) {
733   size_t ctx_size = ((size_t) *n)*sizeof(CeedScalar);
734   *err = CeedQFunctionContextSetData(CeedQFunctionContext_dict[*ctx],
735                                      (CeedMemType)*memtype,
736                                      (CeedCopyMode)*copymode, ctx_size,
737                                      data + *offset);
738 }
739 
740 #define fCeedQFunctionContextGetData \
741     FORTRAN_NAME(ceedqfunctioncontextgetdata,CEEDQFUNCTIONCONTEXTGETDATA)
742 CEED_EXTERN void fCeedQFunctionContextGetData(int *ctx, int *memtype,
743     CeedScalar *data,
744     int64_t *offset, int *err) {
745   CeedScalar *b;
746   CeedQFunctionContext ctx_ = CeedQFunctionContext_dict[*ctx];
747   *err = CeedQFunctionContextGetData(ctx_, (CeedMemType)*memtype, &b);
748   *offset = b - data;
749 }
750 
751 #define fCeedQFunctionContextRestoreData \
752     FORTRAN_NAME(ceedqfunctioncontextrestoredata,CEEDQFUNCTIONCONTEXTRESTOREDATA)
753 CEED_EXTERN void fCeedQFunctionContextRestoreData(int *ctx, CeedScalar *data,
754     int64_t *offset, int *err) {
755   *err = CeedQFunctionContextRestoreData(CeedQFunctionContext_dict[*ctx],
756                                          (void **)&data);
757   *offset = 0;
758 }
759 
760 #define fCeedQFunctionContextView \
761     FORTRAN_NAME(ceedqfunctioncontextview,CEEDQFUNCTIONCONTEXTVIEW)
762 CEED_EXTERN void fCeedQFunctionContextView(int *ctx, int *err) {
763   *err = CeedQFunctionContextView(CeedQFunctionContext_dict[*ctx], stdout);
764 }
765 
766 #define fCeedQFunctionContextDestroy \
767     FORTRAN_NAME(ceedqfunctioncontextdestroy,CEEDQFUNCTIONCONTEXTDESTROY)
768 CEED_EXTERN void fCeedQFunctionContextDestroy(int *ctx, int *err) {
769   if (*ctx == FORTRAN_NULL) return;
770   *err = CeedQFunctionContextDestroy(&CeedQFunctionContext_dict[*ctx]);
771 
772   if (*err == 0) {
773     *ctx = FORTRAN_NULL;
774     CeedQFunctionContext_n--;
775     if (CeedQFunctionContext_n == 0) {
776       CeedFree(&CeedQFunctionContext_dict);
777       CeedQFunctionContext_count = 0;
778       CeedQFunctionContext_count_max = 0;
779     }
780   }
781 }
782 
783 // -----------------------------------------------------------------------------
784 // CeedQFunction
785 // -----------------------------------------------------------------------------
786 static CeedQFunction *CeedQFunction_dict = NULL;
787 static int CeedQFunction_count = 0;
788 static int CeedQFunction_n = 0;
789 static int CeedQFunction_count_max = 0;
790 
791 static int CeedQFunctionFortranStub(void *ctx, int nq,
792                                     const CeedScalar *const *u,
793                                     CeedScalar *const *v) {
794   CeedFortranContext fctx = ctx;
795   CeedQFunctionContext inner_ctx = fctx->inner_ctx;
796   int ierr;
797 
798   CeedScalar *ctx_ = NULL;
799   // Note: Device backends are generating their own kernels from
800   //         single source files, so only Host backends need to
801   //         use this Fortran stub.
802   if (inner_ctx) {
803     ierr = CeedQFunctionContextGetData(inner_ctx, CEED_MEM_HOST, &ctx_);
804     CeedChk(ierr);
805   }
806 
807   fctx->f((void *)ctx_,&nq,u[0],u[1],u[2],u[3],u[4],u[5],u[6],
808           u[7],u[8],u[9],u[10],u[11],u[12],u[13],u[14],u[15],
809           v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],
810           v[10],v[11],v[12],v[13],v[14],v[15],&ierr);
811 
812   if (inner_ctx) {
813     ierr = CeedQFunctionContextRestoreData(inner_ctx, (void *)&ctx_);
814     CeedChk(ierr);
815   }
816 
817   return ierr;
818 }
819 
820 #define fCeedQFunctionCreateInterior \
821     FORTRAN_NAME(ceedqfunctioncreateinterior, CEEDQFUNCTIONCREATEINTERIOR)
822 CEED_EXTERN void fCeedQFunctionCreateInterior(int *ceed, int *vec_length,
823     void (*f)(void *ctx, int *nq,
824               const CeedScalar *u,const CeedScalar *u1,
825               const CeedScalar *u2,const CeedScalar *u3,
826               const CeedScalar *u4,const CeedScalar *u5,
827               const CeedScalar *u6,const CeedScalar *u7,
828               const CeedScalar *u8,const CeedScalar *u9,
829               const CeedScalar *u10,const CeedScalar *u11,
830               const CeedScalar *u12,const CeedScalar *u13,
831               const CeedScalar *u14,const CeedScalar *u15,
832               CeedScalar *v,CeedScalar *v1,CeedScalar *v2,
833               CeedScalar *v3,CeedScalar *v4,
834               CeedScalar *v5,CeedScalar *v6,
835               CeedScalar *v7,CeedScalar *v8,
836               CeedScalar *v9,CeedScalar *v10,
837               CeedScalar *v11,CeedScalar *v12,
838               CeedScalar *v13,CeedScalar *v14,
839               CeedScalar *v15,int *err),
840     const char *source, int *qf, int *err,
841     fortran_charlen_t source_len) {
842   FIX_STRING(source);
843   if (CeedQFunction_count == CeedQFunction_count_max) {
844     CeedQFunction_count_max += CeedQFunction_count_max/2 + 1;
845     CeedRealloc(CeedQFunction_count_max, &CeedQFunction_dict);
846   }
847 
848   CeedQFunction *qf_ = &CeedQFunction_dict[CeedQFunction_count];
849   *err = CeedQFunctionCreateInterior(Ceed_dict[*ceed], *vec_length,
850                                      CeedQFunctionFortranStub, source_c, qf_);
851 
852   if (*err == 0) {
853     *qf = CeedQFunction_count++;
854     CeedQFunction_n++;
855   }
856 
857   CeedFortranContext fctxdata;
858   *err = CeedCalloc(1, &fctxdata);
859   if (*err) return;
860   fctxdata->f = f; fctxdata->inner_ctx = NULL;
861   CeedQFunctionContext fctx;
862   *err = CeedQFunctionContextCreate(Ceed_dict[*ceed], &fctx);
863   if (*err) return;
864   *err = CeedQFunctionContextSetData(fctx, CEED_MEM_HOST, CEED_OWN_POINTER,
865                                      sizeof(*fctxdata), fctxdata);
866   if (*err) return;
867   *err = CeedQFunctionSetContext(*qf_, fctx);
868   if (*err) return;
869   CeedQFunctionContextDestroy(&fctx);
870   if (*err) return;
871 
872   *err = CeedQFunctionSetFortranStatus(*qf_, true);
873 }
874 
875 #define fCeedQFunctionCreateInteriorByName \
876     FORTRAN_NAME(ceedqfunctioncreateinteriorbyname, CEEDQFUNCTIONCREATEINTERIORBYNAME)
877 CEED_EXTERN void fCeedQFunctionCreateInteriorByName(int *ceed, const char *name,
878     int *qf,
879     int *err, fortran_charlen_t name_len) {
880   FIX_STRING(name);
881   if (CeedQFunction_count == CeedQFunction_count_max) {
882     CeedQFunction_count_max += CeedQFunction_count_max/2 + 1;
883     CeedRealloc(CeedQFunction_count_max, &CeedQFunction_dict);
884   }
885 
886   CeedQFunction *qf_ = &CeedQFunction_dict[CeedQFunction_count];
887   *err = CeedQFunctionCreateInteriorByName(Ceed_dict[*ceed], name_c, qf_);
888 
889   if (*err == 0) {
890     *qf = CeedQFunction_count++;
891     CeedQFunction_n++;
892   }
893 }
894 
895 #define fCeedQFunctionCreateIdentity \
896     FORTRAN_NAME(ceedqfunctioncreateidentity, CEEDQFUNCTIONCREATEIDENTITY)
897 CEED_EXTERN void fCeedQFunctionCreateIdentity(int *ceed, int *size, int *inmode,
898     int *outmode, int *qf, int *err) {
899   if (CeedQFunction_count == CeedQFunction_count_max) {
900     CeedQFunction_count_max += CeedQFunction_count_max/2 + 1;
901     CeedRealloc(CeedQFunction_count_max, &CeedQFunction_dict);
902   }
903 
904   CeedQFunction *qf_ = &CeedQFunction_dict[CeedQFunction_count];
905   *err = CeedQFunctionCreateIdentity(Ceed_dict[*ceed], *size,
906                                      (CeedEvalMode)*inmode,
907                                      (CeedEvalMode)*outmode, qf_);
908 
909   if (*err == 0) {
910     *qf = CeedQFunction_count++;
911     CeedQFunction_n++;
912   }
913 }
914 
915 #define fCeedQFunctionAddInput \
916     FORTRAN_NAME(ceedqfunctionaddinput,CEEDQFUNCTIONADDINPUT)
917 CEED_EXTERN void fCeedQFunctionAddInput(int *qf, const char *field_name,
918                                         CeedInt *num_comp, CeedEvalMode *eval_mode, int *err,
919                                         fortran_charlen_t field_name_len) {
920   FIX_STRING(field_name);
921   CeedQFunction qf_ = CeedQFunction_dict[*qf];
922 
923   *err = CeedQFunctionAddInput(qf_, field_name_c, *num_comp, *eval_mode);
924 }
925 
926 #define fCeedQFunctionAddOutput \
927     FORTRAN_NAME(ceedqfunctionaddoutput,CEEDQFUNCTIONADDOUTPUT)
928 CEED_EXTERN void fCeedQFunctionAddOutput(int *qf, const char *field_name,
929     CeedInt *num_comp, CeedEvalMode *eval_mode, int *err,
930     fortran_charlen_t field_name_len) {
931   FIX_STRING(field_name);
932   CeedQFunction qf_ = CeedQFunction_dict[*qf];
933 
934   *err = CeedQFunctionAddOutput(qf_, field_name_c, *num_comp, *eval_mode);
935 }
936 
937 #define fCeedQFunctionSetContext \
938     FORTRAN_NAME(ceedqfunctionsetcontext,CEEDQFUNCTIONSETCONTEXT)
939 CEED_EXTERN void fCeedQFunctionSetContext(int *qf, int *ctx, int *err) {
940   CeedQFunction qf_ = CeedQFunction_dict[*qf];
941   CeedQFunctionContext ctx_ = CeedQFunctionContext_dict[*ctx];
942 
943   CeedQFunctionContext fctx;
944   *err = CeedQFunctionGetContext(qf_, &fctx);
945   if (*err) return;
946   CeedFortranContext fctxdata;
947   *err = CeedQFunctionContextGetData(fctx, CEED_MEM_HOST, &fctxdata);
948   if (*err) return;
949   fctxdata->inner_ctx = ctx_;
950   *err = CeedQFunctionContextRestoreData(fctx, (void **)&fctxdata);
951 }
952 
953 #define fCeedQFunctionView \
954     FORTRAN_NAME(ceedqfunctionview,CEEDQFUNCTIONVIEW)
955 CEED_EXTERN void fCeedQFunctionView(int *qf, int *err) {
956   CeedQFunction qf_ = CeedQFunction_dict[*qf];
957 
958   *err = CeedQFunctionView(qf_, stdout);
959 }
960 
961 #define fCeedQFunctionApply \
962     FORTRAN_NAME(ceedqfunctionapply,CEEDQFUNCTIONAPPLY)
963 //TODO Need Fixing, double pointer
964 CEED_EXTERN void fCeedQFunctionApply(int *qf, int *Q,
965                                      int *u, int *u1, int *u2, int *u3,
966                                      int *u4, int *u5, int *u6, int *u7,
967                                      int *u8, int *u9, int *u10, int *u11,
968                                      int *u12, int *u13, int *u14, int *u15,
969                                      int *v, int *v1, int *v2, int *v3,
970                                      int *v4, int *v5, int *v6, int *v7,
971                                      int *v8, int *v9, int *v10, int *v11,
972                                      int *v12, int *v13, int *v14, int *v15, int *err) {
973   CeedQFunction qf_ = CeedQFunction_dict[*qf];
974   CeedVector *in;
975   *err = CeedCalloc(CEED_FIELD_MAX, &in);
976   if (*err) return;
977   in[0] = *u==FORTRAN_NULL?NULL:CeedVector_dict[*u];
978   in[1] = *u1==FORTRAN_NULL?NULL:CeedVector_dict[*u1];
979   in[2] = *u2==FORTRAN_NULL?NULL:CeedVector_dict[*u2];
980   in[3] = *u3==FORTRAN_NULL?NULL:CeedVector_dict[*u3];
981   in[4] = *u4==FORTRAN_NULL?NULL:CeedVector_dict[*u4];
982   in[5] = *u5==FORTRAN_NULL?NULL:CeedVector_dict[*u5];
983   in[6] = *u6==FORTRAN_NULL?NULL:CeedVector_dict[*u6];
984   in[7] = *u7==FORTRAN_NULL?NULL:CeedVector_dict[*u7];
985   in[8] = *u8==FORTRAN_NULL?NULL:CeedVector_dict[*u8];
986   in[9] = *u9==FORTRAN_NULL?NULL:CeedVector_dict[*u9];
987   in[10] = *u10==FORTRAN_NULL?NULL:CeedVector_dict[*u10];
988   in[11] = *u11==FORTRAN_NULL?NULL:CeedVector_dict[*u11];
989   in[12] = *u12==FORTRAN_NULL?NULL:CeedVector_dict[*u12];
990   in[13] = *u13==FORTRAN_NULL?NULL:CeedVector_dict[*u13];
991   in[14] = *u14==FORTRAN_NULL?NULL:CeedVector_dict[*u14];
992   in[15] = *u15==FORTRAN_NULL?NULL:CeedVector_dict[*u15];
993   CeedVector *out;
994   *err = CeedCalloc(CEED_FIELD_MAX, &out);
995   if (*err) return;
996   out[0] = *v==FORTRAN_NULL?NULL:CeedVector_dict[*v];
997   out[1] = *v1==FORTRAN_NULL?NULL:CeedVector_dict[*v1];
998   out[2] = *v2==FORTRAN_NULL?NULL:CeedVector_dict[*v2];
999   out[3] = *v3==FORTRAN_NULL?NULL:CeedVector_dict[*v3];
1000   out[4] = *v4==FORTRAN_NULL?NULL:CeedVector_dict[*v4];
1001   out[5] = *v5==FORTRAN_NULL?NULL:CeedVector_dict[*v5];
1002   out[6] = *v6==FORTRAN_NULL?NULL:CeedVector_dict[*v6];
1003   out[7] = *v7==FORTRAN_NULL?NULL:CeedVector_dict[*v7];
1004   out[8] = *v8==FORTRAN_NULL?NULL:CeedVector_dict[*v8];
1005   out[9] = *v9==FORTRAN_NULL?NULL:CeedVector_dict[*v9];
1006   out[10] = *v10==FORTRAN_NULL?NULL:CeedVector_dict[*v10];
1007   out[11] = *v11==FORTRAN_NULL?NULL:CeedVector_dict[*v11];
1008   out[12] = *v12==FORTRAN_NULL?NULL:CeedVector_dict[*v12];
1009   out[13] = *v13==FORTRAN_NULL?NULL:CeedVector_dict[*v13];
1010   out[14] = *v14==FORTRAN_NULL?NULL:CeedVector_dict[*v14];
1011   out[15] = *v15==FORTRAN_NULL?NULL:CeedVector_dict[*v15];
1012   *err = CeedQFunctionApply(qf_, *Q, in, out);
1013   if (*err) return;
1014 
1015   *err = CeedFree(&in);
1016   if (*err) return;
1017   *err = CeedFree(&out);
1018 }
1019 
1020 #define fCeedQFunctionDestroy \
1021     FORTRAN_NAME(ceedqfunctiondestroy,CEEDQFUNCTIONDESTROY)
1022 CEED_EXTERN void fCeedQFunctionDestroy(int *qf, int *err) {
1023   if (*qf == FORTRAN_NULL) return;
1024 
1025   *err = CeedQFunctionDestroy(&CeedQFunction_dict[*qf]);
1026   if (*err == 0) {
1027     *qf = FORTRAN_NULL;
1028     CeedQFunction_n--;
1029     if (CeedQFunction_n == 0) {
1030       *err = CeedFree(&CeedQFunction_dict);
1031       CeedQFunction_count = 0;
1032       CeedQFunction_count_max = 0;
1033     }
1034   }
1035 }
1036 
1037 // -----------------------------------------------------------------------------
1038 // CeedOperator
1039 // -----------------------------------------------------------------------------
1040 static CeedOperator *CeedOperator_dict = NULL;
1041 static int CeedOperator_count = 0;
1042 static int CeedOperator_n = 0;
1043 static int CeedOperator_count_max = 0;
1044 
1045 #define fCeedOperatorCreate \
1046     FORTRAN_NAME(ceedoperatorcreate, CEEDOPERATORCREATE)
1047 CEED_EXTERN void fCeedOperatorCreate(int *ceed,
1048                                      int *qf, int *dqf, int *dqfT, int *op, int *err) {
1049   if (CeedOperator_count == CeedOperator_count_max) {
1050     CeedOperator_count_max += CeedOperator_count_max/2 + 1;
1051     CeedRealloc(CeedOperator_count_max, &CeedOperator_dict);
1052   }
1053 
1054   CeedOperator *op_ = &CeedOperator_dict[CeedOperator_count];
1055 
1056   CeedQFunction dqf_  = CEED_QFUNCTION_NONE, dqfT_ = CEED_QFUNCTION_NONE;
1057   if (*dqf  != FORTRAN_QFUNCTION_NONE) dqf_  = CeedQFunction_dict[*dqf ];
1058   if (*dqfT != FORTRAN_QFUNCTION_NONE) dqfT_ = CeedQFunction_dict[*dqfT];
1059 
1060   *err = CeedOperatorCreate(Ceed_dict[*ceed], CeedQFunction_dict[*qf], dqf_,
1061                             dqfT_, op_);
1062   if (*err) return;
1063   *op = CeedOperator_count++;
1064   CeedOperator_n++;
1065 }
1066 
1067 #define fCeedCompositeOperatorCreate \
1068     FORTRAN_NAME(ceedcompositeoperatorcreate, CEEDCOMPOSITEOPERATORCREATE)
1069 CEED_EXTERN void fCeedCompositeOperatorCreate(int *ceed, int *op, int *err) {
1070   if (CeedOperator_count == CeedOperator_count_max) {
1071     CeedOperator_count_max += CeedOperator_count_max/2 + 1;
1072     CeedRealloc(CeedOperator_count_max, &CeedOperator_dict);
1073   }
1074 
1075   CeedOperator *op_ = &CeedOperator_dict[CeedOperator_count];
1076 
1077   *err = CeedCompositeOperatorCreate(Ceed_dict[*ceed], op_);
1078   if (*err) return;
1079   *op = CeedOperator_count++;
1080   CeedOperator_n++;
1081 }
1082 
1083 #define fCeedOperatorSetField \
1084     FORTRAN_NAME(ceedoperatorsetfield,CEEDOPERATORSETFIELD)
1085 CEED_EXTERN void fCeedOperatorSetField(int *op, const char *field_name, int *r,
1086                                        int *b,
1087                                        int *v, int *err, fortran_charlen_t field_name_len) {
1088   FIX_STRING(field_name);
1089   CeedElemRestriction r_;
1090   CeedBasis b_;
1091   CeedVector v_;
1092 
1093   CeedOperator op_ = CeedOperator_dict[*op];
1094 
1095   if (*r == FORTRAN_NULL) {
1096     r_ = NULL;
1097   } else if (*r == FORTRAN_ELEMRESTRICTION_NONE) {
1098     r_ = CEED_ELEMRESTRICTION_NONE;
1099   } else {
1100     r_ = CeedElemRestriction_dict[*r];
1101   }
1102 
1103   if (*b == FORTRAN_NULL) {
1104     b_ = NULL;
1105   } else if (*b == FORTRAN_BASIS_COLLOCATED) {
1106     b_ = CEED_BASIS_COLLOCATED;
1107   } else {
1108     b_ = CeedBasis_dict[*b];
1109   }
1110   if (*v == FORTRAN_NULL) {
1111     v_ = NULL;
1112   } else if (*v == FORTRAN_VECTOR_ACTIVE) {
1113     v_ = CEED_VECTOR_ACTIVE;
1114   } else if (*v == FORTRAN_VECTOR_NONE) {
1115     v_ = CEED_VECTOR_NONE;
1116   } else {
1117     v_ = CeedVector_dict[*v];
1118   }
1119 
1120   *err = CeedOperatorSetField(op_, field_name_c, r_, b_, v_);
1121 }
1122 
1123 #define fCeedCompositeOperatorAddSub \
1124     FORTRAN_NAME(ceedcompositeoperatoraddsub, CEEDCOMPOSITEOPERATORADDSUB)
1125 CEED_EXTERN void fCeedCompositeOperatorAddSub(int *compositeop, int *subop,
1126     int *err) {
1127   CeedOperator compositeop_ = CeedOperator_dict[*compositeop];
1128   CeedOperator subop_ = CeedOperator_dict[*subop];
1129 
1130   *err = CeedCompositeOperatorAddSub(compositeop_, subop_);
1131   if (*err) return;
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