xref: /petsc/src/mat/impls/shell/ftn-custom/zshellf.c (revision 0fc8abbb0d2c66d68d698915e846a5e6ada4b530)
1 #include <petsc/private/fortranimpl.h>
2 #include <petscmat.h>
3 
4 #if defined(PETSC_HAVE_FORTRAN_CAPS)
5 #define matshellsetoperation_            MATSHELLSETOPERATION
6 #define matcreateshell_                  MATCREATESHELL
7 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
8 #define matcreateshell_                  matcreateshell
9 #define matshellsetoperation_            matshellsetoperation
10 #endif
11 
12 /**
13  * Subset of MatOperation that is supported by the Fortran wrappers.
14  */
15 enum FortranMatOperation {
16   FORTRAN_MATOP_MULT = 0,
17   FORTRAN_MATOP_MULT_ADD = 1,
18   FORTRAN_MATOP_MULT_TRANSPOSE = 2,
19   FORTRAN_MATOP_MULT_TRANSPOSE_ADD = 3,
20   FORTRAN_MATOP_SOR = 4,
21   FORTRAN_MATOP_TRANSPOSE = 5,
22   FORTRAN_MATOP_GET_DIAGONAL = 6,
23   FORTRAN_MATOP_DIAGONAL_SCALE = 7,
24   FORTRAN_MATOP_ZERO_ENTRIES = 8,
25   FORTRAN_MATOP_AXPY = 9,
26   FORTRAN_MATOP_SHIFT = 10,
27   FORTRAN_MATOP_DIAGONAL_SET = 11,
28   FORTRAN_MATOP_DESTROY = 12,
29   FORTRAN_MATOP_VIEW = 13,
30   FORTRAN_MATOP_GET_VECS = 14,
31 
32   FORTRAN_MATOP_SIZE = 15
33 };
34 
35 /*
36   The MatShell Matrix Vector product requires a C routine.
37   This C routine then calls the corresponding Fortran routine that was
38   set by the user.
39 */
40 PETSC_EXTERN void PETSC_STDCALL matcreateshell_(MPI_Comm *comm, PetscInt *m, PetscInt *n, PetscInt *M, PetscInt *N, void *ctx, Mat *mat, PetscErrorCode *ierr)
41 {
42   *ierr = MatCreateShell(MPI_Comm_f2c(*(MPI_Fint*)&*comm), *m, *n, *M, *N, ctx, mat);
43 }
44 
45 static PetscErrorCode ourmult(Mat mat, Vec x, Vec y)
46 {
47   PetscErrorCode ierr = 0;
48 
49   (*(PetscErrorCode (PETSC_STDCALL *)(Mat*, Vec*, Vec*, PetscErrorCode*))(((PetscObject) mat)->fortran_func_pointers[FORTRAN_MATOP_MULT]))(&mat, &x, &y, &ierr);
50   return ierr;
51 }
52 
53 static PetscErrorCode ourmultadd(Mat mat, Vec x, Vec y, Vec z)
54 {
55   PetscErrorCode ierr = 0;
56 
57   (*(PetscErrorCode (PETSC_STDCALL *)(Mat*, Vec*, Vec*, Vec*, PetscErrorCode*))(((PetscObject) mat)->fortran_func_pointers[FORTRAN_MATOP_MULT_ADD]))(&mat, &x, &y, &z, &ierr);
58   return ierr;
59 }
60 
61 static PetscErrorCode ourmulttranspose(Mat mat, Vec x, Vec y)
62 {
63   PetscErrorCode ierr = 0;
64 
65   (*(PetscErrorCode (PETSC_STDCALL *)(Mat*, Vec*, Vec*, PetscErrorCode*))(((PetscObject) mat)->fortran_func_pointers[FORTRAN_MATOP_MULT_TRANSPOSE]))(&mat, &x, &y, &ierr);
66   return ierr;
67 }
68 
69 static PetscErrorCode ourmulttransposeadd(Mat mat, Vec x, Vec y, Vec z)
70 {
71   PetscErrorCode ierr = 0;
72 
73   (*(PetscErrorCode (PETSC_STDCALL *)(Mat*, Vec*, Vec*, Vec*, PetscErrorCode*))(((PetscObject) mat)->fortran_func_pointers[FORTRAN_MATOP_MULT_TRANSPOSE_ADD]))(&mat, &x, &y, &z, &ierr);
74   return ierr;
75 }
76 
77 static PetscErrorCode oursor(Mat mat, Vec b, PetscReal omega, MatSORType flg, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
78 {
79   PetscErrorCode ierr = 0;
80 
81   (*(PetscErrorCode (PETSC_STDCALL *)(Mat*, Vec*, PetscReal*, MatSORType*, PetscReal*, PetscInt*, PetscInt*, Vec*, PetscErrorCode*))(((PetscObject) mat)->fortran_func_pointers[FORTRAN_MATOP_SOR]))(&mat, &b, &omega, &flg, &shift, &its, &lits, &x, &ierr);
82   return ierr;
83 }
84 
85 static PetscErrorCode ourtranspose(Mat mat, MatReuse reuse, Mat *B)
86 {
87   PetscErrorCode ierr = 0;
88   Mat *b = (!B ? (Mat *) PETSC_NULL_OBJECT_Fortran : B);
89 
90   (*(PetscErrorCode (PETSC_STDCALL *)(Mat*, MatReuse*, Mat *, PetscErrorCode*))(((PetscObject) mat)->fortran_func_pointers[FORTRAN_MATOP_TRANSPOSE]))(&mat, &reuse, b, &ierr);
91   return ierr;
92 }
93 
94 static PetscErrorCode ourgetdiagonal(Mat mat, Vec x)
95 {
96   PetscErrorCode ierr = 0;
97 
98   (*(PetscErrorCode (PETSC_STDCALL *)(Mat*, Vec*, PetscErrorCode*))(((PetscObject) mat)->fortran_func_pointers[FORTRAN_MATOP_GET_DIAGONAL]))(&mat, &x, &ierr);
99   return ierr;
100 }
101 
102 static PetscErrorCode ourdiagonalscale(Mat mat, Vec l, Vec r)
103 {
104   PetscErrorCode ierr = 0;
105   Vec *a = (!l ? (Vec*) PETSC_NULL_OBJECT_Fortran : &l);
106   Vec *b = (!r ? (Vec*) PETSC_NULL_OBJECT_Fortran : &r);
107 
108   (*(PetscErrorCode (PETSC_STDCALL *)(Mat*, Vec*, Vec*, PetscErrorCode*))(((PetscObject) mat)->fortran_func_pointers[FORTRAN_MATOP_DIAGONAL_SCALE]))(&mat, a, b, &ierr);
109   return ierr;
110 }
111 
112 static PetscErrorCode ourzeroentries(Mat mat)
113 {
114   PetscErrorCode ierr = 0;
115 
116   (*(PetscErrorCode (PETSC_STDCALL *)(Mat*, PetscErrorCode*))(((PetscObject) mat)->fortran_func_pointers[FORTRAN_MATOP_ZERO_ENTRIES]))(&mat, &ierr);
117   return ierr;
118 }
119 
120 static PetscErrorCode ouraxpy(Mat mat, PetscScalar a, Mat X, MatStructure str)
121 {
122   PetscErrorCode ierr = 0;
123 
124   (*(PetscErrorCode (PETSC_STDCALL *)(Mat*, PetscScalar*, Mat*, MatStructure*, PetscErrorCode*))(((PetscObject) mat)->fortran_func_pointers[FORTRAN_MATOP_AXPY]))(&mat, &a, &X, &str, &ierr);
125   return ierr;
126 }
127 
128 static PetscErrorCode ourshift(Mat mat, PetscScalar a)
129 {
130   PetscErrorCode ierr = 0;
131 
132   (*(PetscErrorCode (PETSC_STDCALL *)(Mat*, PetscScalar*, PetscErrorCode*))(((PetscObject) mat)->fortran_func_pointers[FORTRAN_MATOP_SHIFT]))(&mat, &a, &ierr);
133   return ierr;
134 }
135 
136 static PetscErrorCode ourdiagonalset(Mat mat, Vec x, InsertMode ins)
137 {
138   PetscErrorCode ierr = 0;
139 
140   (*(PetscErrorCode (PETSC_STDCALL *)(Mat*, Vec*, InsertMode*, PetscErrorCode*))(((PetscObject) mat)->fortran_func_pointers[FORTRAN_MATOP_DIAGONAL_SET]))(&mat, &x, &ins, &ierr);
141   return ierr;
142 }
143 
144 static PetscErrorCode ourdestroy(Mat mat)
145 {
146   PetscErrorCode ierr = 0;
147 
148   (*(PetscErrorCode (PETSC_STDCALL *)(Mat*, PetscErrorCode*))(((PetscObject) mat)->fortran_func_pointers[FORTRAN_MATOP_DESTROY]))(&mat, &ierr);
149   return ierr;
150 }
151 
152 static PetscErrorCode ourview(Mat mat, PetscViewer v)
153 {
154   PetscErrorCode ierr = 0;
155 
156   (*(PetscErrorCode (PETSC_STDCALL *)(Mat*, PetscViewer*, PetscErrorCode*))(((PetscObject) mat)->fortran_func_pointers[FORTRAN_MATOP_VIEW]))(&mat, &v, &ierr);
157   return ierr;
158 }
159 
160 static PetscErrorCode ourgetvecs(Mat mat, Vec *l, Vec *r)
161 {
162   PetscErrorCode ierr = 0;
163   Vec *a = (!l ? (Vec *) PETSC_NULL_OBJECT_Fortran : l);
164   Vec *b = (!r ? (Vec *) PETSC_NULL_OBJECT_Fortran : r);
165 
166   (*(PetscErrorCode (PETSC_STDCALL *)(Mat*, Vec*, Vec*, PetscErrorCode*))(((PetscObject) mat)->fortran_func_pointers[FORTRAN_MATOP_GET_VECS]))(&mat, a, b, &ierr);
167   return ierr;
168 }
169 
170 PETSC_EXTERN void PETSC_STDCALL matshellsetoperation_(Mat *mat, MatOperation *op, PetscErrorCode (PETSC_STDCALL *f)(Mat*, Vec*, Vec*, PetscErrorCode*), PetscErrorCode *ierr)
171 {
172   MPI_Comm comm;
173 
174   *ierr = PetscObjectGetComm((PetscObject) *mat, &comm);if (*ierr) return;
175   PetscObjectAllocateFortranPointers(*mat, FORTRAN_MATOP_SIZE);
176 
177   switch (*op) {
178   case MATOP_MULT:
179     *ierr = MatShellSetOperation(*mat, *op, (PetscVoidFunction) ourmult);
180     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_MULT] = (PetscVoidFunction) f;
181     break;
182   case MATOP_MULT_ADD:
183     *ierr = MatShellSetOperation(*mat, *op, (PetscVoidFunction) ourmultadd);
184     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_MULT_ADD] = (PetscVoidFunction) f;
185     break;
186   case MATOP_MULT_TRANSPOSE:
187     *ierr = MatShellSetOperation(*mat, *op, (PetscVoidFunction) ourmulttranspose);
188     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_MULT_TRANSPOSE] = (PetscVoidFunction) f;
189     break;
190   case MATOP_MULT_TRANSPOSE_ADD:
191     *ierr = MatShellSetOperation(*mat, *op, (PetscVoidFunction) ourmulttransposeadd);
192     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_MULT_TRANSPOSE_ADD] = (PetscVoidFunction) f;
193     break;
194   case MATOP_SOR:
195     *ierr = MatShellSetOperation(*mat, *op, (PetscVoidFunction) oursor);
196     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_SOR] = (PetscVoidFunction) f;
197     break;
198   case MATOP_TRANSPOSE:
199     *ierr = MatShellSetOperation(*mat, *op, (PetscVoidFunction) ourtranspose);
200     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_TRANSPOSE] = (PetscVoidFunction) f;
201     break;
202   case MATOP_GET_DIAGONAL:
203     *ierr = MatShellSetOperation(*mat, *op, (PetscVoidFunction) ourgetdiagonal);
204     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_GET_DIAGONAL] = (PetscVoidFunction) f;
205     break;
206   case MATOP_DIAGONAL_SCALE:
207     *ierr = MatShellSetOperation(*mat, *op, (PetscVoidFunction) ourdiagonalscale);
208     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_DIAGONAL_SCALE] = (PetscVoidFunction) f;
209     break;
210   case MATOP_ZERO_ENTRIES:
211     *ierr = MatShellSetOperation(*mat, *op, (PetscVoidFunction) ourzeroentries);
212     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_ZERO_ENTRIES] = (PetscVoidFunction) f;
213     break;
214   case MATOP_AXPY:
215     *ierr = MatShellSetOperation(*mat, *op, (PetscVoidFunction) ouraxpy);
216     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_AXPY] = (PetscVoidFunction) f;
217     break;
218   case MATOP_SHIFT:
219     *ierr = MatShellSetOperation(*mat, *op, (PetscVoidFunction) ourshift);
220     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_SHIFT] = (PetscVoidFunction) f;
221     break;
222   case MATOP_DIAGONAL_SET:
223     *ierr = MatShellSetOperation(*mat, *op, (PetscVoidFunction) ourdiagonalset);
224     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_DIAGONAL_SET] = (PetscVoidFunction) f;
225     break;
226   case MATOP_DESTROY:
227     *ierr = MatShellSetOperation(*mat, *op, (PetscVoidFunction) ourdestroy);
228     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_DESTROY] = (PetscVoidFunction) f;
229     break;
230   case MATOP_VIEW:
231     *ierr = MatShellSetOperation(*mat, *op, (PetscVoidFunction) ourview);
232     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_VIEW] = (PetscVoidFunction) f;
233     break;
234   case MATOP_GET_VECS:
235     *ierr = MatShellSetOperation(*mat, *op, (PetscVoidFunction) ourgetvecs);
236     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_GET_VECS] = (PetscVoidFunction) f;
237     break;
238   default:
239     PetscError(comm, __LINE__, "MatShellSetOperation_Fortran", __FILE__, PETSC_ERR_ARG_WRONG, PETSC_ERROR_INITIAL, "Cannot set that matrix operation");
240     *ierr = 1;
241   }
242 }
243