xref: /petsc/src/sys/objects/ftn-custom/zstart.c (revision 8d35c829922277702c93cc5b553e535e652a80df)
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 mpi_init_                  MPI_INIT
215ea309f3SBarry Smith   #define petscgetcomm_              PETSCGETCOMM
22541b5888SSatish Balay   #define petsccommandargumentcount_ PETSCCOMMANDARGUMENTCOUNT
23541b5888SSatish Balay   #define petscgetcommandargument_   PETSCGETCOMMANDARGUMENT
24ba9a049bSBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
255906a408SBlaise Bourdin   #define petscinitializef_          petscinitializef
26ba9a049bSBarry Smith   #define petscfinalize_             petscfinalize
27ba9a049bSBarry Smith   #define petscend_                  petscend
28ba9a049bSBarry Smith   #define mpi_init_                  mpi_init
295ea309f3SBarry Smith   #define petscgetcomm_              petscgetcomm
30541b5888SSatish Balay   #define petsccommandargumentcount_ petsccommandargumentcount
31541b5888SSatish Balay   #define petscgetcommandargument_   petscgetcommandargument
32ba9a049bSBarry Smith #endif
33ba9a049bSBarry Smith 
34ba9a049bSBarry Smith /*
35ba9a049bSBarry Smith     The extra _ is because the f2c compiler puts an
36ba9a049bSBarry Smith   extra _ at the end if the original routine name
37ba9a049bSBarry Smith   contained any _.
38ba9a049bSBarry Smith */
39ba9a049bSBarry Smith #if defined(PETSC_HAVE_FORTRAN_UNDERSCORE_UNDERSCORE)
40ba9a049bSBarry Smith   #define mpi_init_ mpi_init__
41ba9a049bSBarry Smith #endif
42ba9a049bSBarry Smith 
43a7b85bbcSSatish Balay #if defined(PETSC_HAVE_MPIUNI)
44a7b85bbcSSatish Balay   #if defined(mpi_init_)
45a7b85bbcSSatish Balay     #undef mpi_init_
46a7b85bbcSSatish Balay     #if defined(PETSC_HAVE_FORTRAN_CAPS)
47a7b85bbcSSatish Balay       #define mpi_init_ PETSC_MPI_INIT
48a7b85bbcSSatish Balay     #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
49a7b85bbcSSatish Balay       #define mpi_init_ petsc_mpi_init
50a7b85bbcSSatish Balay     #elif defined(PETSC_HAVE_FORTRAN_UNDERSCORE_UNDERSCORE)
51a7b85bbcSSatish Balay       #define mpi_init_ petsc_mpi_init__
52a7b85bbcSSatish Balay     #endif
53a7b85bbcSSatish Balay   #else /* mpi_init_ */
54a7b85bbcSSatish Balay     #define mpi_init_ petsc_mpi_init_
55a7b85bbcSSatish Balay   #endif /* mpi_init_ */
56a7b85bbcSSatish Balay #endif   /* PETSC_HAVE_MPIUNI */
57a7b85bbcSSatish Balay 
5819caf8f3SSatish Balay PETSC_EXTERN void mpi_init_(int *);
5919caf8f3SSatish Balay PETSC_EXTERN void petscgetcomm_(PetscMPIInt *);
60ba9a049bSBarry Smith 
61ba9a049bSBarry Smith /*
62ba9a049bSBarry Smith      Different Fortran compilers handle command lines in different ways
63ba9a049bSBarry Smith */
64*8d35c829SSatish Balay PETSC_EXTERN int            petsccommandargumentcount_(void);
65*8d35c829SSatish Balay PETSC_EXTERN void           petscgetcommandargument_(int *, char *, PETSC_FORTRAN_CHARLEN_T);
66071fcb05SBarry Smith PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **);
6795c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]);
6895c0884eSLisandro Dalcin PETSC_INTERN int            PetscGlobalArgc;
6995c0884eSLisandro Dalcin PETSC_INTERN char         **PetscGlobalArgs;
70ba9a049bSBarry Smith 
71ba9a049bSBarry Smith /*
72a5b23f4aSJose E. Roman     Reads in Fortran command line arguments and sends them to
73d5be86a5SBarry Smith   all processors.
74ba9a049bSBarry Smith */
75ba9a049bSBarry Smith 
76ba9a049bSBarry Smith PetscErrorCode PETScParseFortranArgs_Private(int *argc, char ***argv)
77ba9a049bSBarry Smith {
78ba9a049bSBarry Smith   int         i;
79ba9a049bSBarry Smith   int         warg = 256;
80ba9a049bSBarry Smith   PetscMPIInt rank;
81ba9a049bSBarry Smith   char       *p;
82ba9a049bSBarry Smith 
839566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
84*8d35c829SSatish Balay   if (rank == 0) { *argc = 1 + petsccommandargumentcount_(); }
859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(argc, 1, MPI_INT, 0, PETSC_COMM_WORLD));
86ba9a049bSBarry Smith 
87ba9a049bSBarry Smith   /* PetscTrMalloc() not yet set, so don't use PetscMalloc() */
88dfef5ea7SSatish Balay   PetscCall(PetscMallocAlign((*argc + 1) * (warg * sizeof(char) + sizeof(char *)), PETSC_FALSE, 0, NULL, NULL, (void **)argv));
89ba9a049bSBarry Smith   (*argv)[0] = (char *)(*argv + *argc + 1);
90ba9a049bSBarry Smith 
91dd400576SPatrick Sanan   if (rank == 0) {
929566063dSJacob Faibussowitsch     PetscCall(PetscMemzero((*argv)[0], (*argc) * warg * sizeof(char)));
93ba9a049bSBarry Smith     for (i = 0; i < *argc; i++) {
94ba9a049bSBarry Smith       (*argv)[i + 1] = (*argv)[i] + warg;
95*8d35c829SSatish Balay       petscgetcommandargument_(&i, (*argv)[i], warg);
96ba9a049bSBarry Smith       /* zero out garbage at end of each argument */
97ba9a049bSBarry Smith       p = (*argv)[i] + warg - 1;
98ba9a049bSBarry Smith       while (p > (*argv)[i]) {
99ba9a049bSBarry Smith         if (*p == ' ') *p = 0;
100ba9a049bSBarry Smith         p--;
101ba9a049bSBarry Smith       }
102ba9a049bSBarry Smith     }
103ba9a049bSBarry Smith   }
1049566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast((*argv)[0], *argc * warg, MPI_CHAR, 0, PETSC_COMM_WORLD));
105ba9a049bSBarry Smith   if (rank) {
106a297a907SKarl Rupp     for (i = 0; i < *argc; i++) (*argv)[i + 1] = (*argv)[i] + warg;
107ba9a049bSBarry Smith   }
1083ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
109ba9a049bSBarry Smith }
110ba9a049bSBarry Smith 
111ba9a049bSBarry Smith /* -----------------------------------------------------------------------------------------------*/
112ba9a049bSBarry Smith 
1133274405dSPierre Jolivet PETSC_INTERN PetscErrorCode PetscPreMPIInit_Private(void);
1147f20dbc5SBarry Smith 
11585649d77SJunchao Zhang PETSC_INTERN PetscErrorCode PetscInitFortran_Private(PetscBool readarguments, const char *filename, PetscInt len)
11685649d77SJunchao Zhang {
11785649d77SJunchao Zhang   char *tmp = NULL;
11885649d77SJunchao Zhang 
11985649d77SJunchao Zhang   PetscFunctionBegin;
1209566063dSJacob Faibussowitsch   PetscCall(PetscInitializeFortran());
12185649d77SJunchao Zhang   if (readarguments) {
1229566063dSJacob Faibussowitsch     PetscCall(PETScParseFortranArgs_Private(&PetscGlobalArgc, &PetscGlobalArgs));
12385649d77SJunchao Zhang     if (filename != PETSC_NULL_CHARACTER_Fortran) { /* FIXCHAR */
12485649d77SJunchao Zhang       while ((len > 0) && (filename[len - 1] == ' ')) len--;
1259566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(len + 1, &tmp));
1269566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(tmp, filename, len + 1));
12785649d77SJunchao Zhang     }
1289566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInsert(NULL, &PetscGlobalArgc, &PetscGlobalArgs, tmp));
1299566063dSJacob Faibussowitsch     PetscCall(PetscFree(tmp)); /* FREECHAR */
13085649d77SJunchao Zhang   }
1313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13285649d77SJunchao Zhang }
13385649d77SJunchao Zhang 
134ba9a049bSBarry Smith /*
135ba9a049bSBarry Smith     petscinitialize - Version called from Fortran.
136ba9a049bSBarry Smith 
137811af0c4SBarry Smith     Note:
138ba9a049bSBarry Smith       Since this is called from Fortran it does not return error codes
139ba9a049bSBarry Smith 
140ba9a049bSBarry Smith */
1415906a408SBlaise Bourdin PETSC_EXTERN void petscinitializef_(char *filename, char *help, PetscBool *readarguments, PetscErrorCode *ierr, PETSC_FORTRAN_CHARLEN_T len, PETSC_FORTRAN_CHARLEN_T helplen)
142ba9a049bSBarry Smith {
1434b60c348SBarry Smith   int         j, i;
144ba9a049bSBarry Smith   int         flag;
14585649d77SJunchao Zhang   char        name[256] = {0};
146ba9a049bSBarry Smith   PetscMPIInt f_petsc_comm_world;
147ba9a049bSBarry Smith 
1483ba16761SJacob Faibussowitsch   *ierr = PETSC_SUCCESS;
1493ba16761SJacob Faibussowitsch   if (PetscInitializeCalled) return;
150ba9a049bSBarry Smith   i = 0;
151*8d35c829SSatish Balay   petscgetcommandargument_(&i, name, sizeof(name));
152ba9a049bSBarry Smith   /* Eliminate spaces at the end of the string */
1539350f85dSSatish Balay   for (j = sizeof(name) - 2; j >= 0; j--) {
154ba9a049bSBarry Smith     if (name[j] != ' ') {
155ba9a049bSBarry Smith       name[j + 1] = 0;
156ba9a049bSBarry Smith       break;
157ba9a049bSBarry Smith     }
158ba9a049bSBarry Smith   }
1593ba16761SJacob Faibussowitsch   if (j < 0) {
1603ba16761SJacob Faibussowitsch     *ierr = PetscStrncpy(name, "Unknown Name", 256);
1613ba16761SJacob Faibussowitsch     if (*ierr) return;
1623ba16761SJacob Faibussowitsch   }
163ba9a049bSBarry Smith 
164dd01b7e5SBarry Smith   /* check if PETSC_COMM_WORLD is initialized by the user in Fortran */
1655ea309f3SBarry Smith   petscgetcomm_(&f_petsc_comm_world);
166ba9a049bSBarry Smith   MPI_Initialized(&flag);
167ba9a049bSBarry Smith   if (!flag) {
168ba9a049bSBarry Smith     PetscMPIInt mierr;
169ba9a049bSBarry Smith 
1703ba16761SJacob Faibussowitsch     if (f_petsc_comm_world) {
1713ba16761SJacob Faibussowitsch       *ierr = (*PetscErrorPrintf)("You cannot set PETSC_COMM_WORLD if you have not initialized MPI first\n");
1723ba16761SJacob Faibussowitsch       return;
1733ba16761SJacob Faibussowitsch     }
1744dfee713SSatish Balay 
1753ba16761SJacob Faibussowitsch     *ierr = PetscPreMPIInit_Private();
1763ba16761SJacob Faibussowitsch     if (*ierr) return;
177ba9a049bSBarry Smith     mpi_init_(&mierr);
178ba9a049bSBarry Smith     if (mierr) {
1793ba16761SJacob Faibussowitsch       *ierr = (*PetscErrorPrintf)("PetscInitialize: Calling Fortran MPI_Init()\n");
1803ba16761SJacob Faibussowitsch       *ierr = (PetscErrorCode)mierr;
181ba9a049bSBarry Smith       return;
182ba9a049bSBarry Smith     }
183ba9a049bSBarry Smith     PetscBeganMPI = PETSC_TRUE;
184ba9a049bSBarry Smith   }
185a297a907SKarl 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 */
186a297a907SKarl Rupp   else PETSC_COMM_WORLD = MPI_COMM_WORLD;
187ba9a049bSBarry Smith 
18885649d77SJunchao Zhang   *ierr = PetscInitialize_Common(name, filename, help, PETSC_TRUE, *readarguments, (PetscInt)len);
1893ba16761SJacob Faibussowitsch   if (*ierr) {
1903ba16761SJacob Faibussowitsch     (void)(*PetscErrorPrintf)("PetscInitialize:PetscInitialize_Common\n");
1913ba16761SJacob Faibussowitsch     return;
1923ba16761SJacob Faibussowitsch   }
193ba9a049bSBarry Smith }
194ba9a049bSBarry Smith 
19519caf8f3SSatish Balay PETSC_EXTERN void petscfinalize_(PetscErrorCode *ierr)
196ba9a049bSBarry Smith {
197ba9a049bSBarry Smith   /* was malloced with PetscMallocAlign() so free the same way */
198dfef5ea7SSatish Balay   *ierr = PetscFreeAlign(PetscGlobalArgs, 0, NULL, NULL);
1993ba16761SJacob Faibussowitsch   if (*ierr) {
2003ba16761SJacob Faibussowitsch     (void)(*PetscErrorPrintf)("PetscFinalize:Freeing args\n");
2013ba16761SJacob Faibussowitsch     return;
2023ba16761SJacob Faibussowitsch   }
203ba9a049bSBarry Smith 
204ba9a049bSBarry Smith   *ierr = PetscFinalize();
205ba9a049bSBarry Smith }
206ba9a049bSBarry Smith 
20719caf8f3SSatish Balay PETSC_EXTERN void petscend_(PetscErrorCode *ierr)
208ba9a049bSBarry Smith {
209ba9a049bSBarry Smith   *ierr = PetscEnd();
210ba9a049bSBarry Smith }
211