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