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