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 mpi_init_ MPI_INIT 195ea309f3SBarry Smith #define petscgetcomm_ PETSCGETCOMM 20541b5888SSatish Balay #define petsccommandargumentcount_ PETSCCOMMANDARGUMENTCOUNT 21541b5888SSatish Balay #define petscgetcommandargument_ PETSCGETCOMMANDARGUMENT 22ba9a049bSBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 235906a408SBlaise Bourdin #define petscinitializef_ petscinitializef 24ba9a049bSBarry Smith #define mpi_init_ mpi_init 255ea309f3SBarry Smith #define petscgetcomm_ petscgetcomm 26541b5888SSatish Balay #define petsccommandargumentcount_ petsccommandargumentcount 27541b5888SSatish Balay #define petscgetcommandargument_ petscgetcommandargument 28ba9a049bSBarry Smith #endif 29ba9a049bSBarry Smith 30ba9a049bSBarry Smith /* 31ba9a049bSBarry Smith The extra _ is because the f2c compiler puts an 32ba9a049bSBarry Smith extra _ at the end if the original routine name 33ba9a049bSBarry Smith contained any _. 34ba9a049bSBarry Smith */ 35ba9a049bSBarry Smith #if defined(PETSC_HAVE_FORTRAN_UNDERSCORE_UNDERSCORE) 36ba9a049bSBarry Smith #define mpi_init_ mpi_init__ 37ba9a049bSBarry Smith #endif 38ba9a049bSBarry Smith 39a7b85bbcSSatish Balay #if defined(PETSC_HAVE_MPIUNI) 40a7b85bbcSSatish Balay #if defined(mpi_init_) 41a7b85bbcSSatish Balay #undef mpi_init_ 42a7b85bbcSSatish Balay #if defined(PETSC_HAVE_FORTRAN_CAPS) 43a7b85bbcSSatish Balay #define mpi_init_ PETSC_MPI_INIT 44a7b85bbcSSatish Balay #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 45a7b85bbcSSatish Balay #define mpi_init_ petsc_mpi_init 46a7b85bbcSSatish Balay #elif defined(PETSC_HAVE_FORTRAN_UNDERSCORE_UNDERSCORE) 47a7b85bbcSSatish Balay #define mpi_init_ petsc_mpi_init__ 48a7b85bbcSSatish Balay #endif 49a7b85bbcSSatish Balay #else /* mpi_init_ */ 50a7b85bbcSSatish Balay #define mpi_init_ petsc_mpi_init_ 51a7b85bbcSSatish Balay #endif /* mpi_init_ */ 52a7b85bbcSSatish Balay #endif /* PETSC_HAVE_MPIUNI */ 53a7b85bbcSSatish Balay 5419caf8f3SSatish Balay PETSC_EXTERN void mpi_init_(int *); 5519caf8f3SSatish Balay PETSC_EXTERN void petscgetcomm_(PetscMPIInt *); 56ba9a049bSBarry Smith 57ba9a049bSBarry Smith /* 58ba9a049bSBarry Smith Different Fortran compilers handle command lines in different ways 59ba9a049bSBarry Smith */ 608d35c829SSatish Balay PETSC_EXTERN int petsccommandargumentcount_(void); 618d35c829SSatish Balay PETSC_EXTERN void petscgetcommandargument_(int *, char *, PETSC_FORTRAN_CHARLEN_T); 62071fcb05SBarry Smith PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **); 6395c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]); 6495c0884eSLisandro Dalcin PETSC_INTERN int PetscGlobalArgc; 659f0612e4SBarry Smith PETSC_INTERN char **PetscGlobalArgs, **PetscGlobalArgsFortran; 66ba9a049bSBarry Smith 67ba9a049bSBarry Smith /* 68a5b23f4aSJose E. Roman Reads in Fortran command line arguments and sends them to 69d5be86a5SBarry Smith all processors. 70ba9a049bSBarry Smith */ 71ba9a049bSBarry Smith 72ba9a049bSBarry Smith PetscErrorCode PETScParseFortranArgs_Private(int *argc, char ***argv) 73ba9a049bSBarry Smith { 74ba9a049bSBarry Smith int i; 75ba9a049bSBarry Smith int warg = 256; 76ba9a049bSBarry Smith PetscMPIInt rank; 77ba9a049bSBarry Smith char *p; 78ba9a049bSBarry Smith 799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 808d35c829SSatish Balay if (rank == 0) { *argc = 1 + petsccommandargumentcount_(); } 819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(argc, 1, MPI_INT, 0, PETSC_COMM_WORLD)); 82ba9a049bSBarry Smith 83ba9a049bSBarry Smith /* PetscTrMalloc() not yet set, so don't use PetscMalloc() */ 84dfef5ea7SSatish Balay PetscCall(PetscMallocAlign((*argc + 1) * (warg * sizeof(char) + sizeof(char *)), PETSC_FALSE, 0, NULL, NULL, (void **)argv)); 85ba9a049bSBarry Smith (*argv)[0] = (char *)(*argv + *argc + 1); 86ba9a049bSBarry Smith 87dd400576SPatrick Sanan if (rank == 0) { 889566063dSJacob Faibussowitsch PetscCall(PetscMemzero((*argv)[0], (*argc) * warg * sizeof(char))); 89ba9a049bSBarry Smith for (i = 0; i < *argc; i++) { 90ba9a049bSBarry Smith (*argv)[i + 1] = (*argv)[i] + warg; 918d35c829SSatish Balay petscgetcommandargument_(&i, (*argv)[i], warg); 92ba9a049bSBarry Smith /* zero out garbage at end of each argument */ 93ba9a049bSBarry Smith p = (*argv)[i] + warg - 1; 94ba9a049bSBarry Smith while (p > (*argv)[i]) { 95ba9a049bSBarry Smith if (*p == ' ') *p = 0; 96ba9a049bSBarry Smith p--; 97ba9a049bSBarry Smith } 98ba9a049bSBarry Smith } 99ba9a049bSBarry Smith } 1009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast((*argv)[0], *argc * warg, MPI_CHAR, 0, PETSC_COMM_WORLD)); 101ba9a049bSBarry Smith if (rank) { 102a297a907SKarl Rupp for (i = 0; i < *argc; i++) (*argv)[i + 1] = (*argv)[i] + warg; 103ba9a049bSBarry Smith } 1043ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 105ba9a049bSBarry Smith } 106ba9a049bSBarry Smith 107ba9a049bSBarry Smith /* -----------------------------------------------------------------------------------------------*/ 108ba9a049bSBarry Smith 1093274405dSPierre Jolivet PETSC_INTERN PetscErrorCode PetscPreMPIInit_Private(void); 1107f20dbc5SBarry Smith 111*daa8fb3bSBarry Smith PETSC_INTERN PetscErrorCode PetscInitFortran_Private(const char *filename, PetscInt len) 11285649d77SJunchao Zhang { 11385649d77SJunchao Zhang char *tmp = NULL; 11485649d77SJunchao Zhang 11585649d77SJunchao Zhang PetscFunctionBegin; 1169566063dSJacob Faibussowitsch PetscCall(PetscInitializeFortran()); 1179f0612e4SBarry Smith PetscCall(PETScParseFortranArgs_Private(&PetscGlobalArgc, &PetscGlobalArgsFortran)); 1189f0612e4SBarry Smith PetscGlobalArgs = PetscGlobalArgsFortran; 119*daa8fb3bSBarry Smith if (filename != PETSC_NULL_CHARACTER_Fortran) { /* filename comes from Fortran so may have blanking padding that needs removal */ 12085649d77SJunchao Zhang while ((len > 0) && (filename[len - 1] == ' ')) len--; 1219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len + 1, &tmp)); 1229566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(tmp, filename, len + 1)); 12385649d77SJunchao Zhang } 1249f0612e4SBarry Smith PetscCall(PetscOptionsInsert(NULL, &PetscGlobalArgc, &PetscGlobalArgsFortran, tmp)); 125*daa8fb3bSBarry Smith PetscCall(PetscFree(tmp)); 1263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12785649d77SJunchao Zhang } 12885649d77SJunchao Zhang 129*daa8fb3bSBarry Smith PETSC_EXTERN void petscinitializef_(char *filename, char *help, PetscErrorCode *ierr, PETSC_FORTRAN_CHARLEN_T len, PETSC_FORTRAN_CHARLEN_T helplen) 130ba9a049bSBarry Smith { 1314b60c348SBarry Smith int j, i; 132ba9a049bSBarry Smith int flag; 13385649d77SJunchao Zhang char name[256] = {0}; 134ba9a049bSBarry Smith PetscMPIInt f_petsc_comm_world; 135ba9a049bSBarry Smith 1363ba16761SJacob Faibussowitsch *ierr = PETSC_SUCCESS; 1373ba16761SJacob Faibussowitsch if (PetscInitializeCalled) return; 138ba9a049bSBarry Smith i = 0; 1398d35c829SSatish Balay petscgetcommandargument_(&i, name, sizeof(name)); 140ba9a049bSBarry Smith /* Eliminate spaces at the end of the string */ 1419350f85dSSatish Balay for (j = sizeof(name) - 2; j >= 0; j--) { 142ba9a049bSBarry Smith if (name[j] != ' ') { 143ba9a049bSBarry Smith name[j + 1] = 0; 144ba9a049bSBarry Smith break; 145ba9a049bSBarry Smith } 146ba9a049bSBarry Smith } 1473ba16761SJacob Faibussowitsch if (j < 0) { 1483ba16761SJacob Faibussowitsch *ierr = PetscStrncpy(name, "Unknown Name", 256); 1493ba16761SJacob Faibussowitsch if (*ierr) return; 1503ba16761SJacob Faibussowitsch } 151ba9a049bSBarry Smith 152dd01b7e5SBarry Smith /* check if PETSC_COMM_WORLD is initialized by the user in Fortran */ 1535ea309f3SBarry Smith petscgetcomm_(&f_petsc_comm_world); 154ba9a049bSBarry Smith MPI_Initialized(&flag); 155ba9a049bSBarry Smith if (!flag) { 156ba9a049bSBarry Smith PetscMPIInt mierr; 157ba9a049bSBarry Smith 1583ba16761SJacob Faibussowitsch if (f_petsc_comm_world) { 1593ba16761SJacob Faibussowitsch *ierr = (*PetscErrorPrintf)("You cannot set PETSC_COMM_WORLD if you have not initialized MPI first\n"); 1603ba16761SJacob Faibussowitsch return; 1613ba16761SJacob Faibussowitsch } 1624dfee713SSatish Balay 1633ba16761SJacob Faibussowitsch *ierr = PetscPreMPIInit_Private(); 1643ba16761SJacob Faibussowitsch if (*ierr) return; 165ba9a049bSBarry Smith mpi_init_(&mierr); 166ba9a049bSBarry Smith if (mierr) { 1673ba16761SJacob Faibussowitsch *ierr = (*PetscErrorPrintf)("PetscInitialize: Calling Fortran MPI_Init()\n"); 1683ba16761SJacob Faibussowitsch *ierr = (PetscErrorCode)mierr; 169ba9a049bSBarry Smith return; 170ba9a049bSBarry Smith } 171ba9a049bSBarry Smith PetscBeganMPI = PETSC_TRUE; 172ba9a049bSBarry Smith } 173a297a907SKarl 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 */ 174a297a907SKarl Rupp else PETSC_COMM_WORLD = MPI_COMM_WORLD; 175ba9a049bSBarry Smith 176*daa8fb3bSBarry Smith *ierr = PetscInitialize_Common(name, filename, help, PETSC_TRUE, (PetscInt)len); 1773ba16761SJacob Faibussowitsch if (*ierr) { 1783ba16761SJacob Faibussowitsch (void)(*PetscErrorPrintf)("PetscInitialize:PetscInitialize_Common\n"); 1793ba16761SJacob Faibussowitsch return; 1803ba16761SJacob Faibussowitsch } 181ba9a049bSBarry Smith } 182