1af0996ceSBarry Smith #include <petsc/private/fortranimpl.h> 2cee688dbSBarry Smith #include <petsc/private/f90impl.h> 3c6db04a5SJed Brown #include <petscmat.h> 4665c2dedSJed Brown #include <petscviewer.h> 5f4e70085SSatish Balay 6f4e70085SSatish Balay #if defined(PETSC_HAVE_FORTRAN_CAPS) 77d6bfa3bSBarry Smith #define matdestroymatrices_ MATDESTROYMATRICES 8df750dc8SHong Zhang #define matdestroysubmatrices_ MATDESTROYSUBMATRICES 9f4e70085SSatish Balay #define matgetrowij_ MATGETROWIJ 10f4e70085SSatish Balay #define matrestorerowij_ MATRESTOREROWIJ 11f4e70085SSatish Balay #define matgetrow_ MATGETROW 12f4e70085SSatish Balay #define matrestorerow_ MATRESTOREROW 138c778c55SBarry Smith #define matseqaijgetarray_ MATSEQAIJGETARRAY 146778691eSSatish Balay #define matseqaijrestorearray_ MATSEQAIJRESTOREARRAY 158c778c55SBarry Smith #define matdensegetarray_ MATDENSEGETARRAY 168572280aSBarry Smith #define matdensegetarrayread_ MATDENSEGETARRAYREAD 178c778c55SBarry Smith #define matdenserestorearray_ MATDENSERESTOREARRAY 188572280aSBarry Smith #define matdenserestorearrayread_ MATDENSERESTOREARRAYREAD 197dae84e0SHong Zhang #define matcreatesubmatrices_ MATCREATESUBMATRICES 2081ec7b92Smarius #define matcreatesubmatricesmpi_ MATCREATESUBMATRICESMPI 21b22b330cSBarry Smith #define matnullspacesetfunction_ MATNULLSPACESETFUNCTION 220905d9aaSJed Brown #define matfindnonzerorows_ MATFINDNONZEROROWS 23f4e70085SSatish Balay #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 245928be6bSBarry Smith #define matdestroymatrices_ matdestroymatrices 25df750dc8SHong Zhang #define matdestroysubmatrices_ matdestroysubmatrices 26f4e70085SSatish Balay #define matgetrowij_ matgetrowij 27f4e70085SSatish Balay #define matrestorerowij_ matrestorerowij 28f4e70085SSatish Balay #define matgetrow_ matgetrow 29f4e70085SSatish Balay #define matrestorerow_ matrestorerow 308c778c55SBarry Smith #define matseqaijgetarray_ matseqaijgetarray 318c778c55SBarry Smith #define matseqaijrestorearray_ matseqaijrestorearray 328c778c55SBarry Smith #define matdensegetarray_ matdensegetarray 338572280aSBarry Smith #define matdensegetarrayread_ matdensegetarrayread 348c778c55SBarry Smith #define matdenserestorearray_ matdenserestorearray 358572280aSBarry Smith #define matdenserestorearrayread_ matdenserestorearrayread 367dae84e0SHong Zhang #define matcreatesubmatrices_ matcreatesubmatrices 3781ec7b92Smarius #define matcreatesubmatricesmpi_ matcreatesubmatricesmpi 38b22b330cSBarry Smith #define matnullspacesetfunction_ matnullspacesetfunction 390905d9aaSJed Brown #define matfindnonzerorows_ matfindnonzerorows 40f4e70085SSatish Balay #endif 41f4e70085SSatish Balay 42b22b330cSBarry Smith static PetscErrorCode ournullfunction(MatNullSpace sp, Vec x, void *ctx) 43b22b330cSBarry Smith { 449566063dSJacob Faibussowitsch PetscCallFortranVoidFunction((*(void (*)(MatNullSpace *, Vec *, void *, PetscErrorCode *))(((PetscObject)sp)->fortran_func_pointers[0]))(&sp, &x, ctx, &ierr)); 453ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 46b22b330cSBarry Smith } 47b22b330cSBarry Smith 4819caf8f3SSatish Balay PETSC_EXTERN void matnullspacesetfunction_(MatNullSpace *sp, PetscErrorCode (*rem)(MatNullSpace, Vec, void *), void *ctx, PetscErrorCode *ierr) 49b22b330cSBarry Smith { 50b22b330cSBarry Smith PetscObjectAllocateFortranPointers(*sp, 1); 518434afd1SBarry Smith ((PetscObject)*sp)->fortran_func_pointers[0] = (PetscVoidFn *)rem; 5226fbe8dcSKarl Rupp 53b22b330cSBarry Smith *ierr = MatNullSpaceSetFunction(*sp, ournullfunction, ctx); 54b22b330cSBarry Smith } 55b22b330cSBarry Smith 565975b3b6SBarry Smith PETSC_EXTERN void matgetrowij_(Mat *B, PetscInt *shift, PetscBool *sym, PetscBool *blockcompressed, PetscInt *n, PetscInt *ia, size_t *iia, PetscInt *ja, size_t *jja, PetscBool *done, PetscErrorCode *ierr) 57f4e70085SSatish Balay { 581a83f524SJed Brown const PetscInt *IA, *JA; 595975b3b6SBarry Smith *ierr = MatGetRowIJ(*B, *shift, *sym, *blockcompressed, n, &IA, &JA, done); 605975b3b6SBarry Smith if (*ierr) return; 611a83f524SJed Brown *iia = PetscIntAddressToFortran(ia, (PetscInt *)IA); 621a83f524SJed Brown *jja = PetscIntAddressToFortran(ja, (PetscInt *)JA); 63f4e70085SSatish Balay } 64f4e70085SSatish Balay 655975b3b6SBarry Smith PETSC_EXTERN void matrestorerowij_(Mat *B, PetscInt *shift, PetscBool *sym, PetscBool *blockcompressed, PetscInt *n, PetscInt *ia, size_t *iia, PetscInt *ja, size_t *jja, PetscBool *done, PetscErrorCode *ierr) 66f4e70085SSatish Balay { 671a83f524SJed Brown const PetscInt *IA = PetscIntAddressFromFortran(ia, *iia), *JA = PetscIntAddressFromFortran(ja, *jja); 688f7157efSSatish Balay *ierr = MatRestoreRowIJ(*B, *shift, *sym, *blockcompressed, n, &IA, &JA, done); 69f4e70085SSatish Balay } 70f4e70085SSatish Balay 71f4e70085SSatish Balay /* 72f4e70085SSatish Balay This is a poor way of storing the column and value pointers 73f4e70085SSatish Balay generated by MatGetRow() to be returned with MatRestoreRow() 74f4e70085SSatish Balay but there is not natural,good place else to store them. Hence 75f4e70085SSatish Balay Fortran programmers can only have one outstanding MatGetRows() 76f4e70085SSatish Balay at a time. 77f4e70085SSatish Balay */ 783ba16761SJacob Faibussowitsch static int matgetrowactive = 0; 79dfef5ea7SSatish Balay static const PetscInt *my_ocols = NULL; 80dfef5ea7SSatish Balay static const PetscScalar *my_ovals = NULL; 81f4e70085SSatish Balay 8219caf8f3SSatish Balay PETSC_EXTERN void matgetrow_(Mat *mat, PetscInt *row, PetscInt *ncols, PetscInt *cols, PetscScalar *vals, PetscErrorCode *ierr) 83f4e70085SSatish Balay { 84f4e70085SSatish Balay const PetscInt **oocols = &my_ocols; 85f4e70085SSatish Balay const PetscScalar **oovals = &my_ovals; 86f4e70085SSatish Balay 87f4e70085SSatish Balay if (matgetrowactive) { 883ba16761SJacob Faibussowitsch *ierr = PetscError(PETSC_COMM_SELF, __LINE__, "MatGetRow_Fortran", __FILE__, PETSC_ERR_ARG_WRONGSTATE, PETSC_ERROR_INITIAL, "Cannot have two MatGetRow() active simultaneously\n\ 89f4e70085SSatish Balay call MatRestoreRow() before calling MatGetRow() a second time"); 903ba16761SJacob Faibussowitsch *ierr = PETSC_ERR_ARG_WRONGSTATE; 91f4e70085SSatish Balay return; 92f4e70085SSatish Balay } 93f4e70085SSatish Balay 943ba16761SJacob Faibussowitsch CHKFORTRANNULLINTEGER(cols); 953ba16761SJacob Faibussowitsch if (!cols) oocols = NULL; 963ba16761SJacob Faibussowitsch CHKFORTRANNULLSCALAR(vals); 973ba16761SJacob Faibussowitsch if (!vals) oovals = NULL; 98f4e70085SSatish Balay 99f4e70085SSatish Balay *ierr = MatGetRow(*mat, *row, ncols, oocols, oovals); 100f4e70085SSatish Balay if (*ierr) return; 101f4e70085SSatish Balay 1023ba16761SJacob Faibussowitsch if (oocols) { 1033ba16761SJacob Faibussowitsch *ierr = PetscArraycpy(cols, my_ocols, *ncols); 1043ba16761SJacob Faibussowitsch if (*ierr) return; 1053ba16761SJacob Faibussowitsch } 1063ba16761SJacob Faibussowitsch if (oovals) { 1073ba16761SJacob Faibussowitsch *ierr = PetscArraycpy(vals, my_ovals, *ncols); 1083ba16761SJacob Faibussowitsch if (*ierr) return; 1093ba16761SJacob Faibussowitsch } 110f4e70085SSatish Balay matgetrowactive = 1; 111f4e70085SSatish Balay } 112f4e70085SSatish Balay 11319caf8f3SSatish Balay PETSC_EXTERN void matrestorerow_(Mat *mat, PetscInt *row, PetscInt *ncols, PetscInt *cols, PetscScalar *vals, PetscErrorCode *ierr) 114f4e70085SSatish Balay { 115f4e70085SSatish Balay const PetscInt **oocols = &my_ocols; 116f4e70085SSatish Balay const PetscScalar **oovals = &my_ovals; 1173ba16761SJacob Faibussowitsch 118f4e70085SSatish Balay if (!matgetrowactive) { 1193ba16761SJacob Faibussowitsch *ierr = PetscError(PETSC_COMM_SELF, __LINE__, "MatRestoreRow_Fortran", __FILE__, PETSC_ERR_ARG_WRONGSTATE, PETSC_ERROR_INITIAL, "Must call MatGetRow() first"); 1203ba16761SJacob Faibussowitsch *ierr = PETSC_ERR_ARG_WRONGSTATE; 121f4e70085SSatish Balay return; 122f4e70085SSatish Balay } 1233ba16761SJacob Faibussowitsch CHKFORTRANNULLINTEGER(cols); 1243ba16761SJacob Faibussowitsch if (!cols) oocols = NULL; 1253ba16761SJacob Faibussowitsch CHKFORTRANNULLSCALAR(vals); 1263ba16761SJacob Faibussowitsch if (!vals) oovals = NULL; 127f4e70085SSatish Balay 128f4e70085SSatish Balay *ierr = MatRestoreRow(*mat, *row, ncols, oocols, oovals); 129f4e70085SSatish Balay matgetrowactive = 0; 130f4e70085SSatish Balay } 131f4e70085SSatish Balay 13219caf8f3SSatish Balay PETSC_EXTERN void matseqaijgetarray_(Mat *mat, PetscScalar *fa, size_t *ia, PetscErrorCode *ierr) 133f4e70085SSatish Balay { 134f4e70085SSatish Balay PetscScalar *mm; 135f4e70085SSatish Balay PetscInt m, n; 136f4e70085SSatish Balay 1375975b3b6SBarry Smith *ierr = MatSeqAIJGetArray(*mat, &mm); 1385975b3b6SBarry Smith if (*ierr) return; 1395975b3b6SBarry Smith *ierr = MatGetSize(*mat, &m, &n); 1405975b3b6SBarry Smith if (*ierr) return; 1415975b3b6SBarry Smith *ierr = PetscScalarAddressToFortran((PetscObject)*mat, 1, fa, mm, m * n, ia); 1425975b3b6SBarry Smith if (*ierr) return; 143f4e70085SSatish Balay } 144f4e70085SSatish Balay 14519caf8f3SSatish Balay PETSC_EXTERN void matseqaijrestorearray_(Mat *mat, PetscScalar *fa, size_t *ia, PetscErrorCode *ierr) 146f4e70085SSatish Balay { 147f4e70085SSatish Balay PetscScalar *lx; 148f4e70085SSatish Balay PetscInt m, n; 149f4e70085SSatish Balay 1505975b3b6SBarry Smith *ierr = MatGetSize(*mat, &m, &n); 1515975b3b6SBarry Smith if (*ierr) return; 1525975b3b6SBarry Smith *ierr = PetscScalarAddressFromFortran((PetscObject)*mat, fa, *ia, m * n, &lx); 1535975b3b6SBarry Smith if (*ierr) return; 1545975b3b6SBarry Smith *ierr = MatSeqAIJRestoreArray(*mat, &lx); 1555975b3b6SBarry Smith if (*ierr) return; 156f4e70085SSatish Balay } 157f4e70085SSatish Balay 15819caf8f3SSatish Balay PETSC_EXTERN void matdensegetarray_(Mat *mat, PetscScalar *fa, size_t *ia, PetscErrorCode *ierr) 15973a71a0fSBarry Smith { 16073a71a0fSBarry Smith PetscScalar *mm; 16173a71a0fSBarry Smith PetscInt m, n; 16273a71a0fSBarry Smith 1635975b3b6SBarry Smith *ierr = MatDenseGetArray(*mat, &mm); 1645975b3b6SBarry Smith if (*ierr) return; 1655975b3b6SBarry Smith *ierr = MatGetSize(*mat, &m, &n); 1665975b3b6SBarry Smith if (*ierr) return; 1675975b3b6SBarry Smith *ierr = PetscScalarAddressToFortran((PetscObject)*mat, 1, fa, mm, m * n, ia); 1685975b3b6SBarry Smith if (*ierr) return; 16973a71a0fSBarry Smith } 17073a71a0fSBarry Smith 17119caf8f3SSatish Balay PETSC_EXTERN void matdenserestorearray_(Mat *mat, PetscScalar *fa, size_t *ia, PetscErrorCode *ierr) 17273a71a0fSBarry Smith { 17373a71a0fSBarry Smith PetscScalar *lx; 17473a71a0fSBarry Smith PetscInt m, n; 17573a71a0fSBarry Smith 1765975b3b6SBarry Smith *ierr = MatGetSize(*mat, &m, &n); 1775975b3b6SBarry Smith if (*ierr) return; 1785975b3b6SBarry Smith *ierr = PetscScalarAddressFromFortran((PetscObject)*mat, fa, *ia, m * n, &lx); 1795975b3b6SBarry Smith if (*ierr) return; 1805975b3b6SBarry Smith *ierr = MatDenseRestoreArray(*mat, &lx); 1815975b3b6SBarry Smith if (*ierr) return; 18273a71a0fSBarry Smith } 18373a71a0fSBarry Smith 18419caf8f3SSatish Balay PETSC_EXTERN void matdensegetarrayread_(Mat *mat, PetscScalar *fa, size_t *ia, PetscErrorCode *ierr) 1858572280aSBarry Smith { 1867067c7f7SBarry Smith const PetscScalar *mm; 1878572280aSBarry Smith PetscInt m, n; 1888572280aSBarry Smith 1895975b3b6SBarry Smith *ierr = MatDenseGetArrayRead(*mat, &mm); 1905975b3b6SBarry Smith if (*ierr) return; 1915975b3b6SBarry Smith *ierr = MatGetSize(*mat, &m, &n); 1925975b3b6SBarry Smith if (*ierr) return; 1935975b3b6SBarry Smith *ierr = PetscScalarAddressToFortran((PetscObject)*mat, 1, fa, (PetscScalar *)mm, m * n, ia); 1945975b3b6SBarry Smith if (*ierr) return; 1958572280aSBarry Smith } 1968572280aSBarry Smith 19719caf8f3SSatish Balay PETSC_EXTERN void matdenserestorearrayread_(Mat *mat, PetscScalar *fa, size_t *ia, PetscErrorCode *ierr) 1988572280aSBarry Smith { 1997067c7f7SBarry Smith const PetscScalar *lx; 2008572280aSBarry Smith PetscInt m, n; 2018572280aSBarry Smith 2025975b3b6SBarry Smith *ierr = MatGetSize(*mat, &m, &n); 2035975b3b6SBarry Smith if (*ierr) return; 2045975b3b6SBarry Smith *ierr = PetscScalarAddressFromFortran((PetscObject)*mat, fa, *ia, m * n, (PetscScalar **)&lx); 2055975b3b6SBarry Smith if (*ierr) return; 2065975b3b6SBarry Smith *ierr = MatDenseRestoreArrayRead(*mat, &lx); 2075975b3b6SBarry Smith if (*ierr) return; 2088572280aSBarry Smith } 2098572280aSBarry Smith 210f4e70085SSatish Balay /* 2117dae84e0SHong Zhang MatCreateSubmatrices() is slightly different from C since the 212f4e70085SSatish Balay Fortran provides the array to hold the submatrix objects,while in C that 2137dae84e0SHong Zhang array is allocated by the MatCreateSubmatrices() 214f4e70085SSatish Balay */ 21519caf8f3SSatish Balay PETSC_EXTERN void matcreatesubmatrices_(Mat *mat, PetscInt *n, IS *isrow, IS *iscol, MatReuse *scall, Mat *smat, PetscErrorCode *ierr) 216f4e70085SSatish Balay { 217f4e70085SSatish Balay Mat *lsmat; 218f4e70085SSatish Balay PetscInt i; 219f4e70085SSatish Balay 220f4e70085SSatish Balay if (*scall == MAT_INITIAL_MATRIX) { 2217dae84e0SHong Zhang *ierr = MatCreateSubMatrices(*mat, *n, isrow, iscol, *scall, &lsmat); 22269d47153SPierre Jolivet for (i = 0; i <= *n; i++) { /* lsmat[*n] might be a dummy matrix for saving data structure */ 223f4e70085SSatish Balay smat[i] = lsmat[i]; 224f4e70085SSatish Balay } 225f4e70085SSatish Balay *ierr = PetscFree(lsmat); 226f4e70085SSatish Balay } else { 2277dae84e0SHong Zhang *ierr = MatCreateSubMatrices(*mat, *n, isrow, iscol, *scall, &smat); 228f4e70085SSatish Balay } 229f4e70085SSatish Balay } 230f4e70085SSatish Balay 2317d6bfa3bSBarry Smith /* 23281ec7b92Smarius MatCreateSubmatrices() is slightly different from C since the 23381ec7b92Smarius Fortran provides the array to hold the submatrix objects,while in C that 23481ec7b92Smarius array is allocated by the MatCreateSubmatrices() 23581ec7b92Smarius */ 23619caf8f3SSatish Balay PETSC_EXTERN void matcreatesubmatricesmpi_(Mat *mat, PetscInt *n, IS *isrow, IS *iscol, MatReuse *scall, Mat *smat, PetscErrorCode *ierr) 23781ec7b92Smarius { 23881ec7b92Smarius Mat *lsmat; 23981ec7b92Smarius PetscInt i; 24081ec7b92Smarius 24181ec7b92Smarius if (*scall == MAT_INITIAL_MATRIX) { 24281ec7b92Smarius *ierr = MatCreateSubMatricesMPI(*mat, *n, isrow, iscol, *scall, &lsmat); 24369d47153SPierre Jolivet for (i = 0; i <= *n; i++) { /* lsmat[*n] might be a dummy matrix for saving data structure */ 24481ec7b92Smarius smat[i] = lsmat[i]; 24581ec7b92Smarius } 24681ec7b92Smarius *ierr = PetscFree(lsmat); 24781ec7b92Smarius } else { 24881ec7b92Smarius *ierr = MatCreateSubMatricesMPI(*mat, *n, isrow, iscol, *scall, &smat); 24981ec7b92Smarius } 25081ec7b92Smarius } 25181ec7b92Smarius 25281ec7b92Smarius /* 2537d6bfa3bSBarry Smith MatDestroyMatrices() is slightly different from C since the 254de7ef04eSHong Zhang Fortran does not free the array of matrix objects, while in C that 255de7ef04eSHong Zhang the array is freed 256de7ef04eSHong Zhang */ 25719caf8f3SSatish Balay PETSC_EXTERN void matdestroymatrices_(PetscInt *n, Mat *smat, PetscErrorCode *ierr) 258de7ef04eSHong Zhang { 259de7ef04eSHong Zhang PetscInt i; 260de7ef04eSHong Zhang 261de7ef04eSHong Zhang for (i = 0; i < *n; i++) { 2621fb7b255SJunchao Zhang PETSC_FORTRAN_OBJECT_F_DESTROYED_TO_C_NULL(&smat[i]); 2635975b3b6SBarry Smith *ierr = MatDestroy(&smat[i]); 2645975b3b6SBarry Smith if (*ierr) return; 2651fb7b255SJunchao Zhang PETSC_FORTRAN_OBJECT_C_NULL_TO_F_DESTROYED(&smat[i]); 266de7ef04eSHong Zhang } 267de7ef04eSHong Zhang } 268de7ef04eSHong Zhang 269de7ef04eSHong Zhang /* 270de7ef04eSHong Zhang MatDestroySubMatrices() is slightly different from C since the 2717d6bfa3bSBarry Smith Fortran provides the array to hold the submatrix objects, while in C that 2727dae84e0SHong Zhang array is allocated by the MatCreateSubmatrices() 2730764c050SBarry Smith 2740764c050SBarry Smith An extra matrix may be stored at the end of the array, hence the check see 2750764c050SBarry Smith MatDestroySubMatrices_Dummy() 2767d6bfa3bSBarry Smith */ 27719caf8f3SSatish Balay PETSC_EXTERN void matdestroysubmatrices_(PetscInt *n, Mat *smat, PetscErrorCode *ierr) 2787d6bfa3bSBarry Smith { 279de7ef04eSHong Zhang Mat *lsmat; 2807d6bfa3bSBarry Smith PetscInt i; 2817d6bfa3bSBarry Smith 2820764c050SBarry Smith if (*n == 0) return; 283de7ef04eSHong Zhang *ierr = PetscMalloc1(*n + 1, &lsmat); 284*5d83a8b1SBarry Smith if (*ierr) return; 285*5d83a8b1SBarry Smith for (i = 0; i <= *n; i++) { lsmat[i] = smat[i]; } 286de7ef04eSHong Zhang *ierr = MatDestroySubMatrices(*n, &lsmat); 287*5d83a8b1SBarry Smith if (*ierr) return; 2885975b3b6SBarry Smith for (i = 0; i <= *n; i++) { PETSC_FORTRAN_OBJECT_C_NULL_TO_F_DESTROYED(&smat[i]); } 2891fb7b255SJunchao Zhang } 290