Actual source code: ftnimpl.h
1: #pragma once
3: #include <petsc/private/petscimpl.h>
4: PETSC_INTERN PetscErrorCode PETScParseFortranArgs_Private(int *, char ***);
5: PETSC_EXTERN PetscErrorCode PetscMPIFortranDatatypeToC(MPI_Fint, MPI_Datatype *);
6: PETSC_EXTERN void *PETSC_NULL_MAT_POINTER_Fortran(void);
7: PETSC_EXTERN void *PETSC_NULL_IS_POINTER_Fortran(void);
8: PETSC_EXTERN void *PETSC_NULL_KSP_POINTER_Fortran(void);
10: PETSC_EXTERN PetscErrorCode PetscScalarAddressToFortran(PetscObject, PetscInt, PetscScalar *, PetscScalar *, PetscInt, size_t *);
11: PETSC_EXTERN PetscErrorCode PetscScalarAddressFromFortran(PetscObject, PetscScalar *, size_t, PetscInt, PetscScalar **);
12: PETSC_EXTERN size_t PetscIntAddressToFortran(const PetscInt *, const PetscInt *);
13: PETSC_EXTERN PetscInt *PetscIntAddressFromFortran(const PetscInt *, size_t);
14: PETSC_EXTERN char *PETSC_NULL_CHARACTER_Fortran;
15: PETSC_EXTERN void *PETSC_NULL_INTEGER_Fortran;
16: PETSC_EXTERN void *PETSC_NULL_SCALAR_Fortran;
17: PETSC_EXTERN void *PETSC_NULL_DOUBLE_Fortran;
18: PETSC_EXTERN void *PETSC_NULL_REAL_Fortran;
19: PETSC_EXTERN void *PETSC_NULL_BOOL_Fortran;
20: PETSC_EXTERN void *PETSC_NULL_ENUM_Fortran;
21: PETSC_EXTERN void *PETSC_NULL_INTEGER_ARRAY_Fortran;
22: PETSC_EXTERN void *PETSC_NULL_SCALAR_ARRAY_Fortran;
23: PETSC_EXTERN void *PETSC_NULL_REAL_ARRAY_Fortran;
24: PETSC_EXTERN void *PETSC_NULL_MPI_COMM_Fortran;
25: PETSC_EXTERN void *PETSC_NULL_INTEGER_POINTER_Fortran;
26: PETSC_EXTERN void *PETSC_NULL_SCALAR_POINTER_Fortran;
27: PETSC_EXTERN void *PETSC_NULL_REAL_POINTER_Fortran;
28: PETSC_EXTERN PetscFortranCallbackFn *PETSC_NULL_FUNCTION_Fortran;
30: PETSC_INTERN PetscErrorCode PetscInitFortran_Private(const char *, PetscInt);
32: /* ----------------------------------------------------------------------*/
33: /*
34: PETSc object C pointers are stored directly as
35: Fortran integer*4 or *8 depending on the size of pointers.
36: */
38: /* --------------------------------------------------------------------*/
39: /*
40: Since Fortran does not null terminate strings we need to insure the string is null terminated before passing it
41: to C. This may require a memory allocation which is then freed with FREECHAR().
42: */
43: #define FIXCHAR(a, n, b) \
44: do { \
45: if ((a) == PETSC_NULL_CHARACTER_Fortran) { \
46: (b) = PETSC_NULLPTR; \
47: (a) = PETSC_NULLPTR; \
48: } else { \
49: while (((n) > 0) && ((a)[(n) - 1] == ' ')) (n)--; \
50: *ierr = PetscMalloc1((n) + 1, &(b)); \
51: if (*ierr) return; \
52: *ierr = PetscMemcpy((b), (a), (n)); \
53: (b)[(n)] = '\0'; \
54: if (*ierr) return; \
55: } \
56: } while (0)
57: #define FREECHAR(a, b) \
58: do { \
59: if ((a) != (b)) *ierr = PetscFree(b); \
60: } while (0)
62: /*
63: Fortran expects any unneeded characters at the end of its strings to be filled with the blank character.
64: */
65: #define FIXRETURNCHAR(flg, a, n) \
66: do { \
67: if (flg) { \
68: PETSC_FORTRAN_CHARLEN_T __i; \
69: for (__i = 0; __i < (n) && (a)[__i] != 0; __i++) { }; \
70: for (; __i < (n); __i++) (a)[__i] = ' '; \
71: } \
72: } while (0)
74: /*
75: The cast through PETSC_UINTPTR_T is so that compilers that warn about casting to/from void * to void(*)(void)
76: will not complain about these comparisons. It is not know if this works for all compilers
77: */
78: #define FORTRANNULLINTEGERPOINTER(a) (((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_INTEGER_POINTER_Fortran)
79: #define FORTRANNULLSCALARPOINTER(a) (((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_SCALAR_POINTER_Fortran)
80: #define FORTRANNULLREALPOINTER(a) (((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_REAL_POINTER_Fortran)
81: #define FORTRANNULLISPOINTER(a) (((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_IS_POINTER_Fortran())
82: #define FORTRANNULLMATPOINTER(a) (((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_MAT_POINTER_Fortran())
83: #define FORTRANNULLKSPPOINTER(a) (((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_KSP_POINTER_Fortran())
84: #define FORTRANNULLINTEGER(a) (((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_INTEGER_Fortran || ((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_INTEGER_ARRAY_Fortran)
85: #define FORTRANNULLSCALAR(a) (((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_SCALAR_Fortran || ((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_SCALAR_ARRAY_Fortran)
86: #define FORTRANNULLREAL(a) (((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_REAL_Fortran || ((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_REAL_ARRAY_Fortran)
87: #define FORTRANNULLDOUBLE(a) (((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_DOUBLE_Fortran)
88: #define FORTRANNULLBOOL(a) (((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_BOOL_Fortran)
89: #define FORTRANNULLENUM(a) ((((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_ENUM_Fortran) || (((void *)(PETSC_UINTPTR_T)(a)) == (void *)-50))
90: #define FORTRANNULLCHARACTER(a) (((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_CHARACTER_Fortran)
91: #define FORTRANNULLFUNCTION(a) (((PetscFortranCallbackFn *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_FUNCTION_Fortran)
92: #define FORTRANNULLOBJECT(a) (*(void **)(PETSC_UINTPTR_T)(a) == (void *)0)
93: #define FORTRANNULLMPICOMM(a) (((void *)(PETSC_UINTPTR_T)(a)) == PETSC_NULL_MPI_COMM_Fortran)
95: /*
96: A Fortran object with a value of (void*) 0 is indicated in Fortran by PETSC_NULL_XXXX, it is passed to routines to indicate the argument value is not requested or provided
97: similar to how NULL is used with PETSc objects in C
99: A Fortran object with a value of (void*) PETSC_FORTRAN_TYPE_INITIALIZE is an object that was never created or was destroyed (see checkFortranTypeInitialize()).
101: A Fortran object with a value of (void*) PETSC_FORTRAN_TYPE_NULL_RETURN happens when a PETSc routine returns in one of its arguments a NULL object
102: (it cannot return a value of (void*) PETSC_FORTRAN_TYPE_NULL because if later the returned variable is passed to a creation routine, it would think one has passed in a PETSC_NULL_XXX and error).
104: These three values are used because Fortran always uses pass by reference so one cannot pass a NULL address, only an address with special
105: values at the location.
107: PETSC_FORTRAN_TYPE_INITIALIZE is also defined in include/petsc/finclude/petscsysbase.h
108: */
109: #define PETSC_FORTRAN_TYPE_INITIALIZE (void *)-2
110: #define PETSC_FORTRAN_TYPE_NULL_RETURN (void *)-3
112: #define CHKFORTRANNULL(a) \
113: do { \
114: if (FORTRANNULLINTEGER(a) || FORTRANNULLENUM(a) || FORTRANNULLDOUBLE(a) || FORTRANNULLSCALAR(a) || FORTRANNULLREAL(a) || FORTRANNULLBOOL(a) || FORTRANNULLFUNCTION(a) || FORTRANNULLCHARACTER(a) || FORTRANNULLMPICOMM(a)) (a) = PETSC_NULLPTR; \
115: } while (0)
117: #define CHKFORTRANNULLENUM(a) \
118: do { \
119: if (FORTRANNULLENUM(a)) (a) = PETSC_NULLPTR; \
120: } while (0)
122: #define CHKFORTRANNULLINTEGER(a) \
123: do { \
124: if (FORTRANNULLINTEGER(a) || FORTRANNULLENUM(a)) (a) = PETSC_NULLPTR; \
125: else if (FORTRANNULLDOUBLE(a) || FORTRANNULLSCALAR(a) || FORTRANNULLREAL(a) || FORTRANNULLBOOL(a) || FORTRANNULLFUNCTION(a) || FORTRANNULLCHARACTER(a) || FORTRANNULLMPICOMM(a)) { \
126: *ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, PETSC_ERR_ARG_WRONG, PETSC_ERROR_INITIAL, "Use PETSC_NULL_INTEGER"); \
127: *ierr = PETSC_ERR_ARG_BADPTR; \
128: return; \
129: } \
130: } while (0)
132: #define CHKFORTRANNULLSCALAR(a) \
133: do { \
134: if (FORTRANNULLSCALAR(a)) { \
135: (a) = PETSC_NULLPTR; \
136: } else if (FORTRANNULLINTEGER(a) || FORTRANNULLDOUBLE(a) || FORTRANNULLREAL(a) || FORTRANNULLBOOL(a) || FORTRANNULLFUNCTION(a) || FORTRANNULLCHARACTER(a) || FORTRANNULLMPICOMM(a)) { \
137: *ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, PETSC_ERR_ARG_WRONG, PETSC_ERROR_INITIAL, "Use PETSC_NULL_SCALAR"); \
138: *ierr = PETSC_ERR_ARG_BADPTR; \
139: return; \
140: } \
141: } while (0)
143: #define CHKFORTRANNULLDOUBLE(a) \
144: do { \
145: if (FORTRANNULLDOUBLE(a)) { \
146: (a) = PETSC_NULLPTR; \
147: } else if (FORTRANNULLINTEGER(a) || FORTRANNULLSCALAR(a) || FORTRANNULLREAL(a) || FORTRANNULLBOOL(a) || FORTRANNULLFUNCTION(a) || FORTRANNULLCHARACTER(a) || FORTRANNULLMPICOMM(a)) { \
148: *ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, PETSC_ERR_ARG_WRONG, PETSC_ERROR_INITIAL, "Use PETSC_NULL_DOUBLE"); \
149: *ierr = PETSC_ERR_ARG_BADPTR; \
150: return; \
151: } \
152: } while (0)
154: #define CHKFORTRANNULLREAL(a) \
155: do { \
156: if (FORTRANNULLREAL(a)) { \
157: (a) = PETSC_NULLPTR; \
158: } else if (FORTRANNULLINTEGER(a) || FORTRANNULLDOUBLE(a) || FORTRANNULLSCALAR(a) || FORTRANNULLBOOL(a) || FORTRANNULLFUNCTION(a) || FORTRANNULLCHARACTER(a) || FORTRANNULLMPICOMM(a)) { \
159: *ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, PETSC_ERR_ARG_WRONG, PETSC_ERROR_INITIAL, "Use PETSC_NULL_REAL"); \
160: *ierr = PETSC_ERR_ARG_BADPTR; \
161: return; \
162: } \
163: } while (0)
165: #define CHKFORTRANNULLOBJECT(a) \
166: do { \
167: if (!(*(void **)(a))) { \
168: (a) = PETSC_NULLPTR; \
169: } else if (FORTRANNULLINTEGER(a) || FORTRANNULLDOUBLE(a) || FORTRANNULLSCALAR(a) || FORTRANNULLREAL(a) || FORTRANNULLBOOL(a) || FORTRANNULLFUNCTION(a) || FORTRANNULLCHARACTER(a) || FORTRANNULLMPICOMM(a)) { \
170: *ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, PETSC_ERR_ARG_WRONG, PETSC_ERROR_INITIAL, "Use PETSC_NULL_XXX where XXX is the name of a particular object class"); \
171: *ierr = PETSC_ERR_ARG_BADPTR; \
172: return; \
173: } \
174: } while (0)
176: #define CHKFORTRANNULLBOOL(a) \
177: do { \
178: if (FORTRANNULLBOOL(a)) { \
179: (a) = PETSC_NULLPTR; \
180: } else if (FORTRANNULLSCALAR(a) || FORTRANNULLINTEGER(a) || FORTRANNULLDOUBLE(a) || FORTRANNULLSCALAR(a) || FORTRANNULLREAL(a) || FORTRANNULLFUNCTION(a) || FORTRANNULLCHARACTER(a) || FORTRANNULLMPICOMM(a)) { \
181: *ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, PETSC_ERR_ARG_WRONG, PETSC_ERROR_INITIAL, "Use PETSC_NULL_BOOL"); \
182: *ierr = PETSC_ERR_ARG_BADPTR; \
183: return; \
184: } \
185: } while (0)
187: // Function arguments are code addresses and cannot be dereferenced by FORTRANNULLOBJECT().
188: #define CHKFORTRANNULLFUNCTION(a) \
189: do { \
190: if (FORTRANNULLFUNCTION(a)) { \
191: (a) = PETSC_NULLPTR; \
192: } else if (FORTRANNULLSCALAR(a) || FORTRANNULLDOUBLE(a) || FORTRANNULLREAL(a) || FORTRANNULLINTEGER(a) || FORTRANNULLBOOL(a) || FORTRANNULLCHARACTER(a) || FORTRANNULLMPICOMM(a)) { \
193: *ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, PETSC_ERR_ARG_WRONG, PETSC_ERROR_INITIAL, "Use PETSC_NULL_FUNCTION"); \
194: *ierr = PETSC_ERR_ARG_BADPTR; \
195: return; \
196: } \
197: } while (0)
199: #define CHKFORTRANNULLMPICOMM(a) \
200: do { \
201: if (FORTRANNULLMPICOMM(a)) { \
202: (a) = PETSC_NULLPTR; \
203: } else if (FORTRANNULLINTEGER(a) || FORTRANNULLDOUBLE(a) || FORTRANNULLSCALAR(a) || FORTRANNULLREAL(a) || FORTRANNULLBOOL(a) || FORTRANNULLFUNCTION(a) || FORTRANNULLCHARACTER(a)) { \
204: *ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, PETSC_ERR_ARG_WRONG, PETSC_ERROR_INITIAL, "Use PETSC_NULL_MPI_COMM"); \
205: *ierr = PETSC_ERR_ARG_BADPTR; \
206: return; \
207: } \
208: } while (0)
210: /* In the beginning of Fortran XxxCreate() ensure object is not NULL or already created */
211: #define PETSC_FORTRAN_OBJECT_CREATE(a) \
212: do { \
213: if (!(*(void **)(a))) { \
214: *ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, PETSC_ERR_ARG_WRONG, PETSC_ERROR_INITIAL, "Cannot create PETSC_NULL_XXX object"); \
215: *ierr = PETSC_ERR_ARG_WRONG; \
216: return; \
217: } else if (*((void **)(a)) != PETSC_FORTRAN_TYPE_INITIALIZE && *((void **)(a)) != PETSC_FORTRAN_TYPE_NULL_RETURN) { \
218: *ierr = PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, PETSC_ERR_ARG_WRONG, PETSC_ERROR_INITIAL, "Cannot create already existing object"); \
219: *ierr = PETSC_ERR_ARG_WRONG; \
220: return; \
221: } \
222: } while (0)
224: /*
225: In the beginning of Fortran XxxDestroy(a), if the input object was destroyed, change it to a PETSc C NULL object so that it won't crash C XxxDestory()
226: If it is PETSC_NULL_XXX just return since these objects cannot be destroyed
227: */
228: #define PETSC_FORTRAN_OBJECT_F_DESTROYED_TO_C_NULL(a) \
229: do { \
230: if (!*(void **)(a) || *((void **)(a)) == PETSC_FORTRAN_TYPE_INITIALIZE || *((void **)(a)) == PETSC_FORTRAN_TYPE_NULL_RETURN) { \
231: *ierr = PETSC_SUCCESS; \
232: return; \
233: } \
234: } while (0)
236: /* After C XxxDestroy(a) is called, change a's state from NULL to destroyed, so that it can be used/destroyed again by Fortran.
237: E.g., in VecScatterCreateToAll(x,vscat,seq,ierr), if seq = PETSC_NULL_VEC, PETSc won't create seq. But if seq is a
238: destroyed object (e.g., as a result of a previous Fortran VecDestroy), PETSc will create seq.
239: */
240: #define PETSC_FORTRAN_OBJECT_C_NULL_TO_F_DESTROYED(a) \
241: do { \
242: *((void **)(a)) = PETSC_FORTRAN_TYPE_INITIALIZE; \
243: } while (0)
245: /*
246: Variable type where we stash PETSc object pointers in Fortran.
247: */
248: typedef PETSC_UINTPTR_T PetscFortranAddr;
250: /*
251: These are used to support the default viewers that are
252: created at run time, in C using the , trick.
254: The numbers here must match the numbers in include/petsc/finclude/petscsys.h
255: */
256: #define PETSC_VIEWER_DRAW_WORLD_FORTRAN 4
257: #define PETSC_VIEWER_DRAW_SELF_FORTRAN 5
258: #define PETSC_VIEWER_SOCKET_WORLD_FORTRAN 6
259: #define PETSC_VIEWER_SOCKET_SELF_FORTRAN 7
260: #define PETSC_VIEWER_STDOUT_WORLD_FORTRAN 8
261: #define PETSC_VIEWER_STDOUT_SELF_FORTRAN 9
262: #define PETSC_VIEWER_STDERR_WORLD_FORTRAN 10
263: #define PETSC_VIEWER_STDERR_SELF_FORTRAN 11
264: #define PETSC_VIEWER_BINARY_WORLD_FORTRAN 12
265: #define PETSC_VIEWER_BINARY_SELF_FORTRAN 13
266: #define PETSC_VIEWER_MATLAB_WORLD_FORTRAN 14
267: #define PETSC_VIEWER_MATLAB_SELF_FORTRAN 15
269: static inline PetscViewer PetscPatchDefaultViewers(PetscViewer *v)
270: {
271: if (!v) return PETSC_NULLPTR;
272: if (!(*(void **)v)) return PETSC_NULLPTR;
273: switch (*(PetscFortranAddr *)v) {
274: case PETSC_VIEWER_DRAW_WORLD_FORTRAN:
275: return PETSC_VIEWER_DRAW_WORLD;
276: case PETSC_VIEWER_DRAW_SELF_FORTRAN:
277: return PETSC_VIEWER_DRAW_SELF;
279: case PETSC_VIEWER_STDOUT_WORLD_FORTRAN:
280: return PETSC_VIEWER_STDOUT_WORLD;
281: case PETSC_VIEWER_STDOUT_SELF_FORTRAN:
282: return PETSC_VIEWER_STDOUT_SELF;
284: case PETSC_VIEWER_STDERR_WORLD_FORTRAN:
285: return PETSC_VIEWER_STDERR_WORLD;
286: case PETSC_VIEWER_STDERR_SELF_FORTRAN:
287: return PETSC_VIEWER_STDERR_SELF;
289: case PETSC_VIEWER_BINARY_WORLD_FORTRAN:
290: return PETSC_VIEWER_BINARY_WORLD;
291: case PETSC_VIEWER_BINARY_SELF_FORTRAN:
292: return PETSC_VIEWER_BINARY_SELF;
294: #if PetscDefined(HAVE_MATLAB)
295: case PETSC_VIEWER_MATLAB_SELF_FORTRAN:
296: return PETSC_VIEWER_MATLAB_SELF;
297: case PETSC_VIEWER_MATLAB_WORLD_FORTRAN:
298: return PETSC_VIEWER_MATLAB_WORLD;
299: #endif
301: #if PetscDefined(USE_SOCKET_VIEWER)
302: case PETSC_VIEWER_SOCKET_WORLD_FORTRAN:
303: return PETSC_VIEWER_SOCKET_WORLD;
304: case PETSC_VIEWER_SOCKET_SELF_FORTRAN:
305: return PETSC_VIEWER_SOCKET_SELF;
306: #endif
308: default:
309: return *v;
310: }
311: }
313: #if PetscDefined(USE_SOCKET_VIEWER)
314: #define PetscPatchDefaultViewers_Fortran_Socket(vin, v) \
315: } \
316: else if (*(PetscFortranAddr *)(vin) == PETSC_VIEWER_SOCKET_WORLD_FORTRAN) \
317: { \
318: (v) = PETSC_VIEWER_SOCKET_WORLD; \
319: } \
320: else if (*(PetscFortranAddr *)(vin) == PETSC_VIEWER_SOCKET_SELF_FORTRAN) \
321: { \
322: (v) = PETSC_VIEWER_SOCKET_SELF
323: #else
324: #define PetscPatchDefaultViewers_Fortran_Socket(vin, v)
325: #endif
327: #define PetscPatchDefaultViewers_Fortran(vin, v) \
328: do { \
329: if (*(PetscFortranAddr *)(vin) == PETSC_VIEWER_DRAW_WORLD_FORTRAN) { \
330: (v) = PETSC_VIEWER_DRAW_WORLD; \
331: } else if (*(PetscFortranAddr *)(vin) == PETSC_VIEWER_DRAW_SELF_FORTRAN) { \
332: (v) = PETSC_VIEWER_DRAW_SELF; \
333: } else if (*(PetscFortranAddr *)(vin) == PETSC_VIEWER_STDOUT_WORLD_FORTRAN) { \
334: (v) = PETSC_VIEWER_STDOUT_WORLD; \
335: } else if (*(PetscFortranAddr *)(vin) == PETSC_VIEWER_STDOUT_SELF_FORTRAN) { \
336: (v) = PETSC_VIEWER_STDOUT_SELF; \
337: } else if (*(PetscFortranAddr *)(vin) == PETSC_VIEWER_STDERR_WORLD_FORTRAN) { \
338: (v) = PETSC_VIEWER_STDERR_WORLD; \
339: } else if (*(PetscFortranAddr *)(vin) == PETSC_VIEWER_STDERR_SELF_FORTRAN) { \
340: (v) = PETSC_VIEWER_STDERR_SELF; \
341: } else if (*(PetscFortranAddr *)(vin) == PETSC_VIEWER_BINARY_WORLD_FORTRAN) { \
342: (v) = PETSC_VIEWER_BINARY_WORLD; \
343: } else if (*(PetscFortranAddr *)(vin) == PETSC_VIEWER_BINARY_SELF_FORTRAN) { \
344: (v) = PETSC_VIEWER_BINARY_SELF; \
345: } else if (*(PetscFortranAddr *)(vin) == PETSC_VIEWER_MATLAB_WORLD_FORTRAN) { \
346: (v) = PETSC_VIEWER_BINARY_WORLD; \
347: } else if (*(PetscFortranAddr *)(vin) == PETSC_VIEWER_MATLAB_SELF_FORTRAN) { \
348: (v) = PETSC_VIEWER_BINARY_SELF; \
349: PetscPatchDefaultViewers_Fortran_Socket(vin, v); \
350: } else { \
351: (v) = *(vin); \
352: } \
353: } while (0)
355: /*
356: Allocates enough space to store Fortran function pointers in PETSc object
357: that are needed by the Fortran interface.
358: */
359: #define PetscObjectAllocateFortranPointers(obj, N) \
360: do { \
361: if (!((PetscObject)(obj))->fortran_func_pointers) { \
362: *ierr = PetscCalloc((N) * sizeof(PetscFortranCallbackFn *), &((PetscObject)(obj))->fortran_func_pointers); \
363: if (*ierr) return; \
364: ((PetscObject)(obj))->num_fortran_func_pointers = (N); \
365: } \
366: } while (0)
368: #define PetscCallFortranVoidFunction(...) \
369: do { \
370: PetscErrorCode ierr = PETSC_SUCCESS; \
371: /* the function may or may not access ierr */ \
372: __VA_ARGS__; \
373: PetscCall(ierr); \
374: } while (0)
376: /* Entire function body, _ctx is a "special" variable that can be passed along */
377: #define PetscObjectUseFortranCallback_Private(obj, cid, types, args, cbclass) \
378: do { \
379: void(*func) types, *_ctx; \
380: PetscFunctionBegin; \
381: PetscCall(PetscObjectGetFortranCallback((PetscObject)(obj), (cbclass), (cid), (PetscFortranCallbackFn **)&func, &_ctx)); \
382: if (func) PetscCallFortranVoidFunction((*func)args); \
383: PetscFunctionReturn(PETSC_SUCCESS); \
384: } while (0)
385: #define PetscObjectUseFortranCallback(obj, cid, types, args) PetscObjectUseFortranCallback_Private(obj, cid, types, args, PETSC_FORTRAN_CALLBACK_CLASS)
386: #define PetscObjectUseFortranCallbackSubType(obj, cid, types, args) PetscObjectUseFortranCallback_Private(obj, cid, types, args, PETSC_FORTRAN_CALLBACK_SUBTYPE)
388: /* Disable deprecation warnings while building Fortran wrappers */
389: #undef PETSC_DEPRECATED_OBJECT
390: #define PETSC_DEPRECATED_OBJECT(...)
391: #undef PETSC_DEPRECATED_FUNCTION
392: #define PETSC_DEPRECATED_FUNCTION(...)
393: #undef PETSC_DEPRECATED_ENUM
394: #define PETSC_DEPRECATED_ENUM(...)
395: #undef PETSC_DEPRECATED_TYPEDEF
396: #define PETSC_DEPRECATED_TYPEDEF(...)
397: #undef PETSC_DEPRECATED_MACRO
398: #define PETSC_DEPRECATED_MACRO(...)
400: /* PGI compilers pass in f90 pointers as 2 arguments */
401: #if PetscDefined(HAVE_F90_2PTR_ARG)
402: #define PETSC_F90_2PTR_PROTO_NOVAR , void *
403: #define PETSC_F90_2PTR_PROTO(ptr) , void *ptr
404: #define PETSC_F90_2PTR_PARAM(ptr) , ptr
405: #else
406: #define PETSC_F90_2PTR_PROTO_NOVAR
407: #define PETSC_F90_2PTR_PROTO(ptr)
408: #define PETSC_F90_2PTR_PARAM(ptr)
409: #endif
411: typedef struct {
412: char dummy;
413: } F90Array1d;
414: typedef struct {
415: char dummy;
416: } F90Array2d;
417: typedef struct {
418: char dummy;
419: } F90Array3d;
420: typedef struct {
421: char dummy;
422: } F90Array4d;
424: PETSC_EXTERN PetscErrorCode F90Array1dCreate(void *, MPI_Datatype, PetscInt, PetscInt, F90Array1d *PETSC_F90_2PTR_PROTO_NOVAR);
425: PETSC_EXTERN PetscErrorCode F90Array1dAccess(F90Array1d *, MPI_Datatype, void **PETSC_F90_2PTR_PROTO_NOVAR);
426: PETSC_EXTERN PetscErrorCode F90Array1dDestroy(F90Array1d *, MPI_Datatype PETSC_F90_2PTR_PROTO_NOVAR);
428: /* Fortran routine that nullifies a Fortran pointer array of addresses, for stubs that must return an unassociated array */
429: #if PetscDefined(HAVE_FORTRAN_CAPS)
430: #define f90array1ddestroyfortranaddr_ F90ARRAY1DDESTROYFORTRANADDR
431: #elif !PetscDefined(HAVE_FORTRAN_UNDERSCORE)
432: #define f90array1ddestroyfortranaddr_ f90array1ddestroyfortranaddr
433: #endif
434: PETSC_EXTERN void f90array1ddestroyfortranaddr_(F90Array1d *PETSC_F90_2PTR_PROTO_NOVAR);
436: PETSC_EXTERN PetscErrorCode F90Array2dCreate(void *, MPI_Datatype, PetscInt, PetscInt, PetscInt, PetscInt, F90Array2d *PETSC_F90_2PTR_PROTO_NOVAR);
437: PETSC_EXTERN PetscErrorCode F90Array2dAccess(F90Array2d *, MPI_Datatype, void **PETSC_F90_2PTR_PROTO_NOVAR);
438: PETSC_EXTERN PetscErrorCode F90Array2dDestroy(F90Array2d *, MPI_Datatype PETSC_F90_2PTR_PROTO_NOVAR);
440: PETSC_EXTERN PetscErrorCode F90Array3dCreate(void *, MPI_Datatype, PetscInt, PetscInt, PetscInt, PetscInt, PetscInt, PetscInt, F90Array3d *PETSC_F90_2PTR_PROTO_NOVAR);
441: PETSC_EXTERN PetscErrorCode F90Array3dAccess(F90Array3d *, MPI_Datatype, void **PETSC_F90_2PTR_PROTO_NOVAR);
442: PETSC_EXTERN PetscErrorCode F90Array3dDestroy(F90Array3d *, MPI_Datatype PETSC_F90_2PTR_PROTO_NOVAR);
444: PETSC_EXTERN PetscErrorCode F90Array4dCreate(void *, MPI_Datatype, PetscInt, PetscInt, PetscInt, PetscInt, PetscInt, PetscInt, PetscInt, PetscInt, F90Array4d *PETSC_F90_2PTR_PROTO_NOVAR);
445: PETSC_EXTERN PetscErrorCode F90Array4dAccess(F90Array4d *, MPI_Datatype, void **PETSC_F90_2PTR_PROTO_NOVAR);
446: PETSC_EXTERN PetscErrorCode F90Array4dDestroy(F90Array4d *, MPI_Datatype PETSC_F90_2PTR_PROTO_NOVAR);
448: /*
449: F90Array1dCreate - Given a C pointer to a one dimensional
450: array and its length; this fills in the appropriate Fortran 90
451: pointer data structure.
453: Input Parameters:
454: + array - regular C pointer (address)
455: . type - DataType of the array
456: . start - starting index of the array
457: - len - length of array (in items)
459: Output Parameter:
460: . ptr - Fortran 90 pointer
461: */