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