xref: /petsc/src/sys/objects/ftn-custom/zstart.c (revision dfef5ea798a36ccc664ca1bbe435d183ec21e5c1)
1ba9a049bSBarry Smith /*
2ba9a049bSBarry Smith   This file contains Fortran stubs for PetscInitialize and Finalize.
3ba9a049bSBarry Smith */
4ba9a049bSBarry Smith 
5ba9a049bSBarry Smith /*
6ba9a049bSBarry Smith     This is to prevent the Cray T3D version of MPI (University of Edinburgh)
7ba9a049bSBarry Smith   from stupidly redefining MPI_INIT(). They put this in to detect errors
8ba9a049bSBarry Smith   in C code,but here I do want to be calling the Fortran version from a
9ba9a049bSBarry Smith   C subroutine.
10ba9a049bSBarry Smith */
11ba9a049bSBarry Smith #define T3DMPI_FORTRAN
12ba9a049bSBarry Smith #define T3EMPI_FORTRAN
13ba9a049bSBarry Smith 
14af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
15ba9a049bSBarry Smith 
16519f805aSKarl Rupp #if defined(PETSC_HAVE_FORTRAN_CAPS)
175906a408SBlaise Bourdin   #define petscinitializef_          PETSCINITIALIZEF
18ba9a049bSBarry Smith   #define petscfinalize_             PETSCFINALIZE
19ba9a049bSBarry Smith   #define petscend_                  PETSCEND
20ba9a049bSBarry Smith   #define iargc_                     IARGC
21ba9a049bSBarry Smith   #define getarg_                    GETARG
22ba9a049bSBarry Smith   #define mpi_init_                  MPI_INIT
235ea309f3SBarry Smith   #define petscgetcomm_              PETSCGETCOMM
24541b5888SSatish Balay   #define petsccommandargumentcount_ PETSCCOMMANDARGUMENTCOUNT
25541b5888SSatish Balay   #define petscgetcommandargument_   PETSCGETCOMMANDARGUMENT
26ba9a049bSBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
275906a408SBlaise Bourdin   #define petscinitializef_          petscinitializef
28ba9a049bSBarry Smith   #define petscfinalize_             petscfinalize
29ba9a049bSBarry Smith   #define petscend_                  petscend
30ba9a049bSBarry Smith   #define mpi_init_                  mpi_init
31ba9a049bSBarry Smith   #define iargc_                     iargc
32ba9a049bSBarry Smith   #define getarg_                    getarg
335ea309f3SBarry Smith   #define petscgetcomm_              petscgetcomm
34541b5888SSatish Balay   #define petsccommandargumentcount_ petsccommandargumentcount
35541b5888SSatish Balay   #define petscgetcommandargument_   petscgetcommandargument
36ba9a049bSBarry Smith #endif
37ba9a049bSBarry Smith 
38ba9a049bSBarry Smith #if defined(PETSC_HAVE_NAGF90)
39ba9a049bSBarry Smith   #undef iargc_
40ba9a049bSBarry Smith   #undef getarg_
41ba9a049bSBarry Smith   #define iargc_  f90_unix_MP_iargc
42ba9a049bSBarry Smith   #define getarg_ f90_unix_MP_getarg
43ba9a049bSBarry Smith #endif
44ba9a049bSBarry Smith #if defined(PETSC_USE_NARGS) /* Digital Fortran */
45ba9a049bSBarry Smith   #undef iargc_
46ba9a049bSBarry Smith   #undef getarg_
47ba9a049bSBarry Smith   #define iargc_  NARGS
48ba9a049bSBarry Smith   #define getarg_ GETARG
49dd01b7e5SBarry Smith #elif defined(PETSC_HAVE_PXFGETARG_NEW) /* Cray X1 */
50ba9a049bSBarry Smith   #undef iargc_
51ba9a049bSBarry Smith   #undef getarg_
52ba9a049bSBarry Smith   #define iargc_  ipxfargc_
53ba9a049bSBarry Smith   #define getarg_ pxfgetarg_
54ba9a049bSBarry Smith #endif
55541b5888SSatish Balay 
56541b5888SSatish Balay #if defined(PETSC_HAVE_FORTRAN_GET_COMMAND_ARGUMENT) /* Fortran 2003 */
57541b5888SSatish Balay   #undef iargc_
58541b5888SSatish Balay   #undef getarg_
59541b5888SSatish Balay   #define iargc_  petsccommandargumentcount_
60541b5888SSatish Balay   #define getarg_ petscgetcommandargument_
61ba9a049bSBarry Smith #elif defined(PETSC_HAVE_BGL_IARGC) /* bgl g77 has different external & internal name mangling */
62ba9a049bSBarry Smith   #undef iargc_
63ba9a049bSBarry Smith   #undef getarg_
64ba9a049bSBarry Smith   #define iargc  iargc_
65ba9a049bSBarry Smith   #define getarg getarg_
66ba9a049bSBarry Smith #endif
67ba9a049bSBarry Smith 
68ba9a049bSBarry Smith /*
69ba9a049bSBarry Smith     The extra _ is because the f2c compiler puts an
70ba9a049bSBarry Smith   extra _ at the end if the original routine name
71ba9a049bSBarry Smith   contained any _.
72ba9a049bSBarry Smith */
73ba9a049bSBarry Smith #if defined(PETSC_HAVE_FORTRAN_UNDERSCORE_UNDERSCORE)
74ba9a049bSBarry Smith   #define mpi_init_ mpi_init__
75ba9a049bSBarry Smith #endif
76ba9a049bSBarry Smith 
77a7b85bbcSSatish Balay #if defined(PETSC_HAVE_MPIUNI)
78a7b85bbcSSatish Balay   #if defined(mpi_init_)
79a7b85bbcSSatish Balay     #undef mpi_init_
80a7b85bbcSSatish Balay     #if defined(PETSC_HAVE_FORTRAN_CAPS)
81a7b85bbcSSatish Balay       #define mpi_init_ PETSC_MPI_INIT
82a7b85bbcSSatish Balay     #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
83a7b85bbcSSatish Balay       #define mpi_init_ petsc_mpi_init
84a7b85bbcSSatish Balay     #elif defined(PETSC_HAVE_FORTRAN_UNDERSCORE_UNDERSCORE)
85a7b85bbcSSatish Balay       #define mpi_init_ petsc_mpi_init__
86a7b85bbcSSatish Balay     #endif
87a7b85bbcSSatish Balay   #else /* mpi_init_ */
88a7b85bbcSSatish Balay     #define mpi_init_ petsc_mpi_init_
89a7b85bbcSSatish Balay   #endif /* mpi_init_ */
90a7b85bbcSSatish Balay #endif   /* PETSC_HAVE_MPIUNI */
91a7b85bbcSSatish Balay 
9219caf8f3SSatish Balay PETSC_EXTERN void mpi_init_(int *);
9319caf8f3SSatish Balay PETSC_EXTERN void petscgetcomm_(PetscMPIInt *);
94ba9a049bSBarry Smith 
95ba9a049bSBarry Smith /*
96ba9a049bSBarry Smith      Different Fortran compilers handle command lines in different ways
97ba9a049bSBarry Smith */
98541b5888SSatish Balay #if defined(PETSC_HAVE_FORTRAN_GET_COMMAND_ARGUMENT) /* Fortran 2003  - same as 'else' case */
99a30ec4eaSSatish Balay PETSC_EXTERN int  iargc_(void);
100541b5888SSatish Balay PETSC_EXTERN void getarg_(int *, char *, int);
101541b5888SSatish Balay #elif defined(PETSC_USE_NARGS)
1023274405dSPierre Jolivet PETSC_EXTERN short __stdcall NARGS(void);
1038cc058d9SJed Brown PETSC_EXTERN void __stdcall GETARG(short *, char *, int, short *);
104ba9a049bSBarry Smith 
105ba9a049bSBarry Smith #elif defined(PETSC_HAVE_PXFGETARG_NEW)
1063274405dSPierre Jolivet PETSC_EXTERN int  iargc_(void);
1078cc058d9SJed Brown PETSC_EXTERN void getarg_(int *, char *, int *, int *, int);
108ba9a049bSBarry Smith 
109ba9a049bSBarry Smith #else
1103274405dSPierre Jolivet PETSC_EXTERN int  iargc_(void);
1118cc058d9SJed Brown PETSC_EXTERN void getarg_(int *, char *, int);
112ba9a049bSBarry Smith   /*
113ba9a049bSBarry Smith       The Cray T3D/T3E use the PXFGETARG() function
114ba9a049bSBarry Smith */
115ba9a049bSBarry Smith   #if defined(PETSC_HAVE_PXFGETARG)
1168cc058d9SJed Brown PETSC_EXTERN void PXFGETARG(int *, _fcd, int *, int *);
117ba9a049bSBarry Smith   #endif
118ba9a049bSBarry Smith #endif
119ba9a049bSBarry Smith 
120071fcb05SBarry Smith PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **);
12195c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]);
12295c0884eSLisandro Dalcin PETSC_INTERN int            PetscGlobalArgc;
12395c0884eSLisandro Dalcin PETSC_INTERN char         **PetscGlobalArgs;
124ba9a049bSBarry Smith 
125ba9a049bSBarry Smith /*
126a5b23f4aSJose E. Roman     Reads in Fortran command line arguments and sends them to
127d5be86a5SBarry Smith   all processors.
128ba9a049bSBarry Smith */
129ba9a049bSBarry Smith 
130ba9a049bSBarry Smith PetscErrorCode PETScParseFortranArgs_Private(int *argc, char ***argv)
131ba9a049bSBarry Smith {
132ba9a049bSBarry Smith #if defined(PETSC_USE_NARGS)
133ba9a049bSBarry Smith   short i, flg;
134ba9a049bSBarry Smith #else
135ba9a049bSBarry Smith   int i;
136ba9a049bSBarry Smith #endif
137ba9a049bSBarry Smith   int         warg = 256;
138ba9a049bSBarry Smith   PetscMPIInt rank;
139ba9a049bSBarry Smith   char       *p;
140ba9a049bSBarry Smith 
1419566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
142dd400576SPatrick Sanan   if (rank == 0) {
143ba9a049bSBarry Smith #if defined(PETSC_HAVE_IARG_COUNT_PROGNAME)
144ba9a049bSBarry Smith     *argc = iargc_();
145ba9a049bSBarry Smith #else
146ba9a049bSBarry Smith     /* most compilers do not count the program name for argv[0] */
147ba9a049bSBarry Smith     *argc = 1 + iargc_();
148ba9a049bSBarry Smith #endif
149ba9a049bSBarry Smith   }
1509566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(argc, 1, MPI_INT, 0, PETSC_COMM_WORLD));
151ba9a049bSBarry Smith 
152ba9a049bSBarry Smith   /* PetscTrMalloc() not yet set, so don't use PetscMalloc() */
153*dfef5ea7SSatish Balay   PetscCall(PetscMallocAlign((*argc + 1) * (warg * sizeof(char) + sizeof(char *)), PETSC_FALSE, 0, NULL, NULL, (void **)argv));
154ba9a049bSBarry Smith   (*argv)[0] = (char *)(*argv + *argc + 1);
155ba9a049bSBarry Smith 
156dd400576SPatrick Sanan   if (rank == 0) {
1579566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((*argv)[0], (*argc) * warg * sizeof(char)));
158ba9a049bSBarry Smith     for (i = 0; i < *argc; i++) {
159ba9a049bSBarry Smith       (*argv)[i + 1] = (*argv)[i] + warg;
160541b5888SSatish Balay #if defined(PETSC_HAVE_FORTRAN_GET_COMMAND_ARGUMENT) /* same as 'else' case */
161541b5888SSatish Balay       getarg_(&i, (*argv)[i], warg);
162541b5888SSatish Balay #elif defined(PETSC_HAVE_PXFGETARG_NEW)
1633ba16761SJacob Faibussowitsch       {
1643ba16761SJacob Faibussowitsch         char *tmp = (*argv)[i];
165ba9a049bSBarry Smith         int   ilen;
1669566063dSJacob Faibussowitsch         PetscCallFortranVoidFunction(getarg_(&i, tmp, &ilen, &ierr, warg));
1673ba16761SJacob Faibussowitsch         tmp[ilen] = 0;
1683ba16761SJacob Faibussowitsch       }
169ba9a049bSBarry Smith #elif defined(PETSC_USE_NARGS)
170ba9a049bSBarry Smith       GETARG(&i, (*argv)[i], warg, &flg);
171ba9a049bSBarry Smith #else
172ba9a049bSBarry Smith       getarg_(&i, (*argv)[i], warg);
173ba9a049bSBarry Smith #endif
174ba9a049bSBarry Smith       /* zero out garbage at end of each argument */
175ba9a049bSBarry Smith       p = (*argv)[i] + warg - 1;
176ba9a049bSBarry Smith       while (p > (*argv)[i]) {
177ba9a049bSBarry Smith         if (*p == ' ') *p = 0;
178ba9a049bSBarry Smith         p--;
179ba9a049bSBarry Smith       }
180ba9a049bSBarry Smith     }
181ba9a049bSBarry Smith   }
1829566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast((*argv)[0], *argc * warg, MPI_CHAR, 0, PETSC_COMM_WORLD));
183ba9a049bSBarry Smith   if (rank) {
184a297a907SKarl Rupp     for (i = 0; i < *argc; i++) (*argv)[i + 1] = (*argv)[i] + warg;
185ba9a049bSBarry Smith   }
1863ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
187ba9a049bSBarry Smith }
188ba9a049bSBarry Smith 
189ba9a049bSBarry Smith /* -----------------------------------------------------------------------------------------------*/
190ba9a049bSBarry Smith 
1913274405dSPierre Jolivet PETSC_INTERN PetscErrorCode PetscPreMPIInit_Private(void);
1927f20dbc5SBarry Smith 
19385649d77SJunchao Zhang PETSC_INTERN PetscErrorCode PetscInitFortran_Private(PetscBool readarguments, const char *filename, PetscInt len)
19485649d77SJunchao Zhang {
19585649d77SJunchao Zhang   char *tmp = NULL;
19685649d77SJunchao Zhang 
19785649d77SJunchao Zhang   PetscFunctionBegin;
1989566063dSJacob Faibussowitsch   PetscCall(PetscInitializeFortran());
19985649d77SJunchao Zhang   if (readarguments) {
2009566063dSJacob Faibussowitsch     PetscCall(PETScParseFortranArgs_Private(&PetscGlobalArgc, &PetscGlobalArgs));
20185649d77SJunchao Zhang     if (filename != PETSC_NULL_CHARACTER_Fortran) { /* FIXCHAR */
20285649d77SJunchao Zhang       while ((len > 0) && (filename[len - 1] == ' ')) len--;
2039566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(len + 1, &tmp));
2049566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(tmp, filename, len + 1));
20585649d77SJunchao Zhang     }
2069566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInsert(NULL, &PetscGlobalArgc, &PetscGlobalArgs, tmp));
2079566063dSJacob Faibussowitsch     PetscCall(PetscFree(tmp)); /* FREECHAR */
20885649d77SJunchao Zhang   }
2093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21085649d77SJunchao Zhang }
21185649d77SJunchao Zhang 
212ba9a049bSBarry Smith /*
213ba9a049bSBarry Smith     petscinitialize - Version called from Fortran.
214ba9a049bSBarry Smith 
215811af0c4SBarry Smith     Note:
216ba9a049bSBarry Smith       Since this is called from Fortran it does not return error codes
217ba9a049bSBarry Smith 
218ba9a049bSBarry Smith */
2195906a408SBlaise Bourdin PETSC_EXTERN void petscinitializef_(char *filename, char *help, PetscBool *readarguments, PetscErrorCode *ierr, PETSC_FORTRAN_CHARLEN_T len, PETSC_FORTRAN_CHARLEN_T helplen)
220ba9a049bSBarry Smith {
2214b60c348SBarry Smith   int j, i;
222ba9a049bSBarry Smith #if defined(PETSC_USE_NARGS)
2234b60c348SBarry Smith   short flg;
224ba9a049bSBarry Smith #endif
225ba9a049bSBarry Smith   int         flag;
22685649d77SJunchao Zhang   char        name[256] = {0};
227ba9a049bSBarry Smith   PetscMPIInt f_petsc_comm_world;
228ba9a049bSBarry Smith 
2293ba16761SJacob Faibussowitsch   *ierr = PETSC_SUCCESS;
2303ba16761SJacob Faibussowitsch   if (PetscInitializeCalled) return;
231ba9a049bSBarry Smith   i = 0;
232541b5888SSatish Balay #if defined(PETSC_HAVE_FORTRAN_GET_COMMAND_ARGUMENT) /* same as 'else' case */
2334b60c348SBarry Smith   getarg_(&i, name, sizeof(name));
234541b5888SSatish Balay #elif defined(PETSC_HAVE_PXFGETARG_NEW)
2353ba16761SJacob Faibussowitsch   {
2363ba16761SJacob Faibussowitsch     int ilen, sierr;
237ba9a049bSBarry Smith     getarg_(&i, name, &ilen, &sierr, 256);
2383ba16761SJacob Faibussowitsch     if (sierr) {
2393ba16761SJacob Faibussowitsch       *ierr = PetscStrncpy(name, "Unknown Name", 256);
2403ba16761SJacob Faibussowitsch       if (*ierr) return;
2413ba16761SJacob Faibussowitsch     } else name[ilen] = 0;
242ba9a049bSBarry Smith   }
243ba9a049bSBarry Smith #elif defined(PETSC_USE_NARGS)
244ba9a049bSBarry Smith   GETARG(&i, name, 256, &flg);
245ba9a049bSBarry Smith #else
246ba9a049bSBarry Smith   getarg_(&i, name, 256);
2474b60c348SBarry Smith #endif
248ba9a049bSBarry Smith   /* Eliminate spaces at the end of the string */
2499350f85dSSatish Balay   for (j = sizeof(name) - 2; j >= 0; j--) {
250ba9a049bSBarry Smith     if (name[j] != ' ') {
251ba9a049bSBarry Smith       name[j + 1] = 0;
252ba9a049bSBarry Smith       break;
253ba9a049bSBarry Smith     }
254ba9a049bSBarry Smith   }
2553ba16761SJacob Faibussowitsch   if (j < 0) {
2563ba16761SJacob Faibussowitsch     *ierr = PetscStrncpy(name, "Unknown Name", 256);
2573ba16761SJacob Faibussowitsch     if (*ierr) return;
2583ba16761SJacob Faibussowitsch   }
259ba9a049bSBarry Smith 
260dd01b7e5SBarry Smith   /* check if PETSC_COMM_WORLD is initialized by the user in Fortran */
2615ea309f3SBarry Smith   petscgetcomm_(&f_petsc_comm_world);
262ba9a049bSBarry Smith   MPI_Initialized(&flag);
263ba9a049bSBarry Smith   if (!flag) {
264ba9a049bSBarry Smith     PetscMPIInt mierr;
265ba9a049bSBarry Smith 
2663ba16761SJacob Faibussowitsch     if (f_petsc_comm_world) {
2673ba16761SJacob Faibussowitsch       *ierr = (*PetscErrorPrintf)("You cannot set PETSC_COMM_WORLD if you have not initialized MPI first\n");
2683ba16761SJacob Faibussowitsch       return;
2693ba16761SJacob Faibussowitsch     }
2704dfee713SSatish Balay 
2713ba16761SJacob Faibussowitsch     *ierr = PetscPreMPIInit_Private();
2723ba16761SJacob Faibussowitsch     if (*ierr) return;
273ba9a049bSBarry Smith     mpi_init_(&mierr);
274ba9a049bSBarry Smith     if (mierr) {
2753ba16761SJacob Faibussowitsch       *ierr = (*PetscErrorPrintf)("PetscInitialize: Calling Fortran MPI_Init()\n");
2763ba16761SJacob Faibussowitsch       *ierr = (PetscErrorCode)mierr;
277ba9a049bSBarry Smith       return;
278ba9a049bSBarry Smith     }
279ba9a049bSBarry Smith     PetscBeganMPI = PETSC_TRUE;
280ba9a049bSBarry Smith   }
281a297a907SKarl Rupp   if (f_petsc_comm_world) PETSC_COMM_WORLD = MPI_Comm_f2c(*(MPI_Fint *)&f_petsc_comm_world); /* User called MPI_INITIALIZE() and changed PETSC_COMM_WORLD */
282a297a907SKarl Rupp   else PETSC_COMM_WORLD = MPI_COMM_WORLD;
283ba9a049bSBarry Smith 
28485649d77SJunchao Zhang   *ierr = PetscInitialize_Common(name, filename, help, PETSC_TRUE, *readarguments, (PetscInt)len);
2853ba16761SJacob Faibussowitsch   if (*ierr) {
2863ba16761SJacob Faibussowitsch     (void)(*PetscErrorPrintf)("PetscInitialize:PetscInitialize_Common\n");
2873ba16761SJacob Faibussowitsch     return;
2883ba16761SJacob Faibussowitsch   }
289ba9a049bSBarry Smith }
290ba9a049bSBarry Smith 
29119caf8f3SSatish Balay PETSC_EXTERN void petscfinalize_(PetscErrorCode *ierr)
292ba9a049bSBarry Smith {
293ba9a049bSBarry Smith   /* was malloced with PetscMallocAlign() so free the same way */
294*dfef5ea7SSatish Balay   *ierr = PetscFreeAlign(PetscGlobalArgs, 0, NULL, NULL);
2953ba16761SJacob Faibussowitsch   if (*ierr) {
2963ba16761SJacob Faibussowitsch     (void)(*PetscErrorPrintf)("PetscFinalize:Freeing args\n");
2973ba16761SJacob Faibussowitsch     return;
2983ba16761SJacob Faibussowitsch   }
299ba9a049bSBarry Smith 
300ba9a049bSBarry Smith   *ierr = PetscFinalize();
301ba9a049bSBarry Smith }
302ba9a049bSBarry Smith 
30319caf8f3SSatish Balay PETSC_EXTERN void petscend_(PetscErrorCode *ierr)
304ba9a049bSBarry Smith {
305ba9a049bSBarry Smith   *ierr = PetscEnd();
306ba9a049bSBarry Smith }
307