xref: /petsc/src/mat/interface/ftn-custom/zmatrixf.c (revision 5d83a8b16d06840f96948f1a43aa9c83c769a60a)
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