1e8aa55a4SKris Buschelman /*
2e8aa55a4SKris Buschelman Provides an interface to the IBM RS6000 Essl sparse solver
3e8aa55a4SKris Buschelman
4e8aa55a4SKris Buschelman */
5c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h>
6b24902e0SBarry Smith
7e8aa55a4SKris Buschelman /* #include <essl.h> This doesn't work! */
8e8aa55a4SKris Buschelman
98cc058d9SJed Brown PETSC_EXTERN void dgss(int *, int *, double *, int *, int *, int *, double *, double *, int *);
108cc058d9SJed Brown PETSC_EXTERN void dgsf(int *, int *, int *, double *, int *, int *, int *, int *, double *, double *, double *, int *);
11d3bad8c4SBarry Smith
12e8aa55a4SKris Buschelman typedef struct {
13e8aa55a4SKris Buschelman int n, nz;
14e8aa55a4SKris Buschelman PetscScalar *a;
15e8aa55a4SKris Buschelman int *ia;
16e8aa55a4SKris Buschelman int *ja;
17e8aa55a4SKris Buschelman int lna;
18e8aa55a4SKris Buschelman int iparm[5];
19e8aa55a4SKris Buschelman PetscReal rparm[5];
20e8aa55a4SKris Buschelman PetscReal oparm[5];
21e8aa55a4SKris Buschelman PetscScalar *aux;
22e8aa55a4SKris Buschelman int naux;
23e8aa55a4SKris Buschelman
24ace3abfcSBarry Smith PetscBool CleanUpESSL;
25f0c56d0fSKris Buschelman } Mat_Essl;
26f0c56d0fSKris Buschelman
MatDestroy_Essl(Mat A)2766976f2fSJacob Faibussowitsch static PetscErrorCode MatDestroy_Essl(Mat A)
28d71ae5a4SJacob Faibussowitsch {
29ac913495SBarry Smith Mat_Essl *essl = (Mat_Essl *)A->data;
30e8aa55a4SKris Buschelman
31e8aa55a4SKris Buschelman PetscFunctionBegin;
321baa6e33SBarry Smith if (essl->CleanUpESSL) PetscCall(PetscFree4(essl->a, essl->aux, essl->ia, essl->ja));
339566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data));
343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
35460c4903SKris Buschelman }
36460c4903SKris Buschelman
MatSolve_Essl(Mat A,Vec b,Vec x)3766976f2fSJacob Faibussowitsch static PetscErrorCode MatSolve_Essl(Mat A, Vec b, Vec x)
38d71ae5a4SJacob Faibussowitsch {
39ac913495SBarry Smith Mat_Essl *essl = (Mat_Essl *)A->data;
40e8aa55a4SKris Buschelman PetscScalar *xx;
41c5c20521SJed Brown int nessl, zero = 0;
42e8aa55a4SKris Buschelman
43e8aa55a4SKris Buschelman PetscFunctionBegin;
449566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(A->cmap->n, &nessl));
459566063dSJacob Faibussowitsch PetscCall(VecCopy(b, x));
469566063dSJacob Faibussowitsch PetscCall(VecGetArray(x, &xx));
47c5c20521SJed Brown dgss(&zero, &nessl, essl->a, essl->ia, essl->ja, &essl->lna, xx, essl->aux, &essl->naux);
489566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(x, &xx));
493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
50e8aa55a4SKris Buschelman }
51e8aa55a4SKris Buschelman
MatLUFactorNumeric_Essl(Mat F,Mat A,const MatFactorInfo * info)5266976f2fSJacob Faibussowitsch static PetscErrorCode MatLUFactorNumeric_Essl(Mat F, Mat A, const MatFactorInfo *info)
53d71ae5a4SJacob Faibussowitsch {
54*57508eceSPierre Jolivet Mat_SeqAIJ *aa = (Mat_SeqAIJ *)A->data;
55*57508eceSPierre Jolivet Mat_Essl *essl = (Mat_Essl *)F->data;
56c5c20521SJed Brown int nessl, i, one = 1;
57e8aa55a4SKris Buschelman
58e8aa55a4SKris Buschelman PetscFunctionBegin;
599566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(A->rmap->n, &nessl));
60da81f932SPierre Jolivet /* copy matrix data into silly ESSL data structure (1-based Fortran style) */
61d0f46423SBarry Smith for (i = 0; i < A->rmap->n + 1; i++) essl->ia[i] = aa->i[i] + 1;
62e8aa55a4SKris Buschelman for (i = 0; i < aa->nz; i++) essl->ja[i] = aa->j[i] + 1;
63e8aa55a4SKris Buschelman
649566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(essl->a, aa->a, aa->nz));
65e8aa55a4SKris Buschelman
66e8aa55a4SKris Buschelman /* set Essl options */
67e8aa55a4SKris Buschelman essl->iparm[0] = 1;
68e8aa55a4SKris Buschelman essl->iparm[1] = 5;
69e8aa55a4SKris Buschelman essl->iparm[2] = 1;
70e8aa55a4SKris Buschelman essl->iparm[3] = 0;
71e8aa55a4SKris Buschelman essl->rparm[0] = 1.e-12;
7262331464SKris Buschelman essl->rparm[1] = 1.0;
732205254eSKarl Rupp
749566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL, ((PetscObject)A)->prefix, "-matessl_lu_threshold", &essl->rparm[1], NULL));
75e8aa55a4SKris Buschelman
76c5c20521SJed Brown dgsf(&one, &nessl, &essl->nz, essl->a, essl->ia, essl->ja, &essl->lna, essl->iparm, essl->rparm, essl->oparm, essl->aux, &essl->naux);
77e8aa55a4SKris Buschelman
7835bd34faSBarry Smith F->ops->solve = MatSolve_Essl;
79*57508eceSPierre Jolivet F->assembled = PETSC_TRUE;
80*57508eceSPierre Jolivet F->preallocated = PETSC_TRUE;
813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
82e8aa55a4SKris Buschelman }
83e8aa55a4SKris Buschelman
MatLUFactorSymbolic_Essl(Mat B,Mat A,IS r,IS c,const MatFactorInfo * info)8466976f2fSJacob Faibussowitsch static PetscErrorCode MatLUFactorSymbolic_Essl(Mat B, Mat A, IS r, IS c, const MatFactorInfo *info)
85d71ae5a4SJacob Faibussowitsch {
86eef49c96SKris Buschelman Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
87f0c56d0fSKris Buschelman Mat_Essl *essl;
88e8aa55a4SKris Buschelman PetscReal f = 1.0;
89e8aa55a4SKris Buschelman
90e8aa55a4SKris Buschelman PetscFunctionBegin;
91f4f49eeaSPierre Jolivet essl = (Mat_Essl *)B->data;
92e8aa55a4SKris Buschelman
93e8aa55a4SKris Buschelman /* allocate the work arrays required by ESSL */
94e8aa55a4SKris Buschelman f = info->fill;
959566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(a->nz, &essl->nz));
969566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)(a->nz * f), &essl->lna));
979566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(100 + 10 * A->rmap->n, &essl->naux));
98e8aa55a4SKris Buschelman
99e8aa55a4SKris Buschelman /* since malloc is slow on IBM we try a single malloc */
1009566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(essl->lna, &essl->a, essl->naux, &essl->aux, essl->lna, &essl->ia, essl->lna, &essl->ja));
1012205254eSKarl Rupp
1022f71e704SKris Buschelman essl->CleanUpESSL = PETSC_TRUE;
103e8aa55a4SKris Buschelman
104db4efbfdSBarry Smith B->ops->lufactornumeric = MatLUFactorNumeric_Essl;
1053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
106e8aa55a4SKris Buschelman }
107e8aa55a4SKris Buschelman
MatFactorGetSolverType_essl(Mat A,MatSolverType * type)10866976f2fSJacob Faibussowitsch static PetscErrorCode MatFactorGetSolverType_essl(Mat A, MatSolverType *type)
109d71ae5a4SJacob Faibussowitsch {
11035bd34faSBarry Smith PetscFunctionBegin;
1112692d6eeSBarry Smith *type = MATSOLVERESSL;
1123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
11335bd34faSBarry Smith }
114719d5645SBarry Smith
1152f71e704SKris Buschelman /*MC
1162ef1f0ffSBarry Smith MATSOLVERESSL - "essl" - Provides direct solvers, LU, for sequential matrices via the external package ESSL.
1172f71e704SKris Buschelman
11811a5261eSBarry Smith Works with `MATSEQAIJ` matrices
1192f71e704SKris Buschelman
1202f71e704SKris Buschelman Level: beginner
1212f71e704SKris Buschelman
1221cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `PCLU`, `PCFactorSetMatSolverType()`, `MatSolverType`
1232f71e704SKris Buschelman M*/
1242f71e704SKris Buschelman
MatGetFactor_seqaij_essl(Mat A,MatFactorType ftype,Mat * F)125d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatGetFactor_seqaij_essl(Mat A, MatFactorType ftype, Mat *F)
126d71ae5a4SJacob Faibussowitsch {
127b24902e0SBarry Smith Mat B;
128b24902e0SBarry Smith Mat_Essl *essl;
129e8aa55a4SKris Buschelman
130e8aa55a4SKris Buschelman PetscFunctionBegin;
13108401ef6SPierre Jolivet PetscCheck(A->cmap->N == A->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "matrix must be square");
1329566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
1339566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, PETSC_DECIDE, PETSC_DECIDE, A->rmap->n, A->cmap->n));
1349566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy("essl", &((PetscObject)B)->type_name));
1359566063dSJacob Faibussowitsch PetscCall(MatSetUp(B));
136b24902e0SBarry Smith
1374dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&essl));
1382205254eSKarl Rupp
139ac913495SBarry Smith B->data = essl;
140b24902e0SBarry Smith B->ops->lufactorsymbolic = MatLUFactorSymbolic_Essl;
141ac913495SBarry Smith B->ops->destroy = MatDestroy_Essl;
142ac913495SBarry Smith B->ops->getinfo = MatGetInfo_External;
1432205254eSKarl Rupp
1449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatFactorGetSolverType_C", MatFactorGetSolverType_essl));
1452205254eSKarl Rupp
146d5f3da31SBarry Smith B->factortype = MAT_FACTOR_LU;
1479566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&B->preferredordering[MAT_FACTOR_LU]));
1489566063dSJacob Faibussowitsch PetscCall(PetscFree(B->solvertype));
1499566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERESSL, &B->solvertype));
15000c67f3bSHong Zhang
151b24902e0SBarry Smith *F = B;
1523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
153e8aa55a4SKris Buschelman }
15442c9c57cSBarry Smith
MatSolverTypeRegister_Essl(void)155d1f0640dSPierre Jolivet PETSC_INTERN PetscErrorCode MatSolverTypeRegister_Essl(void)
156d71ae5a4SJacob Faibussowitsch {
15742c9c57cSBarry Smith PetscFunctionBegin;
1589566063dSJacob Faibussowitsch PetscCall(MatSolverTypeRegister(MATSOLVERESSL, MATSEQAIJ, MAT_FACTOR_LU, MatGetFactor_seqaij_essl));
1593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
16042c9c57cSBarry Smith }
161