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