xref: /petsc/src/mat/impls/aij/seq/essl/essl.c (revision be1d678a52e6eff2808b2fa31ae986cdbf03c9fe)
1 #define PETSCMAT_DLL
2 
3 /*
4         Provides an interface to the IBM RS6000 Essl sparse solver
5 
6 */
7 #include "src/mat/impls/aij/seq/aij.h"
8 /* #include <essl.h> This doesn't work!  */
9 
10 typedef struct {
11   int         n,nz;
12   PetscScalar *a;
13   int         *ia;
14   int         *ja;
15   int         lna;
16   int         iparm[5];
17   PetscReal   rparm[5];
18   PetscReal   oparm[5];
19   PetscScalar *aux;
20   int         naux;
21 
22   PetscErrorCode (*MatDuplicate)(Mat,MatDuplicateOption,Mat*);
23   PetscErrorCode (*MatAssemblyEnd)(Mat,MatAssemblyType);
24   PetscErrorCode (*MatLUFactorSymbolic)(Mat,IS,IS,MatFactorInfo*,Mat*);
25   PetscErrorCode (*MatDestroy)(Mat);
26   PetscTruth CleanUpESSL;
27 } Mat_Essl;
28 
29 EXTERN PetscErrorCode MatDuplicate_Essl(Mat,MatDuplicateOption,Mat*);
30 
31 EXTERN_C_BEGIN
32 #undef __FUNCT__
33 #define __FUNCT__ "MatConvert_Essl_SeqAIJ"
34 PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_Essl_SeqAIJ(Mat A,const MatType type,MatReuse reuse,Mat *newmat) {
35   PetscErrorCode ierr;
36   Mat      B=*newmat;
37   Mat_Essl *essl=(Mat_Essl*)A->spptr;
38 
39   PetscFunctionBegin;
40   if (reuse == MAT_INITIAL_MATRIX) {
41     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);
42   }
43   B->ops->duplicate        = essl->MatDuplicate;
44   B->ops->assemblyend      = essl->MatAssemblyEnd;
45   B->ops->lufactorsymbolic = essl->MatLUFactorSymbolic;
46   B->ops->destroy          = essl->MatDestroy;
47 
48   /* free the Essl datastructures */
49   ierr = PetscFree(essl);CHKERRQ(ierr);
50 
51   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_essl_C","",PETSC_NULL);CHKERRQ(ierr);
52   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_essl_seqaij_C","",PETSC_NULL);CHKERRQ(ierr);
53 
54   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
55   *newmat = B;
56   PetscFunctionReturn(0);
57 }
58 EXTERN_C_END
59 
60 #undef __FUNCT__
61 #define __FUNCT__ "MatDestroy_Essl"
62 PetscErrorCode MatDestroy_Essl(Mat A)
63 {
64   PetscErrorCode ierr;
65   Mat_Essl *essl=(Mat_Essl*)A->spptr;
66 
67   PetscFunctionBegin;
68   if (essl->CleanUpESSL) {
69     ierr = PetscFree(essl->a);CHKERRQ(ierr);
70   }
71   ierr = MatConvert_Essl_SeqAIJ(A,MATSEQAIJ,MAT_REUSE_MATRIX,&A);
72   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
73   PetscFunctionReturn(0);
74 }
75 
76 #undef __FUNCT__
77 #define __FUNCT__ "MatSolve_Essl"
78 PetscErrorCode MatSolve_Essl(Mat A,Vec b,Vec x) {
79   Mat_Essl    *essl = (Mat_Essl*)A->spptr;
80   PetscScalar *xx;
81   PetscErrorCode ierr;
82   int         m,zero = 0;
83 
84   PetscFunctionBegin;
85   ierr = VecGetLocalSize(b,&m);CHKERRQ(ierr);
86   ierr = VecCopy(b,x);CHKERRQ(ierr);
87   ierr = VecGetArray(x,&xx);CHKERRQ(ierr);
88   dgss(&zero,&A->n,essl->a,essl->ia,essl->ja,&essl->lna,xx,essl->aux,&essl->naux);
89   ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr);
90   PetscFunctionReturn(0);
91 }
92 
93 #undef __FUNCT__
94 #define __FUNCT__ "MatLUFactorNumeric_Essl"
95 PetscErrorCode MatLUFactorNumeric_Essl(Mat A,MatFactorInfo *info,Mat *F) {
96   Mat_SeqAIJ     *aa=(Mat_SeqAIJ*)(A)->data;
97   Mat_Essl       *essl=(Mat_Essl*)(*F)->spptr;
98   PetscErrorCode ierr;
99   int            i,one = 1;
100 
101   PetscFunctionBegin;
102   /* copy matrix data into silly ESSL data structure (1-based Frotran style) */
103   for (i=0; i<A->m+1; i++) essl->ia[i] = aa->i[i] + 1;
104   for (i=0; i<aa->nz; i++) essl->ja[i]  = aa->j[i] + 1;
105 
106   ierr = PetscMemcpy(essl->a,aa->a,(aa->nz)*sizeof(PetscScalar));CHKERRQ(ierr);
107 
108   /* set Essl options */
109   essl->iparm[0] = 1;
110   essl->iparm[1] = 5;
111   essl->iparm[2] = 1;
112   essl->iparm[3] = 0;
113   essl->rparm[0] = 1.e-12;
114   essl->rparm[1] = 1.0;
115   ierr = PetscOptionsGetReal(A->prefix,"-matessl_lu_threshold",&essl->rparm[1],PETSC_NULL);CHKERRQ(ierr);
116 
117   dgsf(&one,&A->m,&essl->nz,essl->a,essl->ia,essl->ja,&essl->lna,essl->iparm,
118                essl->rparm,essl->oparm,essl->aux,&essl->naux);
119 
120   PetscFunctionReturn(0);
121 }
122 
123 #undef __FUNCT__
124 #define __FUNCT__ "MatLUFactorSymbolic_Essl"
125 PetscErrorCode MatLUFactorSymbolic_Essl(Mat A,IS r,IS c,MatFactorInfo *info,Mat *F) {
126   Mat        B;
127   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
128   PetscErrorCode ierr;
129   int        len;
130   Mat_Essl   *essl;
131   PetscReal  f = 1.0;
132 
133   PetscFunctionBegin;
134   if (A->N != A->M) SETERRQ(PETSC_ERR_ARG_SIZ,"matrix must be square");
135   ierr = MatCreate(A->comm,PETSC_DECIDE,PETSC_DECIDE,A->m,A->n,&B);CHKERRQ(ierr);
136   ierr = MatSetType(B,A->type_name);CHKERRQ(ierr);
137   ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr);
138 
139   B->ops->solve           = MatSolve_Essl;
140   B->ops->lufactornumeric = MatLUFactorNumeric_Essl;
141   B->factor               = FACTOR_LU;
142 
143   essl = (Mat_Essl *)(B->spptr);
144 
145   /* allocate the work arrays required by ESSL */
146   f = info->fill;
147   essl->nz   = a->nz;
148   essl->lna  = (int)a->nz*f;
149   essl->naux = 100 + 10*A->m;
150 
151   /* since malloc is slow on IBM we try a single malloc */
152   len               = essl->lna*(2*sizeof(int)+sizeof(PetscScalar)) + essl->naux*sizeof(PetscScalar);
153   ierr              = PetscMalloc(len,&essl->a);CHKERRQ(ierr);
154   essl->aux         = essl->a + essl->lna;
155   essl->ia          = (int*)(essl->aux + essl->naux);
156   essl->ja          = essl->ia + essl->lna;
157   essl->CleanUpESSL = PETSC_TRUE;
158 
159   ierr = PetscLogObjectMemory(B,len+sizeof(Mat_Essl));CHKERRQ(ierr);
160   *F = B;
161   PetscFunctionReturn(0);
162 }
163 
164 #undef __FUNCT__
165 #define __FUNCT__ "MatAssemblyEnd_Essl"
166 PetscErrorCode MatAssemblyEnd_Essl(Mat A,MatAssemblyType mode) {
167   PetscErrorCode ierr;
168   Mat_Essl *essl=(Mat_Essl*)(A->spptr);
169 
170   PetscFunctionBegin;
171   ierr = (*essl->MatAssemblyEnd)(A,mode);CHKERRQ(ierr);
172 
173   essl->MatLUFactorSymbolic = A->ops->lufactorsymbolic;
174   A->ops->lufactorsymbolic  = MatLUFactorSymbolic_Essl;
175   ierr = PetscLogInfo((0,"MatAssemblyEnd_Essl:Using ESSL for LU factorization and solves\n"));CHKERRQ(ierr);
176   PetscFunctionReturn(0);
177 }
178 
179 EXTERN_C_BEGIN
180 #undef __FUNCT__
181 #define __FUNCT__ "MatConvert_SeqAIJ_Essl"
182 PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqAIJ_Essl(Mat A,const MatType type,MatReuse reuse,Mat *newmat)
183 {
184   Mat      B=*newmat;
185   PetscErrorCode ierr;
186   Mat_Essl *essl;
187 
188   PetscFunctionBegin;
189   if (reuse == MAT_INITIAL_MATRIX) {
190     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
191   }
192 
193   ierr                      = PetscNew(Mat_Essl,&essl);CHKERRQ(ierr);
194   essl->MatDuplicate        = A->ops->duplicate;
195   essl->MatAssemblyEnd      = A->ops->assemblyend;
196   essl->MatLUFactorSymbolic = A->ops->lufactorsymbolic;
197   essl->MatDestroy          = A->ops->destroy;
198   essl->CleanUpESSL         = PETSC_FALSE;
199 
200   B->spptr                  = (void*)essl;
201   B->ops->duplicate         = MatDuplicate_Essl;
202   B->ops->assemblyend       = MatAssemblyEnd_Essl;
203   B->ops->lufactorsymbolic  = MatLUFactorSymbolic_Essl;
204   B->ops->destroy           = MatDestroy_Essl;
205 
206   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_essl_C",
207                                            "MatConvert_SeqAIJ_Essl",MatConvert_SeqAIJ_Essl);CHKERRQ(ierr);
208   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_essl_seqaij_C",
209                                            "MatConvert_Essl_SeqAIJ",MatConvert_Essl_SeqAIJ);CHKERRQ(ierr);
210   ierr = PetscObjectChangeTypeName((PetscObject)B,type);CHKERRQ(ierr);
211 
212   *newmat = B;
213   PetscFunctionReturn(0);
214 }
215 EXTERN_C_END
216 
217 #undef __FUNCT__
218 #define __FUNCT__ "MatDuplicate_Essl"
219 PetscErrorCode MatDuplicate_Essl(Mat A, MatDuplicateOption op, Mat *M) {
220   PetscErrorCode ierr;
221   Mat_Essl *lu = (Mat_Essl *)A->spptr;
222 
223   PetscFunctionBegin;
224   ierr = (*lu->MatDuplicate)(A,op,M);CHKERRQ(ierr);
225   ierr = PetscMemcpy((*M)->spptr,lu,sizeof(Mat_Essl));CHKERRQ(ierr);
226   PetscFunctionReturn(0);
227 }
228 
229 /*MC
230   MATESSL - MATESSL = "essl" - A matrix type providing direct solvers (LU) for sequential matrices
231   via the external package ESSL.
232 
233   If ESSL is installed (see the manual for
234   instructions on how to declare the existence of external packages),
235   a matrix type can be constructed which invokes ESSL solvers.
236   After calling MatCreate(...,A), simply call MatSetType(A,MATESSL).
237   This matrix type is only supported for double precision real.
238 
239   This matrix inherits from MATSEQAIJ.  As a result, MatSeqAIJSetPreallocation is
240   supported for this matrix type.  One can also call MatConvert for an inplace conversion to or from
241   the MATSEQAIJ type without data copy.
242 
243   Options Database Keys:
244 . -mat_type essl - sets the matrix type to "essl" during a call to MatSetFromOptions()
245 
246    Level: beginner
247 
248 .seealso: PCLU
249 M*/
250 
251 EXTERN_C_BEGIN
252 #undef __FUNCT__
253 #define __FUNCT__ "MatCreate_Essl"
254 PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_Essl(Mat A)
255 {
256   PetscErrorCode ierr;
257 
258   PetscFunctionBegin;
259   /* Change type name before calling MatSetType to force proper construction of SeqAIJ and Essl types */
260   ierr = PetscObjectChangeTypeName((PetscObject)A,MATESSL);CHKERRQ(ierr);
261   ierr = MatSetType(A,MATSEQAIJ);
262   ierr = MatConvert_SeqAIJ_Essl(A,MATESSL,MAT_REUSE_MATRIX,&A);CHKERRQ(ierr);
263   PetscFunctionReturn(0);
264 }
265 EXTERN_C_END
266