1d5d45c9bSBarry Smith /* 23369ce9aSBarry Smith Defines the basic matrix operations for the AIJ (compressed row) 3d5d45c9bSBarry Smith matrix storage format. 4d5d45c9bSBarry Smith */ 53369ce9aSBarry Smith 6c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h> /*I "petscmat.h" I*/ 7c6db04a5SJed Brown #include <petscblaslapack.h> 8c6db04a5SJed Brown #include <petscbt.h> 9af0996ceSBarry Smith #include <petsc/private/kernels/blocktranspose.h> 100716a85fSBarry Smith 114099cc6bSBarry Smith PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A) 124099cc6bSBarry Smith { 134099cc6bSBarry Smith PetscBool flg; 144099cc6bSBarry Smith char type[256]; 154099cc6bSBarry Smith 164099cc6bSBarry Smith PetscFunctionBegin; 17d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)A); 189566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-mat_seqaij_type","Matrix SeqAIJ type","MatSeqAIJSetType",MatSeqAIJList,"seqaij",type,256,&flg)); 199566063dSJacob Faibussowitsch if (flg) PetscCall(MatSeqAIJSetType(A,type)); 20d0609cedSBarry Smith PetscOptionsEnd(); 214099cc6bSBarry Smith PetscFunctionReturn(0); 224099cc6bSBarry Smith } 234099cc6bSBarry Smith 24857cbf51SRichard Tran Mills PetscErrorCode MatGetColumnReductions_SeqAIJ(Mat A,PetscInt type,PetscReal *reductions) 250716a85fSBarry Smith { 260716a85fSBarry Smith PetscInt i,m,n; 270716a85fSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 280716a85fSBarry Smith 290716a85fSBarry Smith PetscFunctionBegin; 309566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&m,&n)); 319566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(reductions,n)); 320716a85fSBarry Smith if (type == NORM_2) { 330716a85fSBarry Smith for (i=0; i<aij->i[m]; i++) { 34a873a8cdSSam Reynolds reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]); 350716a85fSBarry Smith } 360716a85fSBarry Smith } else if (type == NORM_1) { 370716a85fSBarry Smith for (i=0; i<aij->i[m]; i++) { 38a873a8cdSSam Reynolds reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]); 390716a85fSBarry Smith } 400716a85fSBarry Smith } else if (type == NORM_INFINITY) { 410716a85fSBarry Smith for (i=0; i<aij->i[m]; i++) { 42a873a8cdSSam Reynolds reductions[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),reductions[aij->j[i]]); 430716a85fSBarry Smith } 44857cbf51SRichard Tran Mills } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) { 45a873a8cdSSam Reynolds for (i=0; i<aij->i[m]; i++) { 46857cbf51SRichard Tran Mills reductions[aij->j[i]] += PetscRealPart(aij->a[i]); 47a873a8cdSSam Reynolds } 48857cbf51SRichard Tran Mills } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) { 49857cbf51SRichard Tran Mills for (i=0; i<aij->i[m]; i++) { 50857cbf51SRichard Tran Mills reductions[aij->j[i]] += PetscImaginaryPart(aij->a[i]); 51857cbf51SRichard Tran Mills } 52857cbf51SRichard Tran Mills } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown reduction type"); 530716a85fSBarry Smith 540716a85fSBarry Smith if (type == NORM_2) { 55a873a8cdSSam Reynolds for (i=0; i<n; i++) reductions[i] = PetscSqrtReal(reductions[i]); 56857cbf51SRichard Tran Mills } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) { 57a873a8cdSSam Reynolds for (i=0; i<n; i++) reductions[i] /= m; 580716a85fSBarry Smith } 590716a85fSBarry Smith PetscFunctionReturn(0); 600716a85fSBarry Smith } 610716a85fSBarry Smith 623a062f41SBarry Smith PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A,IS *is) 633a062f41SBarry Smith { 643a062f41SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 653a062f41SBarry Smith PetscInt i,m=A->rmap->n,cnt = 0, bs = A->rmap->bs; 663a062f41SBarry Smith const PetscInt *jj = a->j,*ii = a->i; 673a062f41SBarry Smith PetscInt *rows; 683a062f41SBarry Smith 693a062f41SBarry Smith PetscFunctionBegin; 703a062f41SBarry Smith for (i=0; i<m; i++) { 713a062f41SBarry Smith if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) { 723a062f41SBarry Smith cnt++; 733a062f41SBarry Smith } 743a062f41SBarry Smith } 759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cnt,&rows)); 763a062f41SBarry Smith cnt = 0; 773a062f41SBarry Smith for (i=0; i<m; i++) { 783a062f41SBarry Smith if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) { 793a062f41SBarry Smith rows[cnt] = i; 803a062f41SBarry Smith cnt++; 813a062f41SBarry Smith } 823a062f41SBarry Smith } 839566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,is)); 843a062f41SBarry Smith PetscFunctionReturn(0); 853a062f41SBarry Smith } 863a062f41SBarry Smith 87f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A,PetscInt *nrows,PetscInt **zrows) 886ce1633cSBarry Smith { 896ce1633cSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 90fff043a9SJunchao Zhang const MatScalar *aa; 916ce1633cSBarry Smith PetscInt i,m=A->rmap->n,cnt = 0; 92b2db7409Sstefano_zampini const PetscInt *ii = a->i,*jj = a->j,*diag; 936ce1633cSBarry Smith PetscInt *rows; 946ce1633cSBarry Smith 956ce1633cSBarry Smith PetscFunctionBegin; 969566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 979566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 986ce1633cSBarry Smith diag = a->diag; 996ce1633cSBarry Smith for (i=0; i<m; i++) { 100b2db7409Sstefano_zampini if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) { 1016ce1633cSBarry Smith cnt++; 1026ce1633cSBarry Smith } 1036ce1633cSBarry Smith } 1049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cnt,&rows)); 1056ce1633cSBarry Smith cnt = 0; 1066ce1633cSBarry Smith for (i=0; i<m; i++) { 107b2db7409Sstefano_zampini if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) { 1086ce1633cSBarry Smith rows[cnt++] = i; 1096ce1633cSBarry Smith } 1106ce1633cSBarry Smith } 111f1f41ecbSJed Brown *nrows = cnt; 112f1f41ecbSJed Brown *zrows = rows; 1139566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 114f1f41ecbSJed Brown PetscFunctionReturn(0); 115f1f41ecbSJed Brown } 116f1f41ecbSJed Brown 117f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows) 118f1f41ecbSJed Brown { 119f1f41ecbSJed Brown PetscInt nrows,*rows; 120f1f41ecbSJed Brown 121f1f41ecbSJed Brown PetscFunctionBegin; 1220298fd71SBarry Smith *zrows = NULL; 1239566063dSJacob Faibussowitsch PetscCall(MatFindZeroDiagonals_SeqAIJ_Private(A,&nrows,&rows)); 1249566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A),nrows,rows,PETSC_OWN_POINTER,zrows)); 1256ce1633cSBarry Smith PetscFunctionReturn(0); 1266ce1633cSBarry Smith } 1276ce1633cSBarry Smith 128b3a44c85SBarry Smith PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows) 129b3a44c85SBarry Smith { 130b3a44c85SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 131b3a44c85SBarry Smith const MatScalar *aa; 132b3a44c85SBarry Smith PetscInt m=A->rmap->n,cnt = 0; 133b3a44c85SBarry Smith const PetscInt *ii; 134b3a44c85SBarry Smith PetscInt n,i,j,*rows; 135b3a44c85SBarry Smith 136b3a44c85SBarry Smith PetscFunctionBegin; 1379566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 138f4259b30SLisandro Dalcin *keptrows = NULL; 139b3a44c85SBarry Smith ii = a->i; 140b3a44c85SBarry Smith for (i=0; i<m; i++) { 141b3a44c85SBarry Smith n = ii[i+1] - ii[i]; 142b3a44c85SBarry Smith if (!n) { 143b3a44c85SBarry Smith cnt++; 144b3a44c85SBarry Smith goto ok1; 145b3a44c85SBarry Smith } 1462e5835c6SStefano Zampini for (j=ii[i]; j<ii[i+1]; j++) { 147b3a44c85SBarry Smith if (aa[j] != 0.0) goto ok1; 148b3a44c85SBarry Smith } 149b3a44c85SBarry Smith cnt++; 150b3a44c85SBarry Smith ok1:; 151b3a44c85SBarry Smith } 1522e5835c6SStefano Zampini if (!cnt) { 1539566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 1542e5835c6SStefano Zampini PetscFunctionReturn(0); 1552e5835c6SStefano Zampini } 1569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n-cnt,&rows)); 157b3a44c85SBarry Smith cnt = 0; 158b3a44c85SBarry Smith for (i=0; i<m; i++) { 159b3a44c85SBarry Smith n = ii[i+1] - ii[i]; 160b3a44c85SBarry Smith if (!n) continue; 1612e5835c6SStefano Zampini for (j=ii[i]; j<ii[i+1]; j++) { 162b3a44c85SBarry Smith if (aa[j] != 0.0) { 163b3a44c85SBarry Smith rows[cnt++] = i; 164b3a44c85SBarry Smith break; 165b3a44c85SBarry Smith } 166b3a44c85SBarry Smith } 167b3a44c85SBarry Smith } 1689566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 1699566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows)); 170b3a44c85SBarry Smith PetscFunctionReturn(0); 171b3a44c85SBarry Smith } 172b3a44c85SBarry Smith 1737087cfbeSBarry Smith PetscErrorCode MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is) 17479299369SBarry Smith { 17579299369SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*) Y->data; 17699e65526SBarry Smith PetscInt i,m = Y->rmap->n; 17799e65526SBarry Smith const PetscInt *diag; 1782e5835c6SStefano Zampini MatScalar *aa; 17999e65526SBarry Smith const PetscScalar *v; 180ace3abfcSBarry Smith PetscBool missing; 18179299369SBarry Smith 18279299369SBarry Smith PetscFunctionBegin; 18309f38230SBarry Smith if (Y->assembled) { 1849566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal_SeqAIJ(Y,&missing,NULL)); 18509f38230SBarry Smith if (!missing) { 18679299369SBarry Smith diag = aij->diag; 1879566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(D,&v)); 1889566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Y,&aa)); 18979299369SBarry Smith if (is == INSERT_VALUES) { 19079299369SBarry Smith for (i=0; i<m; i++) { 19179299369SBarry Smith aa[diag[i]] = v[i]; 19279299369SBarry Smith } 19379299369SBarry Smith } else { 19479299369SBarry Smith for (i=0; i<m; i++) { 19579299369SBarry Smith aa[diag[i]] += v[i]; 19679299369SBarry Smith } 19779299369SBarry Smith } 1989566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Y,&aa)); 1999566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(D,&v)); 20079299369SBarry Smith PetscFunctionReturn(0); 20179299369SBarry Smith } 2029566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(Y)); 20309f38230SBarry Smith } 2049566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet_Default(Y,D,is)); 20509f38230SBarry Smith PetscFunctionReturn(0); 20609f38230SBarry Smith } 20779299369SBarry Smith 2081a83f524SJed Brown PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,const PetscInt *ia[],const PetscInt *ja[],PetscBool *done) 20917ab2063SBarry Smith { 210416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 21197f1f81fSBarry Smith PetscInt i,ishift; 21217ab2063SBarry Smith 2133a40ed3dSBarry Smith PetscFunctionBegin; 214d0f46423SBarry Smith *m = A->rmap->n; 2153a40ed3dSBarry Smith if (!ia) PetscFunctionReturn(0); 216bfeeae90SHong Zhang ishift = 0; 21753e63a63SBarry Smith if (symmetric && !A->structurally_symmetric) { 2189566063dSJacob Faibussowitsch PetscCall(MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,ishift,oshift,(PetscInt**)ia,(PetscInt**)ja)); 219bfeeae90SHong Zhang } else if (oshift == 1) { 2201a83f524SJed Brown PetscInt *tia; 221d0f46423SBarry Smith PetscInt nz = a->i[A->rmap->n]; 2223b2fbd54SBarry Smith /* malloc space and add 1 to i and j indices */ 2239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n+1,&tia)); 2241a83f524SJed Brown for (i=0; i<A->rmap->n+1; i++) tia[i] = a->i[i] + 1; 2251a83f524SJed Brown *ia = tia; 226ecc77c7aSBarry Smith if (ja) { 2271a83f524SJed Brown PetscInt *tja; 2289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz+1,&tja)); 2291a83f524SJed Brown for (i=0; i<nz; i++) tja[i] = a->j[i] + 1; 2301a83f524SJed Brown *ja = tja; 231ecc77c7aSBarry Smith } 2326945ee14SBarry Smith } else { 233ecc77c7aSBarry Smith *ia = a->i; 234ecc77c7aSBarry Smith if (ja) *ja = a->j; 235a2ce50c7SBarry Smith } 2363a40ed3dSBarry Smith PetscFunctionReturn(0); 237a2744918SBarry Smith } 238a2744918SBarry Smith 2391a83f524SJed Brown PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool *done) 2406945ee14SBarry Smith { 2413a40ed3dSBarry Smith PetscFunctionBegin; 2423a40ed3dSBarry Smith if (!ia) PetscFunctionReturn(0); 243bfeeae90SHong Zhang if ((symmetric && !A->structurally_symmetric) || oshift == 1) { 2449566063dSJacob Faibussowitsch PetscCall(PetscFree(*ia)); 2459566063dSJacob Faibussowitsch if (ja) PetscCall(PetscFree(*ja)); 246bcd2baecSBarry Smith } 2473a40ed3dSBarry Smith PetscFunctionReturn(0); 24817ab2063SBarry Smith } 24917ab2063SBarry Smith 2501a83f524SJed Brown PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscBool *done) 2513b2fbd54SBarry Smith { 2523b2fbd54SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 253d0f46423SBarry Smith PetscInt i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n; 25497f1f81fSBarry Smith PetscInt nz = a->i[m],row,*jj,mr,col; 2553b2fbd54SBarry Smith 2563a40ed3dSBarry Smith PetscFunctionBegin; 257899cda47SBarry Smith *nn = n; 2583a40ed3dSBarry Smith if (!ia) PetscFunctionReturn(0); 2593b2fbd54SBarry Smith if (symmetric) { 2609566063dSJacob Faibussowitsch PetscCall(MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,0,oshift,(PetscInt**)ia,(PetscInt**)ja)); 2613b2fbd54SBarry Smith } else { 2629566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n,&collengths)); 2639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n+1,&cia)); 2649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz,&cja)); 2653b2fbd54SBarry Smith jj = a->j; 2663b2fbd54SBarry Smith for (i=0; i<nz; i++) { 267bfeeae90SHong Zhang collengths[jj[i]]++; 2683b2fbd54SBarry Smith } 2693b2fbd54SBarry Smith cia[0] = oshift; 2703b2fbd54SBarry Smith for (i=0; i<n; i++) { 2713b2fbd54SBarry Smith cia[i+1] = cia[i] + collengths[i]; 2723b2fbd54SBarry Smith } 2739566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(collengths,n)); 2743b2fbd54SBarry Smith jj = a->j; 275a93ec695SBarry Smith for (row=0; row<m; row++) { 276a93ec695SBarry Smith mr = a->i[row+1] - a->i[row]; 277a93ec695SBarry Smith for (i=0; i<mr; i++) { 278bfeeae90SHong Zhang col = *jj++; 2792205254eSKarl Rupp 2803b2fbd54SBarry Smith cja[cia[col] + collengths[col]++ - oshift] = row + oshift; 2813b2fbd54SBarry Smith } 2823b2fbd54SBarry Smith } 2839566063dSJacob Faibussowitsch PetscCall(PetscFree(collengths)); 2843b2fbd54SBarry Smith *ia = cia; *ja = cja; 2853b2fbd54SBarry Smith } 2863a40ed3dSBarry Smith PetscFunctionReturn(0); 2873b2fbd54SBarry Smith } 2883b2fbd54SBarry Smith 2891a83f524SJed Brown PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool *done) 2903b2fbd54SBarry Smith { 2913a40ed3dSBarry Smith PetscFunctionBegin; 2923a40ed3dSBarry Smith if (!ia) PetscFunctionReturn(0); 2933b2fbd54SBarry Smith 2949566063dSJacob Faibussowitsch PetscCall(PetscFree(*ia)); 2959566063dSJacob Faibussowitsch PetscCall(PetscFree(*ja)); 2963a40ed3dSBarry Smith PetscFunctionReturn(0); 2973b2fbd54SBarry Smith } 2983b2fbd54SBarry Smith 2997cee066cSHong Zhang /* 3007cee066cSHong Zhang MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from 3017cee066cSHong Zhang MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output 302040ebd07SHong Zhang spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ() 3037cee066cSHong Zhang */ 3047cee066cSHong Zhang PetscErrorCode MatGetColumnIJ_SeqAIJ_Color(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscInt *spidx[],PetscBool *done) 3057cee066cSHong Zhang { 3067cee066cSHong Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3077cee066cSHong Zhang PetscInt i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n; 308071fcb05SBarry Smith PetscInt nz = a->i[m],row,mr,col,tmp; 3097cee066cSHong Zhang PetscInt *cspidx; 310071fcb05SBarry Smith const PetscInt *jj; 3117cee066cSHong Zhang 3127cee066cSHong Zhang PetscFunctionBegin; 3137cee066cSHong Zhang *nn = n; 3147cee066cSHong Zhang if (!ia) PetscFunctionReturn(0); 315625f6d37SHong Zhang 3169566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n,&collengths)); 3179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n+1,&cia)); 3189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz,&cja)); 3199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz,&cspidx)); 3207cee066cSHong Zhang jj = a->j; 3217cee066cSHong Zhang for (i=0; i<nz; i++) { 3227cee066cSHong Zhang collengths[jj[i]]++; 3237cee066cSHong Zhang } 3247cee066cSHong Zhang cia[0] = oshift; 3257cee066cSHong Zhang for (i=0; i<n; i++) { 3267cee066cSHong Zhang cia[i+1] = cia[i] + collengths[i]; 3277cee066cSHong Zhang } 3289566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(collengths,n)); 3297cee066cSHong Zhang jj = a->j; 3307cee066cSHong Zhang for (row=0; row<m; row++) { 3317cee066cSHong Zhang mr = a->i[row+1] - a->i[row]; 3327cee066cSHong Zhang for (i=0; i<mr; i++) { 3337cee066cSHong Zhang col = *jj++; 334071fcb05SBarry Smith tmp = cia[col] + collengths[col]++ - oshift; 335071fcb05SBarry Smith cspidx[tmp] = a->i[row] + i; /* index of a->j */ 336071fcb05SBarry Smith cja[tmp] = row + oshift; 3377cee066cSHong Zhang } 3387cee066cSHong Zhang } 3399566063dSJacob Faibussowitsch PetscCall(PetscFree(collengths)); 340071fcb05SBarry Smith *ia = cia; 341071fcb05SBarry Smith *ja = cja; 3427cee066cSHong Zhang *spidx = cspidx; 3437cee066cSHong Zhang PetscFunctionReturn(0); 3447cee066cSHong Zhang } 3457cee066cSHong Zhang 3467cee066cSHong Zhang PetscErrorCode MatRestoreColumnIJ_SeqAIJ_Color(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscInt *spidx[],PetscBool *done) 3477cee066cSHong Zhang { 3487cee066cSHong Zhang PetscFunctionBegin; 3499566063dSJacob Faibussowitsch PetscCall(MatRestoreColumnIJ_SeqAIJ(A,oshift,symmetric,inodecompressed,n,ia,ja,done)); 3509566063dSJacob Faibussowitsch PetscCall(PetscFree(*spidx)); 3517cee066cSHong Zhang PetscFunctionReturn(0); 3527cee066cSHong Zhang } 3537cee066cSHong Zhang 35487d4246cSBarry Smith PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[]) 35587d4246cSBarry Smith { 35687d4246cSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 35787d4246cSBarry Smith PetscInt *ai = a->i; 358fff043a9SJunchao Zhang PetscScalar *aa; 35987d4246cSBarry Smith 36087d4246cSBarry Smith PetscFunctionBegin; 3619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&aa)); 3629566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aa+ai[row],v,ai[row+1]-ai[row])); 3639566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&aa)); 36487d4246cSBarry Smith PetscFunctionReturn(0); 36587d4246cSBarry Smith } 36687d4246cSBarry Smith 367bd04181cSBarry Smith /* 368bd04181cSBarry Smith MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions 369bd04181cSBarry Smith 370bd04181cSBarry Smith - a single row of values is set with each call 371bd04181cSBarry Smith - no row or column indices are negative or (in error) larger than the number of rows or columns 372bd04181cSBarry Smith - the values are always added to the matrix, not set 373bd04181cSBarry Smith - no new locations are introduced in the nonzero structure of the matrix 374bd04181cSBarry Smith 3751f763a69SBarry Smith This does NOT assume the global column indices are sorted 376bd04181cSBarry Smith 3771f763a69SBarry Smith */ 378bd04181cSBarry Smith 379af0996ceSBarry Smith #include <petsc/private/isimpl.h> 380189e4007SBarry Smith PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is) 381189e4007SBarry Smith { 382189e4007SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3831f763a69SBarry Smith PetscInt low,high,t,row,nrow,i,col,l; 3841f763a69SBarry Smith const PetscInt *rp,*ai = a->i,*ailen = a->ilen,*aj = a->j; 3851f763a69SBarry Smith PetscInt lastcol = -1; 386fff043a9SJunchao Zhang MatScalar *ap,value,*aa; 387189e4007SBarry Smith const PetscInt *ridx = A->rmap->mapping->indices,*cidx = A->cmap->mapping->indices; 388189e4007SBarry Smith 389fff043a9SJunchao Zhang PetscFunctionBegin; 3909566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&aa)); 391f38dd0b8SBarry Smith row = ridx[im[0]]; 3921f763a69SBarry Smith rp = aj + ai[row]; 3931f763a69SBarry Smith ap = aa + ai[row]; 3941f763a69SBarry Smith nrow = ailen[row]; 395189e4007SBarry Smith low = 0; 396189e4007SBarry Smith high = nrow; 397189e4007SBarry Smith for (l=0; l<n; l++) { /* loop over added columns */ 398189e4007SBarry Smith col = cidx[in[l]]; 399f38dd0b8SBarry Smith value = v[l]; 400189e4007SBarry Smith 401189e4007SBarry Smith if (col <= lastcol) low = 0; 402189e4007SBarry Smith else high = nrow; 403189e4007SBarry Smith lastcol = col; 404189e4007SBarry Smith while (high-low > 5) { 405189e4007SBarry Smith t = (low+high)/2; 406189e4007SBarry Smith if (rp[t] > col) high = t; 407189e4007SBarry Smith else low = t; 408189e4007SBarry Smith } 409189e4007SBarry Smith for (i=low; i<high; i++) { 410189e4007SBarry Smith if (rp[i] == col) { 4111f763a69SBarry Smith ap[i] += value; 412189e4007SBarry Smith low = i + 1; 4131f763a69SBarry Smith break; 414189e4007SBarry Smith } 415189e4007SBarry Smith } 416189e4007SBarry Smith } 4179566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&aa)); 418f38dd0b8SBarry Smith return 0; 419189e4007SBarry Smith } 420189e4007SBarry Smith 42197f1f81fSBarry Smith PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is) 42217ab2063SBarry Smith { 423416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 424e2ee6c50SBarry Smith PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N; 42597f1f81fSBarry Smith PetscInt *imax = a->imax,*ai = a->i,*ailen = a->ilen; 426e2ee6c50SBarry Smith PetscInt *aj = a->j,nonew = a->nonew,lastcol = -1; 427ce496241SStefano Zampini MatScalar *ap=NULL,value=0.0,*aa; 428ace3abfcSBarry Smith PetscBool ignorezeroentries = a->ignorezeroentries; 429ace3abfcSBarry Smith PetscBool roworiented = a->roworiented; 43017ab2063SBarry Smith 4313a40ed3dSBarry Smith PetscFunctionBegin; 4329566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&aa)); 43317ab2063SBarry Smith for (k=0; k<m; k++) { /* loop over added rows */ 434416022c9SBarry Smith row = im[k]; 4355ef9f2a5SBarry Smith if (row < 0) continue; 4366bdcaf15SBarry Smith PetscCheck(row < A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT,row,A->rmap->n-1); 437720833daSHong Zhang rp = aj + ai[row]; 438876c6284SHong Zhang if (!A->structure_only) ap = aa + ai[row]; 43917ab2063SBarry Smith rmax = imax[row]; nrow = ailen[row]; 440416022c9SBarry Smith low = 0; 441c71e6ed7SBarry Smith high = nrow; 44217ab2063SBarry Smith for (l=0; l<n; l++) { /* loop over added columns */ 4435ef9f2a5SBarry Smith if (in[l] < 0) continue; 4446bdcaf15SBarry Smith PetscCheck(in[l] < A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT,in[l],A->cmap->n-1); 445bfeeae90SHong Zhang col = in[l]; 446071fcb05SBarry Smith if (v && !A->structure_only) value = roworiented ? v[l + k*n] : v[k + l*m]; 447071fcb05SBarry Smith if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue; 44836db0b34SBarry Smith 4492205254eSKarl Rupp if (col <= lastcol) low = 0; 4502205254eSKarl Rupp else high = nrow; 451e2ee6c50SBarry Smith lastcol = col; 452416022c9SBarry Smith while (high-low > 5) { 453416022c9SBarry Smith t = (low+high)/2; 454416022c9SBarry Smith if (rp[t] > col) high = t; 455416022c9SBarry Smith else low = t; 45617ab2063SBarry Smith } 457416022c9SBarry Smith for (i=low; i<high; i++) { 45817ab2063SBarry Smith if (rp[i] > col) break; 45917ab2063SBarry Smith if (rp[i] == col) { 460876c6284SHong Zhang if (!A->structure_only) { 4610c0d7e18SFande Kong if (is == ADD_VALUES) { 4620c0d7e18SFande Kong ap[i] += value; 4630c0d7e18SFande Kong (void)PetscLogFlops(1.0); 4640c0d7e18SFande Kong } 46517ab2063SBarry Smith else ap[i] = value; 466720833daSHong Zhang } 467e44c0bd4SBarry Smith low = i + 1; 46817ab2063SBarry Smith goto noinsert; 46917ab2063SBarry Smith } 47017ab2063SBarry Smith } 471dcd36c23SBarry Smith if (value == 0.0 && ignorezeroentries && row != col) goto noinsert; 472c2653b3dSLois Curfman McInnes if (nonew == 1) goto noinsert; 47308401ef6SPierre Jolivet PetscCheck(nonew != -1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%" PetscInt_FMT ",%" PetscInt_FMT ") in the matrix",row,col); 474720833daSHong Zhang if (A->structure_only) { 475876c6284SHong Zhang MatSeqXAIJReallocateAIJ_structure_only(A,A->rmap->n,1,nrow,row,col,rmax,ai,aj,rp,imax,nonew,MatScalar); 476720833daSHong Zhang } else { 477fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar); 478720833daSHong Zhang } 479c03d1d03SSatish Balay N = nrow++ - 1; a->nz++; high++; 480416022c9SBarry Smith /* shift up all the later entries in this row */ 4819566063dSJacob Faibussowitsch PetscCall(PetscArraymove(rp+i+1,rp+i,N-i+1)); 48217ab2063SBarry Smith rp[i] = col; 483580bdb30SBarry Smith if (!A->structure_only) { 4849566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ap+i+1,ap+i,N-i+1)); 485580bdb30SBarry Smith ap[i] = value; 486580bdb30SBarry Smith } 487416022c9SBarry Smith low = i + 1; 488e56f5c9eSBarry Smith A->nonzerostate++; 489e44c0bd4SBarry Smith noinsert:; 49017ab2063SBarry Smith } 49117ab2063SBarry Smith ailen[row] = nrow; 49217ab2063SBarry Smith } 4939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&aa)); 4943a40ed3dSBarry Smith PetscFunctionReturn(0); 49517ab2063SBarry Smith } 49617ab2063SBarry Smith 49719b08ed1SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is) 49819b08ed1SBarry Smith { 49919b08ed1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 50019b08ed1SBarry Smith PetscInt *rp,k,row; 50119b08ed1SBarry Smith PetscInt *ai = a->i; 50219b08ed1SBarry Smith PetscInt *aj = a->j; 503fff043a9SJunchao Zhang MatScalar *aa,*ap; 50419b08ed1SBarry Smith 50519b08ed1SBarry Smith PetscFunctionBegin; 50628b400f6SJacob Faibussowitsch PetscCheck(!A->was_assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call on assembled matrix."); 50708401ef6SPierre Jolivet PetscCheck(m*n+a->nz <= a->maxnz,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of entries in matrix will be larger than maximum nonzeros allocated for %" PetscInt_FMT " in MatSeqAIJSetTotalPreallocation()",a->maxnz); 508fff043a9SJunchao Zhang 5099566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&aa)); 51019b08ed1SBarry Smith for (k=0; k<m; k++) { /* loop over added rows */ 51119b08ed1SBarry Smith row = im[k]; 51219b08ed1SBarry Smith rp = aj + ai[row]; 51319b08ed1SBarry Smith ap = aa + ai[row]; 51419b08ed1SBarry Smith 5159566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(rp,in,n*sizeof(PetscInt))); 51619b08ed1SBarry Smith if (!A->structure_only) { 51719b08ed1SBarry Smith if (v) { 5189566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(ap,v,n*sizeof(PetscScalar))); 51919b08ed1SBarry Smith v += n; 52019b08ed1SBarry Smith } else { 5219566063dSJacob Faibussowitsch PetscCall(PetscMemzero(ap,n*sizeof(PetscScalar))); 52219b08ed1SBarry Smith } 52319b08ed1SBarry Smith } 52419b08ed1SBarry Smith a->ilen[row] = n; 52519b08ed1SBarry Smith a->imax[row] = n; 52619b08ed1SBarry Smith a->i[row+1] = a->i[row]+n; 52719b08ed1SBarry Smith a->nz += n; 52819b08ed1SBarry Smith } 5299566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&aa)); 53019b08ed1SBarry Smith PetscFunctionReturn(0); 53119b08ed1SBarry Smith } 53219b08ed1SBarry Smith 53319b08ed1SBarry Smith /*@ 53419b08ed1SBarry Smith MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix. 53519b08ed1SBarry Smith 53619b08ed1SBarry Smith Input Parameters: 53719b08ed1SBarry Smith + A - the SeqAIJ matrix 53819b08ed1SBarry Smith - nztotal - bound on the number of nonzeros 53919b08ed1SBarry Smith 54019b08ed1SBarry Smith Level: advanced 54119b08ed1SBarry Smith 54219b08ed1SBarry Smith Notes: 54319b08ed1SBarry Smith This can be called if you will be provided the matrix row by row (from row zero) with sorted column indices for each row. 54419b08ed1SBarry Smith Simply call MatSetValues() after this call to provide the matrix entries in the usual manner. This matrix may be used 54519b08ed1SBarry Smith as always with multiple matrix assemblies. 54619b08ed1SBarry Smith 547db781477SPatrick Sanan .seealso: `MatSetOption()`, `MAT_SORTED_FULL`, `MatSetValues()`, `MatSeqAIJSetPreallocation()` 54819b08ed1SBarry Smith @*/ 54919b08ed1SBarry Smith 55019b08ed1SBarry Smith PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A,PetscInt nztotal) 55119b08ed1SBarry Smith { 55219b08ed1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 55319b08ed1SBarry Smith 55419b08ed1SBarry Smith PetscFunctionBegin; 5559566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 5569566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 55719b08ed1SBarry Smith a->maxnz = nztotal; 55819b08ed1SBarry Smith if (!a->imax) { 5599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n,&a->imax)); 5609566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt))); 56119b08ed1SBarry Smith } 56219b08ed1SBarry Smith if (!a->ilen) { 5639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n,&a->ilen)); 5649566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt))); 56519b08ed1SBarry Smith } else { 5669566063dSJacob Faibussowitsch PetscCall(PetscMemzero(a->ilen,A->rmap->n*sizeof(PetscInt))); 56719b08ed1SBarry Smith } 56819b08ed1SBarry Smith 56919b08ed1SBarry Smith /* allocate the matrix space */ 57019b08ed1SBarry Smith if (A->structure_only) { 5719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nztotal,&a->j)); 5729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n+1,&a->i)); 5739566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*sizeof(PetscInt))); 57419b08ed1SBarry Smith } else { 5759566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(nztotal,&a->a,nztotal,&a->j,A->rmap->n+1,&a->i)); 5769566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*(sizeof(PetscScalar)+sizeof(PetscInt)))); 57719b08ed1SBarry Smith } 57819b08ed1SBarry Smith a->i[0] = 0; 57919b08ed1SBarry Smith if (A->structure_only) { 58019b08ed1SBarry Smith a->singlemalloc = PETSC_FALSE; 58119b08ed1SBarry Smith a->free_a = PETSC_FALSE; 58219b08ed1SBarry Smith } else { 58319b08ed1SBarry Smith a->singlemalloc = PETSC_TRUE; 58419b08ed1SBarry Smith a->free_a = PETSC_TRUE; 58519b08ed1SBarry Smith } 58619b08ed1SBarry Smith a->free_ij = PETSC_TRUE; 58719b08ed1SBarry Smith A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation; 58819b08ed1SBarry Smith A->preallocated = PETSC_TRUE; 58919b08ed1SBarry Smith PetscFunctionReturn(0); 59019b08ed1SBarry Smith } 59119b08ed1SBarry Smith 592071fcb05SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is) 593071fcb05SBarry Smith { 594071fcb05SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 595071fcb05SBarry Smith PetscInt *rp,k,row; 596071fcb05SBarry Smith PetscInt *ai = a->i,*ailen = a->ilen; 597071fcb05SBarry Smith PetscInt *aj = a->j; 598fff043a9SJunchao Zhang MatScalar *aa,*ap; 599071fcb05SBarry Smith 600071fcb05SBarry Smith PetscFunctionBegin; 6019566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&aa)); 602071fcb05SBarry Smith for (k=0; k<m; k++) { /* loop over added rows */ 603071fcb05SBarry Smith row = im[k]; 6046bdcaf15SBarry Smith PetscCheck(n <= a->imax[row],PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Preallocation for row %" PetscInt_FMT " does not match number of columns provided",n); 605071fcb05SBarry Smith rp = aj + ai[row]; 606071fcb05SBarry Smith ap = aa + ai[row]; 607071fcb05SBarry Smith if (!A->was_assembled) { 6089566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(rp,in,n*sizeof(PetscInt))); 609071fcb05SBarry Smith } 610071fcb05SBarry Smith if (!A->structure_only) { 611071fcb05SBarry Smith if (v) { 6129566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(ap,v,n*sizeof(PetscScalar))); 613071fcb05SBarry Smith v += n; 614071fcb05SBarry Smith } else { 6159566063dSJacob Faibussowitsch PetscCall(PetscMemzero(ap,n*sizeof(PetscScalar))); 616071fcb05SBarry Smith } 617071fcb05SBarry Smith } 618071fcb05SBarry Smith ailen[row] = n; 619071fcb05SBarry Smith a->nz += n; 620071fcb05SBarry Smith } 6219566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&aa)); 622071fcb05SBarry Smith PetscFunctionReturn(0); 623071fcb05SBarry Smith } 624071fcb05SBarry Smith 625a77337e4SBarry Smith PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[]) 6267eb43aa7SLois Curfman McInnes { 6277eb43aa7SLois Curfman McInnes Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 62897f1f81fSBarry Smith PetscInt *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j; 62997f1f81fSBarry Smith PetscInt *ai = a->i,*ailen = a->ilen; 630fff043a9SJunchao Zhang MatScalar *ap,*aa; 6317eb43aa7SLois Curfman McInnes 6323a40ed3dSBarry Smith PetscFunctionBegin; 6339566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&aa)); 6347eb43aa7SLois Curfman McInnes for (k=0; k<m; k++) { /* loop over rows */ 6357eb43aa7SLois Curfman McInnes row = im[k]; 63654c59aa7SJacob Faibussowitsch if (row < 0) {v += n; continue;} /* negative row */ 63754c59aa7SJacob Faibussowitsch PetscCheck(row < A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT,row,A->rmap->n-1); 638bfeeae90SHong Zhang rp = aj + ai[row]; ap = aa + ai[row]; 6397eb43aa7SLois Curfman McInnes nrow = ailen[row]; 6407eb43aa7SLois Curfman McInnes for (l=0; l<n; l++) { /* loop over columns */ 64154c59aa7SJacob Faibussowitsch if (in[l] < 0) {v++; continue;} /* negative column */ 64254c59aa7SJacob Faibussowitsch PetscCheck(in[l] < A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT,in[l],A->cmap->n-1); 643bfeeae90SHong Zhang col = in[l]; 6447eb43aa7SLois Curfman McInnes high = nrow; low = 0; /* assume unsorted */ 6457eb43aa7SLois Curfman McInnes while (high-low > 5) { 6467eb43aa7SLois Curfman McInnes t = (low+high)/2; 6477eb43aa7SLois Curfman McInnes if (rp[t] > col) high = t; 6487eb43aa7SLois Curfman McInnes else low = t; 6497eb43aa7SLois Curfman McInnes } 6507eb43aa7SLois Curfman McInnes for (i=low; i<high; i++) { 6517eb43aa7SLois Curfman McInnes if (rp[i] > col) break; 6527eb43aa7SLois Curfman McInnes if (rp[i] == col) { 653b49de8d1SLois Curfman McInnes *v++ = ap[i]; 6547eb43aa7SLois Curfman McInnes goto finished; 6557eb43aa7SLois Curfman McInnes } 6567eb43aa7SLois Curfman McInnes } 65797e567efSBarry Smith *v++ = 0.0; 6587eb43aa7SLois Curfman McInnes finished:; 6597eb43aa7SLois Curfman McInnes } 6607eb43aa7SLois Curfman McInnes } 6619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&aa)); 6623a40ed3dSBarry Smith PetscFunctionReturn(0); 6637eb43aa7SLois Curfman McInnes } 6647eb43aa7SLois Curfman McInnes 6653ea6fe3dSLisandro Dalcin PetscErrorCode MatView_SeqAIJ_Binary(Mat mat,PetscViewer viewer) 66617ab2063SBarry Smith { 6673ea6fe3dSLisandro Dalcin Mat_SeqAIJ *A = (Mat_SeqAIJ*)mat->data; 668c898d852SStefano Zampini const PetscScalar *av; 6693ea6fe3dSLisandro Dalcin PetscInt header[4],M,N,m,nz,i; 6703ea6fe3dSLisandro Dalcin PetscInt *rowlens; 67117ab2063SBarry Smith 6723a40ed3dSBarry Smith PetscFunctionBegin; 6739566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 6742205254eSKarl Rupp 6753ea6fe3dSLisandro Dalcin M = mat->rmap->N; 6763ea6fe3dSLisandro Dalcin N = mat->cmap->N; 6773ea6fe3dSLisandro Dalcin m = mat->rmap->n; 6783ea6fe3dSLisandro Dalcin nz = A->nz; 679416022c9SBarry Smith 6803ea6fe3dSLisandro Dalcin /* write matrix header */ 6813ea6fe3dSLisandro Dalcin header[0] = MAT_FILE_CLASSID; 6823ea6fe3dSLisandro Dalcin header[1] = M; header[2] = N; header[3] = nz; 6839566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer,header,4,PETSC_INT)); 684416022c9SBarry Smith 6853ea6fe3dSLisandro Dalcin /* fill in and store row lengths */ 6869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m,&rowlens)); 6873ea6fe3dSLisandro Dalcin for (i=0; i<m; i++) rowlens[i] = A->i[i+1] - A->i[i]; 6889566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer,rowlens,m,PETSC_INT)); 6899566063dSJacob Faibussowitsch PetscCall(PetscFree(rowlens)); 6903ea6fe3dSLisandro Dalcin /* store column indices */ 6919566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer,A->j,nz,PETSC_INT)); 692416022c9SBarry Smith /* store nonzero values */ 6939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(mat,&av)); 6949566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryWrite(viewer,av,nz,PETSC_SCALAR)); 6959566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(mat,&av)); 696b37d52dbSMark F. Adams 6973ea6fe3dSLisandro Dalcin /* write block size option to the viewer's .info file */ 6989566063dSJacob Faibussowitsch PetscCall(MatView_Binary_BlockSizes(mat,viewer)); 6993a40ed3dSBarry Smith PetscFunctionReturn(0); 70017ab2063SBarry Smith } 701416022c9SBarry Smith 7027dc0baabSHong Zhang static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A,PetscViewer viewer) 7037dc0baabSHong Zhang { 7047dc0baabSHong Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 7057dc0baabSHong Zhang PetscInt i,k,m=A->rmap->N; 7067dc0baabSHong Zhang 7077dc0baabSHong Zhang PetscFunctionBegin; 7089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE)); 7097dc0baabSHong Zhang for (i=0; i<m; i++) { 7109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"row %" PetscInt_FMT ":",i)); 7117dc0baabSHong Zhang for (k=a->i[i]; k<a->i[i+1]; k++) { 7129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ") ",a->j[k])); 7137dc0baabSHong Zhang } 7149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"\n")); 7157dc0baabSHong Zhang } 7169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE)); 7177dc0baabSHong Zhang PetscFunctionReturn(0); 7187dc0baabSHong Zhang } 7197dc0baabSHong Zhang 72009573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer); 721cd155464SBarry Smith 722dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer) 723416022c9SBarry Smith { 724416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 725c898d852SStefano Zampini const PetscScalar *av; 72660e0710aSBarry Smith PetscInt i,j,m = A->rmap->n; 727e060cb09SBarry Smith const char *name; 728f3ef73ceSBarry Smith PetscViewerFormat format; 72917ab2063SBarry Smith 7303a40ed3dSBarry Smith PetscFunctionBegin; 7317dc0baabSHong Zhang if (A->structure_only) { 7329566063dSJacob Faibussowitsch PetscCall(MatView_SeqAIJ_ASCII_structonly(A,viewer)); 7337dc0baabSHong Zhang PetscFunctionReturn(0); 7347dc0baabSHong Zhang } 73543e49210SHong Zhang 7369566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer,&format)); 7372e5835c6SStefano Zampini if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0); 7382e5835c6SStefano Zampini 739c898d852SStefano Zampini /* trigger copy to CPU if needed */ 7409566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&av)); 7419566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&av)); 74271c2f376SKris Buschelman if (format == PETSC_VIEWER_ASCII_MATLAB) { 74397f1f81fSBarry Smith PetscInt nofinalvalue = 0; 74460e0710aSBarry Smith if (m && ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-1))) { 745c337ccceSJed Brown /* Need a dummy value to ensure the dimension of the matrix. */ 746d00d2cf4SBarry Smith nofinalvalue = 1; 747d00d2cf4SBarry Smith } 7489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE)); 7499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n",m,A->cmap->n)); 7509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %" PetscInt_FMT " \n",a->nz)); 751fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX) 7529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"zzz = zeros(%" PetscInt_FMT ",4);\n",a->nz+nofinalvalue)); 753fbfe6fa7SJed Brown #else 7549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"zzz = zeros(%" PetscInt_FMT ",3);\n",a->nz+nofinalvalue)); 755fbfe6fa7SJed Brown #endif 7569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"zzz = [\n")); 75717ab2063SBarry Smith 75817ab2063SBarry Smith for (i=0; i<m; i++) { 75960e0710aSBarry Smith for (j=a->i[i]; j<a->i[i+1]; j++) { 760aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 7619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT " %18.16e %18.16e\n",i+1,a->j[j]+1,(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]))); 76217ab2063SBarry Smith #else 7639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT " %18.16e\n",i+1,a->j[j]+1,(double)a->a[j])); 76417ab2063SBarry Smith #endif 76517ab2063SBarry Smith } 76617ab2063SBarry Smith } 767d00d2cf4SBarry Smith if (nofinalvalue) { 768c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX) 7699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT " %18.16e %18.16e\n",m,A->cmap->n,0.,0.)); 770c337ccceSJed Brown #else 7719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT " %18.16e\n",m,A->cmap->n,0.0)); 772c337ccceSJed Brown #endif 773d00d2cf4SBarry Smith } 7749566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)A,&name)); 7759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name)); 7769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE)); 777fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_COMMON) { 7789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE)); 77944cd7ae7SLois Curfman McInnes for (i=0; i<m; i++) { 7809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"row %" PetscInt_FMT ":",i)); 78160e0710aSBarry Smith for (j=a->i[i]; j<a->i[i+1]; j++) { 782aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 78336db0b34SBarry Smith if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) { 7849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]))); 78536db0b34SBarry Smith } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) { 7869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]))); 78736db0b34SBarry Smith } else if (PetscRealPart(a->a[j]) != 0.0) { 7889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(a->a[j]))); 7896831982aSBarry Smith } 79044cd7ae7SLois Curfman McInnes #else 7919566063dSJacob Faibussowitsch if (a->a[j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)a->a[j])); 79244cd7ae7SLois Curfman McInnes #endif 79344cd7ae7SLois Curfman McInnes } 7949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"\n")); 79544cd7ae7SLois Curfman McInnes } 7969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE)); 797fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_SYMMODU) { 79897f1f81fSBarry Smith PetscInt nzd=0,fshift=1,*sptr; 7999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE)); 8009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m+1,&sptr)); 801496be53dSLois Curfman McInnes for (i=0; i<m; i++) { 802496be53dSLois Curfman McInnes sptr[i] = nzd+1; 80360e0710aSBarry Smith for (j=a->i[i]; j<a->i[i+1]; j++) { 804496be53dSLois Curfman McInnes if (a->j[j] >= i) { 805aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 80636db0b34SBarry Smith if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++; 807496be53dSLois Curfman McInnes #else 808496be53dSLois Curfman McInnes if (a->a[j] != 0.0) nzd++; 809496be53dSLois Curfman McInnes #endif 810496be53dSLois Curfman McInnes } 811496be53dSLois Curfman McInnes } 812496be53dSLois Curfman McInnes } 8132e44a96cSLois Curfman McInnes sptr[m] = nzd+1; 8149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT "\n\n",m,nzd)); 8152e44a96cSLois Curfman McInnes for (i=0; i<m+1; i+=6) { 8162205254eSKarl Rupp if (i+4<m) { 8179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4],sptr[i+5])); 8182205254eSKarl Rupp } else if (i+3<m) { 8199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4])); 8202205254eSKarl Rupp } else if (i+2<m) { 8219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3])); 8222205254eSKarl Rupp } else if (i+1<m) { 8239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n",sptr[i],sptr[i+1],sptr[i+2])); 8242205254eSKarl Rupp } else if (i<m) { 8259566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT "\n",sptr[i],sptr[i+1])); 8262205254eSKarl Rupp } else { 8279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT "\n",sptr[i])); 8282205254eSKarl Rupp } 829496be53dSLois Curfman McInnes } 8309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"\n")); 8319566063dSJacob Faibussowitsch PetscCall(PetscFree(sptr)); 832496be53dSLois Curfman McInnes for (i=0; i<m; i++) { 83360e0710aSBarry Smith for (j=a->i[i]; j<a->i[i+1]; j++) { 8349566063dSJacob Faibussowitsch if (a->j[j] >= i) PetscCall(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " ",a->j[j]+fshift)); 835496be53dSLois Curfman McInnes } 8369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"\n")); 837496be53dSLois Curfman McInnes } 8389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"\n")); 839496be53dSLois Curfman McInnes for (i=0; i<m; i++) { 84060e0710aSBarry Smith for (j=a->i[i]; j<a->i[i+1]; j++) { 841496be53dSLois Curfman McInnes if (a->j[j] >= i) { 842aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 84336db0b34SBarry Smith if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) { 8449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]))); 8456831982aSBarry Smith } 846496be53dSLois Curfman McInnes #else 8479566063dSJacob Faibussowitsch if (a->a[j] != 0.0) PetscCall(PetscViewerASCIIPrintf(viewer," %18.16e ",(double)a->a[j])); 848496be53dSLois Curfman McInnes #endif 849496be53dSLois Curfman McInnes } 850496be53dSLois Curfman McInnes } 8519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"\n")); 852496be53dSLois Curfman McInnes } 8539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE)); 854fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_DENSE) { 85597f1f81fSBarry Smith PetscInt cnt = 0,jcnt; 85687828ca2SBarry Smith PetscScalar value; 85768f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX) 85868f1ed48SBarry Smith PetscBool realonly = PETSC_TRUE; 85968f1ed48SBarry Smith 86068f1ed48SBarry Smith for (i=0; i<a->i[m]; i++) { 86168f1ed48SBarry Smith if (PetscImaginaryPart(a->a[i]) != 0.0) { 86268f1ed48SBarry Smith realonly = PETSC_FALSE; 86368f1ed48SBarry Smith break; 86468f1ed48SBarry Smith } 86568f1ed48SBarry Smith } 86668f1ed48SBarry Smith #endif 86702594712SBarry Smith 8689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE)); 86902594712SBarry Smith for (i=0; i<m; i++) { 87002594712SBarry Smith jcnt = 0; 871d0f46423SBarry Smith for (j=0; j<A->cmap->n; j++) { 872e24b481bSBarry Smith if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) { 87302594712SBarry Smith value = a->a[cnt++]; 874e24b481bSBarry Smith jcnt++; 87502594712SBarry Smith } else { 87602594712SBarry Smith value = 0.0; 87702594712SBarry Smith } 878aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 87968f1ed48SBarry Smith if (realonly) { 8809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %7.5e ",(double)PetscRealPart(value))); 88168f1ed48SBarry Smith } else { 8829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",(double)PetscRealPart(value),(double)PetscImaginaryPart(value))); 88368f1ed48SBarry Smith } 88402594712SBarry Smith #else 8859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %7.5e ",(double)value)); 88602594712SBarry Smith #endif 88702594712SBarry Smith } 8889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"\n")); 88902594712SBarry Smith } 8909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE)); 8913c215bfdSMatthew Knepley } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) { 892150b93efSMatthew G. Knepley PetscInt fshift=1; 8939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE)); 8943c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX) 8959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate complex general\n")); 8963c215bfdSMatthew Knepley #else 8979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate real general\n")); 8983c215bfdSMatthew Knepley #endif 8999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", m, A->cmap->n, a->nz)); 9003c215bfdSMatthew Knepley for (i=0; i<m; i++) { 90160e0710aSBarry Smith for (j=a->i[i]; j<a->i[i+1]; j++) { 9023c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX) 9039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT " %g %g\n", i+fshift,a->j[j]+fshift,(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]))); 9043c215bfdSMatthew Knepley #else 9059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT " %g\n", i+fshift, a->j[j]+fshift, (double)a->a[j])); 9063c215bfdSMatthew Knepley #endif 9073c215bfdSMatthew Knepley } 9083c215bfdSMatthew Knepley } 9099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE)); 9103a40ed3dSBarry Smith } else { 9119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE)); 912d5f3da31SBarry Smith if (A->factortype) { 91316cd7e1dSShri Abhyankar for (i=0; i<m; i++) { 9149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"row %" PetscInt_FMT ":",i)); 91516cd7e1dSShri Abhyankar /* L part */ 91660e0710aSBarry Smith for (j=a->i[i]; j<a->i[i+1]; j++) { 91716cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX) 91816cd7e1dSShri Abhyankar if (PetscImaginaryPart(a->a[j]) > 0.0) { 9199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]))); 92016cd7e1dSShri Abhyankar } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 9219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])))); 92216cd7e1dSShri Abhyankar } else { 9239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(a->a[j]))); 92416cd7e1dSShri Abhyankar } 92516cd7e1dSShri Abhyankar #else 9269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)a->a[j])); 92716cd7e1dSShri Abhyankar #endif 92816cd7e1dSShri Abhyankar } 92916cd7e1dSShri Abhyankar /* diagonal */ 93016cd7e1dSShri Abhyankar j = a->diag[i]; 93116cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX) 93216cd7e1dSShri Abhyankar if (PetscImaginaryPart(a->a[j]) > 0.0) { 9339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(1.0/a->a[j]),(double)PetscImaginaryPart(1.0/a->a[j]))); 93416cd7e1dSShri Abhyankar } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 9359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(1.0/a->a[j]),(double)(-PetscImaginaryPart(1.0/a->a[j])))); 93616cd7e1dSShri Abhyankar } else { 9379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(1.0/a->a[j]))); 93816cd7e1dSShri Abhyankar } 93916cd7e1dSShri Abhyankar #else 9409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)(1.0/a->a[j]))); 94116cd7e1dSShri Abhyankar #endif 94216cd7e1dSShri Abhyankar 94316cd7e1dSShri Abhyankar /* U part */ 94460e0710aSBarry Smith for (j=a->diag[i+1]+1; j<a->diag[i]; j++) { 94516cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX) 94616cd7e1dSShri Abhyankar if (PetscImaginaryPart(a->a[j]) > 0.0) { 9479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]))); 94816cd7e1dSShri Abhyankar } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 9499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])))); 95016cd7e1dSShri Abhyankar } else { 9519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(a->a[j]))); 95216cd7e1dSShri Abhyankar } 95316cd7e1dSShri Abhyankar #else 9549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)a->a[j])); 95516cd7e1dSShri Abhyankar #endif 95616cd7e1dSShri Abhyankar } 9579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"\n")); 95816cd7e1dSShri Abhyankar } 95916cd7e1dSShri Abhyankar } else { 96017ab2063SBarry Smith for (i=0; i<m; i++) { 9619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"row %" PetscInt_FMT ":",i)); 96260e0710aSBarry Smith for (j=a->i[i]; j<a->i[i+1]; j++) { 963aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 96436db0b34SBarry Smith if (PetscImaginaryPart(a->a[j]) > 0.0) { 9659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]))); 96636db0b34SBarry Smith } else if (PetscImaginaryPart(a->a[j]) < 0.0) { 9679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]))); 9683a40ed3dSBarry Smith } else { 9699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(a->a[j]))); 97017ab2063SBarry Smith } 97117ab2063SBarry Smith #else 9729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)a->a[j])); 97317ab2063SBarry Smith #endif 97417ab2063SBarry Smith } 9759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"\n")); 97617ab2063SBarry Smith } 97716cd7e1dSShri Abhyankar } 9789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE)); 97917ab2063SBarry Smith } 9809566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 9813a40ed3dSBarry Smith PetscFunctionReturn(0); 982416022c9SBarry Smith } 983416022c9SBarry Smith 9849804daf3SBarry Smith #include <petscdraw.h> 985dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa) 986416022c9SBarry Smith { 987480ef9eaSBarry Smith Mat A = (Mat) Aa; 988416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 989383922c3SLisandro Dalcin PetscInt i,j,m = A->rmap->n; 990383922c3SLisandro Dalcin int color; 991b05fc000SLisandro Dalcin PetscReal xl,yl,xr,yr,x_l,x_r,y_l,y_r; 992b0a32e0cSBarry Smith PetscViewer viewer; 993f3ef73ceSBarry Smith PetscViewerFormat format; 994fff043a9SJunchao Zhang const PetscScalar *aa; 995cddf8d76SBarry Smith 9963a40ed3dSBarry Smith PetscFunctionBegin; 9979566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer)); 9989566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer,&format)); 9999566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr)); 1000383922c3SLisandro Dalcin 1001416022c9SBarry Smith /* loop over matrix elements drawing boxes */ 10029566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 1003fb9695e5SSatish Balay if (format != PETSC_VIEWER_DRAW_CONTOUR) { 1004d0609cedSBarry Smith PetscDrawCollectiveBegin(draw); 10050513a670SBarry Smith /* Blue for negative, Cyan for zero and Red for positive */ 1006b0a32e0cSBarry Smith color = PETSC_DRAW_BLUE; 1007416022c9SBarry Smith for (i=0; i<m; i++) { 1008cddf8d76SBarry Smith y_l = m - i - 1.0; y_r = y_l + 1.0; 1009bfeeae90SHong Zhang for (j=a->i[i]; j<a->i[i+1]; j++) { 1010bfeeae90SHong Zhang x_l = a->j[j]; x_r = x_l + 1.0; 1011fff043a9SJunchao Zhang if (PetscRealPart(aa[j]) >= 0.) continue; 10129566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color)); 1013cddf8d76SBarry Smith } 1014cddf8d76SBarry Smith } 1015b0a32e0cSBarry Smith color = PETSC_DRAW_CYAN; 1016cddf8d76SBarry Smith for (i=0; i<m; i++) { 1017cddf8d76SBarry Smith y_l = m - i - 1.0; y_r = y_l + 1.0; 1018bfeeae90SHong Zhang for (j=a->i[i]; j<a->i[i+1]; j++) { 1019bfeeae90SHong Zhang x_l = a->j[j]; x_r = x_l + 1.0; 1020fff043a9SJunchao Zhang if (aa[j] != 0.) continue; 10219566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color)); 1022cddf8d76SBarry Smith } 1023cddf8d76SBarry Smith } 1024b0a32e0cSBarry Smith color = PETSC_DRAW_RED; 1025cddf8d76SBarry Smith for (i=0; i<m; i++) { 1026cddf8d76SBarry Smith y_l = m - i - 1.0; y_r = y_l + 1.0; 1027bfeeae90SHong Zhang for (j=a->i[i]; j<a->i[i+1]; j++) { 1028bfeeae90SHong Zhang x_l = a->j[j]; x_r = x_l + 1.0; 1029fff043a9SJunchao Zhang if (PetscRealPart(aa[j]) <= 0.) continue; 10309566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color)); 1031416022c9SBarry Smith } 1032416022c9SBarry Smith } 1033d0609cedSBarry Smith PetscDrawCollectiveEnd(draw); 10340513a670SBarry Smith } else { 10350513a670SBarry Smith /* use contour shading to indicate magnitude of values */ 10360513a670SBarry Smith /* first determine max of all nonzero values */ 1037b05fc000SLisandro Dalcin PetscReal minv = 0.0, maxv = 0.0; 1038383922c3SLisandro Dalcin PetscInt nz = a->nz, count = 0; 1039b0a32e0cSBarry Smith PetscDraw popup; 10400513a670SBarry Smith 10410513a670SBarry Smith for (i=0; i<nz; i++) { 1042fff043a9SJunchao Zhang if (PetscAbsScalar(aa[i]) > maxv) maxv = PetscAbsScalar(aa[i]); 10430513a670SBarry Smith } 1044383922c3SLisandro Dalcin if (minv >= maxv) maxv = minv + PETSC_SMALL; 10459566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPopup(draw,&popup)); 10469566063dSJacob Faibussowitsch PetscCall(PetscDrawScalePopup(popup,minv,maxv)); 1047383922c3SLisandro Dalcin 1048d0609cedSBarry Smith PetscDrawCollectiveBegin(draw); 10490513a670SBarry Smith for (i=0; i<m; i++) { 1050383922c3SLisandro Dalcin y_l = m - i - 1.0; 1051383922c3SLisandro Dalcin y_r = y_l + 1.0; 1052bfeeae90SHong Zhang for (j=a->i[i]; j<a->i[i+1]; j++) { 1053383922c3SLisandro Dalcin x_l = a->j[j]; 1054383922c3SLisandro Dalcin x_r = x_l + 1.0; 1055fff043a9SJunchao Zhang color = PetscDrawRealToColor(PetscAbsScalar(aa[count]),minv,maxv); 10569566063dSJacob Faibussowitsch PetscCall(PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color)); 10570513a670SBarry Smith count++; 10580513a670SBarry Smith } 10590513a670SBarry Smith } 1060d0609cedSBarry Smith PetscDrawCollectiveEnd(draw); 10610513a670SBarry Smith } 10629566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 1063480ef9eaSBarry Smith PetscFunctionReturn(0); 1064480ef9eaSBarry Smith } 1065cddf8d76SBarry Smith 10669804daf3SBarry Smith #include <petscdraw.h> 1067dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer) 1068480ef9eaSBarry Smith { 1069b0a32e0cSBarry Smith PetscDraw draw; 107036db0b34SBarry Smith PetscReal xr,yr,xl,yl,h,w; 1071ace3abfcSBarry Smith PetscBool isnull; 1072480ef9eaSBarry Smith 1073480ef9eaSBarry Smith PetscFunctionBegin; 10749566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer,0,&draw)); 10759566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw,&isnull)); 1076480ef9eaSBarry Smith if (isnull) PetscFunctionReturn(0); 1077480ef9eaSBarry Smith 1078d0f46423SBarry Smith xr = A->cmap->n; yr = A->rmap->n; h = yr/10.0; w = xr/10.0; 1079480ef9eaSBarry Smith xr += w; yr += h; xl = -w; yl = -h; 10809566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw,xl,yl,xr,yr)); 10819566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer)); 10829566063dSJacob Faibussowitsch PetscCall(PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A)); 10839566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL)); 10849566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 10853a40ed3dSBarry Smith PetscFunctionReturn(0); 1086416022c9SBarry Smith } 1087416022c9SBarry Smith 1088dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer) 1089416022c9SBarry Smith { 1090ace3abfcSBarry Smith PetscBool iascii,isbinary,isdraw; 1091416022c9SBarry Smith 10923a40ed3dSBarry Smith PetscFunctionBegin; 10939566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii)); 10949566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary)); 10959566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw)); 10961baa6e33SBarry Smith if (iascii) PetscCall(MatView_SeqAIJ_ASCII(A,viewer)); 10971baa6e33SBarry Smith else if (isbinary) PetscCall(MatView_SeqAIJ_Binary(A,viewer)); 10981baa6e33SBarry Smith else if (isdraw) PetscCall(MatView_SeqAIJ_Draw(A,viewer)); 10999566063dSJacob Faibussowitsch PetscCall(MatView_SeqAIJ_Inode(A,viewer)); 11003a40ed3dSBarry Smith PetscFunctionReturn(0); 110117ab2063SBarry Smith } 110219bcc07fSBarry Smith 1103dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode) 110417ab2063SBarry Smith { 1105416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1106580bdb30SBarry Smith PetscInt fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax; 1107d0f46423SBarry Smith PetscInt m = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0; 110854f21887SBarry Smith MatScalar *aa = a->a,*ap; 11093447b6efSHong Zhang PetscReal ratio = 0.6; 111017ab2063SBarry Smith 11113a40ed3dSBarry Smith PetscFunctionBegin; 11123a40ed3dSBarry Smith if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0); 11139566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 1114b215bc84SStefano Zampini if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) { 1115b215bc84SStefano Zampini /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */ 11169566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A,mode)); 1117b215bc84SStefano Zampini PetscFunctionReturn(0); 1118b215bc84SStefano Zampini } 111917ab2063SBarry Smith 112043ee02c3SBarry Smith if (m) rmax = ailen[0]; /* determine row with most nonzeros */ 112117ab2063SBarry Smith for (i=1; i<m; i++) { 1122416022c9SBarry Smith /* move each row back by the amount of empty slots (fshift) before it*/ 112317ab2063SBarry Smith fshift += imax[i-1] - ailen[i-1]; 112494a9d846SBarry Smith rmax = PetscMax(rmax,ailen[i]); 112517ab2063SBarry Smith if (fshift) { 1126bfeeae90SHong Zhang ip = aj + ai[i]; 1127bfeeae90SHong Zhang ap = aa + ai[i]; 112817ab2063SBarry Smith N = ailen[i]; 11299566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ip-fshift,ip,N)); 1130580bdb30SBarry Smith if (!A->structure_only) { 11319566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ap-fshift,ap,N)); 113217ab2063SBarry Smith } 113317ab2063SBarry Smith } 113417ab2063SBarry Smith ai[i] = ai[i-1] + ailen[i-1]; 113517ab2063SBarry Smith } 113617ab2063SBarry Smith if (m) { 113717ab2063SBarry Smith fshift += imax[m-1] - ailen[m-1]; 113817ab2063SBarry Smith ai[m] = ai[m-1] + ailen[m-1]; 113917ab2063SBarry Smith } 11407b083b7cSBarry Smith 114117ab2063SBarry Smith /* reset ilen and imax for each row */ 11427b083b7cSBarry Smith a->nonzerorowcnt = 0; 1143396832f4SHong Zhang if (A->structure_only) { 11449566063dSJacob Faibussowitsch PetscCall(PetscFree(a->imax)); 11459566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ilen)); 1146396832f4SHong Zhang } else { /* !A->structure_only */ 114717ab2063SBarry Smith for (i=0; i<m; i++) { 114817ab2063SBarry Smith ailen[i] = imax[i] = ai[i+1] - ai[i]; 11497b083b7cSBarry Smith a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0); 115017ab2063SBarry Smith } 1151396832f4SHong Zhang } 1152bfeeae90SHong Zhang a->nz = ai[m]; 1153aed4548fSBarry Smith PetscCheck(!fshift || a->nounused != -1,PETSC_COMM_SELF,PETSC_ERR_PLIB, "Unused space detected in matrix: %" PetscInt_FMT " X %" PetscInt_FMT ", %" PetscInt_FMT " unneeded", m, A->cmap->n, fshift); 115417ab2063SBarry Smith 11559566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 11569566063dSJacob Faibussowitsch PetscCall(PetscInfo(A,"Matrix size: %" PetscInt_FMT " X %" PetscInt_FMT "; storage space: %" PetscInt_FMT " unneeded,%" PetscInt_FMT " used\n",m,A->cmap->n,fshift,a->nz)); 11579566063dSJacob Faibussowitsch PetscCall(PetscInfo(A,"Number of mallocs during MatSetValues() is %" PetscInt_FMT "\n",a->reallocs)); 11589566063dSJacob Faibussowitsch PetscCall(PetscInfo(A,"Maximum nonzeros in any row is %" PetscInt_FMT "\n",rmax)); 11592205254eSKarl Rupp 11608e58a170SBarry Smith A->info.mallocs += a->reallocs; 1161dd5f02e7SSatish Balay a->reallocs = 0; 11626712e2f1SBarry Smith A->info.nz_unneeded = (PetscReal)fshift; 116336db0b34SBarry Smith a->rmax = rmax; 11644e220ebcSLois Curfman McInnes 1165396832f4SHong Zhang if (!A->structure_only) { 11669566063dSJacob Faibussowitsch PetscCall(MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio)); 1167396832f4SHong Zhang } 11689566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A,mode)); 11693a40ed3dSBarry Smith PetscFunctionReturn(0); 117017ab2063SBarry Smith } 117117ab2063SBarry Smith 117299cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A) 117399cafbc1SBarry Smith { 117499cafbc1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 117599cafbc1SBarry Smith PetscInt i,nz = a->nz; 11762e5835c6SStefano Zampini MatScalar *aa; 117799cafbc1SBarry Smith 117899cafbc1SBarry Smith PetscFunctionBegin; 11799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&aa)); 118099cafbc1SBarry Smith for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]); 11819566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&aa)); 11829566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 118399cafbc1SBarry Smith PetscFunctionReturn(0); 118499cafbc1SBarry Smith } 118599cafbc1SBarry Smith 118699cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A) 118799cafbc1SBarry Smith { 118899cafbc1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 118999cafbc1SBarry Smith PetscInt i,nz = a->nz; 11902e5835c6SStefano Zampini MatScalar *aa; 119199cafbc1SBarry Smith 119299cafbc1SBarry Smith PetscFunctionBegin; 11939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&aa)); 119499cafbc1SBarry Smith for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]); 11959566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&aa)); 11969566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 119799cafbc1SBarry Smith PetscFunctionReturn(0); 119899cafbc1SBarry Smith } 119999cafbc1SBarry Smith 1200dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A) 120117ab2063SBarry Smith { 1202fff043a9SJunchao Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1203fff043a9SJunchao Zhang MatScalar *aa; 12043a40ed3dSBarry Smith 12053a40ed3dSBarry Smith PetscFunctionBegin; 12069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayWrite(A,&aa)); 12079566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(aa,a->i[A->rmap->n])); 12089566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayWrite(A,&aa)); 12099566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 12103a40ed3dSBarry Smith PetscFunctionReturn(0); 121117ab2063SBarry Smith } 1212416022c9SBarry Smith 1213cbc6b225SStefano Zampini PETSC_INTERN PetscErrorCode MatResetPreallocationCOO_SeqAIJ(Mat A) 1214cbc6b225SStefano Zampini { 1215cbc6b225SStefano Zampini Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1216cbc6b225SStefano Zampini 1217cbc6b225SStefano Zampini PetscFunctionBegin; 12189566063dSJacob Faibussowitsch PetscCall(PetscFree(a->perm)); 12199566063dSJacob Faibussowitsch PetscCall(PetscFree(a->jmap)); 1220cbc6b225SStefano Zampini PetscFunctionReturn(0); 1221cbc6b225SStefano Zampini } 1222cbc6b225SStefano Zampini 1223dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A) 122417ab2063SBarry Smith { 1225416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1226d5d45c9bSBarry Smith 12273a40ed3dSBarry Smith PetscFunctionBegin; 1228aa482453SBarry Smith #if defined(PETSC_USE_LOG) 1229c0aa6a63SJacob Faibussowitsch PetscLogObjectState((PetscObject)A,"Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT ", NZ=%" PetscInt_FMT,A->rmap->n,A->cmap->n,a->nz); 123017ab2063SBarry Smith #endif 12319566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i)); 12329566063dSJacob Faibussowitsch PetscCall(MatResetPreallocationCOO_SeqAIJ(A)); 12339566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 12349566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 12359566063dSJacob Faibussowitsch PetscCall(PetscFree(a->diag)); 12369566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ibdiag)); 12379566063dSJacob Faibussowitsch PetscCall(PetscFree(a->imax)); 12389566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ilen)); 12399566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ipre)); 12409566063dSJacob Faibussowitsch PetscCall(PetscFree3(a->idiag,a->mdiag,a->ssor_work)); 12419566063dSJacob Faibussowitsch PetscCall(PetscFree(a->solve_work)); 12429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->icol)); 12439566063dSJacob Faibussowitsch PetscCall(PetscFree(a->saved_values)); 12449566063dSJacob Faibussowitsch PetscCall(PetscFree2(a->compressedrow.i,a->compressedrow.rindex)); 12459566063dSJacob Faibussowitsch PetscCall(MatDestroy_SeqAIJ_Inode(A)); 12469566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 1247901853e0SKris Buschelman 12486718818eSStefano Zampini /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this. 12496718818eSStefano Zampini That function is so heavily used (sometimes in an hidden way through multnumeric function pointers) 12506718818eSStefano Zampini that is hard to properly add this data to the MatProduct data. We free it here to avoid 12516718818eSStefano Zampini users reusing the matrix object with different data to incur in obscure segmentation faults 12526718818eSStefano Zampini due to different matrix sizes */ 12539566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A,"__PETSc__ab_dense",NULL)); 12546718818eSStefano Zampini 12559566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A,NULL)); 12562e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A,"PetscMatlabEnginePut_C",NULL)); 12572e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A,"PetscMatlabEngineGet_C",NULL)); 12589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL)); 12599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL)); 12609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL)); 12619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL)); 12629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL)); 12639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL)); 12642e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijsell_C",NULL)); 12652e956fe4SStefano Zampini #if defined(PETSC_HAVE_MKL_SPARSE) 12662e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijmkl_C",NULL)); 12672e956fe4SStefano Zampini #endif 12684222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA) 12699566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcusparse_C",NULL)); 12709566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",NULL)); 12719566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",NULL)); 12724222ddf1SHong Zhang #endif 12733d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 12749566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijkokkos_C",NULL)); 12753d0639e7SStefano Zampini #endif 12769566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcrl_C",NULL)); 1277af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 12789566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL)); 1279af8000cdSHong Zhang #endif 1280d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 12819566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_scalapack_C",NULL)); 1282d24d4204SJose E. Roman #endif 128363c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 12849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL)); 12859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",NULL)); 128663c07aadSStefano Zampini #endif 12879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL)); 12889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL)); 12899566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL)); 12909566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL)); 12912e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatIsHermitianTranspose_C",NULL)); 12929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL)); 12939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL)); 12949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL)); 12959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL)); 12969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_is_seqaij_C",NULL)); 12979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqdense_seqaij_C",NULL)); 12989566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaij_C",NULL)); 12999566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJKron_C",NULL)); 13009566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",NULL)); 13019566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",NULL)); 13022e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatFactorGetSolverType_C",NULL)); 13032e956fe4SStefano Zampini /* these calls do not belong here: the subclasses Duplicate/Destroy are wrong */ 13042e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaijsell_seqaij_C",NULL)); 13052e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaijperm_seqaij_C",NULL)); 13062e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijviennacl_C",NULL)); 13072e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijviennacl_seqdense_C",NULL)); 13082e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijviennacl_seqaij_C",NULL)); 13093a40ed3dSBarry Smith PetscFunctionReturn(0); 131017ab2063SBarry Smith } 131117ab2063SBarry Smith 1312ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg) 131317ab2063SBarry Smith { 1314416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 13153a40ed3dSBarry Smith 13163a40ed3dSBarry Smith PetscFunctionBegin; 1317a65d3064SKris Buschelman switch (op) { 1318a65d3064SKris Buschelman case MAT_ROW_ORIENTED: 13194e0d8c25SBarry Smith a->roworiented = flg; 1320a65d3064SKris Buschelman break; 1321a9817697SBarry Smith case MAT_KEEP_NONZERO_PATTERN: 1322a9817697SBarry Smith a->keepnonzeropattern = flg; 1323a65d3064SKris Buschelman break; 1324512a5fc5SBarry Smith case MAT_NEW_NONZERO_LOCATIONS: 1325512a5fc5SBarry Smith a->nonew = (flg ? 0 : 1); 1326a65d3064SKris Buschelman break; 1327a65d3064SKris Buschelman case MAT_NEW_NONZERO_LOCATION_ERR: 13284e0d8c25SBarry Smith a->nonew = (flg ? -1 : 0); 1329a65d3064SKris Buschelman break; 1330a65d3064SKris Buschelman case MAT_NEW_NONZERO_ALLOCATION_ERR: 13314e0d8c25SBarry Smith a->nonew = (flg ? -2 : 0); 1332a65d3064SKris Buschelman break; 133328b2fa4aSMatthew Knepley case MAT_UNUSED_NONZERO_LOCATION_ERR: 133428b2fa4aSMatthew Knepley a->nounused = (flg ? -1 : 0); 133528b2fa4aSMatthew Knepley break; 1336a65d3064SKris Buschelman case MAT_IGNORE_ZERO_ENTRIES: 13374e0d8c25SBarry Smith a->ignorezeroentries = flg; 13380df259c2SBarry Smith break; 13393d472b54SHong Zhang case MAT_SPD: 1340b1646e73SJed Brown case MAT_SYMMETRIC: 1341b1646e73SJed Brown case MAT_STRUCTURALLY_SYMMETRIC: 1342b1646e73SJed Brown case MAT_HERMITIAN: 1343b1646e73SJed Brown case MAT_SYMMETRY_ETERNAL: 1344957cac9fSHong Zhang case MAT_STRUCTURE_ONLY: 13455021d80fSJed Brown /* These options are handled directly by MatSetOption() */ 13465021d80fSJed Brown break; 13478c78258cSHong Zhang case MAT_FORCE_DIAGONAL_ENTRIES: 1348a65d3064SKris Buschelman case MAT_IGNORE_OFF_PROC_ENTRIES: 1349a65d3064SKris Buschelman case MAT_USE_HASH_TABLE: 13509566063dSJacob Faibussowitsch PetscCall(PetscInfo(A,"Option %s ignored\n",MatOptions[op])); 1351a65d3064SKris Buschelman break; 1352b87ac2d8SJed Brown case MAT_USE_INODES: 13539566063dSJacob Faibussowitsch PetscCall(MatSetOption_SeqAIJ_Inode(A,MAT_USE_INODES,flg)); 1354b87ac2d8SJed Brown break; 1355c10200c1SHong Zhang case MAT_SUBMAT_SINGLEIS: 1356c10200c1SHong Zhang A->submat_singleis = flg; 1357c10200c1SHong Zhang break; 1358071fcb05SBarry Smith case MAT_SORTED_FULL: 1359071fcb05SBarry Smith if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 1360071fcb05SBarry Smith else A->ops->setvalues = MatSetValues_SeqAIJ; 1361071fcb05SBarry Smith break; 13621a2c6b5cSJunchao Zhang case MAT_FORM_EXPLICIT_TRANSPOSE: 13631a2c6b5cSJunchao Zhang A->form_explicit_transpose = flg; 13641a2c6b5cSJunchao Zhang break; 1365a65d3064SKris Buschelman default: 136698921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op); 1367a65d3064SKris Buschelman } 13683a40ed3dSBarry Smith PetscFunctionReturn(0); 136917ab2063SBarry Smith } 137017ab2063SBarry Smith 1371dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v) 137217ab2063SBarry Smith { 1373416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1374fdc842d1SBarry Smith PetscInt i,j,n,*ai=a->i,*aj=a->j; 1375c898d852SStefano Zampini PetscScalar *x; 1376c898d852SStefano Zampini const PetscScalar *aa; 137717ab2063SBarry Smith 13783a40ed3dSBarry Smith PetscFunctionBegin; 13799566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v,&n)); 138008401ef6SPierre Jolivet PetscCheck(n == A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 13819566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 1382d5f3da31SBarry Smith if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) { 1383d3e70bfaSHong Zhang PetscInt *diag=a->diag; 13849566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v,&x)); 13852c990fa1SHong Zhang for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]]; 13869566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v,&x)); 13879566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 138835e7444dSHong Zhang PetscFunctionReturn(0); 138935e7444dSHong Zhang } 139035e7444dSHong Zhang 13919566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v,&x)); 139235e7444dSHong Zhang for (i=0; i<n; i++) { 1393fdc842d1SBarry Smith x[i] = 0.0; 139435e7444dSHong Zhang for (j=ai[i]; j<ai[i+1]; j++) { 139535e7444dSHong Zhang if (aj[j] == i) { 139635e7444dSHong Zhang x[i] = aa[j]; 139717ab2063SBarry Smith break; 139817ab2063SBarry Smith } 139917ab2063SBarry Smith } 140017ab2063SBarry Smith } 14019566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v,&x)); 14029566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 14033a40ed3dSBarry Smith PetscFunctionReturn(0); 140417ab2063SBarry Smith } 140517ab2063SBarry Smith 1406c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 1407dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy) 140817ab2063SBarry Smith { 1409416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 14105f22a7b3SSebastian Grimberg const MatScalar *aa; 1411d9ca1df4SBarry Smith PetscScalar *y; 1412d9ca1df4SBarry Smith const PetscScalar *x; 1413d0f46423SBarry Smith PetscInt m = A->rmap->n; 14145c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 14155f22a7b3SSebastian Grimberg const MatScalar *v; 1416a77337e4SBarry Smith PetscScalar alpha; 1417d9ca1df4SBarry Smith PetscInt n,i,j; 1418d9ca1df4SBarry Smith const PetscInt *idx,*ii,*ridx=NULL; 14193447b6efSHong Zhang Mat_CompressedRow cprow = a->compressedrow; 1420ace3abfcSBarry Smith PetscBool usecprow = cprow.use; 14215c897100SBarry Smith #endif 142217ab2063SBarry Smith 14233a40ed3dSBarry Smith PetscFunctionBegin; 14249566063dSJacob Faibussowitsch if (zz != yy) PetscCall(VecCopy(zz,yy)); 14259566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx,&x)); 14269566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy,&y)); 14279566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 14285c897100SBarry Smith 14295c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 1430fff043a9SJunchao Zhang fortranmulttransposeaddaij_(&m,x,a->i,a->j,aa,y); 14315c897100SBarry Smith #else 14323447b6efSHong Zhang if (usecprow) { 14333447b6efSHong Zhang m = cprow.nrows; 14343447b6efSHong Zhang ii = cprow.i; 14357b2bb3b9SHong Zhang ridx = cprow.rindex; 14363447b6efSHong Zhang } else { 14373447b6efSHong Zhang ii = a->i; 14383447b6efSHong Zhang } 143917ab2063SBarry Smith for (i=0; i<m; i++) { 14403447b6efSHong Zhang idx = a->j + ii[i]; 1441fff043a9SJunchao Zhang v = aa + ii[i]; 14423447b6efSHong Zhang n = ii[i+1] - ii[i]; 14433447b6efSHong Zhang if (usecprow) { 14447b2bb3b9SHong Zhang alpha = x[ridx[i]]; 14453447b6efSHong Zhang } else { 144617ab2063SBarry Smith alpha = x[i]; 14473447b6efSHong Zhang } 144804fbf559SBarry Smith for (j=0; j<n; j++) y[idx[j]] += alpha*v[j]; 144917ab2063SBarry Smith } 14505c897100SBarry Smith #endif 14519566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*a->nz)); 14529566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx,&x)); 14539566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy,&y)); 14549566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 14553a40ed3dSBarry Smith PetscFunctionReturn(0); 145617ab2063SBarry Smith } 145717ab2063SBarry Smith 1458dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy) 14595c897100SBarry Smith { 14605c897100SBarry Smith PetscFunctionBegin; 14619566063dSJacob Faibussowitsch PetscCall(VecSet(yy,0.0)); 14629566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy)); 14635c897100SBarry Smith PetscFunctionReturn(0); 14645c897100SBarry Smith } 14655c897100SBarry Smith 1466c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 146778b84d54SShri Abhyankar 1468dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy) 146917ab2063SBarry Smith { 1470416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1471d9fead3dSBarry Smith PetscScalar *y; 147254f21887SBarry Smith const PetscScalar *x; 1473fff043a9SJunchao Zhang const MatScalar *aa,*a_a; 1474003131ecSBarry Smith PetscInt m=A->rmap->n; 14750298fd71SBarry Smith const PetscInt *aj,*ii,*ridx=NULL; 14767b083b7cSBarry Smith PetscInt n,i; 1477362ced78SSatish Balay PetscScalar sum; 1478ace3abfcSBarry Smith PetscBool usecprow=a->compressedrow.use; 147917ab2063SBarry Smith 1480b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 148197952fefSHong Zhang #pragma disjoint(*x,*y,*aa) 1482fee21e36SBarry Smith #endif 1483fee21e36SBarry Smith 14843a40ed3dSBarry Smith PetscFunctionBegin; 1485b215bc84SStefano Zampini if (a->inode.use && a->inode.checked) { 14869566063dSJacob Faibussowitsch PetscCall(MatMult_SeqAIJ_Inode(A,xx,yy)); 1487b215bc84SStefano Zampini PetscFunctionReturn(0); 1488b215bc84SStefano Zampini } 14899566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&a_a)); 14909566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx,&x)); 14919566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy,&y)); 1492416022c9SBarry Smith ii = a->i; 14934eb6d288SHong Zhang if (usecprow) { /* use compressed row format */ 14949566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(y,m)); 149597952fefSHong Zhang m = a->compressedrow.nrows; 149697952fefSHong Zhang ii = a->compressedrow.i; 149797952fefSHong Zhang ridx = a->compressedrow.rindex; 149897952fefSHong Zhang for (i=0; i<m; i++) { 149997952fefSHong Zhang n = ii[i+1] - ii[i]; 150097952fefSHong Zhang aj = a->j + ii[i]; 1501fff043a9SJunchao Zhang aa = a_a + ii[i]; 150297952fefSHong Zhang sum = 0.0; 1503003131ecSBarry Smith PetscSparseDensePlusDot(sum,x,aa,aj,n); 1504003131ecSBarry Smith /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 150597952fefSHong Zhang y[*ridx++] = sum; 150697952fefSHong Zhang } 150797952fefSHong Zhang } else { /* do not use compressed row format */ 1508b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ) 15093d3eaba7SBarry Smith aj = a->j; 1510fff043a9SJunchao Zhang aa = a_a; 1511b05257ddSBarry Smith fortranmultaij_(&m,x,ii,aj,aa,y); 1512b05257ddSBarry Smith #else 151317ab2063SBarry Smith for (i=0; i<m; i++) { 1514003131ecSBarry Smith n = ii[i+1] - ii[i]; 1515003131ecSBarry Smith aj = a->j + ii[i]; 1516fff043a9SJunchao Zhang aa = a_a + ii[i]; 151717ab2063SBarry Smith sum = 0.0; 1518003131ecSBarry Smith PetscSparseDensePlusDot(sum,x,aa,aj,n); 151917ab2063SBarry Smith y[i] = sum; 152017ab2063SBarry Smith } 15218d195f9aSBarry Smith #endif 1522b05257ddSBarry Smith } 15239566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*a->nz - a->nonzerorowcnt)); 15249566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx,&x)); 15259566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy,&y)); 15269566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&a_a)); 15273a40ed3dSBarry Smith PetscFunctionReturn(0); 152817ab2063SBarry Smith } 152917ab2063SBarry Smith 1530b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy) 1531b434eb95SMatthew G. Knepley { 1532b434eb95SMatthew G. Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1533b434eb95SMatthew G. Knepley PetscScalar *y; 1534b434eb95SMatthew G. Knepley const PetscScalar *x; 1535fff043a9SJunchao Zhang const MatScalar *aa,*a_a; 1536b434eb95SMatthew G. Knepley PetscInt m=A->rmap->n; 1537b434eb95SMatthew G. Knepley const PetscInt *aj,*ii,*ridx=NULL; 1538b434eb95SMatthew G. Knepley PetscInt n,i,nonzerorow=0; 1539b434eb95SMatthew G. Knepley PetscScalar sum; 1540b434eb95SMatthew G. Knepley PetscBool usecprow=a->compressedrow.use; 1541b434eb95SMatthew G. Knepley 1542b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 1543b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa) 1544b434eb95SMatthew G. Knepley #endif 1545b434eb95SMatthew G. Knepley 1546b434eb95SMatthew G. Knepley PetscFunctionBegin; 15479566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&a_a)); 15489566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx,&x)); 15499566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy,&y)); 1550b434eb95SMatthew G. Knepley if (usecprow) { /* use compressed row format */ 1551b434eb95SMatthew G. Knepley m = a->compressedrow.nrows; 1552b434eb95SMatthew G. Knepley ii = a->compressedrow.i; 1553b434eb95SMatthew G. Knepley ridx = a->compressedrow.rindex; 1554b434eb95SMatthew G. Knepley for (i=0; i<m; i++) { 1555b434eb95SMatthew G. Knepley n = ii[i+1] - ii[i]; 1556b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1557fff043a9SJunchao Zhang aa = a_a + ii[i]; 1558b434eb95SMatthew G. Knepley sum = 0.0; 1559b434eb95SMatthew G. Knepley nonzerorow += (n>0); 1560b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1561b434eb95SMatthew G. Knepley /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 1562b434eb95SMatthew G. Knepley y[*ridx++] = sum; 1563b434eb95SMatthew G. Knepley } 1564b434eb95SMatthew G. Knepley } else { /* do not use compressed row format */ 15653d3eaba7SBarry Smith ii = a->i; 1566b434eb95SMatthew G. Knepley for (i=0; i<m; i++) { 1567b434eb95SMatthew G. Knepley n = ii[i+1] - ii[i]; 1568b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1569fff043a9SJunchao Zhang aa = a_a + ii[i]; 1570b434eb95SMatthew G. Knepley sum = 0.0; 1571b434eb95SMatthew G. Knepley nonzerorow += (n>0); 1572b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1573b434eb95SMatthew G. Knepley y[i] = sum; 1574b434eb95SMatthew G. Knepley } 1575b434eb95SMatthew G. Knepley } 15769566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*a->nz - nonzerorow)); 15779566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx,&x)); 15789566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy,&y)); 15799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&a_a)); 1580b434eb95SMatthew G. Knepley PetscFunctionReturn(0); 1581b434eb95SMatthew G. Knepley } 1582b434eb95SMatthew G. Knepley 1583b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz) 1584b434eb95SMatthew G. Knepley { 1585b434eb95SMatthew G. Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1586b434eb95SMatthew G. Knepley PetscScalar *y,*z; 1587b434eb95SMatthew G. Knepley const PetscScalar *x; 1588fff043a9SJunchao Zhang const MatScalar *aa,*a_a; 1589b434eb95SMatthew G. Knepley PetscInt m = A->rmap->n,*aj,*ii; 1590b434eb95SMatthew G. Knepley PetscInt n,i,*ridx=NULL; 1591b434eb95SMatthew G. Knepley PetscScalar sum; 1592b434eb95SMatthew G. Knepley PetscBool usecprow=a->compressedrow.use; 1593b434eb95SMatthew G. Knepley 1594b434eb95SMatthew G. Knepley PetscFunctionBegin; 15959566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&a_a)); 15969566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx,&x)); 15979566063dSJacob Faibussowitsch PetscCall(VecGetArrayPair(yy,zz,&y,&z)); 1598b434eb95SMatthew G. Knepley if (usecprow) { /* use compressed row format */ 1599b434eb95SMatthew G. Knepley if (zz != yy) { 16009566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(z,y,m)); 1601b434eb95SMatthew G. Knepley } 1602b434eb95SMatthew G. Knepley m = a->compressedrow.nrows; 1603b434eb95SMatthew G. Knepley ii = a->compressedrow.i; 1604b434eb95SMatthew G. Knepley ridx = a->compressedrow.rindex; 1605b434eb95SMatthew G. Knepley for (i=0; i<m; i++) { 1606b434eb95SMatthew G. Knepley n = ii[i+1] - ii[i]; 1607b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1608fff043a9SJunchao Zhang aa = a_a + ii[i]; 1609b434eb95SMatthew G. Knepley sum = y[*ridx]; 1610b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1611b434eb95SMatthew G. Knepley z[*ridx++] = sum; 1612b434eb95SMatthew G. Knepley } 1613b434eb95SMatthew G. Knepley } else { /* do not use compressed row format */ 16143d3eaba7SBarry Smith ii = a->i; 1615b434eb95SMatthew G. Knepley for (i=0; i<m; i++) { 1616b434eb95SMatthew G. Knepley n = ii[i+1] - ii[i]; 1617b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1618fff043a9SJunchao Zhang aa = a_a + ii[i]; 1619b434eb95SMatthew G. Knepley sum = y[i]; 1620b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1621b434eb95SMatthew G. Knepley z[i] = sum; 1622b434eb95SMatthew G. Knepley } 1623b434eb95SMatthew G. Knepley } 16249566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*a->nz)); 16259566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx,&x)); 16269566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayPair(yy,zz,&y,&z)); 16279566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&a_a)); 1628b434eb95SMatthew G. Knepley PetscFunctionReturn(0); 1629b434eb95SMatthew G. Knepley } 1630b434eb95SMatthew G. Knepley 1631c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h> 1632dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz) 163317ab2063SBarry Smith { 1634416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1635f15663dcSBarry Smith PetscScalar *y,*z; 1636f15663dcSBarry Smith const PetscScalar *x; 1637fff043a9SJunchao Zhang const MatScalar *aa,*a_a; 1638d9ca1df4SBarry Smith const PetscInt *aj,*ii,*ridx=NULL; 1639d9ca1df4SBarry Smith PetscInt m = A->rmap->n,n,i; 1640362ced78SSatish Balay PetscScalar sum; 1641ace3abfcSBarry Smith PetscBool usecprow=a->compressedrow.use; 16429ea0dfa2SSatish Balay 16433a40ed3dSBarry Smith PetscFunctionBegin; 1644b215bc84SStefano Zampini if (a->inode.use && a->inode.checked) { 16459566063dSJacob Faibussowitsch PetscCall(MatMultAdd_SeqAIJ_Inode(A,xx,yy,zz)); 1646b215bc84SStefano Zampini PetscFunctionReturn(0); 1647b215bc84SStefano Zampini } 16489566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&a_a)); 16499566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx,&x)); 16509566063dSJacob Faibussowitsch PetscCall(VecGetArrayPair(yy,zz,&y,&z)); 16514eb6d288SHong Zhang if (usecprow) { /* use compressed row format */ 16524eb6d288SHong Zhang if (zz != yy) { 16539566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(z,y,m)); 16544eb6d288SHong Zhang } 165597952fefSHong Zhang m = a->compressedrow.nrows; 165697952fefSHong Zhang ii = a->compressedrow.i; 165797952fefSHong Zhang ridx = a->compressedrow.rindex; 165897952fefSHong Zhang for (i=0; i<m; i++) { 165997952fefSHong Zhang n = ii[i+1] - ii[i]; 166097952fefSHong Zhang aj = a->j + ii[i]; 1661fff043a9SJunchao Zhang aa = a_a + ii[i]; 166297952fefSHong Zhang sum = y[*ridx]; 1663f15663dcSBarry Smith PetscSparseDensePlusDot(sum,x,aa,aj,n); 166497952fefSHong Zhang z[*ridx++] = sum; 166597952fefSHong Zhang } 166697952fefSHong Zhang } else { /* do not use compressed row format */ 16673d3eaba7SBarry Smith ii = a->i; 1668f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ) 16693d3eaba7SBarry Smith aj = a->j; 1670fff043a9SJunchao Zhang aa = a_a; 1671f15663dcSBarry Smith fortranmultaddaij_(&m,x,ii,aj,aa,y,z); 1672f15663dcSBarry Smith #else 167317ab2063SBarry Smith for (i=0; i<m; i++) { 1674f15663dcSBarry Smith n = ii[i+1] - ii[i]; 1675f15663dcSBarry Smith aj = a->j + ii[i]; 1676fff043a9SJunchao Zhang aa = a_a + ii[i]; 167717ab2063SBarry Smith sum = y[i]; 1678f15663dcSBarry Smith PetscSparseDensePlusDot(sum,x,aa,aj,n); 167917ab2063SBarry Smith z[i] = sum; 168017ab2063SBarry Smith } 168102ab625aSSatish Balay #endif 1682f15663dcSBarry Smith } 16839566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*a->nz)); 16849566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx,&x)); 16859566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayPair(yy,zz,&y,&z)); 16869566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&a_a)); 16873a40ed3dSBarry Smith PetscFunctionReturn(0); 168817ab2063SBarry Smith } 168917ab2063SBarry Smith 169017ab2063SBarry Smith /* 169117ab2063SBarry Smith Adds diagonal pointers to sparse matrix structure. 169217ab2063SBarry Smith */ 1693dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A) 169417ab2063SBarry Smith { 1695416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1696d0f46423SBarry Smith PetscInt i,j,m = A->rmap->n; 1697c0c07093SJunchao Zhang PetscBool alreadySet = PETSC_TRUE; 169817ab2063SBarry Smith 16993a40ed3dSBarry Smith PetscFunctionBegin; 170009f38230SBarry Smith if (!a->diag) { 17019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m,&a->diag)); 17029566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt))); 1703c0c07093SJunchao Zhang alreadySet = PETSC_FALSE; 170409f38230SBarry Smith } 1705d0f46423SBarry Smith for (i=0; i<A->rmap->n; i++) { 1706c0c07093SJunchao Zhang /* If A's diagonal is already correctly set, this fast track enables cheap and repeated MatMarkDiagonal_SeqAIJ() calls */ 1707c0c07093SJunchao Zhang if (alreadySet) { 1708c0c07093SJunchao Zhang PetscInt pos = a->diag[i]; 1709c0c07093SJunchao Zhang if (pos >= a->i[i] && pos < a->i[i+1] && a->j[pos] == i) continue; 1710c0c07093SJunchao Zhang } 1711c0c07093SJunchao Zhang 171209f38230SBarry Smith a->diag[i] = a->i[i+1]; 1713bfeeae90SHong Zhang for (j=a->i[i]; j<a->i[i+1]; j++) { 1714bfeeae90SHong Zhang if (a->j[j] == i) { 171509f38230SBarry Smith a->diag[i] = j; 171617ab2063SBarry Smith break; 171717ab2063SBarry Smith } 171817ab2063SBarry Smith } 171917ab2063SBarry Smith } 17203a40ed3dSBarry Smith PetscFunctionReturn(0); 172117ab2063SBarry Smith } 172217ab2063SBarry Smith 172361ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v) 172461ecd0c6SBarry Smith { 172561ecd0c6SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 172661ecd0c6SBarry Smith const PetscInt *diag = (const PetscInt*)a->diag; 172761ecd0c6SBarry Smith const PetscInt *ii = (const PetscInt*) a->i; 172861ecd0c6SBarry Smith PetscInt i,*mdiag = NULL; 172961ecd0c6SBarry Smith PetscInt cnt = 0; /* how many diagonals are missing */ 173061ecd0c6SBarry Smith 173161ecd0c6SBarry Smith PetscFunctionBegin; 173261ecd0c6SBarry Smith if (!A->preallocated || !a->nz) { 17339566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(A,1,NULL)); 17349566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(A,v)); 173561ecd0c6SBarry Smith PetscFunctionReturn(0); 173661ecd0c6SBarry Smith } 173761ecd0c6SBarry Smith 173861ecd0c6SBarry Smith if (a->diagonaldense) { 173961ecd0c6SBarry Smith cnt = 0; 174061ecd0c6SBarry Smith } else { 17419566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n,&mdiag)); 174261ecd0c6SBarry Smith for (i=0; i<A->rmap->n; i++) { 1743349d3b71SJunchao Zhang if (i < A->cmap->n && diag[i] >= ii[i+1]) { /* 'out of range' rows never have diagonals */ 174461ecd0c6SBarry Smith cnt++; 174561ecd0c6SBarry Smith mdiag[i] = 1; 174661ecd0c6SBarry Smith } 174761ecd0c6SBarry Smith } 174861ecd0c6SBarry Smith } 174961ecd0c6SBarry Smith if (!cnt) { 17509566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(A,v)); 175161ecd0c6SBarry Smith } else { 1752b6f2aa54SBarry Smith PetscScalar *olda = a->a; /* preserve pointers to current matrix nonzeros structure and values */ 1753b6f2aa54SBarry Smith PetscInt *oldj = a->j, *oldi = a->i; 175461ecd0c6SBarry Smith PetscBool singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij; 175561ecd0c6SBarry Smith 175661ecd0c6SBarry Smith a->a = NULL; 175761ecd0c6SBarry Smith a->j = NULL; 175861ecd0c6SBarry Smith a->i = NULL; 175961ecd0c6SBarry Smith /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */ 1760349d3b71SJunchao Zhang for (i=0; i<PetscMin(A->rmap->n,A->cmap->n); i++) { 176161ecd0c6SBarry Smith a->imax[i] += mdiag[i]; 176261ecd0c6SBarry Smith } 17639566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax)); 176461ecd0c6SBarry Smith 176561ecd0c6SBarry Smith /* copy old values into new matrix data structure */ 176661ecd0c6SBarry Smith for (i=0; i<A->rmap->n; i++) { 17679566063dSJacob Faibussowitsch PetscCall(MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES)); 1768447d62f5SStefano Zampini if (i < A->cmap->n) { 17699566063dSJacob Faibussowitsch PetscCall(MatSetValue(A,i,i,v,ADD_VALUES)); 177061ecd0c6SBarry Smith } 1771447d62f5SStefano Zampini } 17729566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY)); 17739566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY)); 177461ecd0c6SBarry Smith if (singlemalloc) { 17759566063dSJacob Faibussowitsch PetscCall(PetscFree3(olda,oldj,oldi)); 177661ecd0c6SBarry Smith } else { 17779566063dSJacob Faibussowitsch if (free_a) PetscCall(PetscFree(olda)); 17789566063dSJacob Faibussowitsch if (free_ij) PetscCall(PetscFree(oldj)); 17799566063dSJacob Faibussowitsch if (free_ij) PetscCall(PetscFree(oldi)); 178061ecd0c6SBarry Smith } 178161ecd0c6SBarry Smith } 17829566063dSJacob Faibussowitsch PetscCall(PetscFree(mdiag)); 178361ecd0c6SBarry Smith a->diagonaldense = PETSC_TRUE; 178461ecd0c6SBarry Smith PetscFunctionReturn(0); 178561ecd0c6SBarry Smith } 178661ecd0c6SBarry Smith 1787be5855fcSBarry Smith /* 1788be5855fcSBarry Smith Checks for missing diagonals 1789be5855fcSBarry Smith */ 1790ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool *missing,PetscInt *d) 1791be5855fcSBarry Smith { 1792be5855fcSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 17937734d3b5SMatthew G. Knepley PetscInt *diag,*ii = a->i,i; 1794be5855fcSBarry Smith 1795be5855fcSBarry Smith PetscFunctionBegin; 179609f38230SBarry Smith *missing = PETSC_FALSE; 17977734d3b5SMatthew G. Knepley if (A->rmap->n > 0 && !ii) { 179809f38230SBarry Smith *missing = PETSC_TRUE; 179909f38230SBarry Smith if (d) *d = 0; 18009566063dSJacob Faibussowitsch PetscCall(PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n")); 180109f38230SBarry Smith } else { 180201445905SHong Zhang PetscInt n; 180301445905SHong Zhang n = PetscMin(A->rmap->n, A->cmap->n); 1804f1e2ffcdSBarry Smith diag = a->diag; 180501445905SHong Zhang for (i=0; i<n; i++) { 18067734d3b5SMatthew G. Knepley if (diag[i] >= ii[i+1]) { 180709f38230SBarry Smith *missing = PETSC_TRUE; 180809f38230SBarry Smith if (d) *d = i; 18099566063dSJacob Faibussowitsch PetscCall(PetscInfo(A,"Matrix is missing diagonal number %" PetscInt_FMT "\n",i)); 1810358d2f5dSShri Abhyankar break; 181109f38230SBarry Smith } 1812be5855fcSBarry Smith } 1813be5855fcSBarry Smith } 1814be5855fcSBarry Smith PetscFunctionReturn(0); 1815be5855fcSBarry Smith } 1816be5855fcSBarry Smith 18170da83c2eSBarry Smith #include <petscblaslapack.h> 18180da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h> 18190da83c2eSBarry Smith 18200da83c2eSBarry Smith /* 18210da83c2eSBarry Smith Note that values is allocated externally by the PC and then passed into this routine 18220da83c2eSBarry Smith */ 18230da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag) 18240da83c2eSBarry Smith { 18250da83c2eSBarry Smith PetscInt n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots; 18260da83c2eSBarry Smith PetscBool allowzeropivot,zeropivotdetected=PETSC_FALSE; 18270da83c2eSBarry Smith const PetscReal shift = 0.0; 18280da83c2eSBarry Smith PetscInt ipvt[5]; 18290da83c2eSBarry Smith PetscScalar work[25],*v_work; 18300da83c2eSBarry Smith 18310da83c2eSBarry Smith PetscFunctionBegin; 18320da83c2eSBarry Smith allowzeropivot = PetscNot(A->erroriffailure); 18330da83c2eSBarry Smith for (i=0; i<nblocks; i++) ncnt += bsizes[i]; 183408401ef6SPierre Jolivet PetscCheck(ncnt == n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Total blocksizes %" PetscInt_FMT " doesn't match number matrix rows %" PetscInt_FMT,ncnt,n); 18350da83c2eSBarry Smith for (i=0; i<nblocks; i++) { 18360da83c2eSBarry Smith bsizemax = PetscMax(bsizemax,bsizes[i]); 18370da83c2eSBarry Smith } 18389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsizemax,&indx)); 18390da83c2eSBarry Smith if (bsizemax > 7) { 18409566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots)); 18410da83c2eSBarry Smith } 18420da83c2eSBarry Smith ncnt = 0; 18430da83c2eSBarry Smith for (i=0; i<nblocks; i++) { 18440da83c2eSBarry Smith for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j; 18459566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag)); 18460da83c2eSBarry Smith switch (bsizes[i]) { 18470da83c2eSBarry Smith case 1: 18480da83c2eSBarry Smith *diag = 1.0/(*diag); 18490da83c2eSBarry Smith break; 18500da83c2eSBarry Smith case 2: 18519566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected)); 18520da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18539566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_2(diag)); 18540da83c2eSBarry Smith break; 18550da83c2eSBarry Smith case 3: 18569566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected)); 18570da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18589566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_3(diag)); 18590da83c2eSBarry Smith break; 18600da83c2eSBarry Smith case 4: 18619566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected)); 18620da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18639566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_4(diag)); 18640da83c2eSBarry Smith break; 18650da83c2eSBarry Smith case 5: 18669566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected)); 18670da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18689566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_5(diag)); 18690da83c2eSBarry Smith break; 18700da83c2eSBarry Smith case 6: 18719566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected)); 18720da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18739566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_6(diag)); 18740da83c2eSBarry Smith break; 18750da83c2eSBarry Smith case 7: 18769566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected)); 18770da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18789566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_7(diag)); 18790da83c2eSBarry Smith break; 18800da83c2eSBarry Smith default: 18819566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected)); 18820da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18839566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_N(diag,bsizes[i])); 18840da83c2eSBarry Smith } 18850da83c2eSBarry Smith ncnt += bsizes[i]; 18860da83c2eSBarry Smith diag += bsizes[i]*bsizes[i]; 18870da83c2eSBarry Smith } 18880da83c2eSBarry Smith if (bsizemax > 7) { 18899566063dSJacob Faibussowitsch PetscCall(PetscFree2(v_work,v_pivots)); 18900da83c2eSBarry Smith } 18919566063dSJacob Faibussowitsch PetscCall(PetscFree(indx)); 18920da83c2eSBarry Smith PetscFunctionReturn(0); 18930da83c2eSBarry Smith } 18940da83c2eSBarry Smith 1895422a814eSBarry Smith /* 1896422a814eSBarry Smith Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways 1897422a814eSBarry Smith */ 18987087cfbeSBarry Smith PetscErrorCode MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift) 189971f1c65dSBarry Smith { 190071f1c65dSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data; 1901d0f46423SBarry Smith PetscInt i,*diag,m = A->rmap->n; 19022e5835c6SStefano Zampini const MatScalar *v; 190354f21887SBarry Smith PetscScalar *idiag,*mdiag; 190471f1c65dSBarry Smith 190571f1c65dSBarry Smith PetscFunctionBegin; 190671f1c65dSBarry Smith if (a->idiagvalid) PetscFunctionReturn(0); 19079566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 190871f1c65dSBarry Smith diag = a->diag; 190971f1c65dSBarry Smith if (!a->idiag) { 19109566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work)); 19119566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A,3*m*sizeof(PetscScalar))); 191271f1c65dSBarry Smith } 19132e5835c6SStefano Zampini 191471f1c65dSBarry Smith mdiag = a->mdiag; 191571f1c65dSBarry Smith idiag = a->idiag; 19169566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&v)); 1917422a814eSBarry Smith if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) { 191871f1c65dSBarry Smith for (i=0; i<m; i++) { 191971f1c65dSBarry Smith mdiag[i] = v[diag[i]]; 1920899639b0SHong Zhang if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */ 1921899639b0SHong Zhang if (PetscRealPart(fshift)) { 19229566063dSJacob Faibussowitsch PetscCall(PetscInfo(A,"Zero diagonal on row %" PetscInt_FMT "\n",i)); 19237b6c816cSBarry Smith A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 19247b6c816cSBarry Smith A->factorerror_zeropivot_value = 0.0; 19257b6c816cSBarry Smith A->factorerror_zeropivot_row = i; 192698921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %" PetscInt_FMT,i); 1927899639b0SHong Zhang } 192871f1c65dSBarry Smith idiag[i] = 1.0/v[diag[i]]; 192971f1c65dSBarry Smith } 19309566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(m)); 193171f1c65dSBarry Smith } else { 193271f1c65dSBarry Smith for (i=0; i<m; i++) { 193371f1c65dSBarry Smith mdiag[i] = v[diag[i]]; 193471f1c65dSBarry Smith idiag[i] = omega/(fshift + v[diag[i]]); 193571f1c65dSBarry Smith } 19369566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*m)); 193771f1c65dSBarry Smith } 193871f1c65dSBarry Smith a->idiagvalid = PETSC_TRUE; 19399566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&v)); 194071f1c65dSBarry Smith PetscFunctionReturn(0); 194171f1c65dSBarry Smith } 194271f1c65dSBarry Smith 1943c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h> 194441f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 194517ab2063SBarry Smith { 1946416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1947e6d1f457SBarry Smith PetscScalar *x,d,sum,*t,scale; 19482e5835c6SStefano Zampini const MatScalar *v,*idiag=NULL,*mdiag,*aa; 194954f21887SBarry Smith const PetscScalar *b, *bs,*xb, *ts; 19503d3eaba7SBarry Smith PetscInt n,m = A->rmap->n,i; 195197f1f81fSBarry Smith const PetscInt *idx,*diag; 195217ab2063SBarry Smith 19533a40ed3dSBarry Smith PetscFunctionBegin; 1954b215bc84SStefano Zampini if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) { 19559566063dSJacob Faibussowitsch PetscCall(MatSOR_SeqAIJ_Inode(A,bb,omega,flag,fshift,its,lits,xx)); 1956b215bc84SStefano Zampini PetscFunctionReturn(0); 1957b215bc84SStefano Zampini } 1958b965ef7fSBarry Smith its = its*lits; 195991723122SBarry Smith 196071f1c65dSBarry Smith if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */ 19619566063dSJacob Faibussowitsch if (!a->idiagvalid) PetscCall(MatInvertDiagonal_SeqAIJ(A,omega,fshift)); 196271f1c65dSBarry Smith a->fshift = fshift; 196371f1c65dSBarry Smith a->omega = omega; 1964ed480e8bSBarry Smith 196571f1c65dSBarry Smith diag = a->diag; 196671f1c65dSBarry Smith t = a->ssor_work; 1967ed480e8bSBarry Smith idiag = a->idiag; 196871f1c65dSBarry Smith mdiag = a->mdiag; 1969ed480e8bSBarry Smith 19709566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 19719566063dSJacob Faibussowitsch PetscCall(VecGetArray(xx,&x)); 19729566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(bb,&b)); 1973ed480e8bSBarry Smith /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */ 197417ab2063SBarry Smith if (flag == SOR_APPLY_UPPER) { 197517ab2063SBarry Smith /* apply (U + D/omega) to the vector */ 1976ed480e8bSBarry Smith bs = b; 197717ab2063SBarry Smith for (i=0; i<m; i++) { 197871f1c65dSBarry Smith d = fshift + mdiag[i]; 1979416022c9SBarry Smith n = a->i[i+1] - diag[i] - 1; 1980ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 19812e5835c6SStefano Zampini v = aa + diag[i] + 1; 198217ab2063SBarry Smith sum = b[i]*d/omega; 1983003131ecSBarry Smith PetscSparseDensePlusDot(sum,bs,v,idx,n); 198417ab2063SBarry Smith x[i] = sum; 198517ab2063SBarry Smith } 19869566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx,&x)); 19879566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb,&b)); 19889566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 19899566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 19903a40ed3dSBarry Smith PetscFunctionReturn(0); 199117ab2063SBarry Smith } 1992c783ea89SBarry Smith 199308401ef6SPierre Jolivet PetscCheck(flag != SOR_APPLY_LOWER,PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented"); 19942205254eSKarl Rupp else if (flag & SOR_EISENSTAT) { 19954c500f23SPierre Jolivet /* Let A = L + U + D; where L is lower triangular, 1996887ee2caSBarry Smith U is upper triangular, E = D/omega; This routine applies 199717ab2063SBarry Smith 199817ab2063SBarry Smith (L + E)^{-1} A (U + E)^{-1} 199917ab2063SBarry Smith 2000887ee2caSBarry Smith to a vector efficiently using Eisenstat's trick. 200117ab2063SBarry Smith */ 200217ab2063SBarry Smith scale = (2.0/omega) - 1.0; 200317ab2063SBarry Smith 200417ab2063SBarry Smith /* x = (E + U)^{-1} b */ 200517ab2063SBarry Smith for (i=m-1; i>=0; i--) { 2006416022c9SBarry Smith n = a->i[i+1] - diag[i] - 1; 2007ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 20082e5835c6SStefano Zampini v = aa + diag[i] + 1; 200917ab2063SBarry Smith sum = b[i]; 2010e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum,x,v,idx,n); 2011ed480e8bSBarry Smith x[i] = sum*idiag[i]; 201217ab2063SBarry Smith } 201317ab2063SBarry Smith 201417ab2063SBarry Smith /* t = b - (2*E - D)x */ 20152e5835c6SStefano Zampini v = aa; 20162205254eSKarl Rupp for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i]; 201717ab2063SBarry Smith 201817ab2063SBarry Smith /* t = (E + L)^{-1}t */ 2019ed480e8bSBarry Smith ts = t; 2020416022c9SBarry Smith diag = a->diag; 202117ab2063SBarry Smith for (i=0; i<m; i++) { 2022416022c9SBarry Smith n = diag[i] - a->i[i]; 2023ed480e8bSBarry Smith idx = a->j + a->i[i]; 20242e5835c6SStefano Zampini v = aa + a->i[i]; 202517ab2063SBarry Smith sum = t[i]; 2026003131ecSBarry Smith PetscSparseDenseMinusDot(sum,ts,v,idx,n); 2027ed480e8bSBarry Smith t[i] = sum*idiag[i]; 2028733d66baSBarry Smith /* x = x + t */ 2029733d66baSBarry Smith x[i] += t[i]; 203017ab2063SBarry Smith } 203117ab2063SBarry Smith 20329566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(6.0*m-1 + 2.0*a->nz)); 20339566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx,&x)); 20349566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb,&b)); 20353a40ed3dSBarry Smith PetscFunctionReturn(0); 203617ab2063SBarry Smith } 203717ab2063SBarry Smith if (flag & SOR_ZERO_INITIAL_GUESS) { 203817ab2063SBarry Smith if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 203917ab2063SBarry Smith for (i=0; i<m; i++) { 2040416022c9SBarry Smith n = diag[i] - a->i[i]; 2041ed480e8bSBarry Smith idx = a->j + a->i[i]; 20422e5835c6SStefano Zampini v = aa + a->i[i]; 204317ab2063SBarry Smith sum = b[i]; 2044e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum,x,v,idx,n); 20455c99c7daSBarry Smith t[i] = sum; 2046ed480e8bSBarry Smith x[i] = sum*idiag[i]; 204717ab2063SBarry Smith } 20485c99c7daSBarry Smith xb = t; 20499566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 20503a40ed3dSBarry Smith } else xb = b; 205117ab2063SBarry Smith if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 205217ab2063SBarry Smith for (i=m-1; i>=0; i--) { 2053416022c9SBarry Smith n = a->i[i+1] - diag[i] - 1; 2054ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 20552e5835c6SStefano Zampini v = aa + diag[i] + 1; 205617ab2063SBarry Smith sum = xb[i]; 2057e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum,x,v,idx,n); 20585c99c7daSBarry Smith if (xb == b) { 2059ed480e8bSBarry Smith x[i] = sum*idiag[i]; 20605c99c7daSBarry Smith } else { 2061b19a5dc2SMark Adams x[i] = (1-omega)*x[i] + sum*idiag[i]; /* omega in idiag */ 206217ab2063SBarry Smith } 20635c99c7daSBarry Smith } 20649566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */ 206517ab2063SBarry Smith } 206617ab2063SBarry Smith its--; 206717ab2063SBarry Smith } 206817ab2063SBarry Smith while (its--) { 206917ab2063SBarry Smith if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 207017ab2063SBarry Smith for (i=0; i<m; i++) { 2071b19a5dc2SMark Adams /* lower */ 2072b19a5dc2SMark Adams n = diag[i] - a->i[i]; 2073ed480e8bSBarry Smith idx = a->j + a->i[i]; 20742e5835c6SStefano Zampini v = aa + a->i[i]; 207517ab2063SBarry Smith sum = b[i]; 2076e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum,x,v,idx,n); 2077b19a5dc2SMark Adams t[i] = sum; /* save application of the lower-triangular part */ 2078b19a5dc2SMark Adams /* upper */ 2079b19a5dc2SMark Adams n = a->i[i+1] - diag[i] - 1; 2080b19a5dc2SMark Adams idx = a->j + diag[i] + 1; 20812e5835c6SStefano Zampini v = aa + diag[i] + 1; 2082b19a5dc2SMark Adams PetscSparseDenseMinusDot(sum,x,v,idx,n); 2083b19a5dc2SMark Adams x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */ 208417ab2063SBarry Smith } 2085b19a5dc2SMark Adams xb = t; 20869566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*a->nz)); 2087b19a5dc2SMark Adams } else xb = b; 208817ab2063SBarry Smith if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 208917ab2063SBarry Smith for (i=m-1; i>=0; i--) { 2090b19a5dc2SMark Adams sum = xb[i]; 2091b19a5dc2SMark Adams if (xb == b) { 2092b19a5dc2SMark Adams /* whole matrix (no checkpointing available) */ 2093416022c9SBarry Smith n = a->i[i+1] - a->i[i]; 2094ed480e8bSBarry Smith idx = a->j + a->i[i]; 20952e5835c6SStefano Zampini v = aa + a->i[i]; 2096e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum,x,v,idx,n); 2097ed480e8bSBarry Smith x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i]; 2098b19a5dc2SMark Adams } else { /* lower-triangular part has been saved, so only apply upper-triangular */ 2099b19a5dc2SMark Adams n = a->i[i+1] - diag[i] - 1; 2100b19a5dc2SMark Adams idx = a->j + diag[i] + 1; 21012e5835c6SStefano Zampini v = aa + diag[i] + 1; 2102b19a5dc2SMark Adams PetscSparseDenseMinusDot(sum,x,v,idx,n); 2103b19a5dc2SMark Adams x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */ 210417ab2063SBarry Smith } 2105b19a5dc2SMark Adams } 2106b19a5dc2SMark Adams if (xb == b) { 21079566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*a->nz)); 2108b19a5dc2SMark Adams } else { 21099566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */ 2110b19a5dc2SMark Adams } 211117ab2063SBarry Smith } 211217ab2063SBarry Smith } 21139566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 21149566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx,&x)); 21159566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb,&b)); 2116365a8a9eSBarry Smith PetscFunctionReturn(0); 211717ab2063SBarry Smith } 211817ab2063SBarry Smith 2119dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info) 212017ab2063SBarry Smith { 2121416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 21224e220ebcSLois Curfman McInnes 21233a40ed3dSBarry Smith PetscFunctionBegin; 21244e220ebcSLois Curfman McInnes info->block_size = 1.0; 21253966268fSBarry Smith info->nz_allocated = a->maxnz; 21263966268fSBarry Smith info->nz_used = a->nz; 21273966268fSBarry Smith info->nz_unneeded = (a->maxnz - a->nz); 21283966268fSBarry Smith info->assemblies = A->num_ass; 21293966268fSBarry Smith info->mallocs = A->info.mallocs; 21307adad957SLisandro Dalcin info->memory = ((PetscObject)A)->mem; 2131d5f3da31SBarry Smith if (A->factortype) { 21324e220ebcSLois Curfman McInnes info->fill_ratio_given = A->info.fill_ratio_given; 21334e220ebcSLois Curfman McInnes info->fill_ratio_needed = A->info.fill_ratio_needed; 21344e220ebcSLois Curfman McInnes info->factor_mallocs = A->info.factor_mallocs; 21354e220ebcSLois Curfman McInnes } else { 21364e220ebcSLois Curfman McInnes info->fill_ratio_given = 0; 21374e220ebcSLois Curfman McInnes info->fill_ratio_needed = 0; 21384e220ebcSLois Curfman McInnes info->factor_mallocs = 0; 21394e220ebcSLois Curfman McInnes } 21403a40ed3dSBarry Smith PetscFunctionReturn(0); 214117ab2063SBarry Smith } 214217ab2063SBarry Smith 21432b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 214417ab2063SBarry Smith { 2145416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2146c7da8527SEric Chamberland PetscInt i,m = A->rmap->n - 1; 214797b48c8fSBarry Smith const PetscScalar *xx; 21482e5835c6SStefano Zampini PetscScalar *bb,*aa; 2149c7da8527SEric Chamberland PetscInt d = 0; 215017ab2063SBarry Smith 21513a40ed3dSBarry Smith PetscFunctionBegin; 215297b48c8fSBarry Smith if (x && b) { 21539566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x,&xx)); 21549566063dSJacob Faibussowitsch PetscCall(VecGetArray(b,&bb)); 215597b48c8fSBarry Smith for (i=0; i<N; i++) { 2156aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]); 2157447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 215897b48c8fSBarry Smith bb[rows[i]] = diag*xx[rows[i]]; 215997b48c8fSBarry Smith } 21609566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x,&xx)); 21619566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b,&bb)); 216297b48c8fSBarry Smith } 216397b48c8fSBarry Smith 21649566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&aa)); 2165a9817697SBarry Smith if (a->keepnonzeropattern) { 2166f1e2ffcdSBarry Smith for (i=0; i<N; i++) { 2167aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]); 21689566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]])); 2169f1e2ffcdSBarry Smith } 2170f4df32b1SMatthew Knepley if (diag != 0.0) { 2171c7da8527SEric Chamberland for (i=0; i<N; i++) { 2172c7da8527SEric Chamberland d = rows[i]; 2173447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 217408401ef6SPierre Jolivet PetscCheck(a->diag[d] < a->i[d+1],PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in the zeroed row %" PetscInt_FMT,d); 2175c7da8527SEric Chamberland } 2176f1e2ffcdSBarry Smith for (i=0; i<N; i++) { 2177447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 21782e5835c6SStefano Zampini aa[a->diag[rows[i]]] = diag; 2179f1e2ffcdSBarry Smith } 2180f1e2ffcdSBarry Smith } 2181f1e2ffcdSBarry Smith } else { 2182f4df32b1SMatthew Knepley if (diag != 0.0) { 218317ab2063SBarry Smith for (i=0; i<N; i++) { 2184aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]); 21857ae801bdSBarry Smith if (a->ilen[rows[i]] > 0) { 2186447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) { 2187447d62f5SStefano Zampini a->ilen[rows[i]] = 0; 2188447d62f5SStefano Zampini } else { 2189416022c9SBarry Smith a->ilen[rows[i]] = 1; 21902e5835c6SStefano Zampini aa[a->i[rows[i]]] = diag; 2191bfeeae90SHong Zhang a->j[a->i[rows[i]]] = rows[i]; 2192447d62f5SStefano Zampini } 2193447d62f5SStefano Zampini } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */ 21949566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES)); 219517ab2063SBarry Smith } 219617ab2063SBarry Smith } 21973a40ed3dSBarry Smith } else { 219817ab2063SBarry Smith for (i=0; i<N; i++) { 2199aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]); 2200416022c9SBarry Smith a->ilen[rows[i]] = 0; 220117ab2063SBarry Smith } 220217ab2063SBarry Smith } 2203e56f5c9eSBarry Smith A->nonzerostate++; 2204f1e2ffcdSBarry Smith } 22059566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&aa)); 22069566063dSJacob Faibussowitsch PetscCall((*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY)); 22073a40ed3dSBarry Smith PetscFunctionReturn(0); 220817ab2063SBarry Smith } 220917ab2063SBarry Smith 22106e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 22116e169961SBarry Smith { 22126e169961SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 22136e169961SBarry Smith PetscInt i,j,m = A->rmap->n - 1,d = 0; 22142b40b63fSBarry Smith PetscBool missing,*zeroed,vecs = PETSC_FALSE; 22156e169961SBarry Smith const PetscScalar *xx; 22162e5835c6SStefano Zampini PetscScalar *bb,*aa; 22176e169961SBarry Smith 22186e169961SBarry Smith PetscFunctionBegin; 22192e5835c6SStefano Zampini if (!N) PetscFunctionReturn(0); 22209566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&aa)); 22216e169961SBarry Smith if (x && b) { 22229566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x,&xx)); 22239566063dSJacob Faibussowitsch PetscCall(VecGetArray(b,&bb)); 22242b40b63fSBarry Smith vecs = PETSC_TRUE; 22256e169961SBarry Smith } 22269566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n,&zeroed)); 22276e169961SBarry Smith for (i=0; i<N; i++) { 2228aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]); 22299566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]])); 22302205254eSKarl Rupp 22316e169961SBarry Smith zeroed[rows[i]] = PETSC_TRUE; 22326e169961SBarry Smith } 22336e169961SBarry Smith for (i=0; i<A->rmap->n; i++) { 22346e169961SBarry Smith if (!zeroed[i]) { 22356e169961SBarry Smith for (j=a->i[i]; j<a->i[i+1]; j++) { 22364cf107fdSStefano Zampini if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) { 22372e5835c6SStefano Zampini if (vecs) bb[i] -= aa[j]*xx[a->j[j]]; 22382e5835c6SStefano Zampini aa[j] = 0.0; 22396e169961SBarry Smith } 22406e169961SBarry Smith } 22414cf107fdSStefano Zampini } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i]; 22426e169961SBarry Smith } 22436e169961SBarry Smith if (x && b) { 22449566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x,&xx)); 22459566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b,&bb)); 22466e169961SBarry Smith } 22479566063dSJacob Faibussowitsch PetscCall(PetscFree(zeroed)); 22486e169961SBarry Smith if (diag != 0.0) { 22499566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal_SeqAIJ(A,&missing,&d)); 22501d5a398dSstefano_zampini if (missing) { 22511d5a398dSstefano_zampini for (i=0; i<N; i++) { 22524cf107fdSStefano Zampini if (rows[i] >= A->cmap->N) continue; 2253aed4548fSBarry Smith PetscCheck(!a->nonew || rows[i] < d,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %" PetscInt_FMT " (%" PetscInt_FMT ")",d,rows[i]); 22549566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES)); 22551d5a398dSstefano_zampini } 22561d5a398dSstefano_zampini } else { 22576e169961SBarry Smith for (i=0; i<N; i++) { 22582e5835c6SStefano Zampini aa[a->diag[rows[i]]] = diag; 22596e169961SBarry Smith } 22606e169961SBarry Smith } 22611d5a398dSstefano_zampini } 22629566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&aa)); 22639566063dSJacob Faibussowitsch PetscCall((*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY)); 22646e169961SBarry Smith PetscFunctionReturn(0); 22656e169961SBarry Smith } 22666e169961SBarry Smith 2267a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 226817ab2063SBarry Smith { 2269fff043a9SJunchao Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2270fff043a9SJunchao Zhang const PetscScalar *aa; 2271fff043a9SJunchao Zhang PetscInt *itmp; 227217ab2063SBarry Smith 22733a40ed3dSBarry Smith PetscFunctionBegin; 22749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 2275416022c9SBarry Smith *nz = a->i[row+1] - a->i[row]; 22762e5835c6SStefano Zampini if (v) *v = (PetscScalar*)(aa + a->i[row]); 227717ab2063SBarry Smith if (idx) { 2278bfeeae90SHong Zhang itmp = a->j + a->i[row]; 227926fbe8dcSKarl Rupp if (*nz) *idx = itmp; 2280f4259b30SLisandro Dalcin else *idx = NULL; 228117ab2063SBarry Smith } 22829566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 22833a40ed3dSBarry Smith PetscFunctionReturn(0); 228417ab2063SBarry Smith } 228517ab2063SBarry Smith 2286a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 228717ab2063SBarry Smith { 22883a40ed3dSBarry Smith PetscFunctionBegin; 2289cb4a9cd9SHong Zhang if (nz) *nz = 0; 22902e5835c6SStefano Zampini if (idx) *idx = NULL; 22912e5835c6SStefano Zampini if (v) *v = NULL; 22923a40ed3dSBarry Smith PetscFunctionReturn(0); 229317ab2063SBarry Smith } 229417ab2063SBarry Smith 2295dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm) 229617ab2063SBarry Smith { 2297416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 22982e5835c6SStefano Zampini const MatScalar *v; 229936db0b34SBarry Smith PetscReal sum = 0.0; 230097f1f81fSBarry Smith PetscInt i,j; 230117ab2063SBarry Smith 23023a40ed3dSBarry Smith PetscFunctionBegin; 23039566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&v)); 230417ab2063SBarry Smith if (type == NORM_FROBENIUS) { 2305570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16) 2306570b7f6dSBarry Smith PetscBLASInt one = 1,nz = a->nz; 230773cf7048SBarry Smith PetscStackCallBLAS("BLASnrm2",*nrm = BLASnrm2_(&nz,v,&one)); 2308570b7f6dSBarry Smith #else 2309416022c9SBarry Smith for (i=0; i<a->nz; i++) { 231036db0b34SBarry Smith sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 231117ab2063SBarry Smith } 23128f1a2a5eSBarry Smith *nrm = PetscSqrtReal(sum); 2313570b7f6dSBarry Smith #endif 23149566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*a->nz)); 23153a40ed3dSBarry Smith } else if (type == NORM_1) { 231636db0b34SBarry Smith PetscReal *tmp; 231797f1f81fSBarry Smith PetscInt *jj = a->j; 23189566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->cmap->n+1,&tmp)); 2319064f8208SBarry Smith *nrm = 0.0; 2320416022c9SBarry Smith for (j=0; j<a->nz; j++) { 2321bfeeae90SHong Zhang tmp[*jj++] += PetscAbsScalar(*v); v++; 232217ab2063SBarry Smith } 2323d0f46423SBarry Smith for (j=0; j<A->cmap->n; j++) { 2324064f8208SBarry Smith if (tmp[j] > *nrm) *nrm = tmp[j]; 232517ab2063SBarry Smith } 23269566063dSJacob Faibussowitsch PetscCall(PetscFree(tmp)); 23279566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(PetscMax(a->nz-1,0))); 23283a40ed3dSBarry Smith } else if (type == NORM_INFINITY) { 2329064f8208SBarry Smith *nrm = 0.0; 2330d0f46423SBarry Smith for (j=0; j<A->rmap->n; j++) { 23312e5835c6SStefano Zampini const PetscScalar *v2 = v + a->i[j]; 233217ab2063SBarry Smith sum = 0.0; 2333416022c9SBarry Smith for (i=0; i<a->i[j+1]-a->i[j]; i++) { 23342e5835c6SStefano Zampini sum += PetscAbsScalar(*v2); v2++; 233517ab2063SBarry Smith } 2336064f8208SBarry Smith if (sum > *nrm) *nrm = sum; 233717ab2063SBarry Smith } 23389566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(PetscMax(a->nz-1,0))); 2339f23aa3ddSBarry Smith } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm"); 23409566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&v)); 23413a40ed3dSBarry Smith PetscFunctionReturn(0); 234217ab2063SBarry Smith } 234317ab2063SBarry Smith 23444e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */ 23454e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B) 23464e938277SHong Zhang { 23474e938277SHong Zhang PetscInt i,j,anzj; 23484e938277SHong Zhang Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data,*b; 23494e938277SHong Zhang PetscInt an=A->cmap->N,am=A->rmap->N; 23504e938277SHong Zhang PetscInt *ati,*atj,*atfill,*ai=a->i,*aj=a->j; 23514e938277SHong Zhang 23524e938277SHong Zhang PetscFunctionBegin; 23534e938277SHong Zhang /* Allocate space for symbolic transpose info and work array */ 23549566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(an+1,&ati)); 23559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ai[am],&atj)); 23569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(an,&atfill)); 23574e938277SHong Zhang 23584e938277SHong Zhang /* Walk through aj and count ## of non-zeros in each row of A^T. */ 23594e938277SHong Zhang /* Note: offset by 1 for fast conversion into csr format. */ 236026fbe8dcSKarl Rupp for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1; 23614e938277SHong Zhang /* Form ati for csr format of A^T. */ 236226fbe8dcSKarl Rupp for (i=0;i<an;i++) ati[i+1] += ati[i]; 23634e938277SHong Zhang 23644e938277SHong Zhang /* Copy ati into atfill so we have locations of the next free space in atj */ 23659566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(atfill,ati,an)); 23664e938277SHong Zhang 23674e938277SHong Zhang /* Walk through A row-wise and mark nonzero entries of A^T. */ 23684e938277SHong Zhang for (i=0;i<am;i++) { 23694e938277SHong Zhang anzj = ai[i+1] - ai[i]; 23704e938277SHong Zhang for (j=0;j<anzj;j++) { 23714e938277SHong Zhang atj[atfill[*aj]] = i; 23724e938277SHong Zhang atfill[*aj++] += 1; 23734e938277SHong Zhang } 23744e938277SHong Zhang } 23754e938277SHong Zhang 23764e938277SHong Zhang /* Clean up temporary space and complete requests. */ 23779566063dSJacob Faibussowitsch PetscCall(PetscFree(atfill)); 23789566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B)); 23799566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs))); 23809566063dSJacob Faibussowitsch PetscCall(MatSetType(*B,((PetscObject)A)->type_name)); 2381a2f3521dSMark F. Adams 23824e938277SHong Zhang b = (Mat_SeqAIJ*)((*B)->data); 23834e938277SHong Zhang b->free_a = PETSC_FALSE; 23844e938277SHong Zhang b->free_ij = PETSC_TRUE; 23854e938277SHong Zhang b->nonew = 0; 23864e938277SHong Zhang PetscFunctionReturn(0); 23874e938277SHong Zhang } 23884e938277SHong Zhang 23897087cfbeSBarry Smith PetscErrorCode MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool *f) 2390cd0d46ebSvictorle { 23913d3eaba7SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data; 239254f21887SBarry Smith PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr; 23932e5835c6SStefano Zampini const MatScalar *va,*vb; 239497f1f81fSBarry Smith PetscInt ma,na,mb,nb, i; 2395cd0d46ebSvictorle 2396cd0d46ebSvictorle PetscFunctionBegin; 23979566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&ma,&na)); 23989566063dSJacob Faibussowitsch PetscCall(MatGetSize(B,&mb,&nb)); 23995485867bSBarry Smith if (ma!=nb || na!=mb) { 24005485867bSBarry Smith *f = PETSC_FALSE; 24015485867bSBarry Smith PetscFunctionReturn(0); 24025485867bSBarry Smith } 24039566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&va)); 24049566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B,&vb)); 2405cd0d46ebSvictorle aii = aij->i; bii = bij->i; 2406cd0d46ebSvictorle adx = aij->j; bdx = bij->j; 24079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ma,&aptr)); 24089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mb,&bptr)); 2409cd0d46ebSvictorle for (i=0; i<ma; i++) aptr[i] = aii[i]; 2410cd0d46ebSvictorle for (i=0; i<mb; i++) bptr[i] = bii[i]; 2411cd0d46ebSvictorle 2412cd0d46ebSvictorle *f = PETSC_TRUE; 2413cd0d46ebSvictorle for (i=0; i<ma; i++) { 2414cd0d46ebSvictorle while (aptr[i]<aii[i+1]) { 241597f1f81fSBarry Smith PetscInt idc,idr; 24165485867bSBarry Smith PetscScalar vc,vr; 2417cd0d46ebSvictorle /* column/row index/value */ 24185485867bSBarry Smith idc = adx[aptr[i]]; 24195485867bSBarry Smith idr = bdx[bptr[idc]]; 24205485867bSBarry Smith vc = va[aptr[i]]; 24215485867bSBarry Smith vr = vb[bptr[idc]]; 24225485867bSBarry Smith if (i!=idr || PetscAbsScalar(vc-vr) > tol) { 24235485867bSBarry Smith *f = PETSC_FALSE; 24245485867bSBarry Smith goto done; 2425cd0d46ebSvictorle } else { 24265485867bSBarry Smith aptr[i]++; 24275485867bSBarry Smith if (B || i!=idc) bptr[idc]++; 2428cd0d46ebSvictorle } 2429cd0d46ebSvictorle } 2430cd0d46ebSvictorle } 2431cd0d46ebSvictorle done: 24329566063dSJacob Faibussowitsch PetscCall(PetscFree(aptr)); 24339566063dSJacob Faibussowitsch PetscCall(PetscFree(bptr)); 24349566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&va)); 24359566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B,&vb)); 2436cd0d46ebSvictorle PetscFunctionReturn(0); 2437cd0d46ebSvictorle } 2438cd0d46ebSvictorle 24397087cfbeSBarry Smith PetscErrorCode MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool *f) 24401cbb95d3SBarry Smith { 24413d3eaba7SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data; 244254f21887SBarry Smith PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr; 244354f21887SBarry Smith MatScalar *va,*vb; 24441cbb95d3SBarry Smith PetscInt ma,na,mb,nb, i; 24451cbb95d3SBarry Smith 24461cbb95d3SBarry Smith PetscFunctionBegin; 24479566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&ma,&na)); 24489566063dSJacob Faibussowitsch PetscCall(MatGetSize(B,&mb,&nb)); 24491cbb95d3SBarry Smith if (ma!=nb || na!=mb) { 24501cbb95d3SBarry Smith *f = PETSC_FALSE; 24511cbb95d3SBarry Smith PetscFunctionReturn(0); 24521cbb95d3SBarry Smith } 24531cbb95d3SBarry Smith aii = aij->i; bii = bij->i; 24541cbb95d3SBarry Smith adx = aij->j; bdx = bij->j; 24551cbb95d3SBarry Smith va = aij->a; vb = bij->a; 24569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ma,&aptr)); 24579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mb,&bptr)); 24581cbb95d3SBarry Smith for (i=0; i<ma; i++) aptr[i] = aii[i]; 24591cbb95d3SBarry Smith for (i=0; i<mb; i++) bptr[i] = bii[i]; 24601cbb95d3SBarry Smith 24611cbb95d3SBarry Smith *f = PETSC_TRUE; 24621cbb95d3SBarry Smith for (i=0; i<ma; i++) { 24631cbb95d3SBarry Smith while (aptr[i]<aii[i+1]) { 24641cbb95d3SBarry Smith PetscInt idc,idr; 24651cbb95d3SBarry Smith PetscScalar vc,vr; 24661cbb95d3SBarry Smith /* column/row index/value */ 24671cbb95d3SBarry Smith idc = adx[aptr[i]]; 24681cbb95d3SBarry Smith idr = bdx[bptr[idc]]; 24691cbb95d3SBarry Smith vc = va[aptr[i]]; 24701cbb95d3SBarry Smith vr = vb[bptr[idc]]; 24711cbb95d3SBarry Smith if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) { 24721cbb95d3SBarry Smith *f = PETSC_FALSE; 24731cbb95d3SBarry Smith goto done; 24741cbb95d3SBarry Smith } else { 24751cbb95d3SBarry Smith aptr[i]++; 24761cbb95d3SBarry Smith if (B || i!=idc) bptr[idc]++; 24771cbb95d3SBarry Smith } 24781cbb95d3SBarry Smith } 24791cbb95d3SBarry Smith } 24801cbb95d3SBarry Smith done: 24819566063dSJacob Faibussowitsch PetscCall(PetscFree(aptr)); 24829566063dSJacob Faibussowitsch PetscCall(PetscFree(bptr)); 24831cbb95d3SBarry Smith PetscFunctionReturn(0); 24841cbb95d3SBarry Smith } 24851cbb95d3SBarry Smith 2486ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool *f) 24879e29f15eSvictorle { 24889e29f15eSvictorle PetscFunctionBegin; 24899566063dSJacob Faibussowitsch PetscCall(MatIsTranspose_SeqAIJ(A,A,tol,f)); 24909e29f15eSvictorle PetscFunctionReturn(0); 24919e29f15eSvictorle } 24929e29f15eSvictorle 2493ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool *f) 24941cbb95d3SBarry Smith { 24951cbb95d3SBarry Smith PetscFunctionBegin; 24969566063dSJacob Faibussowitsch PetscCall(MatIsHermitianTranspose_SeqAIJ(A,A,tol,f)); 24971cbb95d3SBarry Smith PetscFunctionReturn(0); 24981cbb95d3SBarry Smith } 24991cbb95d3SBarry Smith 2500dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr) 250117ab2063SBarry Smith { 2502416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2503fff8e43fSBarry Smith const PetscScalar *l,*r; 2504fff8e43fSBarry Smith PetscScalar x; 250554f21887SBarry Smith MatScalar *v; 2506fff8e43fSBarry Smith PetscInt i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz; 2507fff8e43fSBarry Smith const PetscInt *jj; 250817ab2063SBarry Smith 25093a40ed3dSBarry Smith PetscFunctionBegin; 251017ab2063SBarry Smith if (ll) { 25113ea7c6a1SSatish Balay /* The local size is used so that VecMPI can be passed to this routine 25123ea7c6a1SSatish Balay by MatDiagonalScale_MPIAIJ */ 25139566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ll,&m)); 251408401ef6SPierre Jolivet PetscCheck(m == A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length"); 25159566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(ll,&l)); 25169566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&v)); 251717ab2063SBarry Smith for (i=0; i<m; i++) { 251817ab2063SBarry Smith x = l[i]; 2519416022c9SBarry Smith M = a->i[i+1] - a->i[i]; 25202205254eSKarl Rupp for (j=0; j<M; j++) (*v++) *= x; 252117ab2063SBarry Smith } 25229566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(ll,&l)); 25239566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(nz)); 25249566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&v)); 252517ab2063SBarry Smith } 252617ab2063SBarry Smith if (rr) { 25279566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(rr,&n)); 252808401ef6SPierre Jolivet PetscCheck(n == A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length"); 25299566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(rr,&r)); 25309566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&v)); 25312e5835c6SStefano Zampini jj = a->j; 25322205254eSKarl Rupp for (i=0; i<nz; i++) (*v++) *= r[*jj++]; 25339566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&v)); 25349566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(rr,&r)); 25359566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(nz)); 253617ab2063SBarry Smith } 25379566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 25383a40ed3dSBarry Smith PetscFunctionReturn(0); 253917ab2063SBarry Smith } 254017ab2063SBarry Smith 25417dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B) 254217ab2063SBarry Smith { 2543db02288aSLois Curfman McInnes Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*c; 2544d0f46423SBarry Smith PetscInt *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens; 254597f1f81fSBarry Smith PetscInt row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi; 25465d0c19d7SBarry Smith const PetscInt *irow,*icol; 25472e5835c6SStefano Zampini const PetscScalar *aa; 25485d0c19d7SBarry Smith PetscInt nrows,ncols; 254997f1f81fSBarry Smith PetscInt *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen; 255054f21887SBarry Smith MatScalar *a_new,*mat_a; 2551416022c9SBarry Smith Mat C; 2552cdc6f3adSToby Isaac PetscBool stride; 255317ab2063SBarry Smith 25543a40ed3dSBarry Smith PetscFunctionBegin; 25559566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow,&irow)); 25569566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrow,&nrows)); 25579566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscol,&ncols)); 255817ab2063SBarry Smith 25599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride)); 2560ff718158SBarry Smith if (stride) { 25619566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(iscol,&first,&step)); 2562ff718158SBarry Smith } else { 2563ff718158SBarry Smith first = 0; 2564ff718158SBarry Smith step = 0; 2565ff718158SBarry Smith } 2566fee21e36SBarry Smith if (stride && step == 1) { 256702834360SBarry Smith /* special case of contiguous rows */ 25689566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nrows,&lens,nrows,&starts)); 256902834360SBarry Smith /* loop over new rows determining lens and starting points */ 257002834360SBarry Smith for (i=0; i<nrows; i++) { 2571bfeeae90SHong Zhang kstart = ai[irow[i]]; 2572a2744918SBarry Smith kend = kstart + ailen[irow[i]]; 2573a91a9bebSLisandro Dalcin starts[i] = kstart; 257402834360SBarry Smith for (k=kstart; k<kend; k++) { 2575bfeeae90SHong Zhang if (aj[k] >= first) { 257602834360SBarry Smith starts[i] = k; 257702834360SBarry Smith break; 257802834360SBarry Smith } 257902834360SBarry Smith } 2580a2744918SBarry Smith sum = 0; 258102834360SBarry Smith while (k < kend) { 2582bfeeae90SHong Zhang if (aj[k++] >= first+ncols) break; 2583a2744918SBarry Smith sum++; 258402834360SBarry Smith } 2585a2744918SBarry Smith lens[i] = sum; 258602834360SBarry Smith } 258702834360SBarry Smith /* create submatrix */ 2588cddf8d76SBarry Smith if (scall == MAT_REUSE_MATRIX) { 258997f1f81fSBarry Smith PetscInt n_cols,n_rows; 25909566063dSJacob Faibussowitsch PetscCall(MatGetSize(*B,&n_rows,&n_cols)); 2591aed4548fSBarry Smith PetscCheck(n_rows == nrows && n_cols == ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size"); 25929566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*B)); 259308480c60SBarry Smith C = *B; 25943a40ed3dSBarry Smith } else { 25953bef6203SJed Brown PetscInt rbs,cbs; 25969566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),&C)); 25979566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE)); 25989566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(isrow,&rbs)); 25999566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(iscol,&cbs)); 26009566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(C,rbs,cbs)); 26019566063dSJacob Faibussowitsch PetscCall(MatSetType(C,((PetscObject)A)->type_name)); 26029566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens)); 260308480c60SBarry Smith } 2604db02288aSLois Curfman McInnes c = (Mat_SeqAIJ*)C->data; 2605db02288aSLois Curfman McInnes 260602834360SBarry Smith /* loop over rows inserting into submatrix */ 2607db02288aSLois Curfman McInnes a_new = c->a; 2608db02288aSLois Curfman McInnes j_new = c->j; 2609db02288aSLois Curfman McInnes i_new = c->i; 26109566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 261102834360SBarry Smith for (i=0; i<nrows; i++) { 2612a2744918SBarry Smith ii = starts[i]; 2613a2744918SBarry Smith lensi = lens[i]; 2614a2744918SBarry Smith for (k=0; k<lensi; k++) { 2615a2744918SBarry Smith *j_new++ = aj[ii+k] - first; 261602834360SBarry Smith } 26179566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a_new,aa + starts[i],lensi)); 2618a2744918SBarry Smith a_new += lensi; 2619a2744918SBarry Smith i_new[i+1] = i_new[i] + lensi; 2620a2744918SBarry Smith c->ilen[i] = lensi; 262102834360SBarry Smith } 26229566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 26239566063dSJacob Faibussowitsch PetscCall(PetscFree2(lens,starts)); 26243a40ed3dSBarry Smith } else { 26259566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol,&icol)); 26269566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(oldcols,&smap)); 26279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1+nrows,&lens)); 26284dcab191SBarry Smith for (i=0; i<ncols; i++) { 26296bdcaf15SBarry Smith PetscCheck(icol[i] < oldcols,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Requesting column beyond largest column icol[%" PetscInt_FMT "] %" PetscInt_FMT " >= A->cmap->n %" PetscInt_FMT,i,icol[i],oldcols); 26304dcab191SBarry Smith smap[icol[i]] = i+1; 26314dcab191SBarry Smith } 26324dcab191SBarry Smith 263302834360SBarry Smith /* determine lens of each row */ 263402834360SBarry Smith for (i=0; i<nrows; i++) { 2635bfeeae90SHong Zhang kstart = ai[irow[i]]; 263602834360SBarry Smith kend = kstart + a->ilen[irow[i]]; 263702834360SBarry Smith lens[i] = 0; 263802834360SBarry Smith for (k=kstart; k<kend; k++) { 2639bfeeae90SHong Zhang if (smap[aj[k]]) { 264002834360SBarry Smith lens[i]++; 264102834360SBarry Smith } 264202834360SBarry Smith } 264302834360SBarry Smith } 264417ab2063SBarry Smith /* Create and fill new matrix */ 2645a2744918SBarry Smith if (scall == MAT_REUSE_MATRIX) { 2646ace3abfcSBarry Smith PetscBool equal; 26470f5bd95cSBarry Smith 264899141d43SSatish Balay c = (Mat_SeqAIJ*)((*B)->data); 2649aed4548fSBarry Smith PetscCheck((*B)->rmap->n == nrows && (*B)->cmap->n == ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size"); 26509566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal)); 265128b400f6SJacob Faibussowitsch PetscCheck(equal,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros"); 26529566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->ilen,(*B)->rmap->n)); 265308480c60SBarry Smith C = *B; 26543a40ed3dSBarry Smith } else { 26553bef6203SJed Brown PetscInt rbs,cbs; 26569566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),&C)); 26579566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE)); 26589566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(isrow,&rbs)); 26599566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(iscol,&cbs)); 26609566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(C,rbs,cbs)); 26619566063dSJacob Faibussowitsch PetscCall(MatSetType(C,((PetscObject)A)->type_name)); 26629566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens)); 266308480c60SBarry Smith } 26649566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 266599141d43SSatish Balay c = (Mat_SeqAIJ*)(C->data); 266617ab2063SBarry Smith for (i=0; i<nrows; i++) { 266799141d43SSatish Balay row = irow[i]; 2668bfeeae90SHong Zhang kstart = ai[row]; 266999141d43SSatish Balay kend = kstart + a->ilen[row]; 2670bfeeae90SHong Zhang mat_i = c->i[i]; 267199141d43SSatish Balay mat_j = c->j + mat_i; 267299141d43SSatish Balay mat_a = c->a + mat_i; 267399141d43SSatish Balay mat_ilen = c->ilen + i; 267417ab2063SBarry Smith for (k=kstart; k<kend; k++) { 2675bfeeae90SHong Zhang if ((tcol=smap[a->j[k]])) { 2676ed480e8bSBarry Smith *mat_j++ = tcol - 1; 26772e5835c6SStefano Zampini *mat_a++ = aa[k]; 267899141d43SSatish Balay (*mat_ilen)++; 267999141d43SSatish Balay 268017ab2063SBarry Smith } 268117ab2063SBarry Smith } 268217ab2063SBarry Smith } 26839566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 268402834360SBarry Smith /* Free work space */ 26859566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol,&icol)); 26869566063dSJacob Faibussowitsch PetscCall(PetscFree(smap)); 26879566063dSJacob Faibussowitsch PetscCall(PetscFree(lens)); 2688cdc6f3adSToby Isaac /* sort */ 2689cdc6f3adSToby Isaac for (i = 0; i < nrows; i++) { 2690cdc6f3adSToby Isaac PetscInt ilen; 2691cdc6f3adSToby Isaac 2692cdc6f3adSToby Isaac mat_i = c->i[i]; 2693cdc6f3adSToby Isaac mat_j = c->j + mat_i; 2694cdc6f3adSToby Isaac mat_a = c->a + mat_i; 2695cdc6f3adSToby Isaac ilen = c->ilen[i]; 26969566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(ilen,mat_j,mat_a)); 2697cdc6f3adSToby Isaac } 269802834360SBarry Smith } 26998c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE) 27009566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(C,A->boundtocpu)); 2701305c6ccfSStefano Zampini #endif 27029566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY)); 27039566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY)); 270417ab2063SBarry Smith 27059566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow,&irow)); 2706416022c9SBarry Smith *B = C; 27073a40ed3dSBarry Smith PetscFunctionReturn(0); 270817ab2063SBarry Smith } 270917ab2063SBarry Smith 2710fc08c53fSHong Zhang PetscErrorCode MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat) 271182d44351SHong Zhang { 271282d44351SHong Zhang Mat B; 271382d44351SHong Zhang 271482d44351SHong Zhang PetscFunctionBegin; 2715c2d650bdSHong Zhang if (scall == MAT_INITIAL_MATRIX) { 27169566063dSJacob Faibussowitsch PetscCall(MatCreate(subComm,&B)); 27179566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n)); 27189566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B,mat,mat)); 27199566063dSJacob Faibussowitsch PetscCall(MatSetType(B,MATSEQAIJ)); 27209566063dSJacob Faibussowitsch PetscCall(MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE)); 272182d44351SHong Zhang *subMat = B; 2722c2d650bdSHong Zhang } else { 27239566063dSJacob Faibussowitsch PetscCall(MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN)); 2724c2d650bdSHong Zhang } 272582d44351SHong Zhang PetscFunctionReturn(0); 272682d44351SHong Zhang } 272782d44351SHong Zhang 27289a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info) 2729a871dcd8SBarry Smith { 273063b91edcSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data; 273163b91edcSBarry Smith Mat outA; 2732ace3abfcSBarry Smith PetscBool row_identity,col_identity; 273363b91edcSBarry Smith 27343a40ed3dSBarry Smith PetscFunctionBegin; 273508401ef6SPierre Jolivet PetscCheck(info->levels == 0,PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu"); 27361df811f5SHong Zhang 27379566063dSJacob Faibussowitsch PetscCall(ISIdentity(row,&row_identity)); 27389566063dSJacob Faibussowitsch PetscCall(ISIdentity(col,&col_identity)); 2739a871dcd8SBarry Smith 274063b91edcSBarry Smith outA = inA; 2741d5f3da31SBarry Smith outA->factortype = MAT_FACTOR_LU; 27429566063dSJacob Faibussowitsch PetscCall(PetscFree(inA->solvertype)); 27439566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype)); 27442205254eSKarl Rupp 27459566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)row)); 27469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 27472205254eSKarl Rupp 2748c3122656SLisandro Dalcin a->row = row; 27492205254eSKarl Rupp 27509566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)col)); 27519566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 27522205254eSKarl Rupp 2753c3122656SLisandro Dalcin a->col = col; 275463b91edcSBarry Smith 275536db0b34SBarry Smith /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */ 27569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->icol)); 27579566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(col,PETSC_DECIDE,&a->icol)); 27589566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol)); 2759f0ec6fceSSatish Balay 276094a9d846SBarry Smith if (!a->solve_work) { /* this matrix may have been factored before */ 27619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(inA->rmap->n+1,&a->solve_work)); 27629566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar))); 276394a9d846SBarry Smith } 276463b91edcSBarry Smith 27659566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(inA)); 2766137fb511SHong Zhang if (row_identity && col_identity) { 27679566063dSJacob Faibussowitsch PetscCall(MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info)); 2768137fb511SHong Zhang } else { 27699566063dSJacob Faibussowitsch PetscCall(MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info)); 2770137fb511SHong Zhang } 27713a40ed3dSBarry Smith PetscFunctionReturn(0); 2772a871dcd8SBarry Smith } 2773a871dcd8SBarry Smith 2774f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha) 2775f0b747eeSBarry Smith { 2776f0b747eeSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data; 2777dfa0f9e5SStefano Zampini PetscScalar *v; 2778c5df96a5SBarry Smith PetscBLASInt one = 1,bnz; 27793a40ed3dSBarry Smith 27803a40ed3dSBarry Smith PetscFunctionBegin; 27819566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(inA,&v)); 27829566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(a->nz,&bnz)); 2783dfa0f9e5SStefano Zampini PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&alpha,v,&one)); 27849566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 27859566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(inA,&v)); 27869566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(inA)); 27873a40ed3dSBarry Smith PetscFunctionReturn(0); 2788f0b747eeSBarry Smith } 2789f0b747eeSBarry Smith 2790f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj) 279116b64355SHong Zhang { 279216b64355SHong Zhang PetscInt i; 279316b64355SHong Zhang 279416b64355SHong Zhang PetscFunctionBegin; 279516b64355SHong Zhang if (!submatj->id) { /* delete data that are linked only to submats[id=0] */ 27969566063dSJacob Faibussowitsch PetscCall(PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr)); 279716b64355SHong Zhang 279816b64355SHong Zhang for (i=0; i<submatj->nrqr; ++i) { 27999566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->sbuf2[i])); 280016b64355SHong Zhang } 28019566063dSJacob Faibussowitsch PetscCall(PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1)); 280216b64355SHong Zhang 280316b64355SHong Zhang if (submatj->rbuf1) { 28049566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rbuf1[0])); 28059566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rbuf1)); 280616b64355SHong Zhang } 280716b64355SHong Zhang 280816b64355SHong Zhang for (i=0; i<submatj->nrqs; ++i) { 28099566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rbuf3[i])); 281016b64355SHong Zhang } 28119566063dSJacob Faibussowitsch PetscCall(PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3)); 28129566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->pa)); 281316b64355SHong Zhang } 281416b64355SHong Zhang 281516b64355SHong Zhang #if defined(PETSC_USE_CTABLE) 28169566063dSJacob Faibussowitsch PetscCall(PetscTableDestroy((PetscTable*)&submatj->rmap)); 28179566063dSJacob Faibussowitsch if (submatj->cmap_loc) PetscCall(PetscFree(submatj->cmap_loc)); 28189566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rmap_loc)); 281916b64355SHong Zhang #else 28209566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rmap)); 282116b64355SHong Zhang #endif 282216b64355SHong Zhang 282316b64355SHong Zhang if (!submatj->allcolumns) { 282416b64355SHong Zhang #if defined(PETSC_USE_CTABLE) 28259566063dSJacob Faibussowitsch PetscCall(PetscTableDestroy((PetscTable*)&submatj->cmap)); 282616b64355SHong Zhang #else 28279566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->cmap)); 282816b64355SHong Zhang #endif 282916b64355SHong Zhang } 28309566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->row2proc)); 283116b64355SHong Zhang 28329566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj)); 283316b64355SHong Zhang PetscFunctionReturn(0); 283416b64355SHong Zhang } 283516b64355SHong Zhang 28360fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C) 283716b64355SHong Zhang { 283816b64355SHong Zhang Mat_SeqAIJ *c = (Mat_SeqAIJ*)C->data; 28395c39f6d9SHong Zhang Mat_SubSppt *submatj = c->submatis1; 284016b64355SHong Zhang 284116b64355SHong Zhang PetscFunctionBegin; 28429566063dSJacob Faibussowitsch PetscCall((*submatj->destroy)(C)); 28439566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrix_Private(submatj)); 284416b64355SHong Zhang PetscFunctionReturn(0); 284516b64355SHong Zhang } 284616b64355SHong Zhang 284789a1a59bSHong Zhang /* Note this has code duplication with MatDestroySubMatrices_SeqBAIJ() */ 28482d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[]) 28492d033e1fSHong Zhang { 28502d033e1fSHong Zhang PetscInt i; 28510fb991dcSHong Zhang Mat C; 28520fb991dcSHong Zhang Mat_SeqAIJ *c; 28530fb991dcSHong Zhang Mat_SubSppt *submatj; 28542d033e1fSHong Zhang 28552d033e1fSHong Zhang PetscFunctionBegin; 28562d033e1fSHong Zhang for (i=0; i<n; i++) { 28570fb991dcSHong Zhang C = (*mat)[i]; 28580fb991dcSHong Zhang c = (Mat_SeqAIJ*)C->data; 28590fb991dcSHong Zhang submatj = c->submatis1; 28602d033e1fSHong Zhang if (submatj) { 2861682e4c99SStefano Zampini if (--((PetscObject)C)->refct <= 0) { 286226cc229bSBarry Smith PetscCall(PetscFree(C->factorprefix)); 28639566063dSJacob Faibussowitsch PetscCall((*submatj->destroy)(C)); 28649566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrix_Private(submatj)); 28659566063dSJacob Faibussowitsch PetscCall(PetscFree(C->defaultvectype)); 28669566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&C->rmap)); 28679566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&C->cmap)); 28689566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(&C)); 2869682e4c99SStefano Zampini } 28702d033e1fSHong Zhang } else { 28719566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 28722d033e1fSHong Zhang } 28732d033e1fSHong Zhang } 287486e85357SHong Zhang 287563a75b2aSHong Zhang /* Destroy Dummy submatrices created for reuse */ 28769566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices_Dummy(n,mat)); 287763a75b2aSHong Zhang 28789566063dSJacob Faibussowitsch PetscCall(PetscFree(*mat)); 28792d033e1fSHong Zhang PetscFunctionReturn(0); 28802d033e1fSHong Zhang } 28812d033e1fSHong Zhang 28827dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[]) 2883cddf8d76SBarry Smith { 288497f1f81fSBarry Smith PetscInt i; 2885cddf8d76SBarry Smith 28863a40ed3dSBarry Smith PetscFunctionBegin; 2887cddf8d76SBarry Smith if (scall == MAT_INITIAL_MATRIX) { 28889566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n+1,B)); 2889cddf8d76SBarry Smith } 2890cddf8d76SBarry Smith 2891cddf8d76SBarry Smith for (i=0; i<n; i++) { 28929566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i])); 2893cddf8d76SBarry Smith } 28943a40ed3dSBarry Smith PetscFunctionReturn(0); 2895cddf8d76SBarry Smith } 2896cddf8d76SBarry Smith 289797f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov) 28984dcbc457SBarry Smith { 2899e4d965acSSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 29005d0c19d7SBarry Smith PetscInt row,i,j,k,l,m,n,*nidx,isz,val; 29015d0c19d7SBarry Smith const PetscInt *idx; 290297f1f81fSBarry Smith PetscInt start,end,*ai,*aj; 2903f1af5d2fSBarry Smith PetscBT table; 2904bbd702dbSSatish Balay 29053a40ed3dSBarry Smith PetscFunctionBegin; 2906d0f46423SBarry Smith m = A->rmap->n; 2907e4d965acSSatish Balay ai = a->i; 2908bfeeae90SHong Zhang aj = a->j; 29098a047759SSatish Balay 291008401ef6SPierre Jolivet PetscCheck(ov >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used"); 291106763907SSatish Balay 29129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m+1,&nidx)); 29139566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(m,&table)); 291406763907SSatish Balay 2915e4d965acSSatish Balay for (i=0; i<is_max; i++) { 2916b97fc60eSLois Curfman McInnes /* Initialize the two local arrays */ 2917e4d965acSSatish Balay isz = 0; 29189566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(m,table)); 2919e4d965acSSatish Balay 2920e4d965acSSatish Balay /* Extract the indices, assume there can be duplicate entries */ 29219566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is[i],&idx)); 29229566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is[i],&n)); 2923e4d965acSSatish Balay 2924dd097bc3SLois Curfman McInnes /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 2925e4d965acSSatish Balay for (j=0; j<n; ++j) { 29262205254eSKarl Rupp if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j]; 29274dcbc457SBarry Smith } 29289566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is[i],&idx)); 29299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is[i])); 2930e4d965acSSatish Balay 293104a348a9SBarry Smith k = 0; 293204a348a9SBarry Smith for (j=0; j<ov; j++) { /* for each overlap */ 293304a348a9SBarry Smith n = isz; 293406763907SSatish Balay for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */ 2935e4d965acSSatish Balay row = nidx[k]; 2936e4d965acSSatish Balay start = ai[row]; 2937e4d965acSSatish Balay end = ai[row+1]; 293804a348a9SBarry Smith for (l = start; l<end; l++) { 2939efb16452SHong Zhang val = aj[l]; 29402205254eSKarl Rupp if (!PetscBTLookupSet(table,val)) nidx[isz++] = val; 2941e4d965acSSatish Balay } 2942e4d965acSSatish Balay } 2943e4d965acSSatish Balay } 29449566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i))); 2945e4d965acSSatish Balay } 29469566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&table)); 29479566063dSJacob Faibussowitsch PetscCall(PetscFree(nidx)); 29483a40ed3dSBarry Smith PetscFunctionReturn(0); 29494dcbc457SBarry Smith } 295017ab2063SBarry Smith 29510513a670SBarry Smith /* -------------------------------------------------------------- */ 2952dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B) 29530513a670SBarry Smith { 29540513a670SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 29553b98c0a2SBarry Smith PetscInt i,nz = 0,m = A->rmap->n,n = A->cmap->n; 29565d0c19d7SBarry Smith const PetscInt *row,*col; 29575d0c19d7SBarry Smith PetscInt *cnew,j,*lens; 295856cd22aeSBarry Smith IS icolp,irowp; 29590298fd71SBarry Smith PetscInt *cwork = NULL; 29600298fd71SBarry Smith PetscScalar *vwork = NULL; 29610513a670SBarry Smith 29623a40ed3dSBarry Smith PetscFunctionBegin; 29639566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(rowp,PETSC_DECIDE,&irowp)); 29649566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irowp,&row)); 29659566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(colp,PETSC_DECIDE,&icolp)); 29669566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icolp,&col)); 29670513a670SBarry Smith 29680513a670SBarry Smith /* determine lengths of permuted rows */ 29699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m+1,&lens)); 29702205254eSKarl Rupp for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i]; 29719566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),B)); 29729566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B,m,n,m,n)); 29739566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(*B,A,A)); 29749566063dSJacob Faibussowitsch PetscCall(MatSetType(*B,((PetscObject)A)->type_name)); 29759566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens)); 29769566063dSJacob Faibussowitsch PetscCall(PetscFree(lens)); 29770513a670SBarry Smith 29789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n,&cnew)); 29790513a670SBarry Smith for (i=0; i<m; i++) { 29809566063dSJacob Faibussowitsch PetscCall(MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork)); 29812205254eSKarl Rupp for (j=0; j<nz; j++) cnew[j] = col[cwork[j]]; 29829566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES)); 29839566063dSJacob Faibussowitsch PetscCall(MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork)); 29840513a670SBarry Smith } 29859566063dSJacob Faibussowitsch PetscCall(PetscFree(cnew)); 29862205254eSKarl Rupp 29873c7d62e4SBarry Smith (*B)->assembled = PETSC_FALSE; 29882205254eSKarl Rupp 29898c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE) 29909566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(*B,A->boundtocpu)); 29919fe5e383SStefano Zampini #endif 29929566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY)); 29939566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY)); 29949566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irowp,&row)); 29959566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icolp,&col)); 29969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irowp)); 29979566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icolp)); 29986768869dSprj- if (rowp == colp) { 29999566063dSJacob Faibussowitsch PetscCall(MatPropagateSymmetryOptions(A,*B)); 30006768869dSprj- } 30013a40ed3dSBarry Smith PetscFunctionReturn(0); 30020513a670SBarry Smith } 30030513a670SBarry Smith 3004dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str) 3005cb5b572fSBarry Smith { 3006cb5b572fSBarry Smith PetscFunctionBegin; 300733f4a19fSKris Buschelman /* If the two matrices have the same copy implementation, use fast copy. */ 300833f4a19fSKris Buschelman if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) { 3009be6bf707SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3010be6bf707SBarry Smith Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 30112e5835c6SStefano Zampini const PetscScalar *aa; 3012be6bf707SBarry Smith 30139566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 301408401ef6SPierre Jolivet PetscCheck(a->i[A->rmap->n] == b->i[B->rmap->n],PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different %" PetscInt_FMT " != %" PetscInt_FMT,a->i[A->rmap->n],b->i[B->rmap->n]); 30159566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->a,aa,a->i[A->rmap->n])); 30169566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 30179566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 3018cb5b572fSBarry Smith } else { 30199566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A,B,str)); 3020cb5b572fSBarry Smith } 3021cb5b572fSBarry Smith PetscFunctionReturn(0); 3022cb5b572fSBarry Smith } 3023cb5b572fSBarry Smith 30244994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A) 3025273d9f13SBarry Smith { 3026273d9f13SBarry Smith PetscFunctionBegin; 30279566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,NULL)); 3028273d9f13SBarry Smith PetscFunctionReturn(0); 3029273d9f13SBarry Smith } 3030273d9f13SBarry Smith 3031f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[]) 30326c0721eeSBarry Smith { 30336c0721eeSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 30346e111a19SKarl Rupp 30356c0721eeSBarry Smith PetscFunctionBegin; 30366c0721eeSBarry Smith *array = a->a; 30376c0721eeSBarry Smith PetscFunctionReturn(0); 30386c0721eeSBarry Smith } 30396c0721eeSBarry Smith 3040f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[]) 30416c0721eeSBarry Smith { 30426c0721eeSBarry Smith PetscFunctionBegin; 3043f38c1e66SStefano Zampini *array = NULL; 30446c0721eeSBarry Smith PetscFunctionReturn(0); 30456c0721eeSBarry Smith } 3046273d9f13SBarry Smith 30478229c054SShri Abhyankar /* 30488229c054SShri Abhyankar Computes the number of nonzeros per row needed for preallocation when X and Y 30498229c054SShri Abhyankar have different nonzero structure. 30508229c054SShri Abhyankar */ 3051b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz) 3052ec7775f6SShri Abhyankar { 3053b264fe52SHong Zhang PetscInt i,j,k,nzx,nzy; 3054ec7775f6SShri Abhyankar 3055ec7775f6SShri Abhyankar PetscFunctionBegin; 3056ec7775f6SShri Abhyankar /* Set the number of nonzeros in the new matrix */ 3057ec7775f6SShri Abhyankar for (i=0; i<m; i++) { 3058b264fe52SHong Zhang const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i]; 3059b264fe52SHong Zhang nzx = xi[i+1] - xi[i]; 3060b264fe52SHong Zhang nzy = yi[i+1] - yi[i]; 30618af7cee1SJed Brown nnz[i] = 0; 30628af7cee1SJed Brown for (j=0,k=0; j<nzx; j++) { /* Point in X */ 3063b264fe52SHong Zhang for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */ 3064b264fe52SHong Zhang if (k<nzy && yjj[k]==xjj[j]) k++; /* Skip duplicate */ 30658af7cee1SJed Brown nnz[i]++; 30668af7cee1SJed Brown } 30678af7cee1SJed Brown for (; k<nzy; k++) nnz[i]++; 3068ec7775f6SShri Abhyankar } 3069ec7775f6SShri Abhyankar PetscFunctionReturn(0); 3070ec7775f6SShri Abhyankar } 3071ec7775f6SShri Abhyankar 3072b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz) 3073b264fe52SHong Zhang { 3074b264fe52SHong Zhang PetscInt m = Y->rmap->N; 3075b264fe52SHong Zhang Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data; 3076b264fe52SHong Zhang Mat_SeqAIJ *y = (Mat_SeqAIJ*)Y->data; 3077b264fe52SHong Zhang 3078b264fe52SHong Zhang PetscFunctionBegin; 3079b264fe52SHong Zhang /* Set the number of nonzeros in the new matrix */ 30809566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz)); 3081b264fe52SHong Zhang PetscFunctionReturn(0); 3082b264fe52SHong Zhang } 3083b264fe52SHong Zhang 3084f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str) 3085ac90fabeSBarry Smith { 3086ac90fabeSBarry Smith Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data; 3087ac90fabeSBarry Smith 3088ac90fabeSBarry Smith PetscFunctionBegin; 3089134adf20SPierre Jolivet if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) { 3090134adf20SPierre Jolivet PetscBool e = x->nz == y->nz ? PETSC_TRUE : PETSC_FALSE; 3091134adf20SPierre Jolivet if (e) { 30929566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e)); 309381fa06acSBarry Smith if (e) { 30949566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->j,y->j,y->nz,&e)); 3095134adf20SPierre Jolivet if (e) str = SAME_NONZERO_PATTERN; 309681fa06acSBarry Smith } 309781fa06acSBarry Smith } 309854c59aa7SJacob Faibussowitsch if (!e) PetscCheck(str != SAME_NONZERO_PATTERN,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"MatStructure is not SAME_NONZERO_PATTERN"); 309981fa06acSBarry Smith } 3100ac90fabeSBarry Smith if (str == SAME_NONZERO_PATTERN) { 31012e5835c6SStefano Zampini const PetscScalar *xa; 31022e5835c6SStefano Zampini PetscScalar *ya,alpha = a; 310381fa06acSBarry Smith PetscBLASInt one = 1,bnz; 310481fa06acSBarry Smith 31059566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(x->nz,&bnz)); 31069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Y,&ya)); 31079566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(X,&xa)); 31082e5835c6SStefano Zampini PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,xa,&one,ya,&one)); 31099566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(X,&xa)); 31109566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Y,&ya)); 31119566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*bnz)); 31129566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(Y)); 31139566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)Y)); 3114ab784542SHong Zhang } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 31159566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y,a,X,str)); 3116ac90fabeSBarry Smith } else { 31178229c054SShri Abhyankar Mat B; 31188229c054SShri Abhyankar PetscInt *nnz; 31199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Y->rmap->N,&nnz)); 31209566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)Y),&B)); 31219566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name)); 31229566063dSJacob Faibussowitsch PetscCall(MatSetLayouts(B,Y->rmap,Y->cmap)); 31239566063dSJacob Faibussowitsch PetscCall(MatSetType(B,((PetscObject)Y)->type_name)); 31249566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz)); 31259566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B,0,nnz)); 31269566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B,Y,a,X,str)); 31279566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y,&B)); 31289566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 3129ac90fabeSBarry Smith } 3130ac90fabeSBarry Smith PetscFunctionReturn(0); 3131ac90fabeSBarry Smith } 3132ac90fabeSBarry Smith 31332726fb6dSPierre Jolivet PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat) 3134354c94deSBarry Smith { 3135354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX) 3136354c94deSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3137354c94deSBarry Smith PetscInt i,nz; 3138354c94deSBarry Smith PetscScalar *a; 3139354c94deSBarry Smith 3140354c94deSBarry Smith PetscFunctionBegin; 3141354c94deSBarry Smith nz = aij->nz; 31429566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(mat,&a)); 31432205254eSKarl Rupp for (i=0; i<nz; i++) a[i] = PetscConj(a[i]); 31449566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(mat,&a)); 3145354c94deSBarry Smith #else 3146354c94deSBarry Smith PetscFunctionBegin; 3147354c94deSBarry Smith #endif 3148354c94deSBarry Smith PetscFunctionReturn(0); 3149354c94deSBarry Smith } 3150354c94deSBarry Smith 3151985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 3152e34fafa9SBarry Smith { 3153e34fafa9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3154d0f46423SBarry Smith PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 3155e34fafa9SBarry Smith PetscReal atmp; 3156985db425SBarry Smith PetscScalar *x; 3157ce496241SStefano Zampini const MatScalar *aa,*av; 3158e34fafa9SBarry Smith 3159e34fafa9SBarry Smith PetscFunctionBegin; 316028b400f6SJacob Faibussowitsch PetscCheck(!A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 31619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&av)); 3162ce496241SStefano Zampini aa = av; 3163e34fafa9SBarry Smith ai = a->i; 3164e34fafa9SBarry Smith aj = a->j; 3165e34fafa9SBarry Smith 31669566063dSJacob Faibussowitsch PetscCall(VecSet(v,0.0)); 31679566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v,&x)); 31689566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v,&n)); 316908401ef6SPierre Jolivet PetscCheck(n == A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 3170e34fafa9SBarry Smith for (i=0; i<m; i++) { 3171e34fafa9SBarry Smith ncols = ai[1] - ai[0]; ai++; 3172e34fafa9SBarry Smith for (j=0; j<ncols; j++) { 3173985db425SBarry Smith atmp = PetscAbsScalar(*aa); 3174985db425SBarry Smith if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;} 3175985db425SBarry Smith aa++; aj++; 3176985db425SBarry Smith } 3177985db425SBarry Smith } 31789566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v,&x)); 31799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&av)); 3180985db425SBarry Smith PetscFunctionReturn(0); 3181985db425SBarry Smith } 3182985db425SBarry Smith 3183985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 3184985db425SBarry Smith { 3185985db425SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3186d0f46423SBarry Smith PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 3187985db425SBarry Smith PetscScalar *x; 3188ce496241SStefano Zampini const MatScalar *aa,*av; 3189985db425SBarry Smith 3190985db425SBarry Smith PetscFunctionBegin; 319128b400f6SJacob Faibussowitsch PetscCheck(!A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 31929566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&av)); 3193ce496241SStefano Zampini aa = av; 3194985db425SBarry Smith ai = a->i; 3195985db425SBarry Smith aj = a->j; 3196985db425SBarry Smith 31979566063dSJacob Faibussowitsch PetscCall(VecSet(v,0.0)); 31989566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v,&x)); 31999566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v,&n)); 320008401ef6SPierre Jolivet PetscCheck(n == A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 3201985db425SBarry Smith for (i=0; i<m; i++) { 3202985db425SBarry Smith ncols = ai[1] - ai[0]; ai++; 3203d0f46423SBarry Smith if (ncols == A->cmap->n) { /* row is dense */ 3204985db425SBarry Smith x[i] = *aa; if (idx) idx[i] = 0; 3205985db425SBarry Smith } else { /* row is sparse so already KNOW maximum is 0.0 or higher */ 3206985db425SBarry Smith x[i] = 0.0; 3207985db425SBarry Smith if (idx) { 3208985db425SBarry Smith for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */ 3209985db425SBarry Smith if (aj[j] > j) { 3210985db425SBarry Smith idx[i] = j; 3211985db425SBarry Smith break; 3212985db425SBarry Smith } 3213985db425SBarry Smith } 32141a254869SHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 32151a254869SHong Zhang if (j==ncols && j < A->cmap->n) idx[i] = j; 3216985db425SBarry Smith } 3217985db425SBarry Smith } 3218985db425SBarry Smith for (j=0; j<ncols; j++) { 3219985db425SBarry Smith if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 3220985db425SBarry Smith aa++; aj++; 3221985db425SBarry Smith } 3222985db425SBarry Smith } 32239566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v,&x)); 32249566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&av)); 3225985db425SBarry Smith PetscFunctionReturn(0); 3226985db425SBarry Smith } 3227985db425SBarry Smith 3228c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 3229c87e5d42SMatthew Knepley { 3230c87e5d42SMatthew Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3231c87e5d42SMatthew Knepley PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 3232ce496241SStefano Zampini PetscScalar *x; 3233ce496241SStefano Zampini const MatScalar *aa,*av; 3234c87e5d42SMatthew Knepley 3235c87e5d42SMatthew Knepley PetscFunctionBegin; 32369566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&av)); 3237ce496241SStefano Zampini aa = av; 3238c87e5d42SMatthew Knepley ai = a->i; 3239c87e5d42SMatthew Knepley aj = a->j; 3240c87e5d42SMatthew Knepley 32419566063dSJacob Faibussowitsch PetscCall(VecSet(v,0.0)); 32429566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v,&x)); 32439566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v,&n)); 324408401ef6SPierre Jolivet PetscCheck(n == m,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %" PetscInt_FMT " vs. %" PetscInt_FMT " rows", m, n); 3245c87e5d42SMatthew Knepley for (i=0; i<m; i++) { 3246c87e5d42SMatthew Knepley ncols = ai[1] - ai[0]; ai++; 3247f07e67edSHong Zhang if (ncols == A->cmap->n) { /* row is dense */ 3248f07e67edSHong Zhang x[i] = *aa; if (idx) idx[i] = 0; 3249f07e67edSHong Zhang } else { /* row is sparse so already KNOW minimum is 0.0 or higher */ 3250f07e67edSHong Zhang x[i] = 0.0; 3251f07e67edSHong Zhang if (idx) { /* find first implicit 0.0 in the row */ 3252289a08f5SMatthew Knepley for (j=0; j<ncols; j++) { 3253f07e67edSHong Zhang if (aj[j] > j) { 3254f07e67edSHong Zhang idx[i] = j; 32552205254eSKarl Rupp break; 32562205254eSKarl Rupp } 3257289a08f5SMatthew Knepley } 3258f07e67edSHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3259f07e67edSHong Zhang if (j==ncols && j < A->cmap->n) idx[i] = j; 3260f07e67edSHong Zhang } 3261289a08f5SMatthew Knepley } 3262c87e5d42SMatthew Knepley for (j=0; j<ncols; j++) { 3263f07e67edSHong Zhang if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 3264c87e5d42SMatthew Knepley aa++; aj++; 3265c87e5d42SMatthew Knepley } 3266c87e5d42SMatthew Knepley } 32679566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v,&x)); 32689566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&av)); 3269c87e5d42SMatthew Knepley PetscFunctionReturn(0); 3270c87e5d42SMatthew Knepley } 3271c87e5d42SMatthew Knepley 3272985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 3273985db425SBarry Smith { 3274985db425SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3275d9ca1df4SBarry Smith PetscInt i,j,m = A->rmap->n,ncols,n; 3276d9ca1df4SBarry Smith const PetscInt *ai,*aj; 3277985db425SBarry Smith PetscScalar *x; 3278ce496241SStefano Zampini const MatScalar *aa,*av; 3279985db425SBarry Smith 3280985db425SBarry Smith PetscFunctionBegin; 328128b400f6SJacob Faibussowitsch PetscCheck(!A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 32829566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&av)); 3283ce496241SStefano Zampini aa = av; 3284985db425SBarry Smith ai = a->i; 3285985db425SBarry Smith aj = a->j; 3286985db425SBarry Smith 32879566063dSJacob Faibussowitsch PetscCall(VecSet(v,0.0)); 32889566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v,&x)); 32899566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v,&n)); 329008401ef6SPierre Jolivet PetscCheck(n == m,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 3291985db425SBarry Smith for (i=0; i<m; i++) { 3292985db425SBarry Smith ncols = ai[1] - ai[0]; ai++; 3293d0f46423SBarry Smith if (ncols == A->cmap->n) { /* row is dense */ 3294985db425SBarry Smith x[i] = *aa; if (idx) idx[i] = 0; 3295985db425SBarry Smith } else { /* row is sparse so already KNOW minimum is 0.0 or lower */ 3296985db425SBarry Smith x[i] = 0.0; 3297985db425SBarry Smith if (idx) { /* find first implicit 0.0 in the row */ 3298985db425SBarry Smith for (j=0; j<ncols; j++) { 3299985db425SBarry Smith if (aj[j] > j) { 3300985db425SBarry Smith idx[i] = j; 3301985db425SBarry Smith break; 3302985db425SBarry Smith } 3303985db425SBarry Smith } 3304fa213d2fSHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3305fa213d2fSHong Zhang if (j==ncols && j < A->cmap->n) idx[i] = j; 3306985db425SBarry Smith } 3307985db425SBarry Smith } 3308985db425SBarry Smith for (j=0; j<ncols; j++) { 3309985db425SBarry Smith if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 3310985db425SBarry Smith aa++; aj++; 3311e34fafa9SBarry Smith } 3312e34fafa9SBarry Smith } 33139566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v,&x)); 33149566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&av)); 3315e34fafa9SBarry Smith PetscFunctionReturn(0); 3316e34fafa9SBarry Smith } 3317bbead8a2SBarry Smith 3318713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values) 3319bbead8a2SBarry Smith { 3320bbead8a2SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data; 332133d57670SJed Brown PetscInt i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j; 3322bbead8a2SBarry Smith MatScalar *diag,work[25],*v_work; 33230da83c2eSBarry Smith const PetscReal shift = 0.0; 33241a9391e3SHong Zhang PetscBool allowzeropivot,zeropivotdetected=PETSC_FALSE; 3325bbead8a2SBarry Smith 3326bbead8a2SBarry Smith PetscFunctionBegin; 3327a455e926SHong Zhang allowzeropivot = PetscNot(A->erroriffailure); 33284a0d0026SBarry Smith if (a->ibdiagvalid) { 33294a0d0026SBarry Smith if (values) *values = a->ibdiag; 33304a0d0026SBarry Smith PetscFunctionReturn(0); 33314a0d0026SBarry Smith } 33329566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 3333bbead8a2SBarry Smith if (!a->ibdiag) { 33349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bs2*mbs,&a->ibdiag)); 33359566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar))); 3336bbead8a2SBarry Smith } 3337bbead8a2SBarry Smith diag = a->ibdiag; 3338bbead8a2SBarry Smith if (values) *values = a->ibdiag; 3339bbead8a2SBarry Smith /* factor and invert each block */ 3340bbead8a2SBarry Smith switch (bs) { 3341bbead8a2SBarry Smith case 1: 3342bbead8a2SBarry Smith for (i=0; i<mbs; i++) { 33439566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,1,&i,1,&i,diag+i)); 3344ec1892c8SHong Zhang if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) { 3345ec1892c8SHong Zhang if (allowzeropivot) { 33467b6c816cSBarry Smith A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33477b6c816cSBarry Smith A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]); 33487b6c816cSBarry Smith A->factorerror_zeropivot_row = i; 33499566063dSJacob Faibussowitsch PetscCall(PetscInfo(A,"Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON)); 335098921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MAT_LU_ZRPVT,"Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON); 3351ec1892c8SHong Zhang } 3352bbead8a2SBarry Smith diag[i] = (PetscScalar)1.0 / (diag[i] + shift); 3353bbead8a2SBarry Smith } 3354bbead8a2SBarry Smith break; 3355bbead8a2SBarry Smith case 2: 3356bbead8a2SBarry Smith for (i=0; i<mbs; i++) { 3357bbead8a2SBarry Smith ij[0] = 2*i; ij[1] = 2*i + 1; 33589566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,2,ij,2,ij,diag)); 33599566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected)); 33607b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33619566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_2(diag)); 3362bbead8a2SBarry Smith diag += 4; 3363bbead8a2SBarry Smith } 3364bbead8a2SBarry Smith break; 3365bbead8a2SBarry Smith case 3: 3366bbead8a2SBarry Smith for (i=0; i<mbs; i++) { 3367bbead8a2SBarry Smith ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2; 33689566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,3,ij,3,ij,diag)); 33699566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected)); 33707b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33719566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_3(diag)); 3372bbead8a2SBarry Smith diag += 9; 3373bbead8a2SBarry Smith } 3374bbead8a2SBarry Smith break; 3375bbead8a2SBarry Smith case 4: 3376bbead8a2SBarry Smith for (i=0; i<mbs; i++) { 3377bbead8a2SBarry Smith ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3; 33789566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,4,ij,4,ij,diag)); 33799566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected)); 33807b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33819566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_4(diag)); 3382bbead8a2SBarry Smith diag += 16; 3383bbead8a2SBarry Smith } 3384bbead8a2SBarry Smith break; 3385bbead8a2SBarry Smith case 5: 3386bbead8a2SBarry Smith for (i=0; i<mbs; i++) { 3387bbead8a2SBarry Smith ij[0] = 5*i; ij[1] = 5*i + 1; ij[2] = 5*i + 2; ij[3] = 5*i + 3; ij[4] = 5*i + 4; 33889566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,5,ij,5,ij,diag)); 33899566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected)); 33907b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33919566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_5(diag)); 3392bbead8a2SBarry Smith diag += 25; 3393bbead8a2SBarry Smith } 3394bbead8a2SBarry Smith break; 3395bbead8a2SBarry Smith case 6: 3396bbead8a2SBarry Smith for (i=0; i<mbs; i++) { 3397bbead8a2SBarry Smith ij[0] = 6*i; ij[1] = 6*i + 1; ij[2] = 6*i + 2; ij[3] = 6*i + 3; ij[4] = 6*i + 4; ij[5] = 6*i + 5; 33989566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,6,ij,6,ij,diag)); 33999566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected)); 34007b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 34019566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_6(diag)); 3402bbead8a2SBarry Smith diag += 36; 3403bbead8a2SBarry Smith } 3404bbead8a2SBarry Smith break; 3405bbead8a2SBarry Smith case 7: 3406bbead8a2SBarry Smith for (i=0; i<mbs; i++) { 3407bbead8a2SBarry Smith ij[0] = 7*i; ij[1] = 7*i + 1; ij[2] = 7*i + 2; ij[3] = 7*i + 3; ij[4] = 7*i + 4; ij[5] = 7*i + 5; ij[5] = 7*i + 6; 34089566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,7,ij,7,ij,diag)); 34099566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected)); 34107b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 34119566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_7(diag)); 3412bbead8a2SBarry Smith diag += 49; 3413bbead8a2SBarry Smith } 3414bbead8a2SBarry Smith break; 3415bbead8a2SBarry Smith default: 34169566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ)); 3417bbead8a2SBarry Smith for (i=0; i<mbs; i++) { 3418bbead8a2SBarry Smith for (j=0; j<bs; j++) { 3419bbead8a2SBarry Smith IJ[j] = bs*i + j; 3420bbead8a2SBarry Smith } 34219566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,bs,IJ,bs,IJ,diag)); 34229566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected)); 34237b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 34249566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_N(diag,bs)); 3425bbead8a2SBarry Smith diag += bs2; 3426bbead8a2SBarry Smith } 34279566063dSJacob Faibussowitsch PetscCall(PetscFree3(v_work,v_pivots,IJ)); 3428bbead8a2SBarry Smith } 3429bbead8a2SBarry Smith a->ibdiagvalid = PETSC_TRUE; 3430bbead8a2SBarry Smith PetscFunctionReturn(0); 3431bbead8a2SBarry Smith } 3432bbead8a2SBarry Smith 343373a71a0fSBarry Smith static PetscErrorCode MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx) 343473a71a0fSBarry Smith { 343573a71a0fSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)x->data; 3436fff043a9SJunchao Zhang PetscScalar a,*aa; 343773a71a0fSBarry Smith PetscInt m,n,i,j,col; 343873a71a0fSBarry Smith 343973a71a0fSBarry Smith PetscFunctionBegin; 344073a71a0fSBarry Smith if (!x->assembled) { 34419566063dSJacob Faibussowitsch PetscCall(MatGetSize(x,&m,&n)); 344273a71a0fSBarry Smith for (i=0; i<m; i++) { 344373a71a0fSBarry Smith for (j=0; j<aij->imax[i]; j++) { 34449566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValue(rctx,&a)); 344573a71a0fSBarry Smith col = (PetscInt)(n*PetscRealPart(a)); 34469566063dSJacob Faibussowitsch PetscCall(MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES)); 344773a71a0fSBarry Smith } 344873a71a0fSBarry Smith } 3449e2ce353bSJunchao Zhang } else { 34509566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayWrite(x,&aa)); 34519566063dSJacob Faibussowitsch for (i=0; i<aij->nz; i++) PetscCall(PetscRandomGetValue(rctx,aa+i)); 34529566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayWrite(x,&aa)); 3453e2ce353bSJunchao Zhang } 34549566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY)); 34559566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY)); 345673a71a0fSBarry Smith PetscFunctionReturn(0); 345773a71a0fSBarry Smith } 345873a71a0fSBarry Smith 3459679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */ 3460679944adSJunchao Zhang PetscErrorCode MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx) 3461679944adSJunchao Zhang { 3462679944adSJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ*)x->data; 3463679944adSJunchao Zhang PetscScalar a; 3464679944adSJunchao Zhang PetscInt m,n,i,j,col,nskip; 3465679944adSJunchao Zhang 3466679944adSJunchao Zhang PetscFunctionBegin; 3467679944adSJunchao Zhang nskip = high - low; 34689566063dSJacob Faibussowitsch PetscCall(MatGetSize(x,&m,&n)); 3469679944adSJunchao Zhang n -= nskip; /* shrink number of columns where nonzeros can be set */ 3470679944adSJunchao Zhang for (i=0; i<m; i++) { 3471679944adSJunchao Zhang for (j=0; j<aij->imax[i]; j++) { 34729566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValue(rctx,&a)); 3473679944adSJunchao Zhang col = (PetscInt)(n*PetscRealPart(a)); 3474679944adSJunchao Zhang if (col >= low) col += nskip; /* shift col rightward to skip the hole */ 34759566063dSJacob Faibussowitsch PetscCall(MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES)); 3476679944adSJunchao Zhang } 3477e2ce353bSJunchao Zhang } 34789566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY)); 34799566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY)); 3480679944adSJunchao Zhang PetscFunctionReturn(0); 3481679944adSJunchao Zhang } 3482679944adSJunchao Zhang 3483682d7d0cSBarry Smith /* -------------------------------------------------------------------*/ 34840a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ, 3485cb5b572fSBarry Smith MatGetRow_SeqAIJ, 3486cb5b572fSBarry Smith MatRestoreRow_SeqAIJ, 3487cb5b572fSBarry Smith MatMult_SeqAIJ, 348897304618SKris Buschelman /* 4*/ MatMultAdd_SeqAIJ, 34897c922b88SBarry Smith MatMultTranspose_SeqAIJ, 34907c922b88SBarry Smith MatMultTransposeAdd_SeqAIJ, 3491f4259b30SLisandro Dalcin NULL, 3492f4259b30SLisandro Dalcin NULL, 3493f4259b30SLisandro Dalcin NULL, 3494f4259b30SLisandro Dalcin /* 10*/ NULL, 3495cb5b572fSBarry Smith MatLUFactor_SeqAIJ, 3496f4259b30SLisandro Dalcin NULL, 349741f059aeSBarry Smith MatSOR_SeqAIJ, 349891e9d3e2SHong Zhang MatTranspose_SeqAIJ, 349997304618SKris Buschelman /*1 5*/ MatGetInfo_SeqAIJ, 3500cb5b572fSBarry Smith MatEqual_SeqAIJ, 3501cb5b572fSBarry Smith MatGetDiagonal_SeqAIJ, 3502cb5b572fSBarry Smith MatDiagonalScale_SeqAIJ, 3503cb5b572fSBarry Smith MatNorm_SeqAIJ, 3504f4259b30SLisandro Dalcin /* 20*/ NULL, 3505cb5b572fSBarry Smith MatAssemblyEnd_SeqAIJ, 3506cb5b572fSBarry Smith MatSetOption_SeqAIJ, 3507cb5b572fSBarry Smith MatZeroEntries_SeqAIJ, 3508d519adbfSMatthew Knepley /* 24*/ MatZeroRows_SeqAIJ, 3509f4259b30SLisandro Dalcin NULL, 3510f4259b30SLisandro Dalcin NULL, 3511f4259b30SLisandro Dalcin NULL, 3512f4259b30SLisandro Dalcin NULL, 35134994cf47SJed Brown /* 29*/ MatSetUp_SeqAIJ, 3514f4259b30SLisandro Dalcin NULL, 3515f4259b30SLisandro Dalcin NULL, 3516f4259b30SLisandro Dalcin NULL, 3517f4259b30SLisandro Dalcin NULL, 3518d519adbfSMatthew Knepley /* 34*/ MatDuplicate_SeqAIJ, 3519f4259b30SLisandro Dalcin NULL, 3520f4259b30SLisandro Dalcin NULL, 3521cb5b572fSBarry Smith MatILUFactor_SeqAIJ, 3522f4259b30SLisandro Dalcin NULL, 3523d519adbfSMatthew Knepley /* 39*/ MatAXPY_SeqAIJ, 35247dae84e0SHong Zhang MatCreateSubMatrices_SeqAIJ, 3525cb5b572fSBarry Smith MatIncreaseOverlap_SeqAIJ, 3526cb5b572fSBarry Smith MatGetValues_SeqAIJ, 3527cb5b572fSBarry Smith MatCopy_SeqAIJ, 3528d519adbfSMatthew Knepley /* 44*/ MatGetRowMax_SeqAIJ, 3529cb5b572fSBarry Smith MatScale_SeqAIJ, 35307d68702bSBarry Smith MatShift_SeqAIJ, 353179299369SBarry Smith MatDiagonalSet_SeqAIJ, 35326e169961SBarry Smith MatZeroRowsColumns_SeqAIJ, 353373a71a0fSBarry Smith /* 49*/ MatSetRandom_SeqAIJ, 35343b2fbd54SBarry Smith MatGetRowIJ_SeqAIJ, 35353b2fbd54SBarry Smith MatRestoreRowIJ_SeqAIJ, 35363b2fbd54SBarry Smith MatGetColumnIJ_SeqAIJ, 3537a93ec695SBarry Smith MatRestoreColumnIJ_SeqAIJ, 353893dfae19SHong Zhang /* 54*/ MatFDColoringCreate_SeqXAIJ, 3539f4259b30SLisandro Dalcin NULL, 3540f4259b30SLisandro Dalcin NULL, 3541cda55fadSBarry Smith MatPermute_SeqAIJ, 3542f4259b30SLisandro Dalcin NULL, 3543f4259b30SLisandro Dalcin /* 59*/ NULL, 3544b9b97703SBarry Smith MatDestroy_SeqAIJ, 3545b9b97703SBarry Smith MatView_SeqAIJ, 3546f4259b30SLisandro Dalcin NULL, 3547f4259b30SLisandro Dalcin NULL, 3548f4259b30SLisandro Dalcin /* 64*/ NULL, 3549321b30b9SSatish Balay MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ, 3550f4259b30SLisandro Dalcin NULL, 3551f4259b30SLisandro Dalcin NULL, 3552f4259b30SLisandro Dalcin NULL, 3553d519adbfSMatthew Knepley /* 69*/ MatGetRowMaxAbs_SeqAIJ, 3554c87e5d42SMatthew Knepley MatGetRowMinAbs_SeqAIJ, 3555f4259b30SLisandro Dalcin NULL, 3556f4259b30SLisandro Dalcin NULL, 3557f4259b30SLisandro Dalcin NULL, 3558f4259b30SLisandro Dalcin /* 74*/ NULL, 35593acb8795SBarry Smith MatFDColoringApply_AIJ, 3560f4259b30SLisandro Dalcin NULL, 3561f4259b30SLisandro Dalcin NULL, 3562f4259b30SLisandro Dalcin NULL, 35636ce1633cSBarry Smith /* 79*/ MatFindZeroDiagonals_SeqAIJ, 3564f4259b30SLisandro Dalcin NULL, 3565f4259b30SLisandro Dalcin NULL, 3566f4259b30SLisandro Dalcin NULL, 3567bc011b1eSHong Zhang MatLoad_SeqAIJ, 3568d519adbfSMatthew Knepley /* 84*/ MatIsSymmetric_SeqAIJ, 35691cbb95d3SBarry Smith MatIsHermitian_SeqAIJ, 3570f4259b30SLisandro Dalcin NULL, 3571f4259b30SLisandro Dalcin NULL, 3572f4259b30SLisandro Dalcin NULL, 3573f4259b30SLisandro Dalcin /* 89*/ NULL, 3574f4259b30SLisandro Dalcin NULL, 357526be0446SHong Zhang MatMatMultNumeric_SeqAIJ_SeqAIJ, 3576f4259b30SLisandro Dalcin NULL, 3577f4259b30SLisandro Dalcin NULL, 35788fa4b5a6SHong Zhang /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy, 3579f4259b30SLisandro Dalcin NULL, 3580f4259b30SLisandro Dalcin NULL, 35816fc122caSHong Zhang MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ, 3582f4259b30SLisandro Dalcin NULL, 35834222ddf1SHong Zhang /* 99*/ MatProductSetFromOptions_SeqAIJ, 3584f4259b30SLisandro Dalcin NULL, 3585f4259b30SLisandro Dalcin NULL, 358687d4246cSBarry Smith MatConjugate_SeqAIJ, 3587f4259b30SLisandro Dalcin NULL, 3588d519adbfSMatthew Knepley /*104*/ MatSetValuesRow_SeqAIJ, 358999cafbc1SBarry Smith MatRealPart_SeqAIJ, 3590f5edf698SHong Zhang MatImaginaryPart_SeqAIJ, 3591f4259b30SLisandro Dalcin NULL, 3592f4259b30SLisandro Dalcin NULL, 3593cbd44569SHong Zhang /*109*/ MatMatSolve_SeqAIJ, 3594f4259b30SLisandro Dalcin NULL, 35952af78befSBarry Smith MatGetRowMin_SeqAIJ, 3596f4259b30SLisandro Dalcin NULL, 3597599ef60dSHong Zhang MatMissingDiagonal_SeqAIJ, 3598f4259b30SLisandro Dalcin /*114*/ NULL, 3599f4259b30SLisandro Dalcin NULL, 3600f4259b30SLisandro Dalcin NULL, 3601f4259b30SLisandro Dalcin NULL, 3602f4259b30SLisandro Dalcin NULL, 3603f4259b30SLisandro Dalcin /*119*/ NULL, 3604f4259b30SLisandro Dalcin NULL, 3605f4259b30SLisandro Dalcin NULL, 3606f4259b30SLisandro Dalcin NULL, 3607b3a44c85SBarry Smith MatGetMultiProcBlock_SeqAIJ, 36080716a85fSBarry Smith /*124*/ MatFindNonzeroRows_SeqAIJ, 3609a873a8cdSSam Reynolds MatGetColumnReductions_SeqAIJ, 361037868618SMatthew G Knepley MatInvertBlockDiagonal_SeqAIJ, 36110da83c2eSBarry Smith MatInvertVariableBlockDiagonal_SeqAIJ, 3612f4259b30SLisandro Dalcin NULL, 3613f4259b30SLisandro Dalcin /*129*/ NULL, 3614f4259b30SLisandro Dalcin NULL, 3615f4259b30SLisandro Dalcin NULL, 361675648e8dSHong Zhang MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ, 3617b9af6bddSHong Zhang MatTransposeColoringCreate_SeqAIJ, 3618b9af6bddSHong Zhang /*134*/ MatTransColoringApplySpToDen_SeqAIJ, 36192b8ad9a3SHong Zhang MatTransColoringApplyDenToSp_SeqAIJ, 3620f4259b30SLisandro Dalcin NULL, 3621f4259b30SLisandro Dalcin NULL, 36223964eb88SJed Brown MatRARtNumeric_SeqAIJ_SeqAIJ, 3623f4259b30SLisandro Dalcin /*139*/NULL, 3624f4259b30SLisandro Dalcin NULL, 3625f4259b30SLisandro Dalcin NULL, 36263a062f41SBarry Smith MatFDColoringSetUp_SeqXAIJ, 36279c8f2541SHong Zhang MatFindOffBlockDiagonalEntries_SeqAIJ, 36284222ddf1SHong Zhang MatCreateMPIMatConcatenateSeqMat_SeqAIJ, 36294222ddf1SHong Zhang /*145*/MatDestroySubMatrices_SeqAIJ, 3630f4259b30SLisandro Dalcin NULL, 363172833a62Smarkadams4 NULL, 363272833a62Smarkadams4 MatCreateGraph_Simple_AIJ, 363372833a62Smarkadams4 MatFilter_AIJ 36349e29f15eSvictorle }; 363517ab2063SBarry Smith 36367087cfbeSBarry Smith PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices) 3637bef8e0ddSBarry Smith { 3638bef8e0ddSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 363997f1f81fSBarry Smith PetscInt i,nz,n; 3640bef8e0ddSBarry Smith 3641bef8e0ddSBarry Smith PetscFunctionBegin; 3642bef8e0ddSBarry Smith nz = aij->maxnz; 3643d0f46423SBarry Smith n = mat->rmap->n; 3644bef8e0ddSBarry Smith for (i=0; i<nz; i++) { 3645bef8e0ddSBarry Smith aij->j[i] = indices[i]; 3646bef8e0ddSBarry Smith } 3647bef8e0ddSBarry Smith aij->nz = nz; 3648bef8e0ddSBarry Smith for (i=0; i<n; i++) { 3649bef8e0ddSBarry Smith aij->ilen[i] = aij->imax[i]; 3650bef8e0ddSBarry Smith } 3651bef8e0ddSBarry Smith PetscFunctionReturn(0); 3652bef8e0ddSBarry Smith } 3653bef8e0ddSBarry Smith 3654a3bb6f32SFande Kong /* 3655ddea5d60SJunchao Zhang * Given a sparse matrix with global column indices, compact it by using a local column space. 3656ddea5d60SJunchao Zhang * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable() 3657ddea5d60SJunchao Zhang */ 3658a3bb6f32SFande Kong PetscErrorCode MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping) 3659a3bb6f32SFande Kong { 3660a3bb6f32SFande Kong Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3661a3bb6f32SFande Kong PetscTable gid1_lid1; 3662a3bb6f32SFande Kong PetscTablePosition tpos; 366325b670f0SStefano Zampini PetscInt gid,lid,i,ec,nz = aij->nz; 366425b670f0SStefano Zampini PetscInt *garray,*jj = aij->j; 3665a3bb6f32SFande Kong 3666a3bb6f32SFande Kong PetscFunctionBegin; 3667a3bb6f32SFande Kong PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3668a3bb6f32SFande Kong PetscValidPointer(mapping,2); 3669a3bb6f32SFande Kong /* use a table */ 36709566063dSJacob Faibussowitsch PetscCall(PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1)); 3671a3bb6f32SFande Kong ec = 0; 367225b670f0SStefano Zampini for (i=0; i<nz; i++) { 367325b670f0SStefano Zampini PetscInt data,gid1 = jj[i] + 1; 36749566063dSJacob Faibussowitsch PetscCall(PetscTableFind(gid1_lid1,gid1,&data)); 3675a3bb6f32SFande Kong if (!data) { 3676a3bb6f32SFande Kong /* one based table */ 36779566063dSJacob Faibussowitsch PetscCall(PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES)); 3678a3bb6f32SFande Kong } 3679a3bb6f32SFande Kong } 3680a3bb6f32SFande Kong /* form array of columns we need */ 36819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ec,&garray)); 36829566063dSJacob Faibussowitsch PetscCall(PetscTableGetHeadPosition(gid1_lid1,&tpos)); 3683a3bb6f32SFande Kong while (tpos) { 36849566063dSJacob Faibussowitsch PetscCall(PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid)); 3685a3bb6f32SFande Kong gid--; 3686a3bb6f32SFande Kong lid--; 3687a3bb6f32SFande Kong garray[lid] = gid; 3688a3bb6f32SFande Kong } 36899566063dSJacob Faibussowitsch PetscCall(PetscSortInt(ec,garray)); /* sort, and rebuild */ 36909566063dSJacob Faibussowitsch PetscCall(PetscTableRemoveAll(gid1_lid1)); 3691a3bb6f32SFande Kong for (i=0; i<ec; i++) { 36929566063dSJacob Faibussowitsch PetscCall(PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES)); 3693a3bb6f32SFande Kong } 3694a3bb6f32SFande Kong /* compact out the extra columns in B */ 369525b670f0SStefano Zampini for (i=0; i<nz; i++) { 369625b670f0SStefano Zampini PetscInt gid1 = jj[i] + 1; 36979566063dSJacob Faibussowitsch PetscCall(PetscTableFind(gid1_lid1,gid1,&lid)); 3698a3bb6f32SFande Kong lid--; 369925b670f0SStefano Zampini jj[i] = lid; 3700a3bb6f32SFande Kong } 37019566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&mat->cmap)); 37029566063dSJacob Faibussowitsch PetscCall(PetscTableDestroy(&gid1_lid1)); 37039566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap)); 37049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping)); 37059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH)); 3706a3bb6f32SFande Kong PetscFunctionReturn(0); 3707a3bb6f32SFande Kong } 3708a3bb6f32SFande Kong 3709bef8e0ddSBarry Smith /*@ 3710bef8e0ddSBarry Smith MatSeqAIJSetColumnIndices - Set the column indices for all the rows 3711bef8e0ddSBarry Smith in the matrix. 3712bef8e0ddSBarry Smith 3713bef8e0ddSBarry Smith Input Parameters: 3714bef8e0ddSBarry Smith + mat - the SeqAIJ matrix 3715bef8e0ddSBarry Smith - indices - the column indices 3716bef8e0ddSBarry Smith 371715091d37SBarry Smith Level: advanced 371815091d37SBarry Smith 3719bef8e0ddSBarry Smith Notes: 3720bef8e0ddSBarry Smith This can be called if you have precomputed the nonzero structure of the 3721bef8e0ddSBarry Smith matrix and want to provide it to the matrix object to improve the performance 3722bef8e0ddSBarry Smith of the MatSetValues() operation. 3723bef8e0ddSBarry Smith 3724bef8e0ddSBarry Smith You MUST have set the correct numbers of nonzeros per row in the call to 3725d1be2dadSMatthew Knepley MatCreateSeqAIJ(), and the columns indices MUST be sorted. 3726bef8e0ddSBarry Smith 3727bef8e0ddSBarry Smith MUST be called before any calls to MatSetValues(); 3728bef8e0ddSBarry Smith 3729b9617806SBarry Smith The indices should start with zero, not one. 3730b9617806SBarry Smith 3731bef8e0ddSBarry Smith @*/ 37327087cfbeSBarry Smith PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices) 3733bef8e0ddSBarry Smith { 3734bef8e0ddSBarry Smith PetscFunctionBegin; 37350700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3736dadcf809SJacob Faibussowitsch PetscValidIntPointer(indices,2); 3737cac4c232SBarry Smith PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices)); 3738bef8e0ddSBarry Smith PetscFunctionReturn(0); 3739bef8e0ddSBarry Smith } 3740bef8e0ddSBarry Smith 3741be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/ 3742be6bf707SBarry Smith 37437087cfbeSBarry Smith PetscErrorCode MatStoreValues_SeqAIJ(Mat mat) 3744be6bf707SBarry Smith { 3745be6bf707SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3746d0f46423SBarry Smith size_t nz = aij->i[mat->rmap->n]; 3747be6bf707SBarry Smith 3748be6bf707SBarry Smith PetscFunctionBegin; 374928b400f6SJacob Faibussowitsch PetscCheck(aij->nonew,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3750be6bf707SBarry Smith 3751be6bf707SBarry Smith /* allocate space for values if not already there */ 3752be6bf707SBarry Smith if (!aij->saved_values) { 37539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz+1,&aij->saved_values)); 37549566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar))); 3755be6bf707SBarry Smith } 3756be6bf707SBarry Smith 3757be6bf707SBarry Smith /* copy values over */ 37589566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->saved_values,aij->a,nz)); 3759be6bf707SBarry Smith PetscFunctionReturn(0); 3760be6bf707SBarry Smith } 3761be6bf707SBarry Smith 3762be6bf707SBarry Smith /*@ 3763be6bf707SBarry Smith MatStoreValues - Stashes a copy of the matrix values; this allows, for 3764be6bf707SBarry Smith example, reuse of the linear part of a Jacobian, while recomputing the 3765be6bf707SBarry Smith nonlinear portion. 3766be6bf707SBarry Smith 3767be6bf707SBarry Smith Collect on Mat 3768be6bf707SBarry Smith 3769be6bf707SBarry Smith Input Parameters: 37700e609b76SBarry Smith . mat - the matrix (currently only AIJ matrices support this option) 3771be6bf707SBarry Smith 377215091d37SBarry Smith Level: advanced 377315091d37SBarry Smith 3774be6bf707SBarry Smith Common Usage, with SNESSolve(): 3775be6bf707SBarry Smith $ Create Jacobian matrix 3776be6bf707SBarry Smith $ Set linear terms into matrix 3777be6bf707SBarry Smith $ Apply boundary conditions to matrix, at this time matrix must have 3778be6bf707SBarry Smith $ final nonzero structure (i.e. setting the nonlinear terms and applying 3779be6bf707SBarry Smith $ boundary conditions again will not change the nonzero structure 3780512a5fc5SBarry Smith $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3781be6bf707SBarry Smith $ ierr = MatStoreValues(mat); 3782be6bf707SBarry Smith $ Call SNESSetJacobian() with matrix 3783be6bf707SBarry Smith $ In your Jacobian routine 3784be6bf707SBarry Smith $ ierr = MatRetrieveValues(mat); 3785be6bf707SBarry Smith $ Set nonlinear terms in matrix 3786be6bf707SBarry Smith 3787be6bf707SBarry Smith Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself: 3788be6bf707SBarry Smith $ // build linear portion of Jacobian 3789512a5fc5SBarry Smith $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3790be6bf707SBarry Smith $ ierr = MatStoreValues(mat); 3791be6bf707SBarry Smith $ loop over nonlinear iterations 3792be6bf707SBarry Smith $ ierr = MatRetrieveValues(mat); 3793be6bf707SBarry Smith $ // call MatSetValues(mat,...) to set nonliner portion of Jacobian 3794be6bf707SBarry Smith $ // call MatAssemblyBegin/End() on matrix 3795be6bf707SBarry Smith $ Solve linear system with Jacobian 3796be6bf707SBarry Smith $ endloop 3797be6bf707SBarry Smith 3798be6bf707SBarry Smith Notes: 3799be6bf707SBarry Smith Matrix must already be assemblied before calling this routine 3800512a5fc5SBarry Smith Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before 3801be6bf707SBarry Smith calling this routine. 3802be6bf707SBarry Smith 38030c468ba9SBarry Smith When this is called multiple times it overwrites the previous set of stored values 38040c468ba9SBarry Smith and does not allocated additional space. 38050c468ba9SBarry Smith 3806db781477SPatrick Sanan .seealso: `MatRetrieveValues()` 3807be6bf707SBarry Smith 3808be6bf707SBarry Smith @*/ 38097087cfbeSBarry Smith PetscErrorCode MatStoreValues(Mat mat) 3810be6bf707SBarry Smith { 3811be6bf707SBarry Smith PetscFunctionBegin; 38120700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 381328b400f6SJacob Faibussowitsch PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 381428b400f6SJacob Faibussowitsch PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3815cac4c232SBarry Smith PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat)); 3816be6bf707SBarry Smith PetscFunctionReturn(0); 3817be6bf707SBarry Smith } 3818be6bf707SBarry Smith 38197087cfbeSBarry Smith PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat) 3820be6bf707SBarry Smith { 3821be6bf707SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3822d0f46423SBarry Smith PetscInt nz = aij->i[mat->rmap->n]; 3823be6bf707SBarry Smith 3824be6bf707SBarry Smith PetscFunctionBegin; 382528b400f6SJacob Faibussowitsch PetscCheck(aij->nonew,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 382628b400f6SJacob Faibussowitsch PetscCheck(aij->saved_values,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first"); 3827be6bf707SBarry Smith /* copy values over */ 38289566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->a,aij->saved_values,nz)); 3829be6bf707SBarry Smith PetscFunctionReturn(0); 3830be6bf707SBarry Smith } 3831be6bf707SBarry Smith 3832be6bf707SBarry Smith /*@ 3833be6bf707SBarry Smith MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for 3834be6bf707SBarry Smith example, reuse of the linear part of a Jacobian, while recomputing the 3835be6bf707SBarry Smith nonlinear portion. 3836be6bf707SBarry Smith 3837be6bf707SBarry Smith Collect on Mat 3838be6bf707SBarry Smith 3839be6bf707SBarry Smith Input Parameters: 3840386f7cf9SBarry Smith . mat - the matrix (currently only AIJ matrices support this option) 3841be6bf707SBarry Smith 384215091d37SBarry Smith Level: advanced 384315091d37SBarry Smith 3844db781477SPatrick Sanan .seealso: `MatStoreValues()` 3845be6bf707SBarry Smith 3846be6bf707SBarry Smith @*/ 38477087cfbeSBarry Smith PetscErrorCode MatRetrieveValues(Mat mat) 3848be6bf707SBarry Smith { 3849be6bf707SBarry Smith PetscFunctionBegin; 38500700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 385128b400f6SJacob Faibussowitsch PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 385228b400f6SJacob Faibussowitsch PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3853cac4c232SBarry Smith PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat)); 3854be6bf707SBarry Smith PetscFunctionReturn(0); 3855be6bf707SBarry Smith } 3856be6bf707SBarry Smith 3857be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/ 385817ab2063SBarry Smith /*@C 3859682d7d0cSBarry Smith MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format 38600d15e28bSLois Curfman McInnes (the default parallel PETSc format). For good matrix assembly performance 38616e62573dSLois Curfman McInnes the user should preallocate the matrix storage by setting the parameter nz 386251c19458SBarry Smith (or the array nnz). By setting these parameters accurately, performance 38632bd5e0b2SLois Curfman McInnes during matrix assembly can be increased by more than a factor of 50. 386417ab2063SBarry Smith 3865d083f849SBarry Smith Collective 3866db81eaa0SLois Curfman McInnes 386717ab2063SBarry Smith Input Parameters: 3868db81eaa0SLois Curfman McInnes + comm - MPI communicator, set to PETSC_COMM_SELF 386917ab2063SBarry Smith . m - number of rows 387017ab2063SBarry Smith . n - number of columns 387117ab2063SBarry Smith . nz - number of nonzeros per row (same for all rows) 387251c19458SBarry Smith - nnz - array containing the number of nonzeros in the various rows 38730298fd71SBarry Smith (possibly different for each row) or NULL 387417ab2063SBarry Smith 387517ab2063SBarry Smith Output Parameter: 3876416022c9SBarry Smith . A - the matrix 387717ab2063SBarry Smith 3878175b88e8SBarry Smith It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(), 3879f6f02116SRichard Tran Mills MatXXXXSetPreallocation() paradigm instead of this routine directly. 3880175b88e8SBarry Smith [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation] 3881175b88e8SBarry Smith 3882b259b22eSLois Curfman McInnes Notes: 388349a6f317SBarry Smith If nnz is given then nz is ignored 388449a6f317SBarry Smith 388517ab2063SBarry Smith The AIJ format (also called the Yale sparse matrix format or 388617ab2063SBarry Smith compressed row storage), is fully compatible with standard Fortran 77 38870002213bSLois Curfman McInnes storage. That is, the stored row and column indices can begin at 388844cd7ae7SLois Curfman McInnes either one (as in Fortran) or zero. See the users' manual for details. 388917ab2063SBarry Smith 389017ab2063SBarry Smith Specify the preallocated storage with either nz or nnz (not both). 38910298fd71SBarry Smith Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 38923d323bbdSBarry Smith allocation. For large problems you MUST preallocate memory or you 38936da5968aSLois Curfman McInnes will get TERRIBLE performance, see the users' manual chapter on matrices. 389417ab2063SBarry Smith 3895682d7d0cSBarry Smith By default, this format uses inodes (identical nodes) when possible, to 38964fca80b9SLois Curfman McInnes improve numerical efficiency of matrix-vector products and solves. We 3897682d7d0cSBarry Smith search for consecutive rows with the same nonzero structure, thereby 38986c7ebb05SLois Curfman McInnes reusing matrix information to achieve increased efficiency. 38996c7ebb05SLois Curfman McInnes 39006c7ebb05SLois Curfman McInnes Options Database Keys: 3901698d4c6aSKris Buschelman + -mat_no_inode - Do not use inodes 39029db58ca8SBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 390317ab2063SBarry Smith 3904027ccd11SLois Curfman McInnes Level: intermediate 3905027ccd11SLois Curfman McInnes 3906db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()` 390736db0b34SBarry Smith 390817ab2063SBarry Smith @*/ 39097087cfbeSBarry Smith PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A) 391017ab2063SBarry Smith { 39113a40ed3dSBarry Smith PetscFunctionBegin; 39129566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,A)); 39139566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A,m,n,m,n)); 39149566063dSJacob Faibussowitsch PetscCall(MatSetType(*A,MATSEQAIJ)); 39159566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz)); 3916273d9f13SBarry Smith PetscFunctionReturn(0); 3917273d9f13SBarry Smith } 3918273d9f13SBarry Smith 3919273d9f13SBarry Smith /*@C 3920273d9f13SBarry Smith MatSeqAIJSetPreallocation - For good matrix assembly performance 3921273d9f13SBarry Smith the user should preallocate the matrix storage by setting the parameter nz 3922273d9f13SBarry Smith (or the array nnz). By setting these parameters accurately, performance 3923273d9f13SBarry Smith during matrix assembly can be increased by more than a factor of 50. 3924273d9f13SBarry Smith 3925d083f849SBarry Smith Collective 3926273d9f13SBarry Smith 3927273d9f13SBarry Smith Input Parameters: 39281c4f3114SJed Brown + B - The matrix 3929273d9f13SBarry Smith . nz - number of nonzeros per row (same for all rows) 3930273d9f13SBarry Smith - nnz - array containing the number of nonzeros in the various rows 39310298fd71SBarry Smith (possibly different for each row) or NULL 3932273d9f13SBarry Smith 3933273d9f13SBarry Smith Notes: 393449a6f317SBarry Smith If nnz is given then nz is ignored 393549a6f317SBarry Smith 3936273d9f13SBarry Smith The AIJ format (also called the Yale sparse matrix format or 3937273d9f13SBarry Smith compressed row storage), is fully compatible with standard Fortran 77 3938273d9f13SBarry Smith storage. That is, the stored row and column indices can begin at 3939273d9f13SBarry Smith either one (as in Fortran) or zero. See the users' manual for details. 3940273d9f13SBarry Smith 3941273d9f13SBarry Smith Specify the preallocated storage with either nz or nnz (not both). 39420298fd71SBarry Smith Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 3943273d9f13SBarry Smith allocation. For large problems you MUST preallocate memory or you 3944273d9f13SBarry Smith will get TERRIBLE performance, see the users' manual chapter on matrices. 3945273d9f13SBarry Smith 3946aa95bbe8SBarry Smith You can call MatGetInfo() to get information on how effective the preallocation was; 3947aa95bbe8SBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 3948aa95bbe8SBarry Smith You can also run with the option -info and look for messages with the string 3949aa95bbe8SBarry Smith malloc in them to see if additional memory allocation was needed. 3950aa95bbe8SBarry Smith 3951a96a251dSBarry Smith Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix 3952a96a251dSBarry Smith entries or columns indices 3953a96a251dSBarry Smith 3954273d9f13SBarry Smith By default, this format uses inodes (identical nodes) when possible, to 3955273d9f13SBarry Smith improve numerical efficiency of matrix-vector products and solves. We 3956273d9f13SBarry Smith search for consecutive rows with the same nonzero structure, thereby 3957273d9f13SBarry Smith reusing matrix information to achieve increased efficiency. 3958273d9f13SBarry Smith 3959273d9f13SBarry Smith Options Database Keys: 3960698d4c6aSKris Buschelman + -mat_no_inode - Do not use inodes 396147b2e64bSBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 3962273d9f13SBarry Smith 3963273d9f13SBarry Smith Level: intermediate 3964273d9f13SBarry Smith 3965db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()`, `MatGetInfo()`, 3966db781477SPatrick Sanan `MatSeqAIJSetTotalPreallocation()` 3967273d9f13SBarry Smith 3968273d9f13SBarry Smith @*/ 39697087cfbeSBarry Smith PetscErrorCode MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[]) 3970273d9f13SBarry Smith { 3971a23d5eceSKris Buschelman PetscFunctionBegin; 39726ba663aaSJed Brown PetscValidHeaderSpecific(B,MAT_CLASSID,1); 39736ba663aaSJed Brown PetscValidType(B,1); 3974cac4c232SBarry Smith PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz)); 3975a23d5eceSKris Buschelman PetscFunctionReturn(0); 3976a23d5eceSKris Buschelman } 3977a23d5eceSKris Buschelman 39787087cfbeSBarry Smith PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz) 3979a23d5eceSKris Buschelman { 3980273d9f13SBarry Smith Mat_SeqAIJ *b; 39812576faa2SJed Brown PetscBool skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE; 398297f1f81fSBarry Smith PetscInt i; 3983273d9f13SBarry Smith 3984273d9f13SBarry Smith PetscFunctionBegin; 39852576faa2SJed Brown if (nz >= 0 || nnz) realalloc = PETSC_TRUE; 3986a96a251dSBarry Smith if (nz == MAT_SKIP_ALLOCATION) { 3987c461c341SBarry Smith skipallocation = PETSC_TRUE; 3988c461c341SBarry Smith nz = 0; 3989c461c341SBarry Smith } 39909566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 39919566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 3992899cda47SBarry Smith 3993435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 399408401ef6SPierre Jolivet PetscCheck(nz >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %" PetscInt_FMT,nz); 3995cf9c20a2SJed Brown if (PetscUnlikelyDebug(nnz)) { 3996d0f46423SBarry Smith for (i=0; i<B->rmap->n; i++) { 399708401ef6SPierre Jolivet PetscCheck(nnz[i] >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %" PetscInt_FMT " value %" PetscInt_FMT,i,nnz[i]); 399808401ef6SPierre Jolivet PetscCheck(nnz[i] <= B->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %" PetscInt_FMT " value %" PetscInt_FMT " rowlength %" PetscInt_FMT,i,nnz[i],B->cmap->n); 3999b73539f3SBarry Smith } 4000b73539f3SBarry Smith } 4001b73539f3SBarry Smith 4002273d9f13SBarry Smith B->preallocated = PETSC_TRUE; 40032205254eSKarl Rupp 4004273d9f13SBarry Smith b = (Mat_SeqAIJ*)B->data; 4005273d9f13SBarry Smith 4006ab93d7beSBarry Smith if (!skipallocation) { 40072ee49352SLisandro Dalcin if (!b->imax) { 40089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n,&b->imax)); 40099566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt))); 4010071fcb05SBarry Smith } 4011071fcb05SBarry Smith if (!b->ilen) { 4012071fcb05SBarry Smith /* b->ilen will count nonzeros in each row so far. */ 40139566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(B->rmap->n,&b->ilen)); 40149566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt))); 4015071fcb05SBarry Smith } else { 40169566063dSJacob Faibussowitsch PetscCall(PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt))); 40172ee49352SLisandro Dalcin } 4018846b4da1SFande Kong if (!b->ipre) { 40199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n,&b->ipre)); 40209566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt))); 4021846b4da1SFande Kong } 4022273d9f13SBarry Smith if (!nnz) { 4023435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10; 4024c62bd62aSJed Brown else if (nz < 0) nz = 1; 40255d2a9ed1SStefano Zampini nz = PetscMin(nz,B->cmap->n); 4026d0f46423SBarry Smith for (i=0; i<B->rmap->n; i++) b->imax[i] = nz; 4027d0f46423SBarry Smith nz = nz*B->rmap->n; 4028273d9f13SBarry Smith } else { 4029c73702f5SBarry Smith PetscInt64 nz64 = 0; 4030c73702f5SBarry Smith for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];} 40319566063dSJacob Faibussowitsch PetscCall(PetscIntCast(nz64,&nz)); 4032273d9f13SBarry Smith } 4033ab93d7beSBarry Smith 4034273d9f13SBarry Smith /* allocate the matrix space */ 403553dd7562SDmitry Karpeev /* FIXME: should B's old memory be unlogged? */ 40369566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i)); 4037396832f4SHong Zhang if (B->structure_only) { 40389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz,&b->j)); 40399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n+1,&b->i)); 40409566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt))); 4041396832f4SHong Zhang } else { 40429566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i)); 40439566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)))); 4044396832f4SHong Zhang } 4045bfeeae90SHong Zhang b->i[0] = 0; 4046d0f46423SBarry Smith for (i=1; i<B->rmap->n+1; i++) { 40475da197adSKris Buschelman b->i[i] = b->i[i-1] + b->imax[i-1]; 40485da197adSKris Buschelman } 4049396832f4SHong Zhang if (B->structure_only) { 4050396832f4SHong Zhang b->singlemalloc = PETSC_FALSE; 4051396832f4SHong Zhang b->free_a = PETSC_FALSE; 4052396832f4SHong Zhang } else { 4053273d9f13SBarry Smith b->singlemalloc = PETSC_TRUE; 4054e6b907acSBarry Smith b->free_a = PETSC_TRUE; 4055396832f4SHong Zhang } 4056e6b907acSBarry Smith b->free_ij = PETSC_TRUE; 4057c461c341SBarry Smith } else { 4058e6b907acSBarry Smith b->free_a = PETSC_FALSE; 4059e6b907acSBarry Smith b->free_ij = PETSC_FALSE; 4060c461c341SBarry Smith } 4061273d9f13SBarry Smith 4062846b4da1SFande Kong if (b->ipre && nnz != b->ipre && b->imax) { 4063846b4da1SFande Kong /* reserve user-requested sparsity */ 40649566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->ipre,b->imax,B->rmap->n)); 4065846b4da1SFande Kong } 4066846b4da1SFande Kong 4067273d9f13SBarry Smith b->nz = 0; 4068273d9f13SBarry Smith b->maxnz = nz; 4069273d9f13SBarry Smith B->info.nz_unneeded = (double)b->maxnz; 40701baa6e33SBarry Smith if (realalloc) PetscCall(MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE)); 4071cb7b82ddSBarry Smith B->was_assembled = PETSC_FALSE; 4072cb7b82ddSBarry Smith B->assembled = PETSC_FALSE; 40735519a089SJose E. Roman /* We simply deem preallocation has changed nonzero state. Updating the state 40745519a089SJose E. Roman will give clients (like AIJKokkos) a chance to know something has happened. 40755519a089SJose E. Roman */ 40765519a089SJose E. Roman B->nonzerostate++; 4077273d9f13SBarry Smith PetscFunctionReturn(0); 4078273d9f13SBarry Smith } 4079273d9f13SBarry Smith 4080846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A) 4081846b4da1SFande Kong { 4082846b4da1SFande Kong Mat_SeqAIJ *a; 4083a5bbaf83SFande Kong PetscInt i; 4084846b4da1SFande Kong 4085846b4da1SFande Kong PetscFunctionBegin; 4086846b4da1SFande Kong PetscValidHeaderSpecific(A,MAT_CLASSID,1); 408714d0e64fSAlex Lindsay 408814d0e64fSAlex Lindsay /* Check local size. If zero, then return */ 408914d0e64fSAlex Lindsay if (!A->rmap->n) PetscFunctionReturn(0); 409014d0e64fSAlex Lindsay 4091846b4da1SFande Kong a = (Mat_SeqAIJ*)A->data; 40922c814fdeSFande Kong /* if no saved info, we error out */ 409328b400f6SJacob Faibussowitsch PetscCheck(a->ipre,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info "); 40942c814fdeSFande Kong 4095aed4548fSBarry Smith PetscCheck(a->i && a->j && a->a && a->imax && a->ilen,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Memory info is incomplete, and can not reset preallocation "); 40962c814fdeSFande Kong 40979566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->imax,a->ipre,A->rmap->n)); 40989566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(a->ilen,A->rmap->n)); 4099846b4da1SFande Kong a->i[0] = 0; 4100846b4da1SFande Kong for (i=1; i<A->rmap->n+1; i++) { 4101846b4da1SFande Kong a->i[i] = a->i[i-1] + a->imax[i-1]; 4102846b4da1SFande Kong } 4103846b4da1SFande Kong A->preallocated = PETSC_TRUE; 4104846b4da1SFande Kong a->nz = 0; 4105846b4da1SFande Kong a->maxnz = a->i[A->rmap->n]; 4106846b4da1SFande Kong A->info.nz_unneeded = (double)a->maxnz; 4107846b4da1SFande Kong A->was_assembled = PETSC_FALSE; 4108846b4da1SFande Kong A->assembled = PETSC_FALSE; 4109846b4da1SFande Kong PetscFunctionReturn(0); 4110846b4da1SFande Kong } 4111846b4da1SFande Kong 411258d36128SBarry Smith /*@ 4113a1661176SMatthew Knepley MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format. 4114a1661176SMatthew Knepley 4115a1661176SMatthew Knepley Input Parameters: 4116a1661176SMatthew Knepley + B - the matrix 4117a1661176SMatthew Knepley . i - the indices into j for the start of each row (starts with zero) 4118a1661176SMatthew Knepley . j - the column indices for each row (starts with zero) these must be sorted for each row 4119a1661176SMatthew Knepley - v - optional values in the matrix 4120a1661176SMatthew Knepley 4121a1661176SMatthew Knepley Level: developer 4122a1661176SMatthew Knepley 41236a9b8d82SBarry Smith Notes: 412458d36128SBarry Smith The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays() 412558d36128SBarry Smith 41266a9b8d82SBarry Smith This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero 41276a9b8d82SBarry Smith structure will be the union of all the previous nonzero structures. 41286a9b8d82SBarry Smith 41296a9b8d82SBarry Smith Developer Notes: 41306a9b8d82SBarry Smith An optimization could be added to the implementation where it checks if the i, and j are identical to the current i and j and 41316a9b8d82SBarry Smith then just copies the v values directly with PetscMemcpy(). 41326a9b8d82SBarry Smith 41336a9b8d82SBarry Smith This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them. 41346a9b8d82SBarry Smith 4135db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatSeqAIJSetPreallocation()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MatResetPreallocation()` 4136a1661176SMatthew Knepley @*/ 4137a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[]) 4138a1661176SMatthew Knepley { 4139a1661176SMatthew Knepley PetscFunctionBegin; 41400700a824SBarry Smith PetscValidHeaderSpecific(B,MAT_CLASSID,1); 41416ba663aaSJed Brown PetscValidType(B,1); 4142cac4c232SBarry Smith PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v)); 4143a1661176SMatthew Knepley PetscFunctionReturn(0); 4144a1661176SMatthew Knepley } 4145a1661176SMatthew Knepley 41467087cfbeSBarry Smith PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[]) 4147a1661176SMatthew Knepley { 4148a1661176SMatthew Knepley PetscInt i; 4149a1661176SMatthew Knepley PetscInt m,n; 4150a1661176SMatthew Knepley PetscInt nz; 41516a9b8d82SBarry Smith PetscInt *nnz; 4152a1661176SMatthew Knepley 4153a1661176SMatthew Knepley PetscFunctionBegin; 4154aed4548fSBarry Smith PetscCheck(Ii[0] == 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %" PetscInt_FMT, Ii[0]); 4155779a8d59SSatish Balay 41569566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 41579566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 4158779a8d59SSatish Balay 41599566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &m, &n)); 41609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m+1, &nnz)); 4161a1661176SMatthew Knepley for (i = 0; i < m; i++) { 4162b7940d39SSatish Balay nz = Ii[i+1]- Ii[i]; 416308401ef6SPierre Jolivet PetscCheck(nz >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz); 4164a1661176SMatthew Knepley nnz[i] = nz; 4165a1661176SMatthew Knepley } 41669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz)); 41679566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 4168a1661176SMatthew Knepley 4169a1661176SMatthew Knepley for (i = 0; i < m; i++) { 41709566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES)); 4171a1661176SMatthew Knepley } 4172a1661176SMatthew Knepley 41739566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 41749566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 4175a1661176SMatthew Knepley 41769566063dSJacob Faibussowitsch PetscCall(MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE)); 4177a1661176SMatthew Knepley PetscFunctionReturn(0); 4178a1661176SMatthew Knepley } 4179a1661176SMatthew Knepley 4180ad7e164aSPierre Jolivet /*@ 4181ad7e164aSPierre Jolivet MatSeqAIJKron - Computes C, the Kronecker product of A and B. 4182ad7e164aSPierre Jolivet 4183ad7e164aSPierre Jolivet Input Parameters: 4184ad7e164aSPierre Jolivet + A - left-hand side matrix 4185ad7e164aSPierre Jolivet . B - right-hand side matrix 4186ad7e164aSPierre Jolivet - reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 4187ad7e164aSPierre Jolivet 4188ad7e164aSPierre Jolivet Output Parameter: 4189ad7e164aSPierre Jolivet . C - Kronecker product of A and B 4190ad7e164aSPierre Jolivet 4191ad7e164aSPierre Jolivet Level: intermediate 4192ad7e164aSPierre Jolivet 4193ad7e164aSPierre Jolivet Notes: 4194ad7e164aSPierre Jolivet MAT_REUSE_MATRIX can only be used when the nonzero structure of the product matrix has not changed from that last call to MatSeqAIJKron(). 4195ad7e164aSPierre Jolivet 4196db781477SPatrick Sanan .seealso: `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATKAIJ`, `MatReuse` 4197ad7e164aSPierre Jolivet @*/ 4198ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron(Mat A,Mat B,MatReuse reuse,Mat *C) 4199ad7e164aSPierre Jolivet { 4200ad7e164aSPierre Jolivet PetscFunctionBegin; 4201ad7e164aSPierre Jolivet PetscValidHeaderSpecific(A,MAT_CLASSID,1); 4202ad7e164aSPierre Jolivet PetscValidType(A,1); 4203ad7e164aSPierre Jolivet PetscValidHeaderSpecific(B,MAT_CLASSID,2); 4204ad7e164aSPierre Jolivet PetscValidType(B,2); 4205ad7e164aSPierre Jolivet PetscValidPointer(C,4); 4206ad7e164aSPierre Jolivet if (reuse == MAT_REUSE_MATRIX) { 4207ad7e164aSPierre Jolivet PetscValidHeaderSpecific(*C,MAT_CLASSID,4); 4208ad7e164aSPierre Jolivet PetscValidType(*C,4); 4209ad7e164aSPierre Jolivet } 4210cac4c232SBarry Smith PetscTryMethod(A,"MatSeqAIJKron_C",(Mat,Mat,MatReuse,Mat*),(A,B,reuse,C)); 4211ad7e164aSPierre Jolivet PetscFunctionReturn(0); 4212ad7e164aSPierre Jolivet } 4213ad7e164aSPierre Jolivet 4214ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A,Mat B,MatReuse reuse,Mat *C) 4215ad7e164aSPierre Jolivet { 4216ad7e164aSPierre Jolivet Mat newmat; 4217ad7e164aSPierre Jolivet Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 4218ad7e164aSPierre Jolivet Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 4219ad7e164aSPierre Jolivet PetscScalar *v; 4220fff043a9SJunchao Zhang const PetscScalar *aa,*ba; 4221ad7e164aSPierre Jolivet PetscInt *i,*j,m,n,p,q,nnz = 0,am = A->rmap->n,bm = B->rmap->n,an = A->cmap->n, bn = B->cmap->n; 4222ad7e164aSPierre Jolivet PetscBool flg; 4223ad7e164aSPierre Jolivet 4224ad7e164aSPierre Jolivet PetscFunctionBegin; 422528b400f6SJacob Faibussowitsch PetscCheck(!A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 422628b400f6SJacob Faibussowitsch PetscCheck(A->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 422728b400f6SJacob Faibussowitsch PetscCheck(!B->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 422828b400f6SJacob Faibussowitsch PetscCheck(B->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 42299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&flg)); 423028b400f6SJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatType %s",((PetscObject)B)->type_name); 4231aed4548fSBarry Smith PetscCheck(reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatReuse %d",(int)reuse); 4232ad7e164aSPierre Jolivet if (reuse == MAT_INITIAL_MATRIX) { 42339566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(am*bm+1,&i,a->i[am]*b->i[bm],&j)); 42349566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF,&newmat)); 42359566063dSJacob Faibussowitsch PetscCall(MatSetSizes(newmat,am*bm,an*bn,am*bm,an*bn)); 42369566063dSJacob Faibussowitsch PetscCall(MatSetType(newmat,MATAIJ)); 4237ad7e164aSPierre Jolivet i[0] = 0; 4238ad7e164aSPierre Jolivet for (m = 0; m < am; ++m) { 4239ad7e164aSPierre Jolivet for (p = 0; p < bm; ++p) { 4240ad7e164aSPierre Jolivet i[m*bm + p + 1] = i[m*bm + p] + (a->i[m+1] - a->i[m]) * (b->i[p+1] - b->i[p]); 4241ad7e164aSPierre Jolivet for (n = a->i[m]; n < a->i[m+1]; ++n) { 4242ad7e164aSPierre Jolivet for (q = b->i[p]; q < b->i[p+1]; ++q) { 4243ad7e164aSPierre Jolivet j[nnz++] = a->j[n]*bn + b->j[q]; 4244ad7e164aSPierre Jolivet } 4245ad7e164aSPierre Jolivet } 4246ad7e164aSPierre Jolivet } 4247ad7e164aSPierre Jolivet } 42489566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(newmat,i,j,NULL)); 4249ad7e164aSPierre Jolivet *C = newmat; 42509566063dSJacob Faibussowitsch PetscCall(PetscFree2(i,j)); 4251ad7e164aSPierre Jolivet nnz = 0; 4252ad7e164aSPierre Jolivet } 42539566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(*C,&v)); 42549566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 42559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B,&ba)); 4256ad7e164aSPierre Jolivet for (m = 0; m < am; ++m) { 4257ad7e164aSPierre Jolivet for (p = 0; p < bm; ++p) { 4258ad7e164aSPierre Jolivet for (n = a->i[m]; n < a->i[m+1]; ++n) { 4259ad7e164aSPierre Jolivet for (q = b->i[p]; q < b->i[p+1]; ++q) { 4260fff043a9SJunchao Zhang v[nnz++] = aa[n] * ba[q]; 4261ad7e164aSPierre Jolivet } 4262ad7e164aSPierre Jolivet } 4263ad7e164aSPierre Jolivet } 4264ad7e164aSPierre Jolivet } 42659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(*C,&v)); 42669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 42679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B,&ba)); 4268ad7e164aSPierre Jolivet PetscFunctionReturn(0); 4269ad7e164aSPierre Jolivet } 4270ad7e164aSPierre Jolivet 4271c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h> 4272af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h> 4273170fe5c8SBarry Smith 4274170fe5c8SBarry Smith /* 4275170fe5c8SBarry Smith Computes (B'*A')' since computing B*A directly is untenable 4276170fe5c8SBarry Smith 4277170fe5c8SBarry Smith n p p 42782da392ccSBarry Smith [ ] [ ] [ ] 42792da392ccSBarry Smith m [ A ] * n [ B ] = m [ C ] 42802da392ccSBarry Smith [ ] [ ] [ ] 4281170fe5c8SBarry Smith 4282170fe5c8SBarry Smith */ 4283170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C) 4284170fe5c8SBarry Smith { 4285170fe5c8SBarry Smith Mat_SeqDense *sub_a = (Mat_SeqDense*)A->data; 4286170fe5c8SBarry Smith Mat_SeqAIJ *sub_b = (Mat_SeqAIJ*)B->data; 4287170fe5c8SBarry Smith Mat_SeqDense *sub_c = (Mat_SeqDense*)C->data; 428886214ceeSStefano Zampini PetscInt i,j,n,m,q,p; 4289170fe5c8SBarry Smith const PetscInt *ii,*idx; 4290170fe5c8SBarry Smith const PetscScalar *b,*a,*a_q; 4291170fe5c8SBarry Smith PetscScalar *c,*c_q; 429286214ceeSStefano Zampini PetscInt clda = sub_c->lda; 429386214ceeSStefano Zampini PetscInt alda = sub_a->lda; 4294170fe5c8SBarry Smith 4295170fe5c8SBarry Smith PetscFunctionBegin; 4296d0f46423SBarry Smith m = A->rmap->n; 4297d0f46423SBarry Smith n = A->cmap->n; 4298d0f46423SBarry Smith p = B->cmap->n; 4299170fe5c8SBarry Smith a = sub_a->v; 4300170fe5c8SBarry Smith b = sub_b->a; 4301170fe5c8SBarry Smith c = sub_c->v; 430286214ceeSStefano Zampini if (clda == m) { 43039566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c,m*p)); 430486214ceeSStefano Zampini } else { 430586214ceeSStefano Zampini for (j=0;j<p;j++) 430686214ceeSStefano Zampini for (i=0;i<m;i++) 430786214ceeSStefano Zampini c[j*clda + i] = 0.0; 430886214ceeSStefano Zampini } 4309170fe5c8SBarry Smith ii = sub_b->i; 4310170fe5c8SBarry Smith idx = sub_b->j; 4311170fe5c8SBarry Smith for (i=0; i<n; i++) { 4312170fe5c8SBarry Smith q = ii[i+1] - ii[i]; 4313170fe5c8SBarry Smith while (q-->0) { 431486214ceeSStefano Zampini c_q = c + clda*(*idx); 431586214ceeSStefano Zampini a_q = a + alda*i; 4316854c7f52SBarry Smith PetscKernelAXPY(c_q,*b,a_q,m); 4317170fe5c8SBarry Smith idx++; 4318170fe5c8SBarry Smith b++; 4319170fe5c8SBarry Smith } 4320170fe5c8SBarry Smith } 4321170fe5c8SBarry Smith PetscFunctionReturn(0); 4322170fe5c8SBarry Smith } 4323170fe5c8SBarry Smith 43244222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C) 4325170fe5c8SBarry Smith { 4326d0f46423SBarry Smith PetscInt m=A->rmap->n,n=B->cmap->n; 432786214ceeSStefano Zampini PetscBool cisdense; 4328170fe5c8SBarry Smith 4329170fe5c8SBarry Smith PetscFunctionBegin; 433008401ef6SPierre Jolivet PetscCheck(A->cmap->n == B->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %" PetscInt_FMT " != B->rmap->n %" PetscInt_FMT,A->cmap->n,B->rmap->n); 43319566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C,m,n,m,n)); 43329566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C,A,B)); 43339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"")); 433486214ceeSStefano Zampini if (!cisdense) { 43359566063dSJacob Faibussowitsch PetscCall(MatSetType(C,MATDENSE)); 433686214ceeSStefano Zampini } 43379566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 4338d73949e8SHong Zhang 43394222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ; 4340170fe5c8SBarry Smith PetscFunctionReturn(0); 4341170fe5c8SBarry Smith } 4342170fe5c8SBarry Smith 4343170fe5c8SBarry Smith /* ----------------------------------------------------------------*/ 43440bad9183SKris Buschelman /*MC 4345fafad747SKris Buschelman MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices, 43460bad9183SKris Buschelman based on compressed sparse row format. 43470bad9183SKris Buschelman 43480bad9183SKris Buschelman Options Database Keys: 43490bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions() 43500bad9183SKris Buschelman 43510bad9183SKris Buschelman Level: beginner 43520bad9183SKris Buschelman 43530cd7f59aSBarry Smith Notes: 43540cd7f59aSBarry Smith MatSetValues() may be called for this matrix type with a NULL argument for the numerical values, 43550cd7f59aSBarry Smith in this case the values associated with the rows and columns one passes in are set to zero 43560cd7f59aSBarry Smith in the matrix 43570cd7f59aSBarry Smith 43580cd7f59aSBarry Smith MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no 43590cd7f59aSBarry Smith space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored 43600cd7f59aSBarry Smith 43610cd7f59aSBarry Smith Developer Notes: 43620cd7f59aSBarry Smith It would be nice if all matrix formats supported passing NULL in for the numerical values 43630cd7f59aSBarry Smith 4364db781477SPatrick Sanan .seealso: `MatCreateSeqAIJ()`, `MatSetFromOptions()`, `MatSetType()`, `MatCreate()`, `MatType`, `MATSELL`, `MATSEQSELL`, `MATMPISELL` 43650bad9183SKris Buschelman M*/ 43660bad9183SKris Buschelman 4367ccd284c7SBarry Smith /*MC 4368ccd284c7SBarry Smith MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices. 4369ccd284c7SBarry Smith 4370ccd284c7SBarry Smith This matrix type is identical to MATSEQAIJ when constructed with a single process communicator, 4371ccd284c7SBarry Smith and MATMPIAIJ otherwise. As a result, for single process communicators, 4372ed73aabaSBarry Smith MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported 4373ccd284c7SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 4374ccd284c7SBarry Smith the above preallocation routines for simplicity. 4375ccd284c7SBarry Smith 4376ccd284c7SBarry Smith Options Database Keys: 4377ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions() 4378ccd284c7SBarry Smith 437995452b02SPatrick Sanan Developer Notes: 4380ca9cdca7SRichard Tran Mills Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when 4381ccd284c7SBarry Smith enough exist. 4382ccd284c7SBarry Smith 4383ccd284c7SBarry Smith Level: beginner 4384ccd284c7SBarry Smith 4385db781477SPatrick Sanan .seealso: `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATMPIAIJ`, `MATSELL`, `MATSEQSELL`, `MATMPISELL` 4386ccd284c7SBarry Smith M*/ 4387ccd284c7SBarry Smith 4388ccd284c7SBarry Smith /*MC 4389ccd284c7SBarry Smith MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices. 4390ccd284c7SBarry Smith 4391ccd284c7SBarry Smith This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator, 4392ccd284c7SBarry Smith and MATMPIAIJCRL otherwise. As a result, for single process communicators, 4393ccd284c7SBarry Smith MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported 4394ccd284c7SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 4395ccd284c7SBarry Smith the above preallocation routines for simplicity. 4396ccd284c7SBarry Smith 4397ccd284c7SBarry Smith Options Database Keys: 4398ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions() 4399ccd284c7SBarry Smith 4400ccd284c7SBarry Smith Level: beginner 4401ccd284c7SBarry Smith 4402c2e3fba1SPatrick Sanan .seealso: `MatCreateMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL` 4403ccd284c7SBarry Smith M*/ 4404ccd284c7SBarry Smith 44057906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*); 44067906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 44077906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*); 44087906f579SHong Zhang #endif 4409d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 4410d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*); 4411d24d4204SJose E. Roman #endif 44127906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE) 44137906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*); 44147906f579SHong Zhang #endif 44157906f579SHong Zhang 4416d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*); 4417c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*); 44184222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat); 44197906f579SHong Zhang 44208c778c55SBarry Smith /*@C 44218f1ea47aSStefano Zampini MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored 44228c778c55SBarry Smith 44238c778c55SBarry Smith Not Collective 44248c778c55SBarry Smith 44258c778c55SBarry Smith Input Parameter: 4426579dbff0SBarry Smith . mat - a MATSEQAIJ matrix 44278c778c55SBarry Smith 44288c778c55SBarry Smith Output Parameter: 44298c778c55SBarry Smith . array - pointer to the data 44308c778c55SBarry Smith 44318c778c55SBarry Smith Level: intermediate 44328c778c55SBarry Smith 4433db781477SPatrick Sanan .seealso: `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()` 44348c778c55SBarry Smith @*/ 44358c778c55SBarry Smith PetscErrorCode MatSeqAIJGetArray(Mat A,PetscScalar **array) 44368c778c55SBarry Smith { 4437d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 44388c778c55SBarry Smith 44398c778c55SBarry Smith PetscFunctionBegin; 4440d67d9f35SJunchao Zhang if (aij->ops->getarray) { 44419566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarray)(A,array)); 4442d67d9f35SJunchao Zhang } else { 4443d67d9f35SJunchao Zhang *array = aij->a; 4444d67d9f35SJunchao Zhang } 4445d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4446d67d9f35SJunchao Zhang } 4447d67d9f35SJunchao Zhang 4448d67d9f35SJunchao Zhang /*@C 4449d67d9f35SJunchao Zhang MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray() 4450d67d9f35SJunchao Zhang 4451d67d9f35SJunchao Zhang Not Collective 4452d67d9f35SJunchao Zhang 4453d67d9f35SJunchao Zhang Input Parameters: 4454d67d9f35SJunchao Zhang + mat - a MATSEQAIJ matrix 4455d67d9f35SJunchao Zhang - array - pointer to the data 4456d67d9f35SJunchao Zhang 4457d67d9f35SJunchao Zhang Level: intermediate 4458d67d9f35SJunchao Zhang 4459db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayF90()` 4460d67d9f35SJunchao Zhang @*/ 4461d67d9f35SJunchao Zhang PetscErrorCode MatSeqAIJRestoreArray(Mat A,PetscScalar **array) 4462d67d9f35SJunchao Zhang { 4463d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 4464d67d9f35SJunchao Zhang 4465d67d9f35SJunchao Zhang PetscFunctionBegin; 4466d67d9f35SJunchao Zhang if (aij->ops->restorearray) { 44679566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearray)(A,array)); 4468d67d9f35SJunchao Zhang } else { 4469d67d9f35SJunchao Zhang *array = NULL; 4470d67d9f35SJunchao Zhang } 44719566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 44729566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 44738c778c55SBarry Smith PetscFunctionReturn(0); 44748c778c55SBarry Smith } 44758c778c55SBarry Smith 447621e72a00SBarry Smith /*@C 44778f1ea47aSStefano Zampini MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored 44788f1ea47aSStefano Zampini 44798f1ea47aSStefano Zampini Not Collective 44808f1ea47aSStefano Zampini 44818f1ea47aSStefano Zampini Input Parameter: 44828f1ea47aSStefano Zampini . mat - a MATSEQAIJ matrix 44838f1ea47aSStefano Zampini 44848f1ea47aSStefano Zampini Output Parameter: 44858f1ea47aSStefano Zampini . array - pointer to the data 44868f1ea47aSStefano Zampini 44878f1ea47aSStefano Zampini Level: intermediate 44888f1ea47aSStefano Zampini 4489db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()` 44908f1ea47aSStefano Zampini @*/ 44918f1ea47aSStefano Zampini PetscErrorCode MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array) 44928f1ea47aSStefano Zampini { 4493d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 44948f1ea47aSStefano Zampini 44958f1ea47aSStefano Zampini PetscFunctionBegin; 4496d67d9f35SJunchao Zhang if (aij->ops->getarrayread) { 44979566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarrayread)(A,array)); 4498d67d9f35SJunchao Zhang } else { 4499d67d9f35SJunchao Zhang *array = aij->a; 4500d67d9f35SJunchao Zhang } 45018f1ea47aSStefano Zampini PetscFunctionReturn(0); 45028f1ea47aSStefano Zampini } 45038f1ea47aSStefano Zampini 45048f1ea47aSStefano Zampini /*@C 45058f1ea47aSStefano Zampini MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead 45068f1ea47aSStefano Zampini 45078f1ea47aSStefano Zampini Not Collective 45088f1ea47aSStefano Zampini 45098f1ea47aSStefano Zampini Input Parameter: 45108f1ea47aSStefano Zampini . mat - a MATSEQAIJ matrix 45118f1ea47aSStefano Zampini 45128f1ea47aSStefano Zampini Output Parameter: 45138f1ea47aSStefano Zampini . array - pointer to the data 45148f1ea47aSStefano Zampini 45158f1ea47aSStefano Zampini Level: intermediate 45168f1ea47aSStefano Zampini 4517db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 45188f1ea47aSStefano Zampini @*/ 45198f1ea47aSStefano Zampini PetscErrorCode MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array) 45208f1ea47aSStefano Zampini { 4521d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 45228f1ea47aSStefano Zampini 45238f1ea47aSStefano Zampini PetscFunctionBegin; 4524d67d9f35SJunchao Zhang if (aij->ops->restorearrayread) { 45259566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearrayread)(A,array)); 4526d67d9f35SJunchao Zhang } else { 4527d67d9f35SJunchao Zhang *array = NULL; 4528d67d9f35SJunchao Zhang } 4529d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4530d67d9f35SJunchao Zhang } 4531d67d9f35SJunchao Zhang 4532d67d9f35SJunchao Zhang /*@C 4533d67d9f35SJunchao Zhang MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a MATSEQAIJ matrix is stored 4534d67d9f35SJunchao Zhang 4535d67d9f35SJunchao Zhang Not Collective 4536d67d9f35SJunchao Zhang 4537d67d9f35SJunchao Zhang Input Parameter: 4538d67d9f35SJunchao Zhang . mat - a MATSEQAIJ matrix 4539d67d9f35SJunchao Zhang 4540d67d9f35SJunchao Zhang Output Parameter: 4541d67d9f35SJunchao Zhang . array - pointer to the data 4542d67d9f35SJunchao Zhang 4543d67d9f35SJunchao Zhang Level: intermediate 4544d67d9f35SJunchao Zhang 4545db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()` 4546d67d9f35SJunchao Zhang @*/ 4547d67d9f35SJunchao Zhang PetscErrorCode MatSeqAIJGetArrayWrite(Mat A,PetscScalar **array) 4548d67d9f35SJunchao Zhang { 4549d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 4550d67d9f35SJunchao Zhang 4551d67d9f35SJunchao Zhang PetscFunctionBegin; 4552d67d9f35SJunchao Zhang if (aij->ops->getarraywrite) { 45539566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarraywrite)(A,array)); 4554d67d9f35SJunchao Zhang } else { 4555d67d9f35SJunchao Zhang *array = aij->a; 4556d67d9f35SJunchao Zhang } 45579566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 45589566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 4559d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4560d67d9f35SJunchao Zhang } 4561d67d9f35SJunchao Zhang 4562d67d9f35SJunchao Zhang /*@C 4563d67d9f35SJunchao Zhang MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead 4564d67d9f35SJunchao Zhang 4565d67d9f35SJunchao Zhang Not Collective 4566d67d9f35SJunchao Zhang 4567d67d9f35SJunchao Zhang Input Parameter: 4568d67d9f35SJunchao Zhang . mat - a MATSEQAIJ matrix 4569d67d9f35SJunchao Zhang 4570d67d9f35SJunchao Zhang Output Parameter: 4571d67d9f35SJunchao Zhang . array - pointer to the data 4572d67d9f35SJunchao Zhang 4573d67d9f35SJunchao Zhang Level: intermediate 4574d67d9f35SJunchao Zhang 4575db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 4576d67d9f35SJunchao Zhang @*/ 4577d67d9f35SJunchao Zhang PetscErrorCode MatSeqAIJRestoreArrayWrite(Mat A,PetscScalar **array) 4578d67d9f35SJunchao Zhang { 4579d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 4580d67d9f35SJunchao Zhang 4581d67d9f35SJunchao Zhang PetscFunctionBegin; 4582d67d9f35SJunchao Zhang if (aij->ops->restorearraywrite) { 45839566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearraywrite)(A,array)); 4584d67d9f35SJunchao Zhang } else { 4585d67d9f35SJunchao Zhang *array = NULL; 4586d67d9f35SJunchao Zhang } 45878f1ea47aSStefano Zampini PetscFunctionReturn(0); 45888f1ea47aSStefano Zampini } 45898f1ea47aSStefano Zampini 45908f1ea47aSStefano Zampini /*@C 45917ee59b9bSJunchao Zhang MatSeqAIJGetCSRAndMemType - Get the CSR arrays and the memory type of the SEQAIJ matrix 45927ee59b9bSJunchao Zhang 45937ee59b9bSJunchao Zhang Not Collective 45947ee59b9bSJunchao Zhang 45957ee59b9bSJunchao Zhang Input Parameter: 45967ee59b9bSJunchao Zhang . mat - a matrix of type MATSEQAIJ or its subclasses 45977ee59b9bSJunchao Zhang 45987ee59b9bSJunchao Zhang Output Parameters: 45997ee59b9bSJunchao Zhang + i - row map array of the matrix 46007ee59b9bSJunchao Zhang . j - column index array of the matrix 46017ee59b9bSJunchao Zhang . a - data array of the matrix 46027ee59b9bSJunchao Zhang - memtype - memory type of the arrays 46037ee59b9bSJunchao Zhang 46047ee59b9bSJunchao Zhang Notes: 46057ee59b9bSJunchao Zhang Any of the output parameters can be NULL, in which case the corresponding value is not returned. 46067ee59b9bSJunchao Zhang If mat is a device matrix, the arrays are on the device. Otherwise, they are on the host. 46077ee59b9bSJunchao Zhang 46087ee59b9bSJunchao Zhang One can call this routine on a preallocated but not assembled matrix to just get the memory of the CSR underneath the matrix. 46097ee59b9bSJunchao Zhang If the matrix is assembled, the data array 'a' is guaranteed to have the latest values of the matrix. 46107ee59b9bSJunchao Zhang 46117ee59b9bSJunchao Zhang Level: Developer 46127ee59b9bSJunchao Zhang 4613db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 46147ee59b9bSJunchao Zhang @*/ 46157ee59b9bSJunchao Zhang PetscErrorCode MatSeqAIJGetCSRAndMemType(Mat mat,const PetscInt **i,const PetscInt **j,PetscScalar **a,PetscMemType *mtype) 46167ee59b9bSJunchao Zhang { 46177ee59b9bSJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 46187ee59b9bSJunchao Zhang 46197ee59b9bSJunchao Zhang PetscFunctionBegin; 46207ee59b9bSJunchao Zhang PetscCheck(mat->preallocated,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"matrix is not preallocated"); 46217ee59b9bSJunchao Zhang if (aij->ops->getcsrandmemtype) { 46227ee59b9bSJunchao Zhang PetscCall((*aij->ops->getcsrandmemtype)(mat,i,j,a,mtype)); 46237ee59b9bSJunchao Zhang } else { 46247ee59b9bSJunchao Zhang if (i) *i = aij->i; 46257ee59b9bSJunchao Zhang if (j) *j = aij->j; 46267ee59b9bSJunchao Zhang if (a) *a = aij->a; 46277ee59b9bSJunchao Zhang if (mtype) *mtype = PETSC_MEMTYPE_HOST; 46287ee59b9bSJunchao Zhang } 46297ee59b9bSJunchao Zhang PetscFunctionReturn(0); 46307ee59b9bSJunchao Zhang } 46317ee59b9bSJunchao Zhang 46327ee59b9bSJunchao Zhang /*@C 463321e72a00SBarry Smith MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row 463421e72a00SBarry Smith 463521e72a00SBarry Smith Not Collective 463621e72a00SBarry Smith 463721e72a00SBarry Smith Input Parameter: 4638579dbff0SBarry Smith . mat - a MATSEQAIJ matrix 463921e72a00SBarry Smith 464021e72a00SBarry Smith Output Parameter: 464121e72a00SBarry Smith . nz - the maximum number of nonzeros in any row 464221e72a00SBarry Smith 464321e72a00SBarry Smith Level: intermediate 464421e72a00SBarry Smith 4645db781477SPatrick Sanan .seealso: `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()` 464621e72a00SBarry Smith @*/ 464721e72a00SBarry Smith PetscErrorCode MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz) 464821e72a00SBarry Smith { 464921e72a00SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 465021e72a00SBarry Smith 465121e72a00SBarry Smith PetscFunctionBegin; 465221e72a00SBarry Smith *nz = aij->rmax; 465321e72a00SBarry Smith PetscFunctionReturn(0); 465421e72a00SBarry Smith } 465521e72a00SBarry Smith 4656394ed5ebSJunchao Zhang PetscErrorCode MatSetPreallocationCOO_SeqAIJ(Mat mat, PetscCount coo_n, const PetscInt coo_i[], const PetscInt coo_j[]) 4657394ed5ebSJunchao Zhang { 4658394ed5ebSJunchao Zhang MPI_Comm comm; 4659394ed5ebSJunchao Zhang PetscInt *i,*j; 4660394ed5ebSJunchao Zhang PetscInt M,N,row; 4661394ed5ebSJunchao Zhang PetscCount k,p,q,nneg,nnz,start,end; /* Index the coo array, so use PetscCount as their type */ 4662394ed5ebSJunchao Zhang PetscInt *Ai; /* Change to PetscCount once we use it for row pointers */ 4663394ed5ebSJunchao Zhang PetscInt *Aj; 4664394ed5ebSJunchao Zhang PetscScalar *Aa; 4665cbc6b225SStefano Zampini Mat_SeqAIJ *seqaij = (Mat_SeqAIJ*)(mat->data); 4666cbc6b225SStefano Zampini MatType rtype; 4667394ed5ebSJunchao Zhang PetscCount *perm,*jmap; 4668394ed5ebSJunchao Zhang 4669394ed5ebSJunchao Zhang PetscFunctionBegin; 46709566063dSJacob Faibussowitsch PetscCall(MatResetPreallocationCOO_SeqAIJ(mat)); 46719566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat,&comm)); 46729566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat,&M,&N)); 46739566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(coo_n,&i,coo_n,&j)); 46749566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(i,coo_i,coo_n)); /* Make a copy since we'll modify it */ 46759566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(j,coo_j,coo_n)); 46769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n,&perm)); 4677394ed5ebSJunchao Zhang for (k=0; k<coo_n; k++) { /* Ignore entries with negative row or col indices */ 4678394ed5ebSJunchao Zhang if (j[k] < 0) i[k] = -1; 4679394ed5ebSJunchao Zhang perm[k] = k; 4680394ed5ebSJunchao Zhang } 4681394ed5ebSJunchao Zhang 4682394ed5ebSJunchao Zhang /* Sort by row */ 46839566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithIntCountArrayPair(coo_n,i,j,perm)); 4684394ed5ebSJunchao Zhang for (k=0; k<coo_n; k++) {if (i[k] >= 0) break;} /* Advance k to the first row with a non-negative index */ 4685394ed5ebSJunchao Zhang nneg = k; 46869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n-nneg+1,&jmap)); /* +1 to make a CSR-like data structure. jmap[i] originally is the number of repeats for i-th nonzero */ 4687394ed5ebSJunchao Zhang nnz = 0; /* Total number of unique nonzeros to be counted */ 4688394ed5ebSJunchao Zhang jmap++; /* Inc jmap by 1 for convinience */ 4689394ed5ebSJunchao Zhang 46909566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(M+1,&Ai)); /* CSR of A */ 46919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n-nneg,&Aj)); /* We have at most coo_n-nneg unique nonzeros */ 4692394ed5ebSJunchao Zhang 4693394ed5ebSJunchao Zhang /* In each row, sort by column, then unique column indices to get row length */ 4694394ed5ebSJunchao Zhang Ai++; /* Inc by 1 for convinience */ 4695394ed5ebSJunchao Zhang q = 0; /* q-th unique nonzero, with q starting from 0 */ 4696394ed5ebSJunchao Zhang while (k<coo_n) { 4697394ed5ebSJunchao Zhang row = i[k]; 4698394ed5ebSJunchao Zhang start = k; /* [start,end) indices for this row */ 4699394ed5ebSJunchao Zhang while (k<coo_n && i[k] == row) k++; 4700394ed5ebSJunchao Zhang end = k; 47019566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithCountArray(end-start,j+start,perm+start)); 4702394ed5ebSJunchao Zhang /* Find number of unique col entries in this row */ 4703394ed5ebSJunchao Zhang Aj[q] = j[start]; /* Log the first nonzero in this row */ 4704394ed5ebSJunchao Zhang jmap[q] = 1; /* Number of repeats of this nozero entry */ 4705394ed5ebSJunchao Zhang Ai[row] = 1; 4706394ed5ebSJunchao Zhang nnz++; 4707394ed5ebSJunchao Zhang 4708394ed5ebSJunchao Zhang for (p=start+1; p<end; p++) { /* Scan remaining nonzero in this row */ 4709394ed5ebSJunchao Zhang if (j[p] != j[p-1]) { /* Meet a new nonzero */ 4710394ed5ebSJunchao Zhang q++; 4711394ed5ebSJunchao Zhang jmap[q] = 1; 4712394ed5ebSJunchao Zhang Aj[q] = j[p]; 4713394ed5ebSJunchao Zhang Ai[row]++; 4714394ed5ebSJunchao Zhang nnz++; 4715394ed5ebSJunchao Zhang } else { 4716394ed5ebSJunchao Zhang jmap[q]++; 4717394ed5ebSJunchao Zhang } 4718394ed5ebSJunchao Zhang } 4719394ed5ebSJunchao Zhang q++; /* Move to next row and thus next unique nonzero */ 4720394ed5ebSJunchao Zhang } 47219566063dSJacob Faibussowitsch PetscCall(PetscFree2(i,j)); 4722394ed5ebSJunchao Zhang 4723394ed5ebSJunchao Zhang Ai--; /* Back to the beginning of Ai[] */ 4724394ed5ebSJunchao Zhang for (k=0; k<M; k++) Ai[k+1] += Ai[k]; 4725394ed5ebSJunchao Zhang jmap--; /* Back to the beginning of jmap[] */ 4726394ed5ebSJunchao Zhang jmap[0] = 0; 4727394ed5ebSJunchao Zhang for (k=0; k<nnz; k++) jmap[k+1] += jmap[k]; 4728394ed5ebSJunchao Zhang if (nnz < coo_n-nneg) { /* Realloc with actual number of unique nonzeros */ 4729394ed5ebSJunchao Zhang PetscCount *jmap_new; 4730394ed5ebSJunchao Zhang PetscInt *Aj_new; 4731394ed5ebSJunchao Zhang 47329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz+1,&jmap_new)); 47339566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(jmap_new,jmap,nnz+1)); 47349566063dSJacob Faibussowitsch PetscCall(PetscFree(jmap)); 4735394ed5ebSJunchao Zhang jmap = jmap_new; 4736394ed5ebSJunchao Zhang 47379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz,&Aj_new)); 47389566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(Aj_new,Aj,nnz)); 47399566063dSJacob Faibussowitsch PetscCall(PetscFree(Aj)); 4740394ed5ebSJunchao Zhang Aj = Aj_new; 4741394ed5ebSJunchao Zhang } 4742394ed5ebSJunchao Zhang 4743394ed5ebSJunchao Zhang if (nneg) { /* Discard heading entries with negative indices in perm[], as we'll access it from index 0 in MatSetValuesCOO */ 4744394ed5ebSJunchao Zhang PetscCount *perm_new; 4745cbc6b225SStefano Zampini 47469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n-nneg,&perm_new)); 47479566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(perm_new,perm+nneg,coo_n-nneg)); 47489566063dSJacob Faibussowitsch PetscCall(PetscFree(perm)); 4749394ed5ebSJunchao Zhang perm = perm_new; 4750394ed5ebSJunchao Zhang } 4751394ed5ebSJunchao Zhang 47529566063dSJacob Faibussowitsch PetscCall(MatGetRootType_Private(mat,&rtype)); 47539566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nnz,&Aa)); /* Zero the matrix */ 47549566063dSJacob Faibussowitsch PetscCall(MatSetSeqAIJWithArrays_private(PETSC_COMM_SELF,M,N,Ai,Aj,Aa,rtype,mat)); 4755394ed5ebSJunchao Zhang 4756394ed5ebSJunchao Zhang seqaij->singlemalloc = PETSC_FALSE; /* Ai, Aj and Aa are not allocated in one big malloc */ 4757394ed5ebSJunchao Zhang seqaij->free_a = seqaij->free_ij = PETSC_TRUE; /* Let newmat own Ai, Aj and Aa */ 4758394ed5ebSJunchao Zhang /* Record COO fields */ 4759394ed5ebSJunchao Zhang seqaij->coo_n = coo_n; 4760394ed5ebSJunchao Zhang seqaij->Atot = coo_n-nneg; /* Annz is seqaij->nz, so no need to record that again */ 4761394ed5ebSJunchao Zhang seqaij->jmap = jmap; /* of length nnz+1 */ 4762394ed5ebSJunchao Zhang seqaij->perm = perm; 4763394ed5ebSJunchao Zhang PetscFunctionReturn(0); 4764394ed5ebSJunchao Zhang } 4765394ed5ebSJunchao Zhang 4766394ed5ebSJunchao Zhang static PetscErrorCode MatSetValuesCOO_SeqAIJ(Mat A,const PetscScalar v[],InsertMode imode) 4767394ed5ebSJunchao Zhang { 4768394ed5ebSJunchao Zhang Mat_SeqAIJ *aseq = (Mat_SeqAIJ*)A->data; 4769394ed5ebSJunchao Zhang PetscCount i,j,Annz = aseq->nz; 4770394ed5ebSJunchao Zhang PetscCount *perm = aseq->perm,*jmap = aseq->jmap; 4771394ed5ebSJunchao Zhang PetscScalar *Aa; 4772394ed5ebSJunchao Zhang 4773394ed5ebSJunchao Zhang PetscFunctionBegin; 47749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&Aa)); 4775394ed5ebSJunchao Zhang for (i=0; i<Annz; i++) { 4776b6c38306SJunchao Zhang PetscScalar sum = 0.0; 4777b6c38306SJunchao Zhang for (j=jmap[i]; j<jmap[i+1]; j++) sum += v[perm[j]]; 4778b6c38306SJunchao Zhang Aa[i] = (imode == INSERT_VALUES? 0.0 : Aa[i]) + sum; 4779394ed5ebSJunchao Zhang } 47809566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&Aa)); 4781394ed5ebSJunchao Zhang PetscFunctionReturn(0); 4782394ed5ebSJunchao Zhang } 4783394ed5ebSJunchao Zhang 478434b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA) 47855063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat,MatType,MatReuse,Mat*); 478602fe1965SBarry Smith #endif 47873d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 47885063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat,MatType,MatReuse,Mat*); 47893d0639e7SStefano Zampini #endif 479002fe1965SBarry Smith 47918cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B) 4792273d9f13SBarry Smith { 4793273d9f13SBarry Smith Mat_SeqAIJ *b; 479438baddfdSBarry Smith PetscMPIInt size; 4795273d9f13SBarry Smith 4796273d9f13SBarry Smith PetscFunctionBegin; 47979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B),&size)); 479808401ef6SPierre Jolivet PetscCheck(size <= 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1"); 4799273d9f13SBarry Smith 48009566063dSJacob Faibussowitsch PetscCall(PetscNewLog(B,&b)); 48012205254eSKarl Rupp 4802b0a32e0cSBarry Smith B->data = (void*)b; 48032205254eSKarl Rupp 48049566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps))); 4805071fcb05SBarry Smith if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 48062205254eSKarl Rupp 4807f4259b30SLisandro Dalcin b->row = NULL; 4808f4259b30SLisandro Dalcin b->col = NULL; 4809f4259b30SLisandro Dalcin b->icol = NULL; 4810b810aeb4SBarry Smith b->reallocs = 0; 481136db0b34SBarry Smith b->ignorezeroentries = PETSC_FALSE; 4812f1e2ffcdSBarry Smith b->roworiented = PETSC_TRUE; 4813416022c9SBarry Smith b->nonew = 0; 4814f4259b30SLisandro Dalcin b->diag = NULL; 4815f4259b30SLisandro Dalcin b->solve_work = NULL; 4816f4259b30SLisandro Dalcin B->spptr = NULL; 4817f4259b30SLisandro Dalcin b->saved_values = NULL; 4818f4259b30SLisandro Dalcin b->idiag = NULL; 4819f4259b30SLisandro Dalcin b->mdiag = NULL; 4820f4259b30SLisandro Dalcin b->ssor_work = NULL; 482171f1c65dSBarry Smith b->omega = 1.0; 482271f1c65dSBarry Smith b->fshift = 0.0; 482371f1c65dSBarry Smith b->idiagvalid = PETSC_FALSE; 4824bbead8a2SBarry Smith b->ibdiagvalid = PETSC_FALSE; 4825a9817697SBarry Smith b->keepnonzeropattern = PETSC_FALSE; 482617ab2063SBarry Smith 48279566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ)); 4828b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE) 48299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ)); 48309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ)); 4831b3866ffcSBarry Smith #endif 48329566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ)); 48339566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ)); 48349566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ)); 48359566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ)); 48369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ)); 48379566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM)); 48389566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL)); 48399779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 48409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL)); 4841191b95cbSRichard Tran Mills #endif 484234b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA) 48439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE)); 48449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ)); 48459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",MatProductSetFromOptions_SeqAIJ)); 484602fe1965SBarry Smith #endif 48473d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 48489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijkokkos_C",MatConvert_SeqAIJ_SeqAIJKokkos)); 48493d0639e7SStefano Zampini #endif 48509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL)); 4851af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 48529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental)); 4853af8000cdSHong Zhang #endif 4854d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 48559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK)); 4856d24d4204SJose E. Roman #endif 485763c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 48589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE)); 48599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ)); 486063c07aadSStefano Zampini #endif 48619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense)); 48629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL)); 48639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS)); 48649566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ)); 48659566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ)); 48669566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ)); 48679566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ)); 48689566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ)); 48699566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ)); 48709566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ)); 48719566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ)); 48729566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ)); 48739566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJKron_C",MatSeqAIJKron_SeqAIJ)); 48749566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSetPreallocationCOO_C",MatSetPreallocationCOO_SeqAIJ)); 48759566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSetValuesCOO_C",MatSetValuesCOO_SeqAIJ)); 48769566063dSJacob Faibussowitsch PetscCall(MatCreate_SeqAIJ_Inode(B)); 48779566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ)); 48789566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetTypeFromOptions(B)); /* this allows changing the matrix subtype to say MATSEQAIJPERM */ 48793a40ed3dSBarry Smith PetscFunctionReturn(0); 488017ab2063SBarry Smith } 488117ab2063SBarry Smith 4882b24902e0SBarry Smith /* 4883*3893b582SJunchao Zhang Given a matrix generated with MatGetFactor() duplicates all the information in A into C 4884b24902e0SBarry Smith */ 4885ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace) 488617ab2063SBarry Smith { 48872a350339SBarry Smith Mat_SeqAIJ *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data; 4888071fcb05SBarry Smith PetscInt m = A->rmap->n,i; 488917ab2063SBarry Smith 48903a40ed3dSBarry Smith PetscFunctionBegin; 4891aed4548fSBarry Smith PetscCheck(A->assembled || cpvalues == MAT_DO_NOT_COPY_VALUES,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix"); 4892273d9f13SBarry Smith 4893d5f3da31SBarry Smith C->factortype = A->factortype; 4894f4259b30SLisandro Dalcin c->row = NULL; 4895f4259b30SLisandro Dalcin c->col = NULL; 4896f4259b30SLisandro Dalcin c->icol = NULL; 48976ad4291fSHong Zhang c->reallocs = 0; 489817ab2063SBarry Smith 489969272f91SPierre Jolivet C->assembled = A->assembled; 490069272f91SPierre Jolivet C->preallocated = A->preallocated; 490117ab2063SBarry Smith 490269272f91SPierre Jolivet if (A->preallocated) { 49039566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->rmap,&C->rmap)); 49049566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->cmap,&C->cmap)); 4905eec197d1SBarry Smith 49069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m,&c->imax)); 49079566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt))); 49089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m,&c->ilen)); 49099566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt))); 49109566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt))); 491117ab2063SBarry Smith 491217ab2063SBarry Smith /* allocate the matrix space */ 4913f77e22a1SHong Zhang if (mallocmatspace) { 49149566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i)); 49159566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt))); 49162205254eSKarl Rupp 4917f1e2ffcdSBarry Smith c->singlemalloc = PETSC_TRUE; 49182205254eSKarl Rupp 49199566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->i,a->i,m+1)); 492017ab2063SBarry Smith if (m > 0) { 49219566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->j,a->j,a->i[m])); 4922be6bf707SBarry Smith if (cpvalues == MAT_COPY_VALUES) { 49232e5835c6SStefano Zampini const PetscScalar *aa; 49242e5835c6SStefano Zampini 49259566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 49269566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->a,aa,a->i[m])); 49279566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 4928be6bf707SBarry Smith } else { 49299566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->a,a->i[m])); 493017ab2063SBarry Smith } 493108480c60SBarry Smith } 4932f77e22a1SHong Zhang } 493317ab2063SBarry Smith 49346ad4291fSHong Zhang c->ignorezeroentries = a->ignorezeroentries; 4935416022c9SBarry Smith c->roworiented = a->roworiented; 4936416022c9SBarry Smith c->nonew = a->nonew; 4937416022c9SBarry Smith if (a->diag) { 49389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m+1,&c->diag)); 49399566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt))); 49409566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt))); 4941071fcb05SBarry Smith } else c->diag = NULL; 49422205254eSKarl Rupp 4943f4259b30SLisandro Dalcin c->solve_work = NULL; 4944f4259b30SLisandro Dalcin c->saved_values = NULL; 4945f4259b30SLisandro Dalcin c->idiag = NULL; 4946f4259b30SLisandro Dalcin c->ssor_work = NULL; 4947a9817697SBarry Smith c->keepnonzeropattern = a->keepnonzeropattern; 4948e6b907acSBarry Smith c->free_a = PETSC_TRUE; 4949e6b907acSBarry Smith c->free_ij = PETSC_TRUE; 49506ad4291fSHong Zhang 4951893ad86cSHong Zhang c->rmax = a->rmax; 4952416022c9SBarry Smith c->nz = a->nz; 49538ed568f8SMatthew G Knepley c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 4954754ec7b1SSatish Balay 49556ad4291fSHong Zhang c->compressedrow.use = a->compressedrow.use; 49566ad4291fSHong Zhang c->compressedrow.nrows = a->compressedrow.nrows; 4957cd6b891eSBarry Smith if (a->compressedrow.use) { 49586ad4291fSHong Zhang i = a->compressedrow.nrows; 49599566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex)); 49609566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1)); 49619566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i)); 496227ea64f8SHong Zhang } else { 496327ea64f8SHong Zhang c->compressedrow.use = PETSC_FALSE; 49640298fd71SBarry Smith c->compressedrow.i = NULL; 49650298fd71SBarry Smith c->compressedrow.rindex = NULL; 49666ad4291fSHong Zhang } 4967ea632784SBarry Smith c->nonzerorowcnt = a->nonzerorowcnt; 4968e56f5c9eSBarry Smith C->nonzerostate = A->nonzerostate; 49694846f1f5SKris Buschelman 49709566063dSJacob Faibussowitsch PetscCall(MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C)); 497169272f91SPierre Jolivet } 49729566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist)); 49733a40ed3dSBarry Smith PetscFunctionReturn(0); 497417ab2063SBarry Smith } 497517ab2063SBarry Smith 4976b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B) 4977b24902e0SBarry Smith { 4978b24902e0SBarry Smith PetscFunctionBegin; 49799566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),B)); 49809566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n)); 4981cfd3f464SBarry Smith if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) { 49829566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(*B,A,A)); 4983cfd3f464SBarry Smith } 49849566063dSJacob Faibussowitsch PetscCall(MatSetType(*B,((PetscObject)A)->type_name)); 49859566063dSJacob Faibussowitsch PetscCall(MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE)); 4986b24902e0SBarry Smith PetscFunctionReturn(0); 4987b24902e0SBarry Smith } 4988b24902e0SBarry Smith 4989112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer) 4990fbdbba38SShri Abhyankar { 499152f91c60SVaclav Hapla PetscBool isbinary, ishdf5; 499252f91c60SVaclav Hapla 499352f91c60SVaclav Hapla PetscFunctionBegin; 499452f91c60SVaclav Hapla PetscValidHeaderSpecific(newMat,MAT_CLASSID,1); 499552f91c60SVaclav Hapla PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 4996c27b3999SVaclav Hapla /* force binary viewer to load .info file if it has not yet done so */ 49979566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 49989566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary)); 49999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5, &ishdf5)); 500052f91c60SVaclav Hapla if (isbinary) { 50019566063dSJacob Faibussowitsch PetscCall(MatLoad_SeqAIJ_Binary(newMat,viewer)); 500252f91c60SVaclav Hapla } else if (ishdf5) { 500352f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5) 50049566063dSJacob Faibussowitsch PetscCall(MatLoad_AIJ_HDF5(newMat,viewer)); 500552f91c60SVaclav Hapla #else 500652f91c60SVaclav Hapla SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 500752f91c60SVaclav Hapla #endif 500852f91c60SVaclav Hapla } else { 500998921bdaSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"Viewer type %s not yet supported for reading %s matrices",((PetscObject)viewer)->type_name,((PetscObject)newMat)->type_name); 501052f91c60SVaclav Hapla } 501152f91c60SVaclav Hapla PetscFunctionReturn(0); 501252f91c60SVaclav Hapla } 501352f91c60SVaclav Hapla 50143ea6fe3dSLisandro Dalcin PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer) 501552f91c60SVaclav Hapla { 50163ea6fe3dSLisandro Dalcin Mat_SeqAIJ *a = (Mat_SeqAIJ*)mat->data; 50173ea6fe3dSLisandro Dalcin PetscInt header[4],*rowlens,M,N,nz,sum,rows,cols,i; 5018fbdbba38SShri Abhyankar 5019fbdbba38SShri Abhyankar PetscFunctionBegin; 50209566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 5021bbead8a2SBarry Smith 50223ea6fe3dSLisandro Dalcin /* read in matrix header */ 50239566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT)); 502408401ef6SPierre Jolivet PetscCheck(header[0] == MAT_FILE_CLASSID,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file"); 5025fbdbba38SShri Abhyankar M = header[1]; N = header[2]; nz = header[3]; 502608401ef6SPierre Jolivet PetscCheck(M >= 0,PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%" PetscInt_FMT ") in file is negative",M); 502708401ef6SPierre Jolivet PetscCheck(N >= 0,PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%" PetscInt_FMT ") in file is negative",N); 502808401ef6SPierre Jolivet PetscCheck(nz >= 0,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ"); 5029fbdbba38SShri Abhyankar 50303ea6fe3dSLisandro Dalcin /* set block sizes from the viewer's .info file */ 50319566063dSJacob Faibussowitsch PetscCall(MatLoad_Binary_BlockSizes(mat,viewer)); 50323ea6fe3dSLisandro Dalcin /* set local and global sizes if not set already */ 50333ea6fe3dSLisandro Dalcin if (mat->rmap->n < 0) mat->rmap->n = M; 50343ea6fe3dSLisandro Dalcin if (mat->cmap->n < 0) mat->cmap->n = N; 50353ea6fe3dSLisandro Dalcin if (mat->rmap->N < 0) mat->rmap->N = M; 50363ea6fe3dSLisandro Dalcin if (mat->cmap->N < 0) mat->cmap->N = N; 50379566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->rmap)); 50389566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->cmap)); 50393ea6fe3dSLisandro Dalcin 50403ea6fe3dSLisandro Dalcin /* check if the matrix sizes are correct */ 50419566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat,&rows,&cols)); 5042aed4548fSBarry Smith PetscCheck(M == rows && N == cols,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different sizes (%" PetscInt_FMT ", %" PetscInt_FMT ") than the input matrix (%" PetscInt_FMT ", %" PetscInt_FMT ")",M,N,rows,cols); 50433ea6fe3dSLisandro Dalcin 5044fbdbba38SShri Abhyankar /* read in row lengths */ 50459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(M,&rowlens)); 50469566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT)); 50473ea6fe3dSLisandro Dalcin /* check if sum(rowlens) is same as nz */ 50483ea6fe3dSLisandro Dalcin sum = 0; for (i=0; i<M; i++) sum += rowlens[i]; 504908401ef6SPierre Jolivet PetscCheck(sum == nz,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Inconsistent matrix data in file: nonzeros = %" PetscInt_FMT ", sum-row-lengths = %" PetscInt_FMT,nz,sum); 50503ea6fe3dSLisandro Dalcin /* preallocate and check sizes */ 50519566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens)); 50529566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat,&rows,&cols)); 5053aed4548fSBarry Smith PetscCheck(M == rows && N == cols,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different length (%" PetscInt_FMT ", %" PetscInt_FMT ") than the input matrix (%" PetscInt_FMT ", %" PetscInt_FMT ")",M,N,rows,cols); 50543ea6fe3dSLisandro Dalcin /* store row lengths */ 50559566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->ilen,rowlens,M)); 50569566063dSJacob Faibussowitsch PetscCall(PetscFree(rowlens)); 5057fbdbba38SShri Abhyankar 50583ea6fe3dSLisandro Dalcin /* fill in "i" row pointers */ 50593ea6fe3dSLisandro Dalcin a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i]; 50603ea6fe3dSLisandro Dalcin /* read in "j" column indices */ 50619566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT)); 50623ea6fe3dSLisandro Dalcin /* read in "a" nonzero values */ 50639566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR)); 5064fbdbba38SShri Abhyankar 50659566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY)); 50669566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY)); 5067fbdbba38SShri Abhyankar PetscFunctionReturn(0); 5068fbdbba38SShri Abhyankar } 5069fbdbba38SShri Abhyankar 5070ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg) 50717264ac53SSatish Balay { 50727264ac53SSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data; 5073fff043a9SJunchao Zhang const PetscScalar *aa,*ba; 5074eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX) 5075eeffb40dSHong Zhang PetscInt k; 5076eeffb40dSHong Zhang #endif 50777264ac53SSatish Balay 50783a40ed3dSBarry Smith PetscFunctionBegin; 5079bfeeae90SHong Zhang /* If the matrix dimensions are not equal,or no of nonzeros */ 5080d0f46423SBarry Smith if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) { 5081ca44d042SBarry Smith *flg = PETSC_FALSE; 5082ca44d042SBarry Smith PetscFunctionReturn(0); 5083bcd2baecSBarry Smith } 50847264ac53SSatish Balay 50857264ac53SSatish Balay /* if the a->i are the same */ 50869566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(a->i,b->i,A->rmap->n+1,flg)); 5087abc0a331SBarry Smith if (!*flg) PetscFunctionReturn(0); 50887264ac53SSatish Balay 50897264ac53SSatish Balay /* if a->j are the same */ 50909566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(a->j,b->j,a->nz,flg)); 5091abc0a331SBarry Smith if (!*flg) PetscFunctionReturn(0); 5092bcd2baecSBarry Smith 50939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 50949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B,&ba)); 5095bcd2baecSBarry Smith /* if a->a are the same */ 5096eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX) 5097eeffb40dSHong Zhang for (k=0; k<a->nz; k++) { 5098fff043a9SJunchao Zhang if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) { 5099eeffb40dSHong Zhang *flg = PETSC_FALSE; 51003a40ed3dSBarry Smith PetscFunctionReturn(0); 5101eeffb40dSHong Zhang } 5102eeffb40dSHong Zhang } 5103eeffb40dSHong Zhang #else 51049566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(aa,ba,a->nz,flg)); 5105eeffb40dSHong Zhang #endif 51069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 51079566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B,&ba)); 5108eeffb40dSHong Zhang PetscFunctionReturn(0); 51097264ac53SSatish Balay } 511036db0b34SBarry Smith 511105869f15SSatish Balay /*@ 511236db0b34SBarry Smith MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format) 511336db0b34SBarry Smith provided by the user. 511436db0b34SBarry Smith 5115d083f849SBarry Smith Collective 511636db0b34SBarry Smith 511736db0b34SBarry Smith Input Parameters: 511836db0b34SBarry Smith + comm - must be an MPI communicator of size 1 511936db0b34SBarry Smith . m - number of rows 512036db0b34SBarry Smith . n - number of columns 5121483a2f95SBarry Smith . i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix 512236db0b34SBarry Smith . j - column indices 512336db0b34SBarry Smith - a - matrix values 512436db0b34SBarry Smith 512536db0b34SBarry Smith Output Parameter: 512636db0b34SBarry Smith . mat - the matrix 512736db0b34SBarry Smith 512836db0b34SBarry Smith Level: intermediate 512936db0b34SBarry Smith 513036db0b34SBarry Smith Notes: 51310551d7c0SBarry Smith The i, j, and a arrays are not copied by this routine, the user must free these arrays 5132292fb18eSBarry Smith once the matrix is destroyed and not before 513336db0b34SBarry Smith 513436db0b34SBarry Smith You cannot set new nonzero locations into this matrix, that will generate an error. 513536db0b34SBarry Smith 5136bfeeae90SHong Zhang The i and j indices are 0 based 513736db0b34SBarry Smith 5138a4552177SSatish Balay The format which is used for the sparse matrix input, is equivalent to a 5139a4552177SSatish Balay row-major ordering.. i.e for the following matrix, the input data expected is 51408eef79e4SBarry Smith as shown 5141a4552177SSatish Balay 51428eef79e4SBarry Smith $ 1 0 0 51438eef79e4SBarry Smith $ 2 0 3 51448eef79e4SBarry Smith $ 4 5 6 51458eef79e4SBarry Smith $ 51468eef79e4SBarry Smith $ i = {0,1,3,6} [size = nrow+1 = 3+1] 51478eef79e4SBarry Smith $ j = {0,0,2,0,1,2} [size = 6]; values must be sorted for each row 51488eef79e4SBarry Smith $ v = {1,2,3,4,5,6} [size = 6] 5149a4552177SSatish Balay 5150db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateMPIAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()` 515136db0b34SBarry Smith 515236db0b34SBarry Smith @*/ 5153c3c607ccSBarry Smith PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat) 515436db0b34SBarry Smith { 5155cbcfb4deSHong Zhang PetscInt ii; 515636db0b34SBarry Smith Mat_SeqAIJ *aij; 5157cbcfb4deSHong Zhang PetscInt jj; 515836db0b34SBarry Smith 515936db0b34SBarry Smith PetscFunctionBegin; 5160aed4548fSBarry Smith PetscCheck(m <= 0 || i[0] == 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 51619566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,mat)); 51629566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat,m,n,m,n)); 51639566063dSJacob Faibussowitsch /* PetscCall(MatSetBlockSizes(*mat,,)); */ 51649566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat,MATSEQAIJ)); 51659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL)); 5166ab93d7beSBarry Smith aij = (Mat_SeqAIJ*)(*mat)->data; 51679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m,&aij->imax)); 51689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m,&aij->ilen)); 5169ab93d7beSBarry Smith 517036db0b34SBarry Smith aij->i = i; 517136db0b34SBarry Smith aij->j = j; 517236db0b34SBarry Smith aij->a = a; 517336db0b34SBarry Smith aij->singlemalloc = PETSC_FALSE; 517436db0b34SBarry Smith aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 5175e6b907acSBarry Smith aij->free_a = PETSC_FALSE; 5176e6b907acSBarry Smith aij->free_ij = PETSC_FALSE; 517736db0b34SBarry Smith 5178cbc6b225SStefano Zampini for (ii=0,aij->nonzerorowcnt=0,aij->rmax=0; ii<m; ii++) { 517936db0b34SBarry Smith aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii]; 518076bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 5181aed4548fSBarry Smith PetscCheck(i[ii+1] - i[ii] >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row length in i (row indices) row = %" PetscInt_FMT " length = %" PetscInt_FMT,ii,i[ii+1] - i[ii]); 51829985e31cSBarry Smith for (jj=i[ii]+1; jj<i[ii+1]; jj++) { 518308401ef6SPierre Jolivet PetscCheck(j[jj] >= j[jj-1],PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %" PetscInt_FMT " (actual column %" PetscInt_FMT ") in row %" PetscInt_FMT " is not sorted",jj-i[ii],j[jj],ii); 518408401ef6SPierre Jolivet PetscCheck(j[jj] != j[jj-1],PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %" PetscInt_FMT " (actual column %" PetscInt_FMT ") in row %" PetscInt_FMT " is identical to previous entry",jj-i[ii],j[jj],ii); 51859985e31cSBarry Smith } 518636db0b34SBarry Smith } 518776bd3646SJed Brown } 518876bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 518936db0b34SBarry Smith for (ii=0; ii<aij->i[m]; ii++) { 519008401ef6SPierre Jolivet PetscCheck(j[ii] >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %" PetscInt_FMT " index = %" PetscInt_FMT,ii,j[ii]); 5191aed4548fSBarry Smith PetscCheck(j[ii] <= n - 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %" PetscInt_FMT " index = %" PetscInt_FMT,ii,j[ii]); 519236db0b34SBarry Smith } 519376bd3646SJed Brown } 519436db0b34SBarry Smith 51959566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY)); 51969566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY)); 519736db0b34SBarry Smith PetscFunctionReturn(0); 519836db0b34SBarry Smith } 5199cbc6b225SStefano Zampini 5200f62e3866SBarry Smith /*@ 5201d021a1c5SVictor Minden MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format) 52028a0b0e6bSVictor Minden provided by the user. 52038a0b0e6bSVictor Minden 5204d083f849SBarry Smith Collective 52058a0b0e6bSVictor Minden 52068a0b0e6bSVictor Minden Input Parameters: 52078a0b0e6bSVictor Minden + comm - must be an MPI communicator of size 1 52088a0b0e6bSVictor Minden . m - number of rows 52098a0b0e6bSVictor Minden . n - number of columns 52108a0b0e6bSVictor Minden . i - row indices 52118a0b0e6bSVictor Minden . j - column indices 52121230e6d1SVictor Minden . a - matrix values 52131230e6d1SVictor Minden . nz - number of nonzeros 5214f62e3866SBarry Smith - idx - if the i and j indices start with 1 use PETSC_TRUE otherwise use PETSC_FALSE 52158a0b0e6bSVictor Minden 52168a0b0e6bSVictor Minden Output Parameter: 52178a0b0e6bSVictor Minden . mat - the matrix 52188a0b0e6bSVictor Minden 52198a0b0e6bSVictor Minden Level: intermediate 52208a0b0e6bSVictor Minden 5221f62e3866SBarry Smith Example: 5222f62e3866SBarry Smith For the following matrix, the input data expected is as shown (using 0 based indexing) 52239e99939fSJunchao Zhang .vb 52248a0b0e6bSVictor Minden 1 0 0 52258a0b0e6bSVictor Minden 2 0 3 52268a0b0e6bSVictor Minden 4 5 6 52278a0b0e6bSVictor Minden 52288a0b0e6bSVictor Minden i = {0,1,1,2,2,2} 52298a0b0e6bSVictor Minden j = {0,0,2,0,1,2} 52308a0b0e6bSVictor Minden v = {1,2,3,4,5,6} 52319e99939fSJunchao Zhang .ve 52328a0b0e6bSVictor Minden 5233db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateSeqAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()`, `MatSetValuesCOO()` 52348a0b0e6bSVictor Minden 52358a0b0e6bSVictor Minden @*/ 5236c3c607ccSBarry Smith PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx) 52378a0b0e6bSVictor Minden { 5238d021a1c5SVictor Minden PetscInt ii, *nnz, one = 1,row,col; 52398a0b0e6bSVictor Minden 52408a0b0e6bSVictor Minden PetscFunctionBegin; 52419566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m,&nnz)); 52421230e6d1SVictor Minden for (ii = 0; ii < nz; ii++) { 5243c8d679ebSHong Zhang nnz[i[ii] - !!idx] += 1; 52441230e6d1SVictor Minden } 52459566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,mat)); 52469566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat,m,n,m,n)); 52479566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat,MATSEQAIJ)); 52489566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz)); 52491230e6d1SVictor Minden for (ii = 0; ii < nz; ii++) { 52501230e6d1SVictor Minden if (idx) { 52511230e6d1SVictor Minden row = i[ii] - 1; 52521230e6d1SVictor Minden col = j[ii] - 1; 52531230e6d1SVictor Minden } else { 52541230e6d1SVictor Minden row = i[ii]; 52551230e6d1SVictor Minden col = j[ii]; 52568a0b0e6bSVictor Minden } 52579566063dSJacob Faibussowitsch PetscCall(MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES)); 52588a0b0e6bSVictor Minden } 52599566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY)); 52609566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY)); 52619566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 52628a0b0e6bSVictor Minden PetscFunctionReturn(0); 52638a0b0e6bSVictor Minden } 526436db0b34SBarry Smith 5265acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A) 5266acf2f550SJed Brown { 5267acf2f550SJed Brown Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data; 5268acf2f550SJed Brown 5269acf2f550SJed Brown PetscFunctionBegin; 5270acf2f550SJed Brown a->idiagvalid = PETSC_FALSE; 5271acf2f550SJed Brown a->ibdiagvalid = PETSC_FALSE; 52722205254eSKarl Rupp 52739566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal_Inode(A)); 5274acf2f550SJed Brown PetscFunctionReturn(0); 5275acf2f550SJed Brown } 5276acf2f550SJed Brown 52779c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat) 52789c8f2541SHong Zhang { 52798761c3d6SHong Zhang PetscMPIInt size; 52809c8f2541SHong Zhang 52819c8f2541SHong Zhang PetscFunctionBegin; 52829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm,&size)); 52837bbdc51dSHong Zhang if (size == 1) { 52847bbdc51dSHong Zhang if (scall == MAT_INITIAL_MATRIX) { 52859566063dSJacob Faibussowitsch PetscCall(MatDuplicate(inmat,MAT_COPY_VALUES,outmat)); 52867bbdc51dSHong Zhang } else { 52879566063dSJacob Faibussowitsch PetscCall(MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN)); 52887bbdc51dSHong Zhang } 52898761c3d6SHong Zhang } else { 52909566063dSJacob Faibussowitsch PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat)); 52918761c3d6SHong Zhang } 52929c8f2541SHong Zhang PetscFunctionReturn(0); 52939c8f2541SHong Zhang } 52949c8f2541SHong Zhang 529581824310SBarry Smith /* 529653dd7562SDmitry Karpeev Permute A into C's *local* index space using rowemb,colemb. 529753dd7562SDmitry Karpeev The embedding are supposed to be injections and the above implies that the range of rowemb is a subset 529853dd7562SDmitry Karpeev of [0,m), colemb is in [0,n). 529953dd7562SDmitry Karpeev If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A. 530053dd7562SDmitry Karpeev */ 530153dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B) 530253dd7562SDmitry Karpeev { 530353dd7562SDmitry Karpeev /* If making this function public, change the error returned in this function away from _PLIB. */ 530453dd7562SDmitry Karpeev Mat_SeqAIJ *Baij; 530553dd7562SDmitry Karpeev PetscBool seqaij; 530653dd7562SDmitry Karpeev PetscInt m,n,*nz,i,j,count; 530753dd7562SDmitry Karpeev PetscScalar v; 530853dd7562SDmitry Karpeev const PetscInt *rowindices,*colindices; 530953dd7562SDmitry Karpeev 531053dd7562SDmitry Karpeev PetscFunctionBegin; 531153dd7562SDmitry Karpeev if (!B) PetscFunctionReturn(0); 531253dd7562SDmitry Karpeev /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */ 53139566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij)); 531428b400f6SJacob Faibussowitsch PetscCheck(seqaij,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type"); 531553dd7562SDmitry Karpeev if (rowemb) { 53169566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rowemb,&m)); 531708401ef6SPierre Jolivet PetscCheck(m == B->rmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Row IS of size %" PetscInt_FMT " is incompatible with matrix row size %" PetscInt_FMT,m,B->rmap->n); 531853dd7562SDmitry Karpeev } else { 531908401ef6SPierre Jolivet PetscCheck(C->rmap->n == B->rmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix"); 532053dd7562SDmitry Karpeev } 532153dd7562SDmitry Karpeev if (colemb) { 53229566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(colemb,&n)); 532308401ef6SPierre Jolivet PetscCheck(n == B->cmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Diag col IS of size %" PetscInt_FMT " is incompatible with input matrix col size %" PetscInt_FMT,n,B->cmap->n); 532453dd7562SDmitry Karpeev } else { 532508401ef6SPierre Jolivet PetscCheck(C->cmap->n == B->cmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix"); 532653dd7562SDmitry Karpeev } 532753dd7562SDmitry Karpeev 532853dd7562SDmitry Karpeev Baij = (Mat_SeqAIJ*)(B->data); 532953dd7562SDmitry Karpeev if (pattern == DIFFERENT_NONZERO_PATTERN) { 53309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n,&nz)); 533153dd7562SDmitry Karpeev for (i=0; i<B->rmap->n; i++) { 533253dd7562SDmitry Karpeev nz[i] = Baij->i[i+1] - Baij->i[i]; 533353dd7562SDmitry Karpeev } 53349566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(C,0,nz)); 53359566063dSJacob Faibussowitsch PetscCall(PetscFree(nz)); 533653dd7562SDmitry Karpeev } 533753dd7562SDmitry Karpeev if (pattern == SUBSET_NONZERO_PATTERN) { 53389566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(C)); 533953dd7562SDmitry Karpeev } 534053dd7562SDmitry Karpeev count = 0; 534153dd7562SDmitry Karpeev rowindices = NULL; 534253dd7562SDmitry Karpeev colindices = NULL; 534353dd7562SDmitry Karpeev if (rowemb) { 53449566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rowemb,&rowindices)); 534553dd7562SDmitry Karpeev } 534653dd7562SDmitry Karpeev if (colemb) { 53479566063dSJacob Faibussowitsch PetscCall(ISGetIndices(colemb,&colindices)); 534853dd7562SDmitry Karpeev } 534953dd7562SDmitry Karpeev for (i=0; i<B->rmap->n; i++) { 535053dd7562SDmitry Karpeev PetscInt row; 535153dd7562SDmitry Karpeev row = i; 535253dd7562SDmitry Karpeev if (rowindices) row = rowindices[i]; 535353dd7562SDmitry Karpeev for (j=Baij->i[i]; j<Baij->i[i+1]; j++) { 535453dd7562SDmitry Karpeev PetscInt col; 535553dd7562SDmitry Karpeev col = Baij->j[count]; 535653dd7562SDmitry Karpeev if (colindices) col = colindices[col]; 535753dd7562SDmitry Karpeev v = Baij->a[count]; 53589566063dSJacob Faibussowitsch PetscCall(MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES)); 535953dd7562SDmitry Karpeev ++count; 536053dd7562SDmitry Karpeev } 536153dd7562SDmitry Karpeev } 536253dd7562SDmitry Karpeev /* FIXME: set C's nonzerostate correctly. */ 536353dd7562SDmitry Karpeev /* Assembly for C is necessary. */ 536453dd7562SDmitry Karpeev C->preallocated = PETSC_TRUE; 536553dd7562SDmitry Karpeev C->assembled = PETSC_TRUE; 536653dd7562SDmitry Karpeev C->was_assembled = PETSC_FALSE; 536753dd7562SDmitry Karpeev PetscFunctionReturn(0); 536853dd7562SDmitry Karpeev } 536953dd7562SDmitry Karpeev 53704099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL; 53714099cc6bSBarry Smith 53724099cc6bSBarry Smith /*@C 53734099cc6bSBarry Smith MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype 53744099cc6bSBarry Smith 53754099cc6bSBarry Smith Collective on Mat 53764099cc6bSBarry Smith 53774099cc6bSBarry Smith Input Parameters: 53784099cc6bSBarry Smith + mat - the matrix object 53794099cc6bSBarry Smith - matype - matrix type 53804099cc6bSBarry Smith 53814099cc6bSBarry Smith Options Database Key: 53824099cc6bSBarry Smith . -mat_seqai_type <method> - for example seqaijcrl 53834099cc6bSBarry Smith 53844099cc6bSBarry Smith Level: intermediate 53854099cc6bSBarry Smith 5386db781477SPatrick Sanan .seealso: `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`, `Mat` 53874099cc6bSBarry Smith @*/ 53884099cc6bSBarry Smith PetscErrorCode MatSeqAIJSetType(Mat mat, MatType matype) 53894099cc6bSBarry Smith { 53904099cc6bSBarry Smith PetscBool sametype; 53915f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(Mat,MatType,MatReuse,Mat*); 53924099cc6bSBarry Smith 53934099cc6bSBarry Smith PetscFunctionBegin; 53944099cc6bSBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 53959566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat,matype,&sametype)); 53964099cc6bSBarry Smith if (sametype) PetscFunctionReturn(0); 53974099cc6bSBarry Smith 53989566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(MatSeqAIJList,matype,&r)); 53995f80ce2aSJacob Faibussowitsch PetscCheck(r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype); 54009566063dSJacob Faibussowitsch PetscCall((*r)(mat,matype,MAT_INPLACE_MATRIX,&mat)); 54014099cc6bSBarry Smith PetscFunctionReturn(0); 54024099cc6bSBarry Smith } 54034099cc6bSBarry Smith 54044099cc6bSBarry Smith /*@C 54054099cc6bSBarry Smith MatSeqAIJRegister - - Adds a new sub-matrix type for sequential AIJ matrices 54064099cc6bSBarry Smith 54074099cc6bSBarry Smith Not Collective 54084099cc6bSBarry Smith 54094099cc6bSBarry Smith Input Parameters: 54104099cc6bSBarry Smith + name - name of a new user-defined matrix type, for example MATSEQAIJCRL 54114099cc6bSBarry Smith - function - routine to convert to subtype 54124099cc6bSBarry Smith 54134099cc6bSBarry Smith Notes: 54144099cc6bSBarry Smith MatSeqAIJRegister() may be called multiple times to add several user-defined solvers. 54154099cc6bSBarry Smith 54164099cc6bSBarry Smith Then, your matrix can be chosen with the procedural interface at runtime via the option 54174099cc6bSBarry Smith $ -mat_seqaij_type my_mat 54184099cc6bSBarry Smith 54194099cc6bSBarry Smith Level: advanced 54204099cc6bSBarry Smith 5421db781477SPatrick Sanan .seealso: `MatSeqAIJRegisterAll()` 54224099cc6bSBarry Smith 54234099cc6bSBarry Smith Level: advanced 54244099cc6bSBarry Smith @*/ 5425388d47a6SSatish Balay PetscErrorCode MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *)) 54264099cc6bSBarry Smith { 54274099cc6bSBarry Smith PetscFunctionBegin; 54289566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 54299566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&MatSeqAIJList,sname,function)); 54304099cc6bSBarry Smith PetscFunctionReturn(0); 54314099cc6bSBarry Smith } 54324099cc6bSBarry Smith 54334099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE; 54344099cc6bSBarry Smith 54354099cc6bSBarry Smith /*@C 54364099cc6bSBarry Smith MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ 54374099cc6bSBarry Smith 54384099cc6bSBarry Smith Not Collective 54394099cc6bSBarry Smith 54404099cc6bSBarry Smith Level: advanced 54414099cc6bSBarry Smith 5442db781477SPatrick Sanan .seealso: `MatRegisterAll()`, `MatSeqAIJRegister()` 54434099cc6bSBarry Smith @*/ 54444099cc6bSBarry Smith PetscErrorCode MatSeqAIJRegisterAll(void) 54454099cc6bSBarry Smith { 54464099cc6bSBarry Smith PetscFunctionBegin; 54474099cc6bSBarry Smith if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0); 54484099cc6bSBarry Smith MatSeqAIJRegisterAllCalled = PETSC_TRUE; 54494099cc6bSBarry Smith 54509566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJCRL, MatConvert_SeqAIJ_SeqAIJCRL)); 54519566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJPERM, MatConvert_SeqAIJ_SeqAIJPERM)); 54529566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJSELL, MatConvert_SeqAIJ_SeqAIJSELL)); 54539779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 54549566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJMKL, MatConvert_SeqAIJ_SeqAIJMKL)); 5455485f9817SRichard Tran Mills #endif 54565063d097SStefano Zampini #if defined(PETSC_HAVE_CUDA) 54579566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE)); 54585063d097SStefano Zampini #endif 54595063d097SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 54609566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJKOKKOS, MatConvert_SeqAIJ_SeqAIJKokkos)); 54615063d097SStefano Zampini #endif 54624099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA) 54639566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL)); 54644099cc6bSBarry Smith #endif 54654099cc6bSBarry Smith PetscFunctionReturn(0); 54664099cc6bSBarry Smith } 546753dd7562SDmitry Karpeev 546853dd7562SDmitry Karpeev /* 546981824310SBarry Smith Special version for direct calls from Fortran 547081824310SBarry Smith */ 5471af0996ceSBarry Smith #include <petsc/private/fortranimpl.h> 547281824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS) 547381824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ 547481824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 547581824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij 547681824310SBarry Smith #endif 547781824310SBarry Smith 547881824310SBarry Smith /* Change these macros so can be used in void function */ 547998921bdaSJacob Faibussowitsch 548098921bdaSJacob Faibussowitsch /* Change these macros so can be used in void function */ 54819566063dSJacob Faibussowitsch /* Identical to PetscCallVoid, except it assigns to *_ierr */ 54829566063dSJacob Faibussowitsch #undef PetscCall 54839566063dSJacob Faibussowitsch #define PetscCall(...) do { \ 54845f80ce2aSJacob Faibussowitsch PetscErrorCode ierr_msv_mpiaij = __VA_ARGS__; \ 548598921bdaSJacob Faibussowitsch if (PetscUnlikely(ierr_msv_mpiaij)) { \ 548698921bdaSJacob Faibussowitsch *_ierr = PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,ierr_msv_mpiaij,PETSC_ERROR_REPEAT," "); \ 548798921bdaSJacob Faibussowitsch return; \ 548898921bdaSJacob Faibussowitsch } \ 548998921bdaSJacob Faibussowitsch } while (0) 549098921bdaSJacob Faibussowitsch 549198921bdaSJacob Faibussowitsch #undef SETERRQ 549298921bdaSJacob Faibussowitsch #define SETERRQ(comm,ierr,...) do { \ 549398921bdaSJacob Faibussowitsch *_ierr = PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,ierr,PETSC_ERROR_INITIAL,__VA_ARGS__); \ 549498921bdaSJacob Faibussowitsch return; \ 549598921bdaSJacob Faibussowitsch } while (0) 549681824310SBarry Smith 549719caf8f3SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr) 549881824310SBarry Smith { 549981824310SBarry Smith Mat A = *AA; 550081824310SBarry Smith PetscInt m = *mm, n = *nn; 550181824310SBarry Smith InsertMode is = *isis; 550281824310SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 550381824310SBarry Smith PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N; 550481824310SBarry Smith PetscInt *imax,*ai,*ailen; 550581824310SBarry Smith PetscInt *aj,nonew = a->nonew,lastcol = -1; 550654f21887SBarry Smith MatScalar *ap,value,*aa; 5507ace3abfcSBarry Smith PetscBool ignorezeroentries = a->ignorezeroentries; 5508ace3abfcSBarry Smith PetscBool roworiented = a->roworiented; 550981824310SBarry Smith 551081824310SBarry Smith PetscFunctionBegin; 55114994cf47SJed Brown MatCheckPreallocated(A,1); 551281824310SBarry Smith imax = a->imax; 551381824310SBarry Smith ai = a->i; 551481824310SBarry Smith ailen = a->ilen; 551581824310SBarry Smith aj = a->j; 551681824310SBarry Smith aa = a->a; 551781824310SBarry Smith 551881824310SBarry Smith for (k=0; k<m; k++) { /* loop over added rows */ 551981824310SBarry Smith row = im[k]; 552081824310SBarry Smith if (row < 0) continue; 55215f80ce2aSJacob Faibussowitsch PetscCheck(row < A->rmap->n,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large"); 552281824310SBarry Smith rp = aj + ai[row]; ap = aa + ai[row]; 552381824310SBarry Smith rmax = imax[row]; nrow = ailen[row]; 552481824310SBarry Smith low = 0; 552581824310SBarry Smith high = nrow; 552681824310SBarry Smith for (l=0; l<n; l++) { /* loop over added columns */ 552781824310SBarry Smith if (in[l] < 0) continue; 55285f80ce2aSJacob Faibussowitsch PetscCheck(in[l] < A->cmap->n,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large"); 552981824310SBarry Smith col = in[l]; 55302205254eSKarl Rupp if (roworiented) value = v[l + k*n]; 55312205254eSKarl Rupp else value = v[k + l*m]; 55322205254eSKarl Rupp 553381824310SBarry Smith if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue; 553481824310SBarry Smith 55352205254eSKarl Rupp if (col <= lastcol) low = 0; 55362205254eSKarl Rupp else high = nrow; 553781824310SBarry Smith lastcol = col; 553881824310SBarry Smith while (high-low > 5) { 553981824310SBarry Smith t = (low+high)/2; 554081824310SBarry Smith if (rp[t] > col) high = t; 554181824310SBarry Smith else low = t; 554281824310SBarry Smith } 554381824310SBarry Smith for (i=low; i<high; i++) { 554481824310SBarry Smith if (rp[i] > col) break; 554581824310SBarry Smith if (rp[i] == col) { 554681824310SBarry Smith if (is == ADD_VALUES) ap[i] += value; 554781824310SBarry Smith else ap[i] = value; 554881824310SBarry Smith goto noinsert; 554981824310SBarry Smith } 555081824310SBarry Smith } 555181824310SBarry Smith if (value == 0.0 && ignorezeroentries) goto noinsert; 555281824310SBarry Smith if (nonew == 1) goto noinsert; 55535f80ce2aSJacob Faibussowitsch PetscCheck(nonew != -1,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix"); 5554fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar); 555581824310SBarry Smith N = nrow++ - 1; a->nz++; high++; 555681824310SBarry Smith /* shift up all the later entries in this row */ 555781824310SBarry Smith for (ii=N; ii>=i; ii--) { 555881824310SBarry Smith rp[ii+1] = rp[ii]; 555981824310SBarry Smith ap[ii+1] = ap[ii]; 556081824310SBarry Smith } 556181824310SBarry Smith rp[i] = col; 556281824310SBarry Smith ap[i] = value; 5563e56f5c9eSBarry Smith A->nonzerostate++; 556481824310SBarry Smith noinsert:; 556581824310SBarry Smith low = i + 1; 556681824310SBarry Smith } 556781824310SBarry Smith ailen[row] = nrow; 556881824310SBarry Smith } 556981824310SBarry Smith PetscFunctionReturnVoid(); 557081824310SBarry Smith } 557198921bdaSJacob Faibussowitsch /* Undefining these here since they were redefined from their original definition above! No 557298921bdaSJacob Faibussowitsch * other PETSc functions should be defined past this point, as it is impossible to recover the 557398921bdaSJacob Faibussowitsch * original definitions */ 55749566063dSJacob Faibussowitsch #undef PetscCall 557598921bdaSJacob Faibussowitsch #undef SETERRQ 5576