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