xref: /petsc/src/mat/impls/shell/ftn-custom/zshellf.c (revision fbf9dbe564678ed6eff1806adbc4c4f01b9743f4)
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_CREATE_VECS        = 14,
31   FORTRAN_MATOP_GET_DIAGONAL_BLOCK = 15,
32   FORTRAN_MATOP_COPY               = 16,
33   FORTRAN_MATOP_SCALE              = 17,
34   FORTRAN_MATOP_SET_RANDOM         = 18,
35   FORTRAN_MATOP_ASSEMBLY_BEGIN     = 19,
36   FORTRAN_MATOP_ASSEMBLY_END       = 20,
37   FORTRAN_MATOP_SIZE               = 21
38 };
39 
40 /*
41   The MatShell Matrix Vector product requires a C routine.
42   This C routine then calls the corresponding Fortran routine that was
43   set by the user.
44 */
45 PETSC_EXTERN void matcreateshell_(MPI_Comm *comm, PetscInt *m, PetscInt *n, PetscInt *M, PetscInt *N, void *ctx, Mat *mat, PetscErrorCode *ierr)
46 {
47   *ierr = MatCreateShell(MPI_Comm_f2c(*(MPI_Fint *)&*comm), *m, *n, *M, *N, ctx, mat);
48 }
49 
50 static PetscErrorCode ourmult(Mat mat, Vec x, Vec y)
51 {
52   PetscCallFortranVoidFunction((*(void (*)(Mat *, Vec *, Vec *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_MULT]))(&mat, &x, &y, &ierr));
53   return PETSC_SUCCESS;
54 }
55 
56 static PetscErrorCode ourmultadd(Mat mat, Vec x, Vec y, Vec z)
57 {
58   PetscCallFortranVoidFunction((*(void (*)(Mat *, Vec *, Vec *, Vec *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_MULT_ADD]))(&mat, &x, &y, &z, &ierr));
59   return PETSC_SUCCESS;
60 }
61 
62 static PetscErrorCode ourmulttranspose(Mat mat, Vec x, Vec y)
63 {
64   PetscCallFortranVoidFunction((*(void (*)(Mat *, Vec *, Vec *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_MULT_TRANSPOSE]))(&mat, &x, &y, &ierr));
65   return PETSC_SUCCESS;
66 }
67 
68 static PetscErrorCode ourmulttransposeadd(Mat mat, Vec x, Vec y, Vec z)
69 {
70   PetscCallFortranVoidFunction((*(void (*)(Mat *, Vec *, Vec *, Vec *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_MULT_TRANSPOSE_ADD]))(&mat, &x, &y, &z, &ierr));
71   return PETSC_SUCCESS;
72 }
73 
74 static PetscErrorCode oursor(Mat mat, Vec b, PetscReal omega, MatSORType flg, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
75 {
76   PetscErrorCode ierr = PETSC_SUCCESS;
77 
78   (*(void (*)(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);
79   return ierr;
80 }
81 
82 static PetscErrorCode ourtranspose(Mat mat, MatReuse reuse, Mat *B)
83 {
84   Mat  bb = (Mat)-1;
85   Mat *b  = (!B ? &bb : B);
86 
87   PetscCallFortranVoidFunction((*(void (*)(Mat *, MatReuse *, Mat *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_TRANSPOSE]))(&mat, &reuse, b, &ierr));
88   return PETSC_SUCCESS;
89 }
90 
91 static PetscErrorCode ourgetdiagonal(Mat mat, Vec x)
92 {
93   PetscCallFortranVoidFunction((*(void (*)(Mat *, Vec *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_GET_DIAGONAL]))(&mat, &x, &ierr));
94   return PETSC_SUCCESS;
95 }
96 
97 static PetscErrorCode ourdiagonalscale(Mat mat, Vec l, Vec r)
98 {
99   Vec  aa = (Vec)-1;
100   Vec *a  = (!l ? &aa : &l);
101   Vec *b  = (!r ? &aa : &r);
102 
103   PetscCallFortranVoidFunction((*(void (*)(Mat *, Vec *, Vec *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_DIAGONAL_SCALE]))(&mat, a, b, &ierr));
104   return PETSC_SUCCESS;
105 }
106 
107 static PetscErrorCode ourzeroentries(Mat mat)
108 {
109   PetscCallFortranVoidFunction((*(void (*)(Mat *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_ZERO_ENTRIES]))(&mat, &ierr));
110   return PETSC_SUCCESS;
111 }
112 
113 static PetscErrorCode ouraxpy(Mat mat, PetscScalar a, Mat X, MatStructure str)
114 {
115   PetscCallFortranVoidFunction((*(void (*)(Mat *, PetscScalar *, Mat *, MatStructure *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_AXPY]))(&mat, &a, &X, &str, &ierr));
116   return PETSC_SUCCESS;
117 }
118 
119 static PetscErrorCode ourshift(Mat mat, PetscScalar a)
120 {
121   PetscCallFortranVoidFunction((*(void (*)(Mat *, PetscScalar *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_SHIFT]))(&mat, &a, &ierr));
122   return PETSC_SUCCESS;
123 }
124 
125 static PetscErrorCode ourdiagonalset(Mat mat, Vec x, InsertMode ins)
126 {
127   PetscCallFortranVoidFunction((*(void (*)(Mat *, Vec *, InsertMode *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_DIAGONAL_SET]))(&mat, &x, &ins, &ierr));
128   return PETSC_SUCCESS;
129 }
130 
131 static PetscErrorCode ourdestroy(Mat mat)
132 {
133   PetscCallFortranVoidFunction((*(void (*)(Mat *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_DESTROY]))(&mat, &ierr));
134   return PETSC_SUCCESS;
135 }
136 
137 static PetscErrorCode ourview(Mat mat, PetscViewer v)
138 {
139   PetscCallFortranVoidFunction((*(void (*)(Mat *, PetscViewer *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_VIEW]))(&mat, &v, &ierr));
140   return PETSC_SUCCESS;
141 }
142 
143 static PetscErrorCode ourgetvecs(Mat mat, Vec *l, Vec *r)
144 {
145   Vec  aa = (Vec)-1;
146   Vec *a  = (!l ? &aa : l);
147   Vec *b  = (!r ? &aa : r);
148 
149   PetscCallFortranVoidFunction((*(void (*)(Mat *, Vec *, Vec *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_CREATE_VECS]))(&mat, a, b, &ierr));
150   return PETSC_SUCCESS;
151 }
152 
153 static PetscErrorCode ourgetdiagonalblock(Mat mat, Mat *l)
154 {
155   PetscCallFortranVoidFunction((*(void (*)(Mat *, Mat *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_GET_DIAGONAL_BLOCK]))(&mat, l, &ierr));
156   return PETSC_SUCCESS;
157 }
158 
159 static PetscErrorCode ourcopy(Mat mat, Mat B, MatStructure str)
160 {
161   PetscCallFortranVoidFunction((*(void (*)(Mat *, Mat *, MatStructure *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_COPY]))(&mat, &B, &str, &ierr));
162   return PETSC_SUCCESS;
163 }
164 
165 static PetscErrorCode ourscale(Mat mat, PetscScalar a)
166 {
167   PetscCallFortranVoidFunction((*(void (*)(Mat *, PetscScalar *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_SCALE]))(&mat, &a, &ierr));
168   return PETSC_SUCCESS;
169 }
170 
171 static PetscErrorCode oursetrandom(Mat mat, PetscRandom ctx)
172 {
173   PetscCallFortranVoidFunction((*(void (*)(Mat *, PetscRandom *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_SET_RANDOM]))(&mat, &ctx, &ierr));
174   return PETSC_SUCCESS;
175 }
176 
177 static PetscErrorCode ourassemblybegin(Mat mat, MatAssemblyType type)
178 {
179   PetscCallFortranVoidFunction((*(void (*)(Mat *, MatAssemblyType *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_ASSEMBLY_BEGIN]))(&mat, &type, &ierr));
180   return PETSC_SUCCESS;
181 }
182 
183 static PetscErrorCode ourassemblyend(Mat mat, MatAssemblyType type)
184 {
185   PetscCallFortranVoidFunction((*(void (*)(Mat *, MatAssemblyType *, PetscErrorCode *))(((PetscObject)mat)->fortran_func_pointers[FORTRAN_MATOP_ASSEMBLY_END]))(&mat, &type, &ierr));
186   return PETSC_SUCCESS;
187 }
188 
189 PETSC_EXTERN void matshellsetoperation_(Mat *mat, MatOperation *op, PetscErrorCode (*f)(Mat *, Vec *, Vec *, PetscErrorCode *), PetscErrorCode *ierr)
190 {
191   MPI_Comm comm;
192 
193   *ierr = PetscObjectGetComm((PetscObject)*mat, &comm);
194   if (*ierr) return;
195   PetscObjectAllocateFortranPointers(*mat, FORTRAN_MATOP_SIZE);
196 
197   switch (*op) {
198   case MATOP_MULT:
199     *ierr                                                          = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourmult);
200     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_MULT] = (PetscVoidFunction)f;
201     break;
202   case MATOP_MULT_ADD:
203     *ierr                                                              = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourmultadd);
204     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_MULT_ADD] = (PetscVoidFunction)f;
205     break;
206   case MATOP_MULT_TRANSPOSE:
207     *ierr                                                                    = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourmulttranspose);
208     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_MULT_TRANSPOSE] = (PetscVoidFunction)f;
209     break;
210   case MATOP_MULT_TRANSPOSE_ADD:
211     *ierr                                                                        = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourmulttransposeadd);
212     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_MULT_TRANSPOSE_ADD] = (PetscVoidFunction)f;
213     break;
214   case MATOP_SOR:
215     *ierr                                                         = MatShellSetOperation(*mat, *op, (PetscVoidFunction)oursor);
216     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_SOR] = (PetscVoidFunction)f;
217     break;
218   case MATOP_TRANSPOSE:
219     *ierr                                                               = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourtranspose);
220     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_TRANSPOSE] = (PetscVoidFunction)f;
221     break;
222   case MATOP_GET_DIAGONAL:
223     *ierr                                                                  = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourgetdiagonal);
224     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_GET_DIAGONAL] = (PetscVoidFunction)f;
225     break;
226   case MATOP_DIAGONAL_SCALE:
227     *ierr                                                                    = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourdiagonalscale);
228     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_DIAGONAL_SCALE] = (PetscVoidFunction)f;
229     break;
230   case MATOP_ZERO_ENTRIES:
231     *ierr                                                                  = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourzeroentries);
232     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_ZERO_ENTRIES] = (PetscVoidFunction)f;
233     break;
234   case MATOP_AXPY:
235     *ierr                                                          = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ouraxpy);
236     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_AXPY] = (PetscVoidFunction)f;
237     break;
238   case MATOP_SHIFT:
239     *ierr                                                           = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourshift);
240     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_SHIFT] = (PetscVoidFunction)f;
241     break;
242   case MATOP_DIAGONAL_SET:
243     *ierr                                                                  = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourdiagonalset);
244     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_DIAGONAL_SET] = (PetscVoidFunction)f;
245     break;
246   case MATOP_DESTROY:
247     *ierr                                                             = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourdestroy);
248     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_DESTROY] = (PetscVoidFunction)f;
249     break;
250   case MATOP_VIEW:
251     *ierr                                                          = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourview);
252     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_VIEW] = (PetscVoidFunction)f;
253     break;
254   case MATOP_CREATE_VECS:
255     *ierr                                                                 = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourgetvecs);
256     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_CREATE_VECS] = (PetscVoidFunction)f;
257     break;
258   case MATOP_GET_DIAGONAL_BLOCK:
259     *ierr                                                                        = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourgetdiagonalblock);
260     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_GET_DIAGONAL_BLOCK] = (PetscVoidFunction)f;
261     break;
262   case MATOP_COPY:
263     *ierr                                                          = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourcopy);
264     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_COPY] = (PetscVoidFunction)f;
265     break;
266   case MATOP_SCALE:
267     *ierr                                                           = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourscale);
268     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_SCALE] = (PetscVoidFunction)f;
269     break;
270   case MATOP_SET_RANDOM:
271     *ierr                                                                = MatShellSetOperation(*mat, *op, (PetscVoidFunction)oursetrandom);
272     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_SET_RANDOM] = (PetscVoidFunction)f;
273     break;
274   case MATOP_ASSEMBLY_BEGIN:
275     *ierr                                                                    = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourassemblybegin);
276     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_ASSEMBLY_BEGIN] = (PetscVoidFunction)f;
277     break;
278   case MATOP_ASSEMBLY_END:
279     *ierr                                                                  = MatShellSetOperation(*mat, *op, (PetscVoidFunction)ourassemblyend);
280     ((PetscObject)*mat)->fortran_func_pointers[FORTRAN_MATOP_ASSEMBLY_END] = (PetscVoidFunction)f;
281     break;
282   default:
283     *ierr = PetscError(comm, __LINE__, "MatShellSetOperation_Fortran", __FILE__, PETSC_ERR_ARG_WRONG, PETSC_ERROR_INITIAL, "Cannot set that matrix operation");
284     *ierr = PETSC_ERR_ARG_WRONG;
285   }
286 }
287