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)); 1096c45a1595SBarry Smith if (iascii) { 10979566063dSJacob Faibussowitsch PetscCall(MatView_SeqAIJ_ASCII(A,viewer)); 10980f5bd95cSBarry Smith } else if (isbinary) { 10999566063dSJacob Faibussowitsch PetscCall(MatView_SeqAIJ_Binary(A,viewer)); 11000f5bd95cSBarry Smith } else if (isdraw) { 11019566063dSJacob Faibussowitsch PetscCall(MatView_SeqAIJ_Draw(A,viewer)); 110211aeaf0aSBarry Smith } 11039566063dSJacob Faibussowitsch PetscCall(MatView_SeqAIJ_Inode(A,viewer)); 11043a40ed3dSBarry Smith PetscFunctionReturn(0); 110517ab2063SBarry Smith } 110619bcc07fSBarry Smith 1107dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode) 110817ab2063SBarry Smith { 1109416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1110580bdb30SBarry Smith PetscInt fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax; 1111d0f46423SBarry Smith PetscInt m = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0; 111254f21887SBarry Smith MatScalar *aa = a->a,*ap; 11133447b6efSHong Zhang PetscReal ratio = 0.6; 111417ab2063SBarry Smith 11153a40ed3dSBarry Smith PetscFunctionBegin; 11163a40ed3dSBarry Smith if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0); 11179566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 1118b215bc84SStefano Zampini if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) { 1119b215bc84SStefano Zampini /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */ 11209566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A,mode)); 1121b215bc84SStefano Zampini PetscFunctionReturn(0); 1122b215bc84SStefano Zampini } 112317ab2063SBarry Smith 112443ee02c3SBarry Smith if (m) rmax = ailen[0]; /* determine row with most nonzeros */ 112517ab2063SBarry Smith for (i=1; i<m; i++) { 1126416022c9SBarry Smith /* move each row back by the amount of empty slots (fshift) before it*/ 112717ab2063SBarry Smith fshift += imax[i-1] - ailen[i-1]; 112894a9d846SBarry Smith rmax = PetscMax(rmax,ailen[i]); 112917ab2063SBarry Smith if (fshift) { 1130bfeeae90SHong Zhang ip = aj + ai[i]; 1131bfeeae90SHong Zhang ap = aa + ai[i]; 113217ab2063SBarry Smith N = ailen[i]; 11339566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ip-fshift,ip,N)); 1134580bdb30SBarry Smith if (!A->structure_only) { 11359566063dSJacob Faibussowitsch PetscCall(PetscArraymove(ap-fshift,ap,N)); 113617ab2063SBarry Smith } 113717ab2063SBarry Smith } 113817ab2063SBarry Smith ai[i] = ai[i-1] + ailen[i-1]; 113917ab2063SBarry Smith } 114017ab2063SBarry Smith if (m) { 114117ab2063SBarry Smith fshift += imax[m-1] - ailen[m-1]; 114217ab2063SBarry Smith ai[m] = ai[m-1] + ailen[m-1]; 114317ab2063SBarry Smith } 11447b083b7cSBarry Smith 114517ab2063SBarry Smith /* reset ilen and imax for each row */ 11467b083b7cSBarry Smith a->nonzerorowcnt = 0; 1147396832f4SHong Zhang if (A->structure_only) { 11489566063dSJacob Faibussowitsch PetscCall(PetscFree(a->imax)); 11499566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ilen)); 1150396832f4SHong Zhang } else { /* !A->structure_only */ 115117ab2063SBarry Smith for (i=0; i<m; i++) { 115217ab2063SBarry Smith ailen[i] = imax[i] = ai[i+1] - ai[i]; 11537b083b7cSBarry Smith a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0); 115417ab2063SBarry Smith } 1155396832f4SHong Zhang } 1156bfeeae90SHong Zhang a->nz = ai[m]; 1157aed4548fSBarry 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); 115817ab2063SBarry Smith 11599566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 11609566063dSJacob 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)); 11619566063dSJacob Faibussowitsch PetscCall(PetscInfo(A,"Number of mallocs during MatSetValues() is %" PetscInt_FMT "\n",a->reallocs)); 11629566063dSJacob Faibussowitsch PetscCall(PetscInfo(A,"Maximum nonzeros in any row is %" PetscInt_FMT "\n",rmax)); 11632205254eSKarl Rupp 11648e58a170SBarry Smith A->info.mallocs += a->reallocs; 1165dd5f02e7SSatish Balay a->reallocs = 0; 11666712e2f1SBarry Smith A->info.nz_unneeded = (PetscReal)fshift; 116736db0b34SBarry Smith a->rmax = rmax; 11684e220ebcSLois Curfman McInnes 1169396832f4SHong Zhang if (!A->structure_only) { 11709566063dSJacob Faibussowitsch PetscCall(MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio)); 1171396832f4SHong Zhang } 11729566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd_SeqAIJ_Inode(A,mode)); 11733a40ed3dSBarry Smith PetscFunctionReturn(0); 117417ab2063SBarry Smith } 117517ab2063SBarry Smith 117699cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A) 117799cafbc1SBarry Smith { 117899cafbc1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 117999cafbc1SBarry Smith PetscInt i,nz = a->nz; 11802e5835c6SStefano Zampini MatScalar *aa; 118199cafbc1SBarry Smith 118299cafbc1SBarry Smith PetscFunctionBegin; 11839566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&aa)); 118499cafbc1SBarry Smith for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]); 11859566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&aa)); 11869566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 118799cafbc1SBarry Smith PetscFunctionReturn(0); 118899cafbc1SBarry Smith } 118999cafbc1SBarry Smith 119099cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A) 119199cafbc1SBarry Smith { 119299cafbc1SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 119399cafbc1SBarry Smith PetscInt i,nz = a->nz; 11942e5835c6SStefano Zampini MatScalar *aa; 119599cafbc1SBarry Smith 119699cafbc1SBarry Smith PetscFunctionBegin; 11979566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&aa)); 119899cafbc1SBarry Smith for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]); 11999566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&aa)); 12009566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 120199cafbc1SBarry Smith PetscFunctionReturn(0); 120299cafbc1SBarry Smith } 120399cafbc1SBarry Smith 1204dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A) 120517ab2063SBarry Smith { 1206fff043a9SJunchao Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1207fff043a9SJunchao Zhang MatScalar *aa; 12083a40ed3dSBarry Smith 12093a40ed3dSBarry Smith PetscFunctionBegin; 12109566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayWrite(A,&aa)); 12119566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(aa,a->i[A->rmap->n])); 12129566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayWrite(A,&aa)); 12139566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 12143a40ed3dSBarry Smith PetscFunctionReturn(0); 121517ab2063SBarry Smith } 1216416022c9SBarry Smith 1217cbc6b225SStefano Zampini PETSC_INTERN PetscErrorCode MatResetPreallocationCOO_SeqAIJ(Mat A) 1218cbc6b225SStefano Zampini { 1219cbc6b225SStefano Zampini Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1220cbc6b225SStefano Zampini 1221cbc6b225SStefano Zampini PetscFunctionBegin; 12229566063dSJacob Faibussowitsch PetscCall(PetscFree(a->perm)); 12239566063dSJacob Faibussowitsch PetscCall(PetscFree(a->jmap)); 1224cbc6b225SStefano Zampini PetscFunctionReturn(0); 1225cbc6b225SStefano Zampini } 1226cbc6b225SStefano Zampini 1227dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A) 122817ab2063SBarry Smith { 1229416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1230d5d45c9bSBarry Smith 12313a40ed3dSBarry Smith PetscFunctionBegin; 1232aa482453SBarry Smith #if defined(PETSC_USE_LOG) 1233c0aa6a63SJacob Faibussowitsch PetscLogObjectState((PetscObject)A,"Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT ", NZ=%" PetscInt_FMT,A->rmap->n,A->cmap->n,a->nz); 123417ab2063SBarry Smith #endif 12359566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i)); 12369566063dSJacob Faibussowitsch PetscCall(MatResetPreallocationCOO_SeqAIJ(A)); 12379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 12389566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 12399566063dSJacob Faibussowitsch PetscCall(PetscFree(a->diag)); 12409566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ibdiag)); 12419566063dSJacob Faibussowitsch PetscCall(PetscFree(a->imax)); 12429566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ilen)); 12439566063dSJacob Faibussowitsch PetscCall(PetscFree(a->ipre)); 12449566063dSJacob Faibussowitsch PetscCall(PetscFree3(a->idiag,a->mdiag,a->ssor_work)); 12459566063dSJacob Faibussowitsch PetscCall(PetscFree(a->solve_work)); 12469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->icol)); 12479566063dSJacob Faibussowitsch PetscCall(PetscFree(a->saved_values)); 12489566063dSJacob Faibussowitsch PetscCall(PetscFree2(a->compressedrow.i,a->compressedrow.rindex)); 12499566063dSJacob Faibussowitsch PetscCall(MatDestroy_SeqAIJ_Inode(A)); 12509566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 1251901853e0SKris Buschelman 12526718818eSStefano Zampini /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this. 12536718818eSStefano Zampini That function is so heavily used (sometimes in an hidden way through multnumeric function pointers) 12546718818eSStefano Zampini that is hard to properly add this data to the MatProduct data. We free it here to avoid 12556718818eSStefano Zampini users reusing the matrix object with different data to incur in obscure segmentation faults 12566718818eSStefano Zampini due to different matrix sizes */ 12579566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A,"__PETSc__ab_dense",NULL)); 12586718818eSStefano Zampini 12599566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A,NULL)); 12609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL)); 12619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL)); 12629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL)); 12639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL)); 12649566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL)); 12659566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL)); 12664222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA) 12679566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcusparse_C",NULL)); 12689566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",NULL)); 12699566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",NULL)); 12704222ddf1SHong Zhang #endif 12713d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 12729566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijkokkos_C",NULL)); 12733d0639e7SStefano Zampini #endif 12749566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcrl_C",NULL)); 1275af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 12769566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL)); 1277af8000cdSHong Zhang #endif 1278d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 12799566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_scalapack_C",NULL)); 1280d24d4204SJose E. Roman #endif 128163c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 12829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL)); 12839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",NULL)); 128463c07aadSStefano Zampini #endif 12859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL)); 12869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL)); 12879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL)); 12889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL)); 12899566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL)); 12909566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL)); 12919566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL)); 12929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL)); 12939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_is_seqaij_C",NULL)); 12949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqdense_seqaij_C",NULL)); 12959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaij_C",NULL)); 12969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJKron_C",NULL)); 12979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",NULL)); 12989566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",NULL)); 12993a40ed3dSBarry Smith PetscFunctionReturn(0); 130017ab2063SBarry Smith } 130117ab2063SBarry Smith 1302ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg) 130317ab2063SBarry Smith { 1304416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 13053a40ed3dSBarry Smith 13063a40ed3dSBarry Smith PetscFunctionBegin; 1307a65d3064SKris Buschelman switch (op) { 1308a65d3064SKris Buschelman case MAT_ROW_ORIENTED: 13094e0d8c25SBarry Smith a->roworiented = flg; 1310a65d3064SKris Buschelman break; 1311a9817697SBarry Smith case MAT_KEEP_NONZERO_PATTERN: 1312a9817697SBarry Smith a->keepnonzeropattern = flg; 1313a65d3064SKris Buschelman break; 1314512a5fc5SBarry Smith case MAT_NEW_NONZERO_LOCATIONS: 1315512a5fc5SBarry Smith a->nonew = (flg ? 0 : 1); 1316a65d3064SKris Buschelman break; 1317a65d3064SKris Buschelman case MAT_NEW_NONZERO_LOCATION_ERR: 13184e0d8c25SBarry Smith a->nonew = (flg ? -1 : 0); 1319a65d3064SKris Buschelman break; 1320a65d3064SKris Buschelman case MAT_NEW_NONZERO_ALLOCATION_ERR: 13214e0d8c25SBarry Smith a->nonew = (flg ? -2 : 0); 1322a65d3064SKris Buschelman break; 132328b2fa4aSMatthew Knepley case MAT_UNUSED_NONZERO_LOCATION_ERR: 132428b2fa4aSMatthew Knepley a->nounused = (flg ? -1 : 0); 132528b2fa4aSMatthew Knepley break; 1326a65d3064SKris Buschelman case MAT_IGNORE_ZERO_ENTRIES: 13274e0d8c25SBarry Smith a->ignorezeroentries = flg; 13280df259c2SBarry Smith break; 13293d472b54SHong Zhang case MAT_SPD: 1330b1646e73SJed Brown case MAT_SYMMETRIC: 1331b1646e73SJed Brown case MAT_STRUCTURALLY_SYMMETRIC: 1332b1646e73SJed Brown case MAT_HERMITIAN: 1333b1646e73SJed Brown case MAT_SYMMETRY_ETERNAL: 1334957cac9fSHong Zhang case MAT_STRUCTURE_ONLY: 13355021d80fSJed Brown /* These options are handled directly by MatSetOption() */ 13365021d80fSJed Brown break; 13378c78258cSHong Zhang case MAT_FORCE_DIAGONAL_ENTRIES: 1338a65d3064SKris Buschelman case MAT_IGNORE_OFF_PROC_ENTRIES: 1339a65d3064SKris Buschelman case MAT_USE_HASH_TABLE: 13409566063dSJacob Faibussowitsch PetscCall(PetscInfo(A,"Option %s ignored\n",MatOptions[op])); 1341a65d3064SKris Buschelman break; 1342b87ac2d8SJed Brown case MAT_USE_INODES: 13439566063dSJacob Faibussowitsch PetscCall(MatSetOption_SeqAIJ_Inode(A,MAT_USE_INODES,flg)); 1344b87ac2d8SJed Brown break; 1345c10200c1SHong Zhang case MAT_SUBMAT_SINGLEIS: 1346c10200c1SHong Zhang A->submat_singleis = flg; 1347c10200c1SHong Zhang break; 1348071fcb05SBarry Smith case MAT_SORTED_FULL: 1349071fcb05SBarry Smith if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 1350071fcb05SBarry Smith else A->ops->setvalues = MatSetValues_SeqAIJ; 1351071fcb05SBarry Smith break; 13521a2c6b5cSJunchao Zhang case MAT_FORM_EXPLICIT_TRANSPOSE: 13531a2c6b5cSJunchao Zhang A->form_explicit_transpose = flg; 13541a2c6b5cSJunchao Zhang break; 1355a65d3064SKris Buschelman default: 135698921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op); 1357a65d3064SKris Buschelman } 13583a40ed3dSBarry Smith PetscFunctionReturn(0); 135917ab2063SBarry Smith } 136017ab2063SBarry Smith 1361dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v) 136217ab2063SBarry Smith { 1363416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1364fdc842d1SBarry Smith PetscInt i,j,n,*ai=a->i,*aj=a->j; 1365c898d852SStefano Zampini PetscScalar *x; 1366c898d852SStefano Zampini const PetscScalar *aa; 136717ab2063SBarry Smith 13683a40ed3dSBarry Smith PetscFunctionBegin; 13699566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v,&n)); 137008401ef6SPierre Jolivet PetscCheck(n == A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 13719566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 1372d5f3da31SBarry Smith if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) { 1373d3e70bfaSHong Zhang PetscInt *diag=a->diag; 13749566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v,&x)); 13752c990fa1SHong Zhang for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]]; 13769566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v,&x)); 13779566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 137835e7444dSHong Zhang PetscFunctionReturn(0); 137935e7444dSHong Zhang } 138035e7444dSHong Zhang 13819566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v,&x)); 138235e7444dSHong Zhang for (i=0; i<n; i++) { 1383fdc842d1SBarry Smith x[i] = 0.0; 138435e7444dSHong Zhang for (j=ai[i]; j<ai[i+1]; j++) { 138535e7444dSHong Zhang if (aj[j] == i) { 138635e7444dSHong Zhang x[i] = aa[j]; 138717ab2063SBarry Smith break; 138817ab2063SBarry Smith } 138917ab2063SBarry Smith } 139017ab2063SBarry Smith } 13919566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v,&x)); 13929566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 13933a40ed3dSBarry Smith PetscFunctionReturn(0); 139417ab2063SBarry Smith } 139517ab2063SBarry Smith 1396c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 1397dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy) 139817ab2063SBarry Smith { 1399416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 14005f22a7b3SSebastian Grimberg const MatScalar *aa; 1401d9ca1df4SBarry Smith PetscScalar *y; 1402d9ca1df4SBarry Smith const PetscScalar *x; 1403d0f46423SBarry Smith PetscInt m = A->rmap->n; 14045c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 14055f22a7b3SSebastian Grimberg const MatScalar *v; 1406a77337e4SBarry Smith PetscScalar alpha; 1407d9ca1df4SBarry Smith PetscInt n,i,j; 1408d9ca1df4SBarry Smith const PetscInt *idx,*ii,*ridx=NULL; 14093447b6efSHong Zhang Mat_CompressedRow cprow = a->compressedrow; 1410ace3abfcSBarry Smith PetscBool usecprow = cprow.use; 14115c897100SBarry Smith #endif 141217ab2063SBarry Smith 14133a40ed3dSBarry Smith PetscFunctionBegin; 14149566063dSJacob Faibussowitsch if (zz != yy) PetscCall(VecCopy(zz,yy)); 14159566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx,&x)); 14169566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy,&y)); 14179566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 14185c897100SBarry Smith 14195c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ) 1420fff043a9SJunchao Zhang fortranmulttransposeaddaij_(&m,x,a->i,a->j,aa,y); 14215c897100SBarry Smith #else 14223447b6efSHong Zhang if (usecprow) { 14233447b6efSHong Zhang m = cprow.nrows; 14243447b6efSHong Zhang ii = cprow.i; 14257b2bb3b9SHong Zhang ridx = cprow.rindex; 14263447b6efSHong Zhang } else { 14273447b6efSHong Zhang ii = a->i; 14283447b6efSHong Zhang } 142917ab2063SBarry Smith for (i=0; i<m; i++) { 14303447b6efSHong Zhang idx = a->j + ii[i]; 1431fff043a9SJunchao Zhang v = aa + ii[i]; 14323447b6efSHong Zhang n = ii[i+1] - ii[i]; 14333447b6efSHong Zhang if (usecprow) { 14347b2bb3b9SHong Zhang alpha = x[ridx[i]]; 14353447b6efSHong Zhang } else { 143617ab2063SBarry Smith alpha = x[i]; 14373447b6efSHong Zhang } 143804fbf559SBarry Smith for (j=0; j<n; j++) y[idx[j]] += alpha*v[j]; 143917ab2063SBarry Smith } 14405c897100SBarry Smith #endif 14419566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*a->nz)); 14429566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx,&x)); 14439566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy,&y)); 14449566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 14453a40ed3dSBarry Smith PetscFunctionReturn(0); 144617ab2063SBarry Smith } 144717ab2063SBarry Smith 1448dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy) 14495c897100SBarry Smith { 14505c897100SBarry Smith PetscFunctionBegin; 14519566063dSJacob Faibussowitsch PetscCall(VecSet(yy,0.0)); 14529566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy)); 14535c897100SBarry Smith PetscFunctionReturn(0); 14545c897100SBarry Smith } 14555c897100SBarry Smith 1456c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h> 145778b84d54SShri Abhyankar 1458dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy) 145917ab2063SBarry Smith { 1460416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1461d9fead3dSBarry Smith PetscScalar *y; 146254f21887SBarry Smith const PetscScalar *x; 1463fff043a9SJunchao Zhang const MatScalar *aa,*a_a; 1464003131ecSBarry Smith PetscInt m=A->rmap->n; 14650298fd71SBarry Smith const PetscInt *aj,*ii,*ridx=NULL; 14667b083b7cSBarry Smith PetscInt n,i; 1467362ced78SSatish Balay PetscScalar sum; 1468ace3abfcSBarry Smith PetscBool usecprow=a->compressedrow.use; 146917ab2063SBarry Smith 1470b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 147197952fefSHong Zhang #pragma disjoint(*x,*y,*aa) 1472fee21e36SBarry Smith #endif 1473fee21e36SBarry Smith 14743a40ed3dSBarry Smith PetscFunctionBegin; 1475b215bc84SStefano Zampini if (a->inode.use && a->inode.checked) { 14769566063dSJacob Faibussowitsch PetscCall(MatMult_SeqAIJ_Inode(A,xx,yy)); 1477b215bc84SStefano Zampini PetscFunctionReturn(0); 1478b215bc84SStefano Zampini } 14799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&a_a)); 14809566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx,&x)); 14819566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy,&y)); 1482416022c9SBarry Smith ii = a->i; 14834eb6d288SHong Zhang if (usecprow) { /* use compressed row format */ 14849566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(y,m)); 148597952fefSHong Zhang m = a->compressedrow.nrows; 148697952fefSHong Zhang ii = a->compressedrow.i; 148797952fefSHong Zhang ridx = a->compressedrow.rindex; 148897952fefSHong Zhang for (i=0; i<m; i++) { 148997952fefSHong Zhang n = ii[i+1] - ii[i]; 149097952fefSHong Zhang aj = a->j + ii[i]; 1491fff043a9SJunchao Zhang aa = a_a + ii[i]; 149297952fefSHong Zhang sum = 0.0; 1493003131ecSBarry Smith PetscSparseDensePlusDot(sum,x,aa,aj,n); 1494003131ecSBarry Smith /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 149597952fefSHong Zhang y[*ridx++] = sum; 149697952fefSHong Zhang } 149797952fefSHong Zhang } else { /* do not use compressed row format */ 1498b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ) 14993d3eaba7SBarry Smith aj = a->j; 1500fff043a9SJunchao Zhang aa = a_a; 1501b05257ddSBarry Smith fortranmultaij_(&m,x,ii,aj,aa,y); 1502b05257ddSBarry Smith #else 150317ab2063SBarry Smith for (i=0; i<m; i++) { 1504003131ecSBarry Smith n = ii[i+1] - ii[i]; 1505003131ecSBarry Smith aj = a->j + ii[i]; 1506fff043a9SJunchao Zhang aa = a_a + ii[i]; 150717ab2063SBarry Smith sum = 0.0; 1508003131ecSBarry Smith PetscSparseDensePlusDot(sum,x,aa,aj,n); 150917ab2063SBarry Smith y[i] = sum; 151017ab2063SBarry Smith } 15118d195f9aSBarry Smith #endif 1512b05257ddSBarry Smith } 15139566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*a->nz - a->nonzerorowcnt)); 15149566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx,&x)); 15159566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy,&y)); 15169566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&a_a)); 15173a40ed3dSBarry Smith PetscFunctionReturn(0); 151817ab2063SBarry Smith } 151917ab2063SBarry Smith 1520b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy) 1521b434eb95SMatthew G. Knepley { 1522b434eb95SMatthew G. Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1523b434eb95SMatthew G. Knepley PetscScalar *y; 1524b434eb95SMatthew G. Knepley const PetscScalar *x; 1525fff043a9SJunchao Zhang const MatScalar *aa,*a_a; 1526b434eb95SMatthew G. Knepley PetscInt m=A->rmap->n; 1527b434eb95SMatthew G. Knepley const PetscInt *aj,*ii,*ridx=NULL; 1528b434eb95SMatthew G. Knepley PetscInt n,i,nonzerorow=0; 1529b434eb95SMatthew G. Knepley PetscScalar sum; 1530b434eb95SMatthew G. Knepley PetscBool usecprow=a->compressedrow.use; 1531b434eb95SMatthew G. Knepley 1532b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT) 1533b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa) 1534b434eb95SMatthew G. Knepley #endif 1535b434eb95SMatthew G. Knepley 1536b434eb95SMatthew G. Knepley PetscFunctionBegin; 15379566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&a_a)); 15389566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx,&x)); 15399566063dSJacob Faibussowitsch PetscCall(VecGetArray(yy,&y)); 1540b434eb95SMatthew G. Knepley if (usecprow) { /* use compressed row format */ 1541b434eb95SMatthew G. Knepley m = a->compressedrow.nrows; 1542b434eb95SMatthew G. Knepley ii = a->compressedrow.i; 1543b434eb95SMatthew G. Knepley ridx = a->compressedrow.rindex; 1544b434eb95SMatthew G. Knepley for (i=0; i<m; i++) { 1545b434eb95SMatthew G. Knepley n = ii[i+1] - ii[i]; 1546b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1547fff043a9SJunchao Zhang aa = a_a + ii[i]; 1548b434eb95SMatthew G. Knepley sum = 0.0; 1549b434eb95SMatthew G. Knepley nonzerorow += (n>0); 1550b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1551b434eb95SMatthew G. Knepley /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */ 1552b434eb95SMatthew G. Knepley y[*ridx++] = sum; 1553b434eb95SMatthew G. Knepley } 1554b434eb95SMatthew G. Knepley } else { /* do not use compressed row format */ 15553d3eaba7SBarry Smith ii = a->i; 1556b434eb95SMatthew G. Knepley for (i=0; i<m; i++) { 1557b434eb95SMatthew G. Knepley n = ii[i+1] - ii[i]; 1558b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1559fff043a9SJunchao Zhang aa = a_a + ii[i]; 1560b434eb95SMatthew G. Knepley sum = 0.0; 1561b434eb95SMatthew G. Knepley nonzerorow += (n>0); 1562b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1563b434eb95SMatthew G. Knepley y[i] = sum; 1564b434eb95SMatthew G. Knepley } 1565b434eb95SMatthew G. Knepley } 15669566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*a->nz - nonzerorow)); 15679566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx,&x)); 15689566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(yy,&y)); 15699566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&a_a)); 1570b434eb95SMatthew G. Knepley PetscFunctionReturn(0); 1571b434eb95SMatthew G. Knepley } 1572b434eb95SMatthew G. Knepley 1573b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz) 1574b434eb95SMatthew G. Knepley { 1575b434eb95SMatthew G. Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1576b434eb95SMatthew G. Knepley PetscScalar *y,*z; 1577b434eb95SMatthew G. Knepley const PetscScalar *x; 1578fff043a9SJunchao Zhang const MatScalar *aa,*a_a; 1579b434eb95SMatthew G. Knepley PetscInt m = A->rmap->n,*aj,*ii; 1580b434eb95SMatthew G. Knepley PetscInt n,i,*ridx=NULL; 1581b434eb95SMatthew G. Knepley PetscScalar sum; 1582b434eb95SMatthew G. Knepley PetscBool usecprow=a->compressedrow.use; 1583b434eb95SMatthew G. Knepley 1584b434eb95SMatthew G. Knepley PetscFunctionBegin; 15859566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&a_a)); 15869566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx,&x)); 15879566063dSJacob Faibussowitsch PetscCall(VecGetArrayPair(yy,zz,&y,&z)); 1588b434eb95SMatthew G. Knepley if (usecprow) { /* use compressed row format */ 1589b434eb95SMatthew G. Knepley if (zz != yy) { 15909566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(z,y,m)); 1591b434eb95SMatthew G. Knepley } 1592b434eb95SMatthew G. Knepley m = a->compressedrow.nrows; 1593b434eb95SMatthew G. Knepley ii = a->compressedrow.i; 1594b434eb95SMatthew G. Knepley ridx = a->compressedrow.rindex; 1595b434eb95SMatthew G. Knepley for (i=0; i<m; i++) { 1596b434eb95SMatthew G. Knepley n = ii[i+1] - ii[i]; 1597b434eb95SMatthew G. Knepley aj = a->j + ii[i]; 1598fff043a9SJunchao Zhang aa = a_a + ii[i]; 1599b434eb95SMatthew G. Knepley sum = y[*ridx]; 1600b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1601b434eb95SMatthew G. Knepley z[*ridx++] = sum; 1602b434eb95SMatthew G. Knepley } 1603b434eb95SMatthew G. Knepley } else { /* do not use compressed row format */ 16043d3eaba7SBarry Smith ii = a->i; 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[i]; 1610b434eb95SMatthew G. Knepley PetscSparseDenseMaxDot(sum,x,aa,aj,n); 1611b434eb95SMatthew G. Knepley z[i] = sum; 1612b434eb95SMatthew G. Knepley } 1613b434eb95SMatthew G. Knepley } 16149566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*a->nz)); 16159566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx,&x)); 16169566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayPair(yy,zz,&y,&z)); 16179566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&a_a)); 1618b434eb95SMatthew G. Knepley PetscFunctionReturn(0); 1619b434eb95SMatthew G. Knepley } 1620b434eb95SMatthew G. Knepley 1621c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h> 1622dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz) 162317ab2063SBarry Smith { 1624416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1625f15663dcSBarry Smith PetscScalar *y,*z; 1626f15663dcSBarry Smith const PetscScalar *x; 1627fff043a9SJunchao Zhang const MatScalar *aa,*a_a; 1628d9ca1df4SBarry Smith const PetscInt *aj,*ii,*ridx=NULL; 1629d9ca1df4SBarry Smith PetscInt m = A->rmap->n,n,i; 1630362ced78SSatish Balay PetscScalar sum; 1631ace3abfcSBarry Smith PetscBool usecprow=a->compressedrow.use; 16329ea0dfa2SSatish Balay 16333a40ed3dSBarry Smith PetscFunctionBegin; 1634b215bc84SStefano Zampini if (a->inode.use && a->inode.checked) { 16359566063dSJacob Faibussowitsch PetscCall(MatMultAdd_SeqAIJ_Inode(A,xx,yy,zz)); 1636b215bc84SStefano Zampini PetscFunctionReturn(0); 1637b215bc84SStefano Zampini } 16389566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&a_a)); 16399566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(xx,&x)); 16409566063dSJacob Faibussowitsch PetscCall(VecGetArrayPair(yy,zz,&y,&z)); 16414eb6d288SHong Zhang if (usecprow) { /* use compressed row format */ 16424eb6d288SHong Zhang if (zz != yy) { 16439566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(z,y,m)); 16444eb6d288SHong Zhang } 164597952fefSHong Zhang m = a->compressedrow.nrows; 164697952fefSHong Zhang ii = a->compressedrow.i; 164797952fefSHong Zhang ridx = a->compressedrow.rindex; 164897952fefSHong Zhang for (i=0; i<m; i++) { 164997952fefSHong Zhang n = ii[i+1] - ii[i]; 165097952fefSHong Zhang aj = a->j + ii[i]; 1651fff043a9SJunchao Zhang aa = a_a + ii[i]; 165297952fefSHong Zhang sum = y[*ridx]; 1653f15663dcSBarry Smith PetscSparseDensePlusDot(sum,x,aa,aj,n); 165497952fefSHong Zhang z[*ridx++] = sum; 165597952fefSHong Zhang } 165697952fefSHong Zhang } else { /* do not use compressed row format */ 16573d3eaba7SBarry Smith ii = a->i; 1658f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ) 16593d3eaba7SBarry Smith aj = a->j; 1660fff043a9SJunchao Zhang aa = a_a; 1661f15663dcSBarry Smith fortranmultaddaij_(&m,x,ii,aj,aa,y,z); 1662f15663dcSBarry Smith #else 166317ab2063SBarry Smith for (i=0; i<m; i++) { 1664f15663dcSBarry Smith n = ii[i+1] - ii[i]; 1665f15663dcSBarry Smith aj = a->j + ii[i]; 1666fff043a9SJunchao Zhang aa = a_a + ii[i]; 166717ab2063SBarry Smith sum = y[i]; 1668f15663dcSBarry Smith PetscSparseDensePlusDot(sum,x,aa,aj,n); 166917ab2063SBarry Smith z[i] = sum; 167017ab2063SBarry Smith } 167102ab625aSSatish Balay #endif 1672f15663dcSBarry Smith } 16739566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*a->nz)); 16749566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(xx,&x)); 16759566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayPair(yy,zz,&y,&z)); 16769566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&a_a)); 16773a40ed3dSBarry Smith PetscFunctionReturn(0); 167817ab2063SBarry Smith } 167917ab2063SBarry Smith 168017ab2063SBarry Smith /* 168117ab2063SBarry Smith Adds diagonal pointers to sparse matrix structure. 168217ab2063SBarry Smith */ 1683dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A) 168417ab2063SBarry Smith { 1685416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1686d0f46423SBarry Smith PetscInt i,j,m = A->rmap->n; 1687c0c07093SJunchao Zhang PetscBool alreadySet = PETSC_TRUE; 168817ab2063SBarry Smith 16893a40ed3dSBarry Smith PetscFunctionBegin; 169009f38230SBarry Smith if (!a->diag) { 16919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m,&a->diag)); 16929566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt))); 1693c0c07093SJunchao Zhang alreadySet = PETSC_FALSE; 169409f38230SBarry Smith } 1695d0f46423SBarry Smith for (i=0; i<A->rmap->n; i++) { 1696c0c07093SJunchao Zhang /* If A's diagonal is already correctly set, this fast track enables cheap and repeated MatMarkDiagonal_SeqAIJ() calls */ 1697c0c07093SJunchao Zhang if (alreadySet) { 1698c0c07093SJunchao Zhang PetscInt pos = a->diag[i]; 1699c0c07093SJunchao Zhang if (pos >= a->i[i] && pos < a->i[i+1] && a->j[pos] == i) continue; 1700c0c07093SJunchao Zhang } 1701c0c07093SJunchao Zhang 170209f38230SBarry Smith a->diag[i] = a->i[i+1]; 1703bfeeae90SHong Zhang for (j=a->i[i]; j<a->i[i+1]; j++) { 1704bfeeae90SHong Zhang if (a->j[j] == i) { 170509f38230SBarry Smith a->diag[i] = j; 170617ab2063SBarry Smith break; 170717ab2063SBarry Smith } 170817ab2063SBarry Smith } 170917ab2063SBarry Smith } 17103a40ed3dSBarry Smith PetscFunctionReturn(0); 171117ab2063SBarry Smith } 171217ab2063SBarry Smith 171361ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v) 171461ecd0c6SBarry Smith { 171561ecd0c6SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 171661ecd0c6SBarry Smith const PetscInt *diag = (const PetscInt*)a->diag; 171761ecd0c6SBarry Smith const PetscInt *ii = (const PetscInt*) a->i; 171861ecd0c6SBarry Smith PetscInt i,*mdiag = NULL; 171961ecd0c6SBarry Smith PetscInt cnt = 0; /* how many diagonals are missing */ 172061ecd0c6SBarry Smith 172161ecd0c6SBarry Smith PetscFunctionBegin; 172261ecd0c6SBarry Smith if (!A->preallocated || !a->nz) { 17239566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(A,1,NULL)); 17249566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(A,v)); 172561ecd0c6SBarry Smith PetscFunctionReturn(0); 172661ecd0c6SBarry Smith } 172761ecd0c6SBarry Smith 172861ecd0c6SBarry Smith if (a->diagonaldense) { 172961ecd0c6SBarry Smith cnt = 0; 173061ecd0c6SBarry Smith } else { 17319566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n,&mdiag)); 173261ecd0c6SBarry Smith for (i=0; i<A->rmap->n; i++) { 173361ecd0c6SBarry Smith if (diag[i] >= ii[i+1]) { 173461ecd0c6SBarry Smith cnt++; 173561ecd0c6SBarry Smith mdiag[i] = 1; 173661ecd0c6SBarry Smith } 173761ecd0c6SBarry Smith } 173861ecd0c6SBarry Smith } 173961ecd0c6SBarry Smith if (!cnt) { 17409566063dSJacob Faibussowitsch PetscCall(MatShift_Basic(A,v)); 174161ecd0c6SBarry Smith } else { 1742b6f2aa54SBarry Smith PetscScalar *olda = a->a; /* preserve pointers to current matrix nonzeros structure and values */ 1743b6f2aa54SBarry Smith PetscInt *oldj = a->j, *oldi = a->i; 174461ecd0c6SBarry Smith PetscBool singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij; 174561ecd0c6SBarry Smith 174661ecd0c6SBarry Smith a->a = NULL; 174761ecd0c6SBarry Smith a->j = NULL; 174861ecd0c6SBarry Smith a->i = NULL; 174961ecd0c6SBarry Smith /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */ 175061ecd0c6SBarry Smith for (i=0; i<A->rmap->n; i++) { 175161ecd0c6SBarry Smith a->imax[i] += mdiag[i]; 1752447d62f5SStefano Zampini a->imax[i] = PetscMin(a->imax[i],A->cmap->n); 175361ecd0c6SBarry Smith } 17549566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax)); 175561ecd0c6SBarry Smith 175661ecd0c6SBarry Smith /* copy old values into new matrix data structure */ 175761ecd0c6SBarry Smith for (i=0; i<A->rmap->n; i++) { 17589566063dSJacob Faibussowitsch PetscCall(MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES)); 1759447d62f5SStefano Zampini if (i < A->cmap->n) { 17609566063dSJacob Faibussowitsch PetscCall(MatSetValue(A,i,i,v,ADD_VALUES)); 176161ecd0c6SBarry Smith } 1762447d62f5SStefano Zampini } 17639566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY)); 17649566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY)); 176561ecd0c6SBarry Smith if (singlemalloc) { 17669566063dSJacob Faibussowitsch PetscCall(PetscFree3(olda,oldj,oldi)); 176761ecd0c6SBarry Smith } else { 17689566063dSJacob Faibussowitsch if (free_a) PetscCall(PetscFree(olda)); 17699566063dSJacob Faibussowitsch if (free_ij) PetscCall(PetscFree(oldj)); 17709566063dSJacob Faibussowitsch if (free_ij) PetscCall(PetscFree(oldi)); 177161ecd0c6SBarry Smith } 177261ecd0c6SBarry Smith } 17739566063dSJacob Faibussowitsch PetscCall(PetscFree(mdiag)); 177461ecd0c6SBarry Smith a->diagonaldense = PETSC_TRUE; 177561ecd0c6SBarry Smith PetscFunctionReturn(0); 177661ecd0c6SBarry Smith } 177761ecd0c6SBarry Smith 1778be5855fcSBarry Smith /* 1779be5855fcSBarry Smith Checks for missing diagonals 1780be5855fcSBarry Smith */ 1781ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool *missing,PetscInt *d) 1782be5855fcSBarry Smith { 1783be5855fcSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 17847734d3b5SMatthew G. Knepley PetscInt *diag,*ii = a->i,i; 1785be5855fcSBarry Smith 1786be5855fcSBarry Smith PetscFunctionBegin; 178709f38230SBarry Smith *missing = PETSC_FALSE; 17887734d3b5SMatthew G. Knepley if (A->rmap->n > 0 && !ii) { 178909f38230SBarry Smith *missing = PETSC_TRUE; 179009f38230SBarry Smith if (d) *d = 0; 17919566063dSJacob Faibussowitsch PetscCall(PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n")); 179209f38230SBarry Smith } else { 179301445905SHong Zhang PetscInt n; 179401445905SHong Zhang n = PetscMin(A->rmap->n, A->cmap->n); 1795f1e2ffcdSBarry Smith diag = a->diag; 179601445905SHong Zhang for (i=0; i<n; i++) { 17977734d3b5SMatthew G. Knepley if (diag[i] >= ii[i+1]) { 179809f38230SBarry Smith *missing = PETSC_TRUE; 179909f38230SBarry Smith if (d) *d = i; 18009566063dSJacob Faibussowitsch PetscCall(PetscInfo(A,"Matrix is missing diagonal number %" PetscInt_FMT "\n",i)); 1801358d2f5dSShri Abhyankar break; 180209f38230SBarry Smith } 1803be5855fcSBarry Smith } 1804be5855fcSBarry Smith } 1805be5855fcSBarry Smith PetscFunctionReturn(0); 1806be5855fcSBarry Smith } 1807be5855fcSBarry Smith 18080da83c2eSBarry Smith #include <petscblaslapack.h> 18090da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h> 18100da83c2eSBarry Smith 18110da83c2eSBarry Smith /* 18120da83c2eSBarry Smith Note that values is allocated externally by the PC and then passed into this routine 18130da83c2eSBarry Smith */ 18140da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag) 18150da83c2eSBarry Smith { 18160da83c2eSBarry Smith PetscInt n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots; 18170da83c2eSBarry Smith PetscBool allowzeropivot,zeropivotdetected=PETSC_FALSE; 18180da83c2eSBarry Smith const PetscReal shift = 0.0; 18190da83c2eSBarry Smith PetscInt ipvt[5]; 18200da83c2eSBarry Smith PetscScalar work[25],*v_work; 18210da83c2eSBarry Smith 18220da83c2eSBarry Smith PetscFunctionBegin; 18230da83c2eSBarry Smith allowzeropivot = PetscNot(A->erroriffailure); 18240da83c2eSBarry Smith for (i=0; i<nblocks; i++) ncnt += bsizes[i]; 182508401ef6SPierre 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); 18260da83c2eSBarry Smith for (i=0; i<nblocks; i++) { 18270da83c2eSBarry Smith bsizemax = PetscMax(bsizemax,bsizes[i]); 18280da83c2eSBarry Smith } 18299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsizemax,&indx)); 18300da83c2eSBarry Smith if (bsizemax > 7) { 18319566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots)); 18320da83c2eSBarry Smith } 18330da83c2eSBarry Smith ncnt = 0; 18340da83c2eSBarry Smith for (i=0; i<nblocks; i++) { 18350da83c2eSBarry Smith for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j; 18369566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag)); 18370da83c2eSBarry Smith switch (bsizes[i]) { 18380da83c2eSBarry Smith case 1: 18390da83c2eSBarry Smith *diag = 1.0/(*diag); 18400da83c2eSBarry Smith break; 18410da83c2eSBarry Smith case 2: 18429566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected)); 18430da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18449566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_2(diag)); 18450da83c2eSBarry Smith break; 18460da83c2eSBarry Smith case 3: 18479566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected)); 18480da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18499566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_3(diag)); 18500da83c2eSBarry Smith break; 18510da83c2eSBarry Smith case 4: 18529566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected)); 18530da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18549566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_4(diag)); 18550da83c2eSBarry Smith break; 18560da83c2eSBarry Smith case 5: 18579566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected)); 18580da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18599566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_5(diag)); 18600da83c2eSBarry Smith break; 18610da83c2eSBarry Smith case 6: 18629566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected)); 18630da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18649566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_6(diag)); 18650da83c2eSBarry Smith break; 18660da83c2eSBarry Smith case 7: 18679566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected)); 18680da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18699566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_7(diag)); 18700da83c2eSBarry Smith break; 18710da83c2eSBarry Smith default: 18729566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected)); 18730da83c2eSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 18749566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_N(diag,bsizes[i])); 18750da83c2eSBarry Smith } 18760da83c2eSBarry Smith ncnt += bsizes[i]; 18770da83c2eSBarry Smith diag += bsizes[i]*bsizes[i]; 18780da83c2eSBarry Smith } 18790da83c2eSBarry Smith if (bsizemax > 7) { 18809566063dSJacob Faibussowitsch PetscCall(PetscFree2(v_work,v_pivots)); 18810da83c2eSBarry Smith } 18829566063dSJacob Faibussowitsch PetscCall(PetscFree(indx)); 18830da83c2eSBarry Smith PetscFunctionReturn(0); 18840da83c2eSBarry Smith } 18850da83c2eSBarry Smith 1886422a814eSBarry Smith /* 1887422a814eSBarry Smith Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways 1888422a814eSBarry Smith */ 18897087cfbeSBarry Smith PetscErrorCode MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift) 189071f1c65dSBarry Smith { 189171f1c65dSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data; 1892d0f46423SBarry Smith PetscInt i,*diag,m = A->rmap->n; 18932e5835c6SStefano Zampini const MatScalar *v; 189454f21887SBarry Smith PetscScalar *idiag,*mdiag; 189571f1c65dSBarry Smith 189671f1c65dSBarry Smith PetscFunctionBegin; 189771f1c65dSBarry Smith if (a->idiagvalid) PetscFunctionReturn(0); 18989566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 189971f1c65dSBarry Smith diag = a->diag; 190071f1c65dSBarry Smith if (!a->idiag) { 19019566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work)); 19029566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A,3*m*sizeof(PetscScalar))); 190371f1c65dSBarry Smith } 19042e5835c6SStefano Zampini 190571f1c65dSBarry Smith mdiag = a->mdiag; 190671f1c65dSBarry Smith idiag = a->idiag; 19079566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&v)); 1908422a814eSBarry Smith if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) { 190971f1c65dSBarry Smith for (i=0; i<m; i++) { 191071f1c65dSBarry Smith mdiag[i] = v[diag[i]]; 1911899639b0SHong Zhang if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */ 1912899639b0SHong Zhang if (PetscRealPart(fshift)) { 19139566063dSJacob Faibussowitsch PetscCall(PetscInfo(A,"Zero diagonal on row %" PetscInt_FMT "\n",i)); 19147b6c816cSBarry Smith A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 19157b6c816cSBarry Smith A->factorerror_zeropivot_value = 0.0; 19167b6c816cSBarry Smith A->factorerror_zeropivot_row = i; 191798921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %" PetscInt_FMT,i); 1918899639b0SHong Zhang } 191971f1c65dSBarry Smith idiag[i] = 1.0/v[diag[i]]; 192071f1c65dSBarry Smith } 19219566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(m)); 192271f1c65dSBarry Smith } else { 192371f1c65dSBarry Smith for (i=0; i<m; i++) { 192471f1c65dSBarry Smith mdiag[i] = v[diag[i]]; 192571f1c65dSBarry Smith idiag[i] = omega/(fshift + v[diag[i]]); 192671f1c65dSBarry Smith } 19279566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*m)); 192871f1c65dSBarry Smith } 192971f1c65dSBarry Smith a->idiagvalid = PETSC_TRUE; 19309566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&v)); 193171f1c65dSBarry Smith PetscFunctionReturn(0); 193271f1c65dSBarry Smith } 193371f1c65dSBarry Smith 1934c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h> 193541f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 193617ab2063SBarry Smith { 1937416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 1938e6d1f457SBarry Smith PetscScalar *x,d,sum,*t,scale; 19392e5835c6SStefano Zampini const MatScalar *v,*idiag=NULL,*mdiag,*aa; 194054f21887SBarry Smith const PetscScalar *b, *bs,*xb, *ts; 19413d3eaba7SBarry Smith PetscInt n,m = A->rmap->n,i; 194297f1f81fSBarry Smith const PetscInt *idx,*diag; 194317ab2063SBarry Smith 19443a40ed3dSBarry Smith PetscFunctionBegin; 1945b215bc84SStefano Zampini if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) { 19469566063dSJacob Faibussowitsch PetscCall(MatSOR_SeqAIJ_Inode(A,bb,omega,flag,fshift,its,lits,xx)); 1947b215bc84SStefano Zampini PetscFunctionReturn(0); 1948b215bc84SStefano Zampini } 1949b965ef7fSBarry Smith its = its*lits; 195091723122SBarry Smith 195171f1c65dSBarry Smith if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */ 19529566063dSJacob Faibussowitsch if (!a->idiagvalid) PetscCall(MatInvertDiagonal_SeqAIJ(A,omega,fshift)); 195371f1c65dSBarry Smith a->fshift = fshift; 195471f1c65dSBarry Smith a->omega = omega; 1955ed480e8bSBarry Smith 195671f1c65dSBarry Smith diag = a->diag; 195771f1c65dSBarry Smith t = a->ssor_work; 1958ed480e8bSBarry Smith idiag = a->idiag; 195971f1c65dSBarry Smith mdiag = a->mdiag; 1960ed480e8bSBarry Smith 19619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 19629566063dSJacob Faibussowitsch PetscCall(VecGetArray(xx,&x)); 19639566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(bb,&b)); 1964ed480e8bSBarry Smith /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */ 196517ab2063SBarry Smith if (flag == SOR_APPLY_UPPER) { 196617ab2063SBarry Smith /* apply (U + D/omega) to the vector */ 1967ed480e8bSBarry Smith bs = b; 196817ab2063SBarry Smith for (i=0; i<m; i++) { 196971f1c65dSBarry Smith d = fshift + mdiag[i]; 1970416022c9SBarry Smith n = a->i[i+1] - diag[i] - 1; 1971ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 19722e5835c6SStefano Zampini v = aa + diag[i] + 1; 197317ab2063SBarry Smith sum = b[i]*d/omega; 1974003131ecSBarry Smith PetscSparseDensePlusDot(sum,bs,v,idx,n); 197517ab2063SBarry Smith x[i] = sum; 197617ab2063SBarry Smith } 19779566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx,&x)); 19789566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb,&b)); 19799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 19809566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 19813a40ed3dSBarry Smith PetscFunctionReturn(0); 198217ab2063SBarry Smith } 1983c783ea89SBarry Smith 198408401ef6SPierre Jolivet PetscCheck(flag != SOR_APPLY_LOWER,PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented"); 19852205254eSKarl Rupp else if (flag & SOR_EISENSTAT) { 19864c500f23SPierre Jolivet /* Let A = L + U + D; where L is lower triangular, 1987887ee2caSBarry Smith U is upper triangular, E = D/omega; This routine applies 198817ab2063SBarry Smith 198917ab2063SBarry Smith (L + E)^{-1} A (U + E)^{-1} 199017ab2063SBarry Smith 1991887ee2caSBarry Smith to a vector efficiently using Eisenstat's trick. 199217ab2063SBarry Smith */ 199317ab2063SBarry Smith scale = (2.0/omega) - 1.0; 199417ab2063SBarry Smith 199517ab2063SBarry Smith /* x = (E + U)^{-1} b */ 199617ab2063SBarry Smith for (i=m-1; i>=0; i--) { 1997416022c9SBarry Smith n = a->i[i+1] - diag[i] - 1; 1998ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 19992e5835c6SStefano Zampini v = aa + diag[i] + 1; 200017ab2063SBarry Smith sum = b[i]; 2001e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum,x,v,idx,n); 2002ed480e8bSBarry Smith x[i] = sum*idiag[i]; 200317ab2063SBarry Smith } 200417ab2063SBarry Smith 200517ab2063SBarry Smith /* t = b - (2*E - D)x */ 20062e5835c6SStefano Zampini v = aa; 20072205254eSKarl Rupp for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i]; 200817ab2063SBarry Smith 200917ab2063SBarry Smith /* t = (E + L)^{-1}t */ 2010ed480e8bSBarry Smith ts = t; 2011416022c9SBarry Smith diag = a->diag; 201217ab2063SBarry Smith for (i=0; i<m; i++) { 2013416022c9SBarry Smith n = diag[i] - a->i[i]; 2014ed480e8bSBarry Smith idx = a->j + a->i[i]; 20152e5835c6SStefano Zampini v = aa + a->i[i]; 201617ab2063SBarry Smith sum = t[i]; 2017003131ecSBarry Smith PetscSparseDenseMinusDot(sum,ts,v,idx,n); 2018ed480e8bSBarry Smith t[i] = sum*idiag[i]; 2019733d66baSBarry Smith /* x = x + t */ 2020733d66baSBarry Smith x[i] += t[i]; 202117ab2063SBarry Smith } 202217ab2063SBarry Smith 20239566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(6.0*m-1 + 2.0*a->nz)); 20249566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx,&x)); 20259566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb,&b)); 20263a40ed3dSBarry Smith PetscFunctionReturn(0); 202717ab2063SBarry Smith } 202817ab2063SBarry Smith if (flag & SOR_ZERO_INITIAL_GUESS) { 202917ab2063SBarry Smith if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 203017ab2063SBarry Smith for (i=0; i<m; i++) { 2031416022c9SBarry Smith n = diag[i] - a->i[i]; 2032ed480e8bSBarry Smith idx = a->j + a->i[i]; 20332e5835c6SStefano Zampini v = aa + a->i[i]; 203417ab2063SBarry Smith sum = b[i]; 2035e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum,x,v,idx,n); 20365c99c7daSBarry Smith t[i] = sum; 2037ed480e8bSBarry Smith x[i] = sum*idiag[i]; 203817ab2063SBarry Smith } 20395c99c7daSBarry Smith xb = t; 20409566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 20413a40ed3dSBarry Smith } else xb = b; 204217ab2063SBarry Smith if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 204317ab2063SBarry Smith for (i=m-1; i>=0; i--) { 2044416022c9SBarry Smith n = a->i[i+1] - diag[i] - 1; 2045ed480e8bSBarry Smith idx = a->j + diag[i] + 1; 20462e5835c6SStefano Zampini v = aa + diag[i] + 1; 204717ab2063SBarry Smith sum = xb[i]; 2048e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum,x,v,idx,n); 20495c99c7daSBarry Smith if (xb == b) { 2050ed480e8bSBarry Smith x[i] = sum*idiag[i]; 20515c99c7daSBarry Smith } else { 2052b19a5dc2SMark Adams x[i] = (1-omega)*x[i] + sum*idiag[i]; /* omega in idiag */ 205317ab2063SBarry Smith } 20545c99c7daSBarry Smith } 20559566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */ 205617ab2063SBarry Smith } 205717ab2063SBarry Smith its--; 205817ab2063SBarry Smith } 205917ab2063SBarry Smith while (its--) { 206017ab2063SBarry Smith if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) { 206117ab2063SBarry Smith for (i=0; i<m; i++) { 2062b19a5dc2SMark Adams /* lower */ 2063b19a5dc2SMark Adams n = diag[i] - a->i[i]; 2064ed480e8bSBarry Smith idx = a->j + a->i[i]; 20652e5835c6SStefano Zampini v = aa + a->i[i]; 206617ab2063SBarry Smith sum = b[i]; 2067e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum,x,v,idx,n); 2068b19a5dc2SMark Adams t[i] = sum; /* save application of the lower-triangular part */ 2069b19a5dc2SMark Adams /* upper */ 2070b19a5dc2SMark Adams n = a->i[i+1] - diag[i] - 1; 2071b19a5dc2SMark Adams idx = a->j + diag[i] + 1; 20722e5835c6SStefano Zampini v = aa + diag[i] + 1; 2073b19a5dc2SMark Adams PetscSparseDenseMinusDot(sum,x,v,idx,n); 2074b19a5dc2SMark Adams x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */ 207517ab2063SBarry Smith } 2076b19a5dc2SMark Adams xb = t; 20779566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*a->nz)); 2078b19a5dc2SMark Adams } else xb = b; 207917ab2063SBarry Smith if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) { 208017ab2063SBarry Smith for (i=m-1; i>=0; i--) { 2081b19a5dc2SMark Adams sum = xb[i]; 2082b19a5dc2SMark Adams if (xb == b) { 2083b19a5dc2SMark Adams /* whole matrix (no checkpointing available) */ 2084416022c9SBarry Smith n = a->i[i+1] - a->i[i]; 2085ed480e8bSBarry Smith idx = a->j + a->i[i]; 20862e5835c6SStefano Zampini v = aa + a->i[i]; 2087e6d1f457SBarry Smith PetscSparseDenseMinusDot(sum,x,v,idx,n); 2088ed480e8bSBarry Smith x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i]; 2089b19a5dc2SMark Adams } else { /* lower-triangular part has been saved, so only apply upper-triangular */ 2090b19a5dc2SMark Adams n = a->i[i+1] - diag[i] - 1; 2091b19a5dc2SMark Adams idx = a->j + diag[i] + 1; 20922e5835c6SStefano Zampini v = aa + diag[i] + 1; 2093b19a5dc2SMark Adams PetscSparseDenseMinusDot(sum,x,v,idx,n); 2094b19a5dc2SMark Adams x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */ 209517ab2063SBarry Smith } 2096b19a5dc2SMark Adams } 2097b19a5dc2SMark Adams if (xb == b) { 20989566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*a->nz)); 2099b19a5dc2SMark Adams } else { 21009566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */ 2101b19a5dc2SMark Adams } 210217ab2063SBarry Smith } 210317ab2063SBarry Smith } 21049566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 21059566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(xx,&x)); 21069566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(bb,&b)); 2107365a8a9eSBarry Smith PetscFunctionReturn(0); 210817ab2063SBarry Smith } 210917ab2063SBarry Smith 2110dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info) 211117ab2063SBarry Smith { 2112416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 21134e220ebcSLois Curfman McInnes 21143a40ed3dSBarry Smith PetscFunctionBegin; 21154e220ebcSLois Curfman McInnes info->block_size = 1.0; 21163966268fSBarry Smith info->nz_allocated = a->maxnz; 21173966268fSBarry Smith info->nz_used = a->nz; 21183966268fSBarry Smith info->nz_unneeded = (a->maxnz - a->nz); 21193966268fSBarry Smith info->assemblies = A->num_ass; 21203966268fSBarry Smith info->mallocs = A->info.mallocs; 21217adad957SLisandro Dalcin info->memory = ((PetscObject)A)->mem; 2122d5f3da31SBarry Smith if (A->factortype) { 21234e220ebcSLois Curfman McInnes info->fill_ratio_given = A->info.fill_ratio_given; 21244e220ebcSLois Curfman McInnes info->fill_ratio_needed = A->info.fill_ratio_needed; 21254e220ebcSLois Curfman McInnes info->factor_mallocs = A->info.factor_mallocs; 21264e220ebcSLois Curfman McInnes } else { 21274e220ebcSLois Curfman McInnes info->fill_ratio_given = 0; 21284e220ebcSLois Curfman McInnes info->fill_ratio_needed = 0; 21294e220ebcSLois Curfman McInnes info->factor_mallocs = 0; 21304e220ebcSLois Curfman McInnes } 21313a40ed3dSBarry Smith PetscFunctionReturn(0); 213217ab2063SBarry Smith } 213317ab2063SBarry Smith 21342b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 213517ab2063SBarry Smith { 2136416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2137c7da8527SEric Chamberland PetscInt i,m = A->rmap->n - 1; 213897b48c8fSBarry Smith const PetscScalar *xx; 21392e5835c6SStefano Zampini PetscScalar *bb,*aa; 2140c7da8527SEric Chamberland PetscInt d = 0; 214117ab2063SBarry Smith 21423a40ed3dSBarry Smith PetscFunctionBegin; 214397b48c8fSBarry Smith if (x && b) { 21449566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x,&xx)); 21459566063dSJacob Faibussowitsch PetscCall(VecGetArray(b,&bb)); 214697b48c8fSBarry Smith for (i=0; i<N; i++) { 2147aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]); 2148447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 214997b48c8fSBarry Smith bb[rows[i]] = diag*xx[rows[i]]; 215097b48c8fSBarry Smith } 21519566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x,&xx)); 21529566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b,&bb)); 215397b48c8fSBarry Smith } 215497b48c8fSBarry Smith 21559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&aa)); 2156a9817697SBarry Smith if (a->keepnonzeropattern) { 2157f1e2ffcdSBarry Smith for (i=0; i<N; i++) { 2158aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]); 21599566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]])); 2160f1e2ffcdSBarry Smith } 2161f4df32b1SMatthew Knepley if (diag != 0.0) { 2162c7da8527SEric Chamberland for (i=0; i<N; i++) { 2163c7da8527SEric Chamberland d = rows[i]; 2164447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 216508401ef6SPierre 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); 2166c7da8527SEric Chamberland } 2167f1e2ffcdSBarry Smith for (i=0; i<N; i++) { 2168447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) continue; 21692e5835c6SStefano Zampini aa[a->diag[rows[i]]] = diag; 2170f1e2ffcdSBarry Smith } 2171f1e2ffcdSBarry Smith } 2172f1e2ffcdSBarry Smith } else { 2173f4df32b1SMatthew Knepley if (diag != 0.0) { 217417ab2063SBarry Smith for (i=0; i<N; i++) { 2175aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]); 21767ae801bdSBarry Smith if (a->ilen[rows[i]] > 0) { 2177447d62f5SStefano Zampini if (rows[i] >= A->cmap->n) { 2178447d62f5SStefano Zampini a->ilen[rows[i]] = 0; 2179447d62f5SStefano Zampini } else { 2180416022c9SBarry Smith a->ilen[rows[i]] = 1; 21812e5835c6SStefano Zampini aa[a->i[rows[i]]] = diag; 2182bfeeae90SHong Zhang a->j[a->i[rows[i]]] = rows[i]; 2183447d62f5SStefano Zampini } 2184447d62f5SStefano Zampini } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */ 21859566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES)); 218617ab2063SBarry Smith } 218717ab2063SBarry Smith } 21883a40ed3dSBarry Smith } else { 218917ab2063SBarry Smith for (i=0; i<N; i++) { 2190aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]); 2191416022c9SBarry Smith a->ilen[rows[i]] = 0; 219217ab2063SBarry Smith } 219317ab2063SBarry Smith } 2194e56f5c9eSBarry Smith A->nonzerostate++; 2195f1e2ffcdSBarry Smith } 21969566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&aa)); 21979566063dSJacob Faibussowitsch PetscCall((*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY)); 21983a40ed3dSBarry Smith PetscFunctionReturn(0); 219917ab2063SBarry Smith } 220017ab2063SBarry Smith 22016e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 22026e169961SBarry Smith { 22036e169961SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 22046e169961SBarry Smith PetscInt i,j,m = A->rmap->n - 1,d = 0; 22052b40b63fSBarry Smith PetscBool missing,*zeroed,vecs = PETSC_FALSE; 22066e169961SBarry Smith const PetscScalar *xx; 22072e5835c6SStefano Zampini PetscScalar *bb,*aa; 22086e169961SBarry Smith 22096e169961SBarry Smith PetscFunctionBegin; 22102e5835c6SStefano Zampini if (!N) PetscFunctionReturn(0); 22119566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&aa)); 22126e169961SBarry Smith if (x && b) { 22139566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x,&xx)); 22149566063dSJacob Faibussowitsch PetscCall(VecGetArray(b,&bb)); 22152b40b63fSBarry Smith vecs = PETSC_TRUE; 22166e169961SBarry Smith } 22179566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n,&zeroed)); 22186e169961SBarry Smith for (i=0; i<N; i++) { 2219aed4548fSBarry Smith PetscCheck(rows[i] >= 0 && rows[i] <= m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]); 22209566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]])); 22212205254eSKarl Rupp 22226e169961SBarry Smith zeroed[rows[i]] = PETSC_TRUE; 22236e169961SBarry Smith } 22246e169961SBarry Smith for (i=0; i<A->rmap->n; i++) { 22256e169961SBarry Smith if (!zeroed[i]) { 22266e169961SBarry Smith for (j=a->i[i]; j<a->i[i+1]; j++) { 22274cf107fdSStefano Zampini if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) { 22282e5835c6SStefano Zampini if (vecs) bb[i] -= aa[j]*xx[a->j[j]]; 22292e5835c6SStefano Zampini aa[j] = 0.0; 22306e169961SBarry Smith } 22316e169961SBarry Smith } 22324cf107fdSStefano Zampini } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i]; 22336e169961SBarry Smith } 22346e169961SBarry Smith if (x && b) { 22359566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x,&xx)); 22369566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b,&bb)); 22376e169961SBarry Smith } 22389566063dSJacob Faibussowitsch PetscCall(PetscFree(zeroed)); 22396e169961SBarry Smith if (diag != 0.0) { 22409566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal_SeqAIJ(A,&missing,&d)); 22411d5a398dSstefano_zampini if (missing) { 22421d5a398dSstefano_zampini for (i=0; i<N; i++) { 22434cf107fdSStefano Zampini if (rows[i] >= A->cmap->N) continue; 2244aed4548fSBarry 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]); 22459566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES)); 22461d5a398dSstefano_zampini } 22471d5a398dSstefano_zampini } else { 22486e169961SBarry Smith for (i=0; i<N; i++) { 22492e5835c6SStefano Zampini aa[a->diag[rows[i]]] = diag; 22506e169961SBarry Smith } 22516e169961SBarry Smith } 22521d5a398dSstefano_zampini } 22539566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&aa)); 22549566063dSJacob Faibussowitsch PetscCall((*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY)); 22556e169961SBarry Smith PetscFunctionReturn(0); 22566e169961SBarry Smith } 22576e169961SBarry Smith 2258a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 225917ab2063SBarry Smith { 2260fff043a9SJunchao Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2261fff043a9SJunchao Zhang const PetscScalar *aa; 2262fff043a9SJunchao Zhang PetscInt *itmp; 226317ab2063SBarry Smith 22643a40ed3dSBarry Smith PetscFunctionBegin; 22659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 2266416022c9SBarry Smith *nz = a->i[row+1] - a->i[row]; 22672e5835c6SStefano Zampini if (v) *v = (PetscScalar*)(aa + a->i[row]); 226817ab2063SBarry Smith if (idx) { 2269bfeeae90SHong Zhang itmp = a->j + a->i[row]; 227026fbe8dcSKarl Rupp if (*nz) *idx = itmp; 2271f4259b30SLisandro Dalcin else *idx = NULL; 227217ab2063SBarry Smith } 22739566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 22743a40ed3dSBarry Smith PetscFunctionReturn(0); 227517ab2063SBarry Smith } 227617ab2063SBarry Smith 2277a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 227817ab2063SBarry Smith { 22793a40ed3dSBarry Smith PetscFunctionBegin; 2280cb4a9cd9SHong Zhang if (nz) *nz = 0; 22812e5835c6SStefano Zampini if (idx) *idx = NULL; 22822e5835c6SStefano Zampini if (v) *v = NULL; 22833a40ed3dSBarry Smith PetscFunctionReturn(0); 228417ab2063SBarry Smith } 228517ab2063SBarry Smith 2286dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm) 228717ab2063SBarry Smith { 2288416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 22892e5835c6SStefano Zampini const MatScalar *v; 229036db0b34SBarry Smith PetscReal sum = 0.0; 229197f1f81fSBarry Smith PetscInt i,j; 229217ab2063SBarry Smith 22933a40ed3dSBarry Smith PetscFunctionBegin; 22949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&v)); 229517ab2063SBarry Smith if (type == NORM_FROBENIUS) { 2296570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16) 2297570b7f6dSBarry Smith PetscBLASInt one = 1,nz = a->nz; 229873cf7048SBarry Smith PetscStackCallBLAS("BLASnrm2",*nrm = BLASnrm2_(&nz,v,&one)); 2299570b7f6dSBarry Smith #else 2300416022c9SBarry Smith for (i=0; i<a->nz; i++) { 230136db0b34SBarry Smith sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 230217ab2063SBarry Smith } 23038f1a2a5eSBarry Smith *nrm = PetscSqrtReal(sum); 2304570b7f6dSBarry Smith #endif 23059566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*a->nz)); 23063a40ed3dSBarry Smith } else if (type == NORM_1) { 230736db0b34SBarry Smith PetscReal *tmp; 230897f1f81fSBarry Smith PetscInt *jj = a->j; 23099566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->cmap->n+1,&tmp)); 2310064f8208SBarry Smith *nrm = 0.0; 2311416022c9SBarry Smith for (j=0; j<a->nz; j++) { 2312bfeeae90SHong Zhang tmp[*jj++] += PetscAbsScalar(*v); v++; 231317ab2063SBarry Smith } 2314d0f46423SBarry Smith for (j=0; j<A->cmap->n; j++) { 2315064f8208SBarry Smith if (tmp[j] > *nrm) *nrm = tmp[j]; 231617ab2063SBarry Smith } 23179566063dSJacob Faibussowitsch PetscCall(PetscFree(tmp)); 23189566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(PetscMax(a->nz-1,0))); 23193a40ed3dSBarry Smith } else if (type == NORM_INFINITY) { 2320064f8208SBarry Smith *nrm = 0.0; 2321d0f46423SBarry Smith for (j=0; j<A->rmap->n; j++) { 23222e5835c6SStefano Zampini const PetscScalar *v2 = v + a->i[j]; 232317ab2063SBarry Smith sum = 0.0; 2324416022c9SBarry Smith for (i=0; i<a->i[j+1]-a->i[j]; i++) { 23252e5835c6SStefano Zampini sum += PetscAbsScalar(*v2); v2++; 232617ab2063SBarry Smith } 2327064f8208SBarry Smith if (sum > *nrm) *nrm = sum; 232817ab2063SBarry Smith } 23299566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(PetscMax(a->nz-1,0))); 2330f23aa3ddSBarry Smith } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm"); 23319566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&v)); 23323a40ed3dSBarry Smith PetscFunctionReturn(0); 233317ab2063SBarry Smith } 233417ab2063SBarry Smith 23354e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */ 23364e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B) 23374e938277SHong Zhang { 23384e938277SHong Zhang PetscInt i,j,anzj; 23394e938277SHong Zhang Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data,*b; 23404e938277SHong Zhang PetscInt an=A->cmap->N,am=A->rmap->N; 23414e938277SHong Zhang PetscInt *ati,*atj,*atfill,*ai=a->i,*aj=a->j; 23424e938277SHong Zhang 23434e938277SHong Zhang PetscFunctionBegin; 23444e938277SHong Zhang /* Allocate space for symbolic transpose info and work array */ 23459566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(an+1,&ati)); 23469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ai[am],&atj)); 23479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(an,&atfill)); 23484e938277SHong Zhang 23494e938277SHong Zhang /* Walk through aj and count ## of non-zeros in each row of A^T. */ 23504e938277SHong Zhang /* Note: offset by 1 for fast conversion into csr format. */ 235126fbe8dcSKarl Rupp for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1; 23524e938277SHong Zhang /* Form ati for csr format of A^T. */ 235326fbe8dcSKarl Rupp for (i=0;i<an;i++) ati[i+1] += ati[i]; 23544e938277SHong Zhang 23554e938277SHong Zhang /* Copy ati into atfill so we have locations of the next free space in atj */ 23569566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(atfill,ati,an)); 23574e938277SHong Zhang 23584e938277SHong Zhang /* Walk through A row-wise and mark nonzero entries of A^T. */ 23594e938277SHong Zhang for (i=0;i<am;i++) { 23604e938277SHong Zhang anzj = ai[i+1] - ai[i]; 23614e938277SHong Zhang for (j=0;j<anzj;j++) { 23624e938277SHong Zhang atj[atfill[*aj]] = i; 23634e938277SHong Zhang atfill[*aj++] += 1; 23644e938277SHong Zhang } 23654e938277SHong Zhang } 23664e938277SHong Zhang 23674e938277SHong Zhang /* Clean up temporary space and complete requests. */ 23689566063dSJacob Faibussowitsch PetscCall(PetscFree(atfill)); 23699566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B)); 23709566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs))); 23719566063dSJacob Faibussowitsch PetscCall(MatSetType(*B,((PetscObject)A)->type_name)); 2372a2f3521dSMark F. Adams 23734e938277SHong Zhang b = (Mat_SeqAIJ*)((*B)->data); 23744e938277SHong Zhang b->free_a = PETSC_FALSE; 23754e938277SHong Zhang b->free_ij = PETSC_TRUE; 23764e938277SHong Zhang b->nonew = 0; 23774e938277SHong Zhang PetscFunctionReturn(0); 23784e938277SHong Zhang } 23794e938277SHong Zhang 23807087cfbeSBarry Smith PetscErrorCode MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool *f) 2381cd0d46ebSvictorle { 23823d3eaba7SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data; 238354f21887SBarry Smith PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr; 23842e5835c6SStefano Zampini const MatScalar *va,*vb; 238597f1f81fSBarry Smith PetscInt ma,na,mb,nb, i; 2386cd0d46ebSvictorle 2387cd0d46ebSvictorle PetscFunctionBegin; 23889566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&ma,&na)); 23899566063dSJacob Faibussowitsch PetscCall(MatGetSize(B,&mb,&nb)); 23905485867bSBarry Smith if (ma!=nb || na!=mb) { 23915485867bSBarry Smith *f = PETSC_FALSE; 23925485867bSBarry Smith PetscFunctionReturn(0); 23935485867bSBarry Smith } 23949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&va)); 23959566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B,&vb)); 2396cd0d46ebSvictorle aii = aij->i; bii = bij->i; 2397cd0d46ebSvictorle adx = aij->j; bdx = bij->j; 23989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ma,&aptr)); 23999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mb,&bptr)); 2400cd0d46ebSvictorle for (i=0; i<ma; i++) aptr[i] = aii[i]; 2401cd0d46ebSvictorle for (i=0; i<mb; i++) bptr[i] = bii[i]; 2402cd0d46ebSvictorle 2403cd0d46ebSvictorle *f = PETSC_TRUE; 2404cd0d46ebSvictorle for (i=0; i<ma; i++) { 2405cd0d46ebSvictorle while (aptr[i]<aii[i+1]) { 240697f1f81fSBarry Smith PetscInt idc,idr; 24075485867bSBarry Smith PetscScalar vc,vr; 2408cd0d46ebSvictorle /* column/row index/value */ 24095485867bSBarry Smith idc = adx[aptr[i]]; 24105485867bSBarry Smith idr = bdx[bptr[idc]]; 24115485867bSBarry Smith vc = va[aptr[i]]; 24125485867bSBarry Smith vr = vb[bptr[idc]]; 24135485867bSBarry Smith if (i!=idr || PetscAbsScalar(vc-vr) > tol) { 24145485867bSBarry Smith *f = PETSC_FALSE; 24155485867bSBarry Smith goto done; 2416cd0d46ebSvictorle } else { 24175485867bSBarry Smith aptr[i]++; 24185485867bSBarry Smith if (B || i!=idc) bptr[idc]++; 2419cd0d46ebSvictorle } 2420cd0d46ebSvictorle } 2421cd0d46ebSvictorle } 2422cd0d46ebSvictorle done: 24239566063dSJacob Faibussowitsch PetscCall(PetscFree(aptr)); 24249566063dSJacob Faibussowitsch PetscCall(PetscFree(bptr)); 24259566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&va)); 24269566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B,&vb)); 2427cd0d46ebSvictorle PetscFunctionReturn(0); 2428cd0d46ebSvictorle } 2429cd0d46ebSvictorle 24307087cfbeSBarry Smith PetscErrorCode MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool *f) 24311cbb95d3SBarry Smith { 24323d3eaba7SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data; 243354f21887SBarry Smith PetscInt *adx,*bdx,*aii,*bii,*aptr,*bptr; 243454f21887SBarry Smith MatScalar *va,*vb; 24351cbb95d3SBarry Smith PetscInt ma,na,mb,nb, i; 24361cbb95d3SBarry Smith 24371cbb95d3SBarry Smith PetscFunctionBegin; 24389566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&ma,&na)); 24399566063dSJacob Faibussowitsch PetscCall(MatGetSize(B,&mb,&nb)); 24401cbb95d3SBarry Smith if (ma!=nb || na!=mb) { 24411cbb95d3SBarry Smith *f = PETSC_FALSE; 24421cbb95d3SBarry Smith PetscFunctionReturn(0); 24431cbb95d3SBarry Smith } 24441cbb95d3SBarry Smith aii = aij->i; bii = bij->i; 24451cbb95d3SBarry Smith adx = aij->j; bdx = bij->j; 24461cbb95d3SBarry Smith va = aij->a; vb = bij->a; 24479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ma,&aptr)); 24489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mb,&bptr)); 24491cbb95d3SBarry Smith for (i=0; i<ma; i++) aptr[i] = aii[i]; 24501cbb95d3SBarry Smith for (i=0; i<mb; i++) bptr[i] = bii[i]; 24511cbb95d3SBarry Smith 24521cbb95d3SBarry Smith *f = PETSC_TRUE; 24531cbb95d3SBarry Smith for (i=0; i<ma; i++) { 24541cbb95d3SBarry Smith while (aptr[i]<aii[i+1]) { 24551cbb95d3SBarry Smith PetscInt idc,idr; 24561cbb95d3SBarry Smith PetscScalar vc,vr; 24571cbb95d3SBarry Smith /* column/row index/value */ 24581cbb95d3SBarry Smith idc = adx[aptr[i]]; 24591cbb95d3SBarry Smith idr = bdx[bptr[idc]]; 24601cbb95d3SBarry Smith vc = va[aptr[i]]; 24611cbb95d3SBarry Smith vr = vb[bptr[idc]]; 24621cbb95d3SBarry Smith if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) { 24631cbb95d3SBarry Smith *f = PETSC_FALSE; 24641cbb95d3SBarry Smith goto done; 24651cbb95d3SBarry Smith } else { 24661cbb95d3SBarry Smith aptr[i]++; 24671cbb95d3SBarry Smith if (B || i!=idc) bptr[idc]++; 24681cbb95d3SBarry Smith } 24691cbb95d3SBarry Smith } 24701cbb95d3SBarry Smith } 24711cbb95d3SBarry Smith done: 24729566063dSJacob Faibussowitsch PetscCall(PetscFree(aptr)); 24739566063dSJacob Faibussowitsch PetscCall(PetscFree(bptr)); 24741cbb95d3SBarry Smith PetscFunctionReturn(0); 24751cbb95d3SBarry Smith } 24761cbb95d3SBarry Smith 2477ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool *f) 24789e29f15eSvictorle { 24799e29f15eSvictorle PetscFunctionBegin; 24809566063dSJacob Faibussowitsch PetscCall(MatIsTranspose_SeqAIJ(A,A,tol,f)); 24819e29f15eSvictorle PetscFunctionReturn(0); 24829e29f15eSvictorle } 24839e29f15eSvictorle 2484ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool *f) 24851cbb95d3SBarry Smith { 24861cbb95d3SBarry Smith PetscFunctionBegin; 24879566063dSJacob Faibussowitsch PetscCall(MatIsHermitianTranspose_SeqAIJ(A,A,tol,f)); 24881cbb95d3SBarry Smith PetscFunctionReturn(0); 24891cbb95d3SBarry Smith } 24901cbb95d3SBarry Smith 2491dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr) 249217ab2063SBarry Smith { 2493416022c9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2494fff8e43fSBarry Smith const PetscScalar *l,*r; 2495fff8e43fSBarry Smith PetscScalar x; 249654f21887SBarry Smith MatScalar *v; 2497fff8e43fSBarry Smith PetscInt i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz; 2498fff8e43fSBarry Smith const PetscInt *jj; 249917ab2063SBarry Smith 25003a40ed3dSBarry Smith PetscFunctionBegin; 250117ab2063SBarry Smith if (ll) { 25023ea7c6a1SSatish Balay /* The local size is used so that VecMPI can be passed to this routine 25033ea7c6a1SSatish Balay by MatDiagonalScale_MPIAIJ */ 25049566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ll,&m)); 250508401ef6SPierre Jolivet PetscCheck(m == A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length"); 25069566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(ll,&l)); 25079566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&v)); 250817ab2063SBarry Smith for (i=0; i<m; i++) { 250917ab2063SBarry Smith x = l[i]; 2510416022c9SBarry Smith M = a->i[i+1] - a->i[i]; 25112205254eSKarl Rupp for (j=0; j<M; j++) (*v++) *= x; 251217ab2063SBarry Smith } 25139566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(ll,&l)); 25149566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(nz)); 25159566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&v)); 251617ab2063SBarry Smith } 251717ab2063SBarry Smith if (rr) { 25189566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(rr,&n)); 251908401ef6SPierre Jolivet PetscCheck(n == A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length"); 25209566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(rr,&r)); 25219566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&v)); 25222e5835c6SStefano Zampini jj = a->j; 25232205254eSKarl Rupp for (i=0; i<nz; i++) (*v++) *= r[*jj++]; 25249566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&v)); 25259566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(rr,&r)); 25269566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(nz)); 252717ab2063SBarry Smith } 25289566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 25293a40ed3dSBarry Smith PetscFunctionReturn(0); 253017ab2063SBarry Smith } 253117ab2063SBarry Smith 25327dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B) 253317ab2063SBarry Smith { 2534db02288aSLois Curfman McInnes Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*c; 2535d0f46423SBarry Smith PetscInt *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens; 253697f1f81fSBarry Smith PetscInt row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi; 25375d0c19d7SBarry Smith const PetscInt *irow,*icol; 25382e5835c6SStefano Zampini const PetscScalar *aa; 25395d0c19d7SBarry Smith PetscInt nrows,ncols; 254097f1f81fSBarry Smith PetscInt *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen; 254154f21887SBarry Smith MatScalar *a_new,*mat_a; 2542416022c9SBarry Smith Mat C; 2543cdc6f3adSToby Isaac PetscBool stride; 254417ab2063SBarry Smith 25453a40ed3dSBarry Smith PetscFunctionBegin; 25469566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow,&irow)); 25479566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrow,&nrows)); 25489566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscol,&ncols)); 254917ab2063SBarry Smith 25509566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride)); 2551ff718158SBarry Smith if (stride) { 25529566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(iscol,&first,&step)); 2553ff718158SBarry Smith } else { 2554ff718158SBarry Smith first = 0; 2555ff718158SBarry Smith step = 0; 2556ff718158SBarry Smith } 2557fee21e36SBarry Smith if (stride && step == 1) { 255802834360SBarry Smith /* special case of contiguous rows */ 25599566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nrows,&lens,nrows,&starts)); 256002834360SBarry Smith /* loop over new rows determining lens and starting points */ 256102834360SBarry Smith for (i=0; i<nrows; i++) { 2562bfeeae90SHong Zhang kstart = ai[irow[i]]; 2563a2744918SBarry Smith kend = kstart + ailen[irow[i]]; 2564a91a9bebSLisandro Dalcin starts[i] = kstart; 256502834360SBarry Smith for (k=kstart; k<kend; k++) { 2566bfeeae90SHong Zhang if (aj[k] >= first) { 256702834360SBarry Smith starts[i] = k; 256802834360SBarry Smith break; 256902834360SBarry Smith } 257002834360SBarry Smith } 2571a2744918SBarry Smith sum = 0; 257202834360SBarry Smith while (k < kend) { 2573bfeeae90SHong Zhang if (aj[k++] >= first+ncols) break; 2574a2744918SBarry Smith sum++; 257502834360SBarry Smith } 2576a2744918SBarry Smith lens[i] = sum; 257702834360SBarry Smith } 257802834360SBarry Smith /* create submatrix */ 2579cddf8d76SBarry Smith if (scall == MAT_REUSE_MATRIX) { 258097f1f81fSBarry Smith PetscInt n_cols,n_rows; 25819566063dSJacob Faibussowitsch PetscCall(MatGetSize(*B,&n_rows,&n_cols)); 2582aed4548fSBarry Smith PetscCheck(n_rows == nrows && n_cols == ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size"); 25839566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*B)); 258408480c60SBarry Smith C = *B; 25853a40ed3dSBarry Smith } else { 25863bef6203SJed Brown PetscInt rbs,cbs; 25879566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),&C)); 25889566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE)); 25899566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(isrow,&rbs)); 25909566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(iscol,&cbs)); 25919566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(C,rbs,cbs)); 25929566063dSJacob Faibussowitsch PetscCall(MatSetType(C,((PetscObject)A)->type_name)); 25939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens)); 259408480c60SBarry Smith } 2595db02288aSLois Curfman McInnes c = (Mat_SeqAIJ*)C->data; 2596db02288aSLois Curfman McInnes 259702834360SBarry Smith /* loop over rows inserting into submatrix */ 2598db02288aSLois Curfman McInnes a_new = c->a; 2599db02288aSLois Curfman McInnes j_new = c->j; 2600db02288aSLois Curfman McInnes i_new = c->i; 26019566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 260202834360SBarry Smith for (i=0; i<nrows; i++) { 2603a2744918SBarry Smith ii = starts[i]; 2604a2744918SBarry Smith lensi = lens[i]; 2605a2744918SBarry Smith for (k=0; k<lensi; k++) { 2606a2744918SBarry Smith *j_new++ = aj[ii+k] - first; 260702834360SBarry Smith } 26089566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a_new,aa + starts[i],lensi)); 2609a2744918SBarry Smith a_new += lensi; 2610a2744918SBarry Smith i_new[i+1] = i_new[i] + lensi; 2611a2744918SBarry Smith c->ilen[i] = lensi; 261202834360SBarry Smith } 26139566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 26149566063dSJacob Faibussowitsch PetscCall(PetscFree2(lens,starts)); 26153a40ed3dSBarry Smith } else { 26169566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol,&icol)); 26179566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(oldcols,&smap)); 26189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1+nrows,&lens)); 26194dcab191SBarry Smith for (i=0; i<ncols; i++) { 26206bdcaf15SBarry 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); 26214dcab191SBarry Smith smap[icol[i]] = i+1; 26224dcab191SBarry Smith } 26234dcab191SBarry Smith 262402834360SBarry Smith /* determine lens of each row */ 262502834360SBarry Smith for (i=0; i<nrows; i++) { 2626bfeeae90SHong Zhang kstart = ai[irow[i]]; 262702834360SBarry Smith kend = kstart + a->ilen[irow[i]]; 262802834360SBarry Smith lens[i] = 0; 262902834360SBarry Smith for (k=kstart; k<kend; k++) { 2630bfeeae90SHong Zhang if (smap[aj[k]]) { 263102834360SBarry Smith lens[i]++; 263202834360SBarry Smith } 263302834360SBarry Smith } 263402834360SBarry Smith } 263517ab2063SBarry Smith /* Create and fill new matrix */ 2636a2744918SBarry Smith if (scall == MAT_REUSE_MATRIX) { 2637ace3abfcSBarry Smith PetscBool equal; 26380f5bd95cSBarry Smith 263999141d43SSatish Balay c = (Mat_SeqAIJ*)((*B)->data); 2640aed4548fSBarry Smith PetscCheck((*B)->rmap->n == nrows && (*B)->cmap->n == ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size"); 26419566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal)); 264228b400f6SJacob Faibussowitsch PetscCheck(equal,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros"); 26439566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->ilen,(*B)->rmap->n)); 264408480c60SBarry Smith C = *B; 26453a40ed3dSBarry Smith } else { 26463bef6203SJed Brown PetscInt rbs,cbs; 26479566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),&C)); 26489566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE)); 26499566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(isrow,&rbs)); 26509566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(iscol,&cbs)); 26519566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(C,rbs,cbs)); 26529566063dSJacob Faibussowitsch PetscCall(MatSetType(C,((PetscObject)A)->type_name)); 26539566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens)); 265408480c60SBarry Smith } 26559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 265699141d43SSatish Balay c = (Mat_SeqAIJ*)(C->data); 265717ab2063SBarry Smith for (i=0; i<nrows; i++) { 265899141d43SSatish Balay row = irow[i]; 2659bfeeae90SHong Zhang kstart = ai[row]; 266099141d43SSatish Balay kend = kstart + a->ilen[row]; 2661bfeeae90SHong Zhang mat_i = c->i[i]; 266299141d43SSatish Balay mat_j = c->j + mat_i; 266399141d43SSatish Balay mat_a = c->a + mat_i; 266499141d43SSatish Balay mat_ilen = c->ilen + i; 266517ab2063SBarry Smith for (k=kstart; k<kend; k++) { 2666bfeeae90SHong Zhang if ((tcol=smap[a->j[k]])) { 2667ed480e8bSBarry Smith *mat_j++ = tcol - 1; 26682e5835c6SStefano Zampini *mat_a++ = aa[k]; 266999141d43SSatish Balay (*mat_ilen)++; 267099141d43SSatish Balay 267117ab2063SBarry Smith } 267217ab2063SBarry Smith } 267317ab2063SBarry Smith } 26749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 267502834360SBarry Smith /* Free work space */ 26769566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol,&icol)); 26779566063dSJacob Faibussowitsch PetscCall(PetscFree(smap)); 26789566063dSJacob Faibussowitsch PetscCall(PetscFree(lens)); 2679cdc6f3adSToby Isaac /* sort */ 2680cdc6f3adSToby Isaac for (i = 0; i < nrows; i++) { 2681cdc6f3adSToby Isaac PetscInt ilen; 2682cdc6f3adSToby Isaac 2683cdc6f3adSToby Isaac mat_i = c->i[i]; 2684cdc6f3adSToby Isaac mat_j = c->j + mat_i; 2685cdc6f3adSToby Isaac mat_a = c->a + mat_i; 2686cdc6f3adSToby Isaac ilen = c->ilen[i]; 26879566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(ilen,mat_j,mat_a)); 2688cdc6f3adSToby Isaac } 268902834360SBarry Smith } 26908c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE) 26919566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(C,A->boundtocpu)); 2692305c6ccfSStefano Zampini #endif 26939566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY)); 26949566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY)); 269517ab2063SBarry Smith 26969566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow,&irow)); 2697416022c9SBarry Smith *B = C; 26983a40ed3dSBarry Smith PetscFunctionReturn(0); 269917ab2063SBarry Smith } 270017ab2063SBarry Smith 2701fc08c53fSHong Zhang PetscErrorCode MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat) 270282d44351SHong Zhang { 270382d44351SHong Zhang Mat B; 270482d44351SHong Zhang 270582d44351SHong Zhang PetscFunctionBegin; 2706c2d650bdSHong Zhang if (scall == MAT_INITIAL_MATRIX) { 27079566063dSJacob Faibussowitsch PetscCall(MatCreate(subComm,&B)); 27089566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n)); 27099566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B,mat,mat)); 27109566063dSJacob Faibussowitsch PetscCall(MatSetType(B,MATSEQAIJ)); 27119566063dSJacob Faibussowitsch PetscCall(MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE)); 271282d44351SHong Zhang *subMat = B; 2713c2d650bdSHong Zhang } else { 27149566063dSJacob Faibussowitsch PetscCall(MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN)); 2715c2d650bdSHong Zhang } 271682d44351SHong Zhang PetscFunctionReturn(0); 271782d44351SHong Zhang } 271882d44351SHong Zhang 27199a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info) 2720a871dcd8SBarry Smith { 272163b91edcSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data; 272263b91edcSBarry Smith Mat outA; 2723ace3abfcSBarry Smith PetscBool row_identity,col_identity; 272463b91edcSBarry Smith 27253a40ed3dSBarry Smith PetscFunctionBegin; 272608401ef6SPierre Jolivet PetscCheck(info->levels == 0,PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu"); 27271df811f5SHong Zhang 27289566063dSJacob Faibussowitsch PetscCall(ISIdentity(row,&row_identity)); 27299566063dSJacob Faibussowitsch PetscCall(ISIdentity(col,&col_identity)); 2730a871dcd8SBarry Smith 273163b91edcSBarry Smith outA = inA; 2732d5f3da31SBarry Smith outA->factortype = MAT_FACTOR_LU; 27339566063dSJacob Faibussowitsch PetscCall(PetscFree(inA->solvertype)); 27349566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype)); 27352205254eSKarl Rupp 27369566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)row)); 27379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->row)); 27382205254eSKarl Rupp 2739c3122656SLisandro Dalcin a->row = row; 27402205254eSKarl Rupp 27419566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)col)); 27429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->col)); 27432205254eSKarl Rupp 2744c3122656SLisandro Dalcin a->col = col; 274563b91edcSBarry Smith 274636db0b34SBarry Smith /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */ 27479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&a->icol)); 27489566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(col,PETSC_DECIDE,&a->icol)); 27499566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol)); 2750f0ec6fceSSatish Balay 275194a9d846SBarry Smith if (!a->solve_work) { /* this matrix may have been factored before */ 27529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(inA->rmap->n+1,&a->solve_work)); 27539566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar))); 275494a9d846SBarry Smith } 275563b91edcSBarry Smith 27569566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(inA)); 2757137fb511SHong Zhang if (row_identity && col_identity) { 27589566063dSJacob Faibussowitsch PetscCall(MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info)); 2759137fb511SHong Zhang } else { 27609566063dSJacob Faibussowitsch PetscCall(MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info)); 2761137fb511SHong Zhang } 27623a40ed3dSBarry Smith PetscFunctionReturn(0); 2763a871dcd8SBarry Smith } 2764a871dcd8SBarry Smith 2765f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha) 2766f0b747eeSBarry Smith { 2767f0b747eeSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data; 2768dfa0f9e5SStefano Zampini PetscScalar *v; 2769c5df96a5SBarry Smith PetscBLASInt one = 1,bnz; 27703a40ed3dSBarry Smith 27713a40ed3dSBarry Smith PetscFunctionBegin; 27729566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(inA,&v)); 27739566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(a->nz,&bnz)); 2774dfa0f9e5SStefano Zampini PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&alpha,v,&one)); 27759566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(a->nz)); 27769566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(inA,&v)); 27779566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(inA)); 27783a40ed3dSBarry Smith PetscFunctionReturn(0); 2779f0b747eeSBarry Smith } 2780f0b747eeSBarry Smith 2781f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj) 278216b64355SHong Zhang { 278316b64355SHong Zhang PetscInt i; 278416b64355SHong Zhang 278516b64355SHong Zhang PetscFunctionBegin; 278616b64355SHong Zhang if (!submatj->id) { /* delete data that are linked only to submats[id=0] */ 27879566063dSJacob Faibussowitsch PetscCall(PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr)); 278816b64355SHong Zhang 278916b64355SHong Zhang for (i=0; i<submatj->nrqr; ++i) { 27909566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->sbuf2[i])); 279116b64355SHong Zhang } 27929566063dSJacob Faibussowitsch PetscCall(PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1)); 279316b64355SHong Zhang 279416b64355SHong Zhang if (submatj->rbuf1) { 27959566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rbuf1[0])); 27969566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rbuf1)); 279716b64355SHong Zhang } 279816b64355SHong Zhang 279916b64355SHong Zhang for (i=0; i<submatj->nrqs; ++i) { 28009566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rbuf3[i])); 280116b64355SHong Zhang } 28029566063dSJacob Faibussowitsch PetscCall(PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3)); 28039566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->pa)); 280416b64355SHong Zhang } 280516b64355SHong Zhang 280616b64355SHong Zhang #if defined(PETSC_USE_CTABLE) 28079566063dSJacob Faibussowitsch PetscCall(PetscTableDestroy((PetscTable*)&submatj->rmap)); 28089566063dSJacob Faibussowitsch if (submatj->cmap_loc) PetscCall(PetscFree(submatj->cmap_loc)); 28099566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rmap_loc)); 281016b64355SHong Zhang #else 28119566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->rmap)); 281216b64355SHong Zhang #endif 281316b64355SHong Zhang 281416b64355SHong Zhang if (!submatj->allcolumns) { 281516b64355SHong Zhang #if defined(PETSC_USE_CTABLE) 28169566063dSJacob Faibussowitsch PetscCall(PetscTableDestroy((PetscTable*)&submatj->cmap)); 281716b64355SHong Zhang #else 28189566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->cmap)); 281916b64355SHong Zhang #endif 282016b64355SHong Zhang } 28219566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj->row2proc)); 282216b64355SHong Zhang 28239566063dSJacob Faibussowitsch PetscCall(PetscFree(submatj)); 282416b64355SHong Zhang PetscFunctionReturn(0); 282516b64355SHong Zhang } 282616b64355SHong Zhang 28270fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C) 282816b64355SHong Zhang { 282916b64355SHong Zhang Mat_SeqAIJ *c = (Mat_SeqAIJ*)C->data; 28305c39f6d9SHong Zhang Mat_SubSppt *submatj = c->submatis1; 283116b64355SHong Zhang 283216b64355SHong Zhang PetscFunctionBegin; 28339566063dSJacob Faibussowitsch PetscCall((*submatj->destroy)(C)); 28349566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrix_Private(submatj)); 283516b64355SHong Zhang PetscFunctionReturn(0); 283616b64355SHong Zhang } 283716b64355SHong Zhang 28382d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[]) 28392d033e1fSHong Zhang { 28402d033e1fSHong Zhang PetscInt i; 28410fb991dcSHong Zhang Mat C; 28420fb991dcSHong Zhang Mat_SeqAIJ *c; 28430fb991dcSHong Zhang Mat_SubSppt *submatj; 28442d033e1fSHong Zhang 28452d033e1fSHong Zhang PetscFunctionBegin; 28462d033e1fSHong Zhang for (i=0; i<n; i++) { 28470fb991dcSHong Zhang C = (*mat)[i]; 28480fb991dcSHong Zhang c = (Mat_SeqAIJ*)C->data; 28490fb991dcSHong Zhang submatj = c->submatis1; 28502d033e1fSHong Zhang if (submatj) { 2851682e4c99SStefano Zampini if (--((PetscObject)C)->refct <= 0) { 28529566063dSJacob Faibussowitsch PetscCall((*submatj->destroy)(C)); 28539566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrix_Private(submatj)); 28549566063dSJacob Faibussowitsch PetscCall(PetscFree(C->defaultvectype)); 28559566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&C->rmap)); 28569566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&C->cmap)); 28579566063dSJacob Faibussowitsch PetscCall(PetscHeaderDestroy(&C)); 2858682e4c99SStefano Zampini } 28592d033e1fSHong Zhang } else { 28609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 28612d033e1fSHong Zhang } 28622d033e1fSHong Zhang } 286386e85357SHong Zhang 286463a75b2aSHong Zhang /* Destroy Dummy submatrices created for reuse */ 28659566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices_Dummy(n,mat)); 286663a75b2aSHong Zhang 28679566063dSJacob Faibussowitsch PetscCall(PetscFree(*mat)); 28682d033e1fSHong Zhang PetscFunctionReturn(0); 28692d033e1fSHong Zhang } 28702d033e1fSHong Zhang 28717dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[]) 2872cddf8d76SBarry Smith { 287397f1f81fSBarry Smith PetscInt i; 2874cddf8d76SBarry Smith 28753a40ed3dSBarry Smith PetscFunctionBegin; 2876cddf8d76SBarry Smith if (scall == MAT_INITIAL_MATRIX) { 28779566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n+1,B)); 2878cddf8d76SBarry Smith } 2879cddf8d76SBarry Smith 2880cddf8d76SBarry Smith for (i=0; i<n; i++) { 28819566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i])); 2882cddf8d76SBarry Smith } 28833a40ed3dSBarry Smith PetscFunctionReturn(0); 2884cddf8d76SBarry Smith } 2885cddf8d76SBarry Smith 288697f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov) 28874dcbc457SBarry Smith { 2888e4d965acSSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 28895d0c19d7SBarry Smith PetscInt row,i,j,k,l,m,n,*nidx,isz,val; 28905d0c19d7SBarry Smith const PetscInt *idx; 289197f1f81fSBarry Smith PetscInt start,end,*ai,*aj; 2892f1af5d2fSBarry Smith PetscBT table; 2893bbd702dbSSatish Balay 28943a40ed3dSBarry Smith PetscFunctionBegin; 2895d0f46423SBarry Smith m = A->rmap->n; 2896e4d965acSSatish Balay ai = a->i; 2897bfeeae90SHong Zhang aj = a->j; 28988a047759SSatish Balay 289908401ef6SPierre Jolivet PetscCheck(ov >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used"); 290006763907SSatish Balay 29019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m+1,&nidx)); 29029566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(m,&table)); 290306763907SSatish Balay 2904e4d965acSSatish Balay for (i=0; i<is_max; i++) { 2905b97fc60eSLois Curfman McInnes /* Initialize the two local arrays */ 2906e4d965acSSatish Balay isz = 0; 29079566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(m,table)); 2908e4d965acSSatish Balay 2909e4d965acSSatish Balay /* Extract the indices, assume there can be duplicate entries */ 29109566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is[i],&idx)); 29119566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is[i],&n)); 2912e4d965acSSatish Balay 2913dd097bc3SLois Curfman McInnes /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */ 2914e4d965acSSatish Balay for (j=0; j<n; ++j) { 29152205254eSKarl Rupp if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j]; 29164dcbc457SBarry Smith } 29179566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is[i],&idx)); 29189566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is[i])); 2919e4d965acSSatish Balay 292004a348a9SBarry Smith k = 0; 292104a348a9SBarry Smith for (j=0; j<ov; j++) { /* for each overlap */ 292204a348a9SBarry Smith n = isz; 292306763907SSatish Balay for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */ 2924e4d965acSSatish Balay row = nidx[k]; 2925e4d965acSSatish Balay start = ai[row]; 2926e4d965acSSatish Balay end = ai[row+1]; 292704a348a9SBarry Smith for (l = start; l<end; l++) { 2928efb16452SHong Zhang val = aj[l]; 29292205254eSKarl Rupp if (!PetscBTLookupSet(table,val)) nidx[isz++] = val; 2930e4d965acSSatish Balay } 2931e4d965acSSatish Balay } 2932e4d965acSSatish Balay } 29339566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i))); 2934e4d965acSSatish Balay } 29359566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&table)); 29369566063dSJacob Faibussowitsch PetscCall(PetscFree(nidx)); 29373a40ed3dSBarry Smith PetscFunctionReturn(0); 29384dcbc457SBarry Smith } 293917ab2063SBarry Smith 29400513a670SBarry Smith /* -------------------------------------------------------------- */ 2941dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B) 29420513a670SBarry Smith { 29430513a670SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 29443b98c0a2SBarry Smith PetscInt i,nz = 0,m = A->rmap->n,n = A->cmap->n; 29455d0c19d7SBarry Smith const PetscInt *row,*col; 29465d0c19d7SBarry Smith PetscInt *cnew,j,*lens; 294756cd22aeSBarry Smith IS icolp,irowp; 29480298fd71SBarry Smith PetscInt *cwork = NULL; 29490298fd71SBarry Smith PetscScalar *vwork = NULL; 29500513a670SBarry Smith 29513a40ed3dSBarry Smith PetscFunctionBegin; 29529566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(rowp,PETSC_DECIDE,&irowp)); 29539566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irowp,&row)); 29549566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(colp,PETSC_DECIDE,&icolp)); 29559566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icolp,&col)); 29560513a670SBarry Smith 29570513a670SBarry Smith /* determine lengths of permuted rows */ 29589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m+1,&lens)); 29592205254eSKarl Rupp for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i]; 29609566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),B)); 29619566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B,m,n,m,n)); 29629566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(*B,A,A)); 29639566063dSJacob Faibussowitsch PetscCall(MatSetType(*B,((PetscObject)A)->type_name)); 29649566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens)); 29659566063dSJacob Faibussowitsch PetscCall(PetscFree(lens)); 29660513a670SBarry Smith 29679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n,&cnew)); 29680513a670SBarry Smith for (i=0; i<m; i++) { 29699566063dSJacob Faibussowitsch PetscCall(MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork)); 29702205254eSKarl Rupp for (j=0; j<nz; j++) cnew[j] = col[cwork[j]]; 29719566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES)); 29729566063dSJacob Faibussowitsch PetscCall(MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork)); 29730513a670SBarry Smith } 29749566063dSJacob Faibussowitsch PetscCall(PetscFree(cnew)); 29752205254eSKarl Rupp 29763c7d62e4SBarry Smith (*B)->assembled = PETSC_FALSE; 29772205254eSKarl Rupp 29788c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE) 29799566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(*B,A->boundtocpu)); 29809fe5e383SStefano Zampini #endif 29819566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY)); 29829566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY)); 29839566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irowp,&row)); 29849566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icolp,&col)); 29859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irowp)); 29869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icolp)); 29876768869dSprj- if (rowp == colp) { 29889566063dSJacob Faibussowitsch PetscCall(MatPropagateSymmetryOptions(A,*B)); 29896768869dSprj- } 29903a40ed3dSBarry Smith PetscFunctionReturn(0); 29910513a670SBarry Smith } 29920513a670SBarry Smith 2993dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str) 2994cb5b572fSBarry Smith { 2995cb5b572fSBarry Smith PetscFunctionBegin; 299633f4a19fSKris Buschelman /* If the two matrices have the same copy implementation, use fast copy. */ 299733f4a19fSKris Buschelman if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) { 2998be6bf707SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 2999be6bf707SBarry Smith Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 30002e5835c6SStefano Zampini const PetscScalar *aa; 3001be6bf707SBarry Smith 30029566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 300308401ef6SPierre 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]); 30049566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->a,aa,a->i[A->rmap->n])); 30059566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 30069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 3007cb5b572fSBarry Smith } else { 30089566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A,B,str)); 3009cb5b572fSBarry Smith } 3010cb5b572fSBarry Smith PetscFunctionReturn(0); 3011cb5b572fSBarry Smith } 3012cb5b572fSBarry Smith 30134994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A) 3014273d9f13SBarry Smith { 3015273d9f13SBarry Smith PetscFunctionBegin; 30169566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,NULL)); 3017273d9f13SBarry Smith PetscFunctionReturn(0); 3018273d9f13SBarry Smith } 3019273d9f13SBarry Smith 3020f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[]) 30216c0721eeSBarry Smith { 30226c0721eeSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 30236e111a19SKarl Rupp 30246c0721eeSBarry Smith PetscFunctionBegin; 30256c0721eeSBarry Smith *array = a->a; 30266c0721eeSBarry Smith PetscFunctionReturn(0); 30276c0721eeSBarry Smith } 30286c0721eeSBarry Smith 3029f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[]) 30306c0721eeSBarry Smith { 30316c0721eeSBarry Smith PetscFunctionBegin; 3032f38c1e66SStefano Zampini *array = NULL; 30336c0721eeSBarry Smith PetscFunctionReturn(0); 30346c0721eeSBarry Smith } 3035273d9f13SBarry Smith 30368229c054SShri Abhyankar /* 30378229c054SShri Abhyankar Computes the number of nonzeros per row needed for preallocation when X and Y 30388229c054SShri Abhyankar have different nonzero structure. 30398229c054SShri Abhyankar */ 3040b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz) 3041ec7775f6SShri Abhyankar { 3042b264fe52SHong Zhang PetscInt i,j,k,nzx,nzy; 3043ec7775f6SShri Abhyankar 3044ec7775f6SShri Abhyankar PetscFunctionBegin; 3045ec7775f6SShri Abhyankar /* Set the number of nonzeros in the new matrix */ 3046ec7775f6SShri Abhyankar for (i=0; i<m; i++) { 3047b264fe52SHong Zhang const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i]; 3048b264fe52SHong Zhang nzx = xi[i+1] - xi[i]; 3049b264fe52SHong Zhang nzy = yi[i+1] - yi[i]; 30508af7cee1SJed Brown nnz[i] = 0; 30518af7cee1SJed Brown for (j=0,k=0; j<nzx; j++) { /* Point in X */ 3052b264fe52SHong Zhang for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */ 3053b264fe52SHong Zhang if (k<nzy && yjj[k]==xjj[j]) k++; /* Skip duplicate */ 30548af7cee1SJed Brown nnz[i]++; 30558af7cee1SJed Brown } 30568af7cee1SJed Brown for (; k<nzy; k++) nnz[i]++; 3057ec7775f6SShri Abhyankar } 3058ec7775f6SShri Abhyankar PetscFunctionReturn(0); 3059ec7775f6SShri Abhyankar } 3060ec7775f6SShri Abhyankar 3061b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz) 3062b264fe52SHong Zhang { 3063b264fe52SHong Zhang PetscInt m = Y->rmap->N; 3064b264fe52SHong Zhang Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data; 3065b264fe52SHong Zhang Mat_SeqAIJ *y = (Mat_SeqAIJ*)Y->data; 3066b264fe52SHong Zhang 3067b264fe52SHong Zhang PetscFunctionBegin; 3068b264fe52SHong Zhang /* Set the number of nonzeros in the new matrix */ 30699566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz)); 3070b264fe52SHong Zhang PetscFunctionReturn(0); 3071b264fe52SHong Zhang } 3072b264fe52SHong Zhang 3073f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str) 3074ac90fabeSBarry Smith { 3075ac90fabeSBarry Smith Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data; 3076ac90fabeSBarry Smith 3077ac90fabeSBarry Smith PetscFunctionBegin; 3078134adf20SPierre Jolivet if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) { 3079134adf20SPierre Jolivet PetscBool e = x->nz == y->nz ? PETSC_TRUE : PETSC_FALSE; 3080134adf20SPierre Jolivet if (e) { 30819566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e)); 308281fa06acSBarry Smith if (e) { 30839566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(x->j,y->j,y->nz,&e)); 3084134adf20SPierre Jolivet if (e) str = SAME_NONZERO_PATTERN; 308581fa06acSBarry Smith } 308681fa06acSBarry Smith } 308754c59aa7SJacob Faibussowitsch if (!e) PetscCheck(str != SAME_NONZERO_PATTERN,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"MatStructure is not SAME_NONZERO_PATTERN"); 308881fa06acSBarry Smith } 3089ac90fabeSBarry Smith if (str == SAME_NONZERO_PATTERN) { 30902e5835c6SStefano Zampini const PetscScalar *xa; 30912e5835c6SStefano Zampini PetscScalar *ya,alpha = a; 309281fa06acSBarry Smith PetscBLASInt one = 1,bnz; 309381fa06acSBarry Smith 30949566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(x->nz,&bnz)); 30959566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Y,&ya)); 30969566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(X,&xa)); 30972e5835c6SStefano Zampini PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,xa,&one,ya,&one)); 30989566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(X,&xa)); 30999566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Y,&ya)); 31009566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2.0*bnz)); 31019566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(Y)); 31029566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)Y)); 3103ab784542SHong Zhang } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 31049566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y,a,X,str)); 3105ac90fabeSBarry Smith } else { 31068229c054SShri Abhyankar Mat B; 31078229c054SShri Abhyankar PetscInt *nnz; 31089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Y->rmap->N,&nnz)); 31099566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)Y),&B)); 31109566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name)); 31119566063dSJacob Faibussowitsch PetscCall(MatSetLayouts(B,Y->rmap,Y->cmap)); 31129566063dSJacob Faibussowitsch PetscCall(MatSetType(B,((PetscObject)Y)->type_name)); 31139566063dSJacob Faibussowitsch PetscCall(MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz)); 31149566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B,0,nnz)); 31159566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B,Y,a,X,str)); 31169566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y,&B)); 31179566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 3118ac90fabeSBarry Smith } 3119ac90fabeSBarry Smith PetscFunctionReturn(0); 3120ac90fabeSBarry Smith } 3121ac90fabeSBarry Smith 31222726fb6dSPierre Jolivet PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat) 3123354c94deSBarry Smith { 3124354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX) 3125354c94deSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3126354c94deSBarry Smith PetscInt i,nz; 3127354c94deSBarry Smith PetscScalar *a; 3128354c94deSBarry Smith 3129354c94deSBarry Smith PetscFunctionBegin; 3130354c94deSBarry Smith nz = aij->nz; 31319566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(mat,&a)); 31322205254eSKarl Rupp for (i=0; i<nz; i++) a[i] = PetscConj(a[i]); 31339566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(mat,&a)); 3134354c94deSBarry Smith #else 3135354c94deSBarry Smith PetscFunctionBegin; 3136354c94deSBarry Smith #endif 3137354c94deSBarry Smith PetscFunctionReturn(0); 3138354c94deSBarry Smith } 3139354c94deSBarry Smith 3140985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 3141e34fafa9SBarry Smith { 3142e34fafa9SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3143d0f46423SBarry Smith PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 3144e34fafa9SBarry Smith PetscReal atmp; 3145985db425SBarry Smith PetscScalar *x; 3146ce496241SStefano Zampini const MatScalar *aa,*av; 3147e34fafa9SBarry Smith 3148e34fafa9SBarry Smith PetscFunctionBegin; 314928b400f6SJacob Faibussowitsch PetscCheck(!A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 31509566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&av)); 3151ce496241SStefano Zampini aa = av; 3152e34fafa9SBarry Smith ai = a->i; 3153e34fafa9SBarry Smith aj = a->j; 3154e34fafa9SBarry Smith 31559566063dSJacob Faibussowitsch PetscCall(VecSet(v,0.0)); 31569566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v,&x)); 31579566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v,&n)); 315808401ef6SPierre Jolivet PetscCheck(n == A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 3159e34fafa9SBarry Smith for (i=0; i<m; i++) { 3160e34fafa9SBarry Smith ncols = ai[1] - ai[0]; ai++; 3161e34fafa9SBarry Smith for (j=0; j<ncols; j++) { 3162985db425SBarry Smith atmp = PetscAbsScalar(*aa); 3163985db425SBarry Smith if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;} 3164985db425SBarry Smith aa++; aj++; 3165985db425SBarry Smith } 3166985db425SBarry Smith } 31679566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v,&x)); 31689566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&av)); 3169985db425SBarry Smith PetscFunctionReturn(0); 3170985db425SBarry Smith } 3171985db425SBarry Smith 3172985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 3173985db425SBarry Smith { 3174985db425SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3175d0f46423SBarry Smith PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 3176985db425SBarry Smith PetscScalar *x; 3177ce496241SStefano Zampini const MatScalar *aa,*av; 3178985db425SBarry Smith 3179985db425SBarry Smith PetscFunctionBegin; 318028b400f6SJacob Faibussowitsch PetscCheck(!A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 31819566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&av)); 3182ce496241SStefano Zampini aa = av; 3183985db425SBarry Smith ai = a->i; 3184985db425SBarry Smith aj = a->j; 3185985db425SBarry Smith 31869566063dSJacob Faibussowitsch PetscCall(VecSet(v,0.0)); 31879566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v,&x)); 31889566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v,&n)); 318908401ef6SPierre Jolivet PetscCheck(n == A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 3190985db425SBarry Smith for (i=0; i<m; i++) { 3191985db425SBarry Smith ncols = ai[1] - ai[0]; ai++; 3192d0f46423SBarry Smith if (ncols == A->cmap->n) { /* row is dense */ 3193985db425SBarry Smith x[i] = *aa; if (idx) idx[i] = 0; 3194985db425SBarry Smith } else { /* row is sparse so already KNOW maximum is 0.0 or higher */ 3195985db425SBarry Smith x[i] = 0.0; 3196985db425SBarry Smith if (idx) { 3197985db425SBarry Smith for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */ 3198985db425SBarry Smith if (aj[j] > j) { 3199985db425SBarry Smith idx[i] = j; 3200985db425SBarry Smith break; 3201985db425SBarry Smith } 3202985db425SBarry Smith } 32031a254869SHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 32041a254869SHong Zhang if (j==ncols && j < A->cmap->n) idx[i] = j; 3205985db425SBarry Smith } 3206985db425SBarry Smith } 3207985db425SBarry Smith for (j=0; j<ncols; j++) { 3208985db425SBarry Smith if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 3209985db425SBarry Smith aa++; aj++; 3210985db425SBarry Smith } 3211985db425SBarry Smith } 32129566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v,&x)); 32139566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&av)); 3214985db425SBarry Smith PetscFunctionReturn(0); 3215985db425SBarry Smith } 3216985db425SBarry Smith 3217c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 3218c87e5d42SMatthew Knepley { 3219c87e5d42SMatthew Knepley Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3220c87e5d42SMatthew Knepley PetscInt i,j,m = A->rmap->n,*ai,*aj,ncols,n; 3221ce496241SStefano Zampini PetscScalar *x; 3222ce496241SStefano Zampini const MatScalar *aa,*av; 3223c87e5d42SMatthew Knepley 3224c87e5d42SMatthew Knepley PetscFunctionBegin; 32259566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&av)); 3226ce496241SStefano Zampini aa = av; 3227c87e5d42SMatthew Knepley ai = a->i; 3228c87e5d42SMatthew Knepley aj = a->j; 3229c87e5d42SMatthew Knepley 32309566063dSJacob Faibussowitsch PetscCall(VecSet(v,0.0)); 32319566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v,&x)); 32329566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v,&n)); 323308401ef6SPierre Jolivet PetscCheck(n == m,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %" PetscInt_FMT " vs. %" PetscInt_FMT " rows", m, n); 3234c87e5d42SMatthew Knepley for (i=0; i<m; i++) { 3235c87e5d42SMatthew Knepley ncols = ai[1] - ai[0]; ai++; 3236f07e67edSHong Zhang if (ncols == A->cmap->n) { /* row is dense */ 3237f07e67edSHong Zhang x[i] = *aa; if (idx) idx[i] = 0; 3238f07e67edSHong Zhang } else { /* row is sparse so already KNOW minimum is 0.0 or higher */ 3239f07e67edSHong Zhang x[i] = 0.0; 3240f07e67edSHong Zhang if (idx) { /* find first implicit 0.0 in the row */ 3241289a08f5SMatthew Knepley for (j=0; j<ncols; j++) { 3242f07e67edSHong Zhang if (aj[j] > j) { 3243f07e67edSHong Zhang idx[i] = j; 32442205254eSKarl Rupp break; 32452205254eSKarl Rupp } 3246289a08f5SMatthew Knepley } 3247f07e67edSHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3248f07e67edSHong Zhang if (j==ncols && j < A->cmap->n) idx[i] = j; 3249f07e67edSHong Zhang } 3250289a08f5SMatthew Knepley } 3251c87e5d42SMatthew Knepley for (j=0; j<ncols; j++) { 3252f07e67edSHong Zhang if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 3253c87e5d42SMatthew Knepley aa++; aj++; 3254c87e5d42SMatthew Knepley } 3255c87e5d42SMatthew Knepley } 32569566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v,&x)); 32579566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&av)); 3258c87e5d42SMatthew Knepley PetscFunctionReturn(0); 3259c87e5d42SMatthew Knepley } 3260c87e5d42SMatthew Knepley 3261985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[]) 3262985db425SBarry Smith { 3263985db425SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 3264d9ca1df4SBarry Smith PetscInt i,j,m = A->rmap->n,ncols,n; 3265d9ca1df4SBarry Smith const PetscInt *ai,*aj; 3266985db425SBarry Smith PetscScalar *x; 3267ce496241SStefano Zampini const MatScalar *aa,*av; 3268985db425SBarry Smith 3269985db425SBarry Smith PetscFunctionBegin; 327028b400f6SJacob Faibussowitsch PetscCheck(!A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 32719566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&av)); 3272ce496241SStefano Zampini aa = av; 3273985db425SBarry Smith ai = a->i; 3274985db425SBarry Smith aj = a->j; 3275985db425SBarry Smith 32769566063dSJacob Faibussowitsch PetscCall(VecSet(v,0.0)); 32779566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(v,&x)); 32789566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v,&n)); 327908401ef6SPierre Jolivet PetscCheck(n == m,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector"); 3280985db425SBarry Smith for (i=0; i<m; i++) { 3281985db425SBarry Smith ncols = ai[1] - ai[0]; ai++; 3282d0f46423SBarry Smith if (ncols == A->cmap->n) { /* row is dense */ 3283985db425SBarry Smith x[i] = *aa; if (idx) idx[i] = 0; 3284985db425SBarry Smith } else { /* row is sparse so already KNOW minimum is 0.0 or lower */ 3285985db425SBarry Smith x[i] = 0.0; 3286985db425SBarry Smith if (idx) { /* find first implicit 0.0 in the row */ 3287985db425SBarry Smith for (j=0; j<ncols; j++) { 3288985db425SBarry Smith if (aj[j] > j) { 3289985db425SBarry Smith idx[i] = j; 3290985db425SBarry Smith break; 3291985db425SBarry Smith } 3292985db425SBarry Smith } 3293fa213d2fSHong Zhang /* in case first implicit 0.0 in the row occurs at ncols-th column */ 3294fa213d2fSHong Zhang if (j==ncols && j < A->cmap->n) idx[i] = j; 3295985db425SBarry Smith } 3296985db425SBarry Smith } 3297985db425SBarry Smith for (j=0; j<ncols; j++) { 3298985db425SBarry Smith if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;} 3299985db425SBarry Smith aa++; aj++; 3300e34fafa9SBarry Smith } 3301e34fafa9SBarry Smith } 33029566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(v,&x)); 33039566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&av)); 3304e34fafa9SBarry Smith PetscFunctionReturn(0); 3305e34fafa9SBarry Smith } 3306bbead8a2SBarry Smith 3307713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values) 3308bbead8a2SBarry Smith { 3309bbead8a2SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*) A->data; 331033d57670SJed Brown PetscInt i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j; 3311bbead8a2SBarry Smith MatScalar *diag,work[25],*v_work; 33120da83c2eSBarry Smith const PetscReal shift = 0.0; 33131a9391e3SHong Zhang PetscBool allowzeropivot,zeropivotdetected=PETSC_FALSE; 3314bbead8a2SBarry Smith 3315bbead8a2SBarry Smith PetscFunctionBegin; 3316a455e926SHong Zhang allowzeropivot = PetscNot(A->erroriffailure); 33174a0d0026SBarry Smith if (a->ibdiagvalid) { 33184a0d0026SBarry Smith if (values) *values = a->ibdiag; 33194a0d0026SBarry Smith PetscFunctionReturn(0); 33204a0d0026SBarry Smith } 33219566063dSJacob Faibussowitsch PetscCall(MatMarkDiagonal_SeqAIJ(A)); 3322bbead8a2SBarry Smith if (!a->ibdiag) { 33239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bs2*mbs,&a->ibdiag)); 33249566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar))); 3325bbead8a2SBarry Smith } 3326bbead8a2SBarry Smith diag = a->ibdiag; 3327bbead8a2SBarry Smith if (values) *values = a->ibdiag; 3328bbead8a2SBarry Smith /* factor and invert each block */ 3329bbead8a2SBarry Smith switch (bs) { 3330bbead8a2SBarry Smith case 1: 3331bbead8a2SBarry Smith for (i=0; i<mbs; i++) { 33329566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,1,&i,1,&i,diag+i)); 3333ec1892c8SHong Zhang if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) { 3334ec1892c8SHong Zhang if (allowzeropivot) { 33357b6c816cSBarry Smith A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33367b6c816cSBarry Smith A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]); 33377b6c816cSBarry Smith A->factorerror_zeropivot_row = i; 33389566063dSJacob Faibussowitsch PetscCall(PetscInfo(A,"Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON)); 333998921bdaSJacob 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); 3340ec1892c8SHong Zhang } 3341bbead8a2SBarry Smith diag[i] = (PetscScalar)1.0 / (diag[i] + shift); 3342bbead8a2SBarry Smith } 3343bbead8a2SBarry Smith break; 3344bbead8a2SBarry Smith case 2: 3345bbead8a2SBarry Smith for (i=0; i<mbs; i++) { 3346bbead8a2SBarry Smith ij[0] = 2*i; ij[1] = 2*i + 1; 33479566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,2,ij,2,ij,diag)); 33489566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected)); 33497b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33509566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_2(diag)); 3351bbead8a2SBarry Smith diag += 4; 3352bbead8a2SBarry Smith } 3353bbead8a2SBarry Smith break; 3354bbead8a2SBarry Smith case 3: 3355bbead8a2SBarry Smith for (i=0; i<mbs; i++) { 3356bbead8a2SBarry Smith ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2; 33579566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,3,ij,3,ij,diag)); 33589566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected)); 33597b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33609566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_3(diag)); 3361bbead8a2SBarry Smith diag += 9; 3362bbead8a2SBarry Smith } 3363bbead8a2SBarry Smith break; 3364bbead8a2SBarry Smith case 4: 3365bbead8a2SBarry Smith for (i=0; i<mbs; i++) { 3366bbead8a2SBarry Smith ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3; 33679566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,4,ij,4,ij,diag)); 33689566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected)); 33697b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33709566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_4(diag)); 3371bbead8a2SBarry Smith diag += 16; 3372bbead8a2SBarry Smith } 3373bbead8a2SBarry Smith break; 3374bbead8a2SBarry Smith case 5: 3375bbead8a2SBarry Smith for (i=0; i<mbs; i++) { 3376bbead8a2SBarry 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; 33779566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,5,ij,5,ij,diag)); 33789566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected)); 33797b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33809566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_5(diag)); 3381bbead8a2SBarry Smith diag += 25; 3382bbead8a2SBarry Smith } 3383bbead8a2SBarry Smith break; 3384bbead8a2SBarry Smith case 6: 3385bbead8a2SBarry Smith for (i=0; i<mbs; i++) { 3386bbead8a2SBarry 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; 33879566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,6,ij,6,ij,diag)); 33889566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected)); 33897b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 33909566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_6(diag)); 3391bbead8a2SBarry Smith diag += 36; 3392bbead8a2SBarry Smith } 3393bbead8a2SBarry Smith break; 3394bbead8a2SBarry Smith case 7: 3395bbead8a2SBarry Smith for (i=0; i<mbs; i++) { 3396bbead8a2SBarry 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; 33979566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,7,ij,7,ij,diag)); 33989566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected)); 33997b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 34009566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_7(diag)); 3401bbead8a2SBarry Smith diag += 49; 3402bbead8a2SBarry Smith } 3403bbead8a2SBarry Smith break; 3404bbead8a2SBarry Smith default: 34059566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ)); 3406bbead8a2SBarry Smith for (i=0; i<mbs; i++) { 3407bbead8a2SBarry Smith for (j=0; j<bs; j++) { 3408bbead8a2SBarry Smith IJ[j] = bs*i + j; 3409bbead8a2SBarry Smith } 34109566063dSJacob Faibussowitsch PetscCall(MatGetValues(A,bs,IJ,bs,IJ,diag)); 34119566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected)); 34127b6c816cSBarry Smith if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT; 34139566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_transpose_A_N(diag,bs)); 3414bbead8a2SBarry Smith diag += bs2; 3415bbead8a2SBarry Smith } 34169566063dSJacob Faibussowitsch PetscCall(PetscFree3(v_work,v_pivots,IJ)); 3417bbead8a2SBarry Smith } 3418bbead8a2SBarry Smith a->ibdiagvalid = PETSC_TRUE; 3419bbead8a2SBarry Smith PetscFunctionReturn(0); 3420bbead8a2SBarry Smith } 3421bbead8a2SBarry Smith 342273a71a0fSBarry Smith static PetscErrorCode MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx) 342373a71a0fSBarry Smith { 342473a71a0fSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)x->data; 3425fff043a9SJunchao Zhang PetscScalar a,*aa; 342673a71a0fSBarry Smith PetscInt m,n,i,j,col; 342773a71a0fSBarry Smith 342873a71a0fSBarry Smith PetscFunctionBegin; 342973a71a0fSBarry Smith if (!x->assembled) { 34309566063dSJacob Faibussowitsch PetscCall(MatGetSize(x,&m,&n)); 343173a71a0fSBarry Smith for (i=0; i<m; i++) { 343273a71a0fSBarry Smith for (j=0; j<aij->imax[i]; j++) { 34339566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValue(rctx,&a)); 343473a71a0fSBarry Smith col = (PetscInt)(n*PetscRealPart(a)); 34359566063dSJacob Faibussowitsch PetscCall(MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES)); 343673a71a0fSBarry Smith } 343773a71a0fSBarry Smith } 3438e2ce353bSJunchao Zhang } else { 34399566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayWrite(x,&aa)); 34409566063dSJacob Faibussowitsch for (i=0; i<aij->nz; i++) PetscCall(PetscRandomGetValue(rctx,aa+i)); 34419566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayWrite(x,&aa)); 3442e2ce353bSJunchao Zhang } 34439566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY)); 34449566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY)); 344573a71a0fSBarry Smith PetscFunctionReturn(0); 344673a71a0fSBarry Smith } 344773a71a0fSBarry Smith 3448679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */ 3449679944adSJunchao Zhang PetscErrorCode MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx) 3450679944adSJunchao Zhang { 3451679944adSJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ*)x->data; 3452679944adSJunchao Zhang PetscScalar a; 3453679944adSJunchao Zhang PetscInt m,n,i,j,col,nskip; 3454679944adSJunchao Zhang 3455679944adSJunchao Zhang PetscFunctionBegin; 3456679944adSJunchao Zhang nskip = high - low; 34579566063dSJacob Faibussowitsch PetscCall(MatGetSize(x,&m,&n)); 3458679944adSJunchao Zhang n -= nskip; /* shrink number of columns where nonzeros can be set */ 3459679944adSJunchao Zhang for (i=0; i<m; i++) { 3460679944adSJunchao Zhang for (j=0; j<aij->imax[i]; j++) { 34619566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValue(rctx,&a)); 3462679944adSJunchao Zhang col = (PetscInt)(n*PetscRealPart(a)); 3463679944adSJunchao Zhang if (col >= low) col += nskip; /* shift col rightward to skip the hole */ 34649566063dSJacob Faibussowitsch PetscCall(MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES)); 3465679944adSJunchao Zhang } 3466e2ce353bSJunchao Zhang } 34679566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY)); 34689566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY)); 3469679944adSJunchao Zhang PetscFunctionReturn(0); 3470679944adSJunchao Zhang } 3471679944adSJunchao Zhang 3472682d7d0cSBarry Smith /* -------------------------------------------------------------------*/ 34730a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ, 3474cb5b572fSBarry Smith MatGetRow_SeqAIJ, 3475cb5b572fSBarry Smith MatRestoreRow_SeqAIJ, 3476cb5b572fSBarry Smith MatMult_SeqAIJ, 347797304618SKris Buschelman /* 4*/ MatMultAdd_SeqAIJ, 34787c922b88SBarry Smith MatMultTranspose_SeqAIJ, 34797c922b88SBarry Smith MatMultTransposeAdd_SeqAIJ, 3480f4259b30SLisandro Dalcin NULL, 3481f4259b30SLisandro Dalcin NULL, 3482f4259b30SLisandro Dalcin NULL, 3483f4259b30SLisandro Dalcin /* 10*/ NULL, 3484cb5b572fSBarry Smith MatLUFactor_SeqAIJ, 3485f4259b30SLisandro Dalcin NULL, 348641f059aeSBarry Smith MatSOR_SeqAIJ, 348791e9d3e2SHong Zhang MatTranspose_SeqAIJ, 348897304618SKris Buschelman /*1 5*/ MatGetInfo_SeqAIJ, 3489cb5b572fSBarry Smith MatEqual_SeqAIJ, 3490cb5b572fSBarry Smith MatGetDiagonal_SeqAIJ, 3491cb5b572fSBarry Smith MatDiagonalScale_SeqAIJ, 3492cb5b572fSBarry Smith MatNorm_SeqAIJ, 3493f4259b30SLisandro Dalcin /* 20*/ NULL, 3494cb5b572fSBarry Smith MatAssemblyEnd_SeqAIJ, 3495cb5b572fSBarry Smith MatSetOption_SeqAIJ, 3496cb5b572fSBarry Smith MatZeroEntries_SeqAIJ, 3497d519adbfSMatthew Knepley /* 24*/ MatZeroRows_SeqAIJ, 3498f4259b30SLisandro Dalcin NULL, 3499f4259b30SLisandro Dalcin NULL, 3500f4259b30SLisandro Dalcin NULL, 3501f4259b30SLisandro Dalcin NULL, 35024994cf47SJed Brown /* 29*/ MatSetUp_SeqAIJ, 3503f4259b30SLisandro Dalcin NULL, 3504f4259b30SLisandro Dalcin NULL, 3505f4259b30SLisandro Dalcin NULL, 3506f4259b30SLisandro Dalcin NULL, 3507d519adbfSMatthew Knepley /* 34*/ MatDuplicate_SeqAIJ, 3508f4259b30SLisandro Dalcin NULL, 3509f4259b30SLisandro Dalcin NULL, 3510cb5b572fSBarry Smith MatILUFactor_SeqAIJ, 3511f4259b30SLisandro Dalcin NULL, 3512d519adbfSMatthew Knepley /* 39*/ MatAXPY_SeqAIJ, 35137dae84e0SHong Zhang MatCreateSubMatrices_SeqAIJ, 3514cb5b572fSBarry Smith MatIncreaseOverlap_SeqAIJ, 3515cb5b572fSBarry Smith MatGetValues_SeqAIJ, 3516cb5b572fSBarry Smith MatCopy_SeqAIJ, 3517d519adbfSMatthew Knepley /* 44*/ MatGetRowMax_SeqAIJ, 3518cb5b572fSBarry Smith MatScale_SeqAIJ, 35197d68702bSBarry Smith MatShift_SeqAIJ, 352079299369SBarry Smith MatDiagonalSet_SeqAIJ, 35216e169961SBarry Smith MatZeroRowsColumns_SeqAIJ, 352273a71a0fSBarry Smith /* 49*/ MatSetRandom_SeqAIJ, 35233b2fbd54SBarry Smith MatGetRowIJ_SeqAIJ, 35243b2fbd54SBarry Smith MatRestoreRowIJ_SeqAIJ, 35253b2fbd54SBarry Smith MatGetColumnIJ_SeqAIJ, 3526a93ec695SBarry Smith MatRestoreColumnIJ_SeqAIJ, 352793dfae19SHong Zhang /* 54*/ MatFDColoringCreate_SeqXAIJ, 3528f4259b30SLisandro Dalcin NULL, 3529f4259b30SLisandro Dalcin NULL, 3530cda55fadSBarry Smith MatPermute_SeqAIJ, 3531f4259b30SLisandro Dalcin NULL, 3532f4259b30SLisandro Dalcin /* 59*/ NULL, 3533b9b97703SBarry Smith MatDestroy_SeqAIJ, 3534b9b97703SBarry Smith MatView_SeqAIJ, 3535f4259b30SLisandro Dalcin NULL, 3536f4259b30SLisandro Dalcin NULL, 3537f4259b30SLisandro Dalcin /* 64*/ NULL, 3538321b30b9SSatish Balay MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ, 3539f4259b30SLisandro Dalcin NULL, 3540f4259b30SLisandro Dalcin NULL, 3541f4259b30SLisandro Dalcin NULL, 3542d519adbfSMatthew Knepley /* 69*/ MatGetRowMaxAbs_SeqAIJ, 3543c87e5d42SMatthew Knepley MatGetRowMinAbs_SeqAIJ, 3544f4259b30SLisandro Dalcin NULL, 3545f4259b30SLisandro Dalcin NULL, 3546f4259b30SLisandro Dalcin NULL, 3547f4259b30SLisandro Dalcin /* 74*/ NULL, 35483acb8795SBarry Smith MatFDColoringApply_AIJ, 3549f4259b30SLisandro Dalcin NULL, 3550f4259b30SLisandro Dalcin NULL, 3551f4259b30SLisandro Dalcin NULL, 35526ce1633cSBarry Smith /* 79*/ MatFindZeroDiagonals_SeqAIJ, 3553f4259b30SLisandro Dalcin NULL, 3554f4259b30SLisandro Dalcin NULL, 3555f4259b30SLisandro Dalcin NULL, 3556bc011b1eSHong Zhang MatLoad_SeqAIJ, 3557d519adbfSMatthew Knepley /* 84*/ MatIsSymmetric_SeqAIJ, 35581cbb95d3SBarry Smith MatIsHermitian_SeqAIJ, 3559f4259b30SLisandro Dalcin NULL, 3560f4259b30SLisandro Dalcin NULL, 3561f4259b30SLisandro Dalcin NULL, 3562f4259b30SLisandro Dalcin /* 89*/ NULL, 3563f4259b30SLisandro Dalcin NULL, 356426be0446SHong Zhang MatMatMultNumeric_SeqAIJ_SeqAIJ, 3565f4259b30SLisandro Dalcin NULL, 3566f4259b30SLisandro Dalcin NULL, 35678fa4b5a6SHong Zhang /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy, 3568f4259b30SLisandro Dalcin NULL, 3569f4259b30SLisandro Dalcin NULL, 35706fc122caSHong Zhang MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ, 3571f4259b30SLisandro Dalcin NULL, 35724222ddf1SHong Zhang /* 99*/ MatProductSetFromOptions_SeqAIJ, 3573f4259b30SLisandro Dalcin NULL, 3574f4259b30SLisandro Dalcin NULL, 357587d4246cSBarry Smith MatConjugate_SeqAIJ, 3576f4259b30SLisandro Dalcin NULL, 3577d519adbfSMatthew Knepley /*104*/ MatSetValuesRow_SeqAIJ, 357899cafbc1SBarry Smith MatRealPart_SeqAIJ, 3579f5edf698SHong Zhang MatImaginaryPart_SeqAIJ, 3580f4259b30SLisandro Dalcin NULL, 3581f4259b30SLisandro Dalcin NULL, 3582cbd44569SHong Zhang /*109*/ MatMatSolve_SeqAIJ, 3583f4259b30SLisandro Dalcin NULL, 35842af78befSBarry Smith MatGetRowMin_SeqAIJ, 3585f4259b30SLisandro Dalcin NULL, 3586599ef60dSHong Zhang MatMissingDiagonal_SeqAIJ, 3587f4259b30SLisandro Dalcin /*114*/ NULL, 3588f4259b30SLisandro Dalcin NULL, 3589f4259b30SLisandro Dalcin NULL, 3590f4259b30SLisandro Dalcin NULL, 3591f4259b30SLisandro Dalcin NULL, 3592f4259b30SLisandro Dalcin /*119*/ NULL, 3593f4259b30SLisandro Dalcin NULL, 3594f4259b30SLisandro Dalcin NULL, 3595f4259b30SLisandro Dalcin NULL, 3596b3a44c85SBarry Smith MatGetMultiProcBlock_SeqAIJ, 35970716a85fSBarry Smith /*124*/ MatFindNonzeroRows_SeqAIJ, 3598a873a8cdSSam Reynolds MatGetColumnReductions_SeqAIJ, 359937868618SMatthew G Knepley MatInvertBlockDiagonal_SeqAIJ, 36000da83c2eSBarry Smith MatInvertVariableBlockDiagonal_SeqAIJ, 3601f4259b30SLisandro Dalcin NULL, 3602f4259b30SLisandro Dalcin /*129*/ NULL, 3603f4259b30SLisandro Dalcin NULL, 3604f4259b30SLisandro Dalcin NULL, 360575648e8dSHong Zhang MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ, 3606b9af6bddSHong Zhang MatTransposeColoringCreate_SeqAIJ, 3607b9af6bddSHong Zhang /*134*/ MatTransColoringApplySpToDen_SeqAIJ, 36082b8ad9a3SHong Zhang MatTransColoringApplyDenToSp_SeqAIJ, 3609f4259b30SLisandro Dalcin NULL, 3610f4259b30SLisandro Dalcin NULL, 36113964eb88SJed Brown MatRARtNumeric_SeqAIJ_SeqAIJ, 3612f4259b30SLisandro Dalcin /*139*/NULL, 3613f4259b30SLisandro Dalcin NULL, 3614f4259b30SLisandro Dalcin NULL, 36153a062f41SBarry Smith MatFDColoringSetUp_SeqXAIJ, 36169c8f2541SHong Zhang MatFindOffBlockDiagonalEntries_SeqAIJ, 36174222ddf1SHong Zhang MatCreateMPIMatConcatenateSeqMat_SeqAIJ, 36184222ddf1SHong Zhang /*145*/MatDestroySubMatrices_SeqAIJ, 3619f4259b30SLisandro Dalcin NULL, 3620f4259b30SLisandro Dalcin NULL 36219e29f15eSvictorle }; 362217ab2063SBarry Smith 36237087cfbeSBarry Smith PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices) 3624bef8e0ddSBarry Smith { 3625bef8e0ddSBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 362697f1f81fSBarry Smith PetscInt i,nz,n; 3627bef8e0ddSBarry Smith 3628bef8e0ddSBarry Smith PetscFunctionBegin; 3629bef8e0ddSBarry Smith nz = aij->maxnz; 3630d0f46423SBarry Smith n = mat->rmap->n; 3631bef8e0ddSBarry Smith for (i=0; i<nz; i++) { 3632bef8e0ddSBarry Smith aij->j[i] = indices[i]; 3633bef8e0ddSBarry Smith } 3634bef8e0ddSBarry Smith aij->nz = nz; 3635bef8e0ddSBarry Smith for (i=0; i<n; i++) { 3636bef8e0ddSBarry Smith aij->ilen[i] = aij->imax[i]; 3637bef8e0ddSBarry Smith } 3638bef8e0ddSBarry Smith PetscFunctionReturn(0); 3639bef8e0ddSBarry Smith } 3640bef8e0ddSBarry Smith 3641a3bb6f32SFande Kong /* 3642ddea5d60SJunchao Zhang * Given a sparse matrix with global column indices, compact it by using a local column space. 3643ddea5d60SJunchao Zhang * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable() 3644ddea5d60SJunchao Zhang */ 3645a3bb6f32SFande Kong PetscErrorCode MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping) 3646a3bb6f32SFande Kong { 3647a3bb6f32SFande Kong Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3648a3bb6f32SFande Kong PetscTable gid1_lid1; 3649a3bb6f32SFande Kong PetscTablePosition tpos; 365025b670f0SStefano Zampini PetscInt gid,lid,i,ec,nz = aij->nz; 365125b670f0SStefano Zampini PetscInt *garray,*jj = aij->j; 3652a3bb6f32SFande Kong 3653a3bb6f32SFande Kong PetscFunctionBegin; 3654a3bb6f32SFande Kong PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3655a3bb6f32SFande Kong PetscValidPointer(mapping,2); 3656a3bb6f32SFande Kong /* use a table */ 36579566063dSJacob Faibussowitsch PetscCall(PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1)); 3658a3bb6f32SFande Kong ec = 0; 365925b670f0SStefano Zampini for (i=0; i<nz; i++) { 366025b670f0SStefano Zampini PetscInt data,gid1 = jj[i] + 1; 36619566063dSJacob Faibussowitsch PetscCall(PetscTableFind(gid1_lid1,gid1,&data)); 3662a3bb6f32SFande Kong if (!data) { 3663a3bb6f32SFande Kong /* one based table */ 36649566063dSJacob Faibussowitsch PetscCall(PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES)); 3665a3bb6f32SFande Kong } 3666a3bb6f32SFande Kong } 3667a3bb6f32SFande Kong /* form array of columns we need */ 36689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ec,&garray)); 36699566063dSJacob Faibussowitsch PetscCall(PetscTableGetHeadPosition(gid1_lid1,&tpos)); 3670a3bb6f32SFande Kong while (tpos) { 36719566063dSJacob Faibussowitsch PetscCall(PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid)); 3672a3bb6f32SFande Kong gid--; 3673a3bb6f32SFande Kong lid--; 3674a3bb6f32SFande Kong garray[lid] = gid; 3675a3bb6f32SFande Kong } 36769566063dSJacob Faibussowitsch PetscCall(PetscSortInt(ec,garray)); /* sort, and rebuild */ 36779566063dSJacob Faibussowitsch PetscCall(PetscTableRemoveAll(gid1_lid1)); 3678a3bb6f32SFande Kong for (i=0; i<ec; i++) { 36799566063dSJacob Faibussowitsch PetscCall(PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES)); 3680a3bb6f32SFande Kong } 3681a3bb6f32SFande Kong /* compact out the extra columns in B */ 368225b670f0SStefano Zampini for (i=0; i<nz; i++) { 368325b670f0SStefano Zampini PetscInt gid1 = jj[i] + 1; 36849566063dSJacob Faibussowitsch PetscCall(PetscTableFind(gid1_lid1,gid1,&lid)); 3685a3bb6f32SFande Kong lid--; 368625b670f0SStefano Zampini jj[i] = lid; 3687a3bb6f32SFande Kong } 36889566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&mat->cmap)); 36899566063dSJacob Faibussowitsch PetscCall(PetscTableDestroy(&gid1_lid1)); 36909566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap)); 36919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping)); 36929566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH)); 3693a3bb6f32SFande Kong PetscFunctionReturn(0); 3694a3bb6f32SFande Kong } 3695a3bb6f32SFande Kong 3696bef8e0ddSBarry Smith /*@ 3697bef8e0ddSBarry Smith MatSeqAIJSetColumnIndices - Set the column indices for all the rows 3698bef8e0ddSBarry Smith in the matrix. 3699bef8e0ddSBarry Smith 3700bef8e0ddSBarry Smith Input Parameters: 3701bef8e0ddSBarry Smith + mat - the SeqAIJ matrix 3702bef8e0ddSBarry Smith - indices - the column indices 3703bef8e0ddSBarry Smith 370415091d37SBarry Smith Level: advanced 370515091d37SBarry Smith 3706bef8e0ddSBarry Smith Notes: 3707bef8e0ddSBarry Smith This can be called if you have precomputed the nonzero structure of the 3708bef8e0ddSBarry Smith matrix and want to provide it to the matrix object to improve the performance 3709bef8e0ddSBarry Smith of the MatSetValues() operation. 3710bef8e0ddSBarry Smith 3711bef8e0ddSBarry Smith You MUST have set the correct numbers of nonzeros per row in the call to 3712d1be2dadSMatthew Knepley MatCreateSeqAIJ(), and the columns indices MUST be sorted. 3713bef8e0ddSBarry Smith 3714bef8e0ddSBarry Smith MUST be called before any calls to MatSetValues(); 3715bef8e0ddSBarry Smith 3716b9617806SBarry Smith The indices should start with zero, not one. 3717b9617806SBarry Smith 3718bef8e0ddSBarry Smith @*/ 37197087cfbeSBarry Smith PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices) 3720bef8e0ddSBarry Smith { 3721bef8e0ddSBarry Smith PetscFunctionBegin; 37220700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 3723dadcf809SJacob Faibussowitsch PetscValidIntPointer(indices,2); 3724cac4c232SBarry Smith PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices)); 3725bef8e0ddSBarry Smith PetscFunctionReturn(0); 3726bef8e0ddSBarry Smith } 3727bef8e0ddSBarry Smith 3728be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/ 3729be6bf707SBarry Smith 37307087cfbeSBarry Smith PetscErrorCode MatStoreValues_SeqAIJ(Mat mat) 3731be6bf707SBarry Smith { 3732be6bf707SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3733d0f46423SBarry Smith size_t nz = aij->i[mat->rmap->n]; 3734be6bf707SBarry Smith 3735be6bf707SBarry Smith PetscFunctionBegin; 373628b400f6SJacob Faibussowitsch PetscCheck(aij->nonew,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 3737be6bf707SBarry Smith 3738be6bf707SBarry Smith /* allocate space for values if not already there */ 3739be6bf707SBarry Smith if (!aij->saved_values) { 37409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz+1,&aij->saved_values)); 37419566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar))); 3742be6bf707SBarry Smith } 3743be6bf707SBarry Smith 3744be6bf707SBarry Smith /* copy values over */ 37459566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->saved_values,aij->a,nz)); 3746be6bf707SBarry Smith PetscFunctionReturn(0); 3747be6bf707SBarry Smith } 3748be6bf707SBarry Smith 3749be6bf707SBarry Smith /*@ 3750be6bf707SBarry Smith MatStoreValues - Stashes a copy of the matrix values; this allows, for 3751be6bf707SBarry Smith example, reuse of the linear part of a Jacobian, while recomputing the 3752be6bf707SBarry Smith nonlinear portion. 3753be6bf707SBarry Smith 3754be6bf707SBarry Smith Collect on Mat 3755be6bf707SBarry Smith 3756be6bf707SBarry Smith Input Parameters: 37570e609b76SBarry Smith . mat - the matrix (currently only AIJ matrices support this option) 3758be6bf707SBarry Smith 375915091d37SBarry Smith Level: advanced 376015091d37SBarry Smith 3761be6bf707SBarry Smith Common Usage, with SNESSolve(): 3762be6bf707SBarry Smith $ Create Jacobian matrix 3763be6bf707SBarry Smith $ Set linear terms into matrix 3764be6bf707SBarry Smith $ Apply boundary conditions to matrix, at this time matrix must have 3765be6bf707SBarry Smith $ final nonzero structure (i.e. setting the nonlinear terms and applying 3766be6bf707SBarry Smith $ boundary conditions again will not change the nonzero structure 3767512a5fc5SBarry Smith $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3768be6bf707SBarry Smith $ ierr = MatStoreValues(mat); 3769be6bf707SBarry Smith $ Call SNESSetJacobian() with matrix 3770be6bf707SBarry Smith $ In your Jacobian routine 3771be6bf707SBarry Smith $ ierr = MatRetrieveValues(mat); 3772be6bf707SBarry Smith $ Set nonlinear terms in matrix 3773be6bf707SBarry Smith 3774be6bf707SBarry Smith Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself: 3775be6bf707SBarry Smith $ // build linear portion of Jacobian 3776512a5fc5SBarry Smith $ ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); 3777be6bf707SBarry Smith $ ierr = MatStoreValues(mat); 3778be6bf707SBarry Smith $ loop over nonlinear iterations 3779be6bf707SBarry Smith $ ierr = MatRetrieveValues(mat); 3780be6bf707SBarry Smith $ // call MatSetValues(mat,...) to set nonliner portion of Jacobian 3781be6bf707SBarry Smith $ // call MatAssemblyBegin/End() on matrix 3782be6bf707SBarry Smith $ Solve linear system with Jacobian 3783be6bf707SBarry Smith $ endloop 3784be6bf707SBarry Smith 3785be6bf707SBarry Smith Notes: 3786be6bf707SBarry Smith Matrix must already be assemblied before calling this routine 3787512a5fc5SBarry Smith Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before 3788be6bf707SBarry Smith calling this routine. 3789be6bf707SBarry Smith 37900c468ba9SBarry Smith When this is called multiple times it overwrites the previous set of stored values 37910c468ba9SBarry Smith and does not allocated additional space. 37920c468ba9SBarry Smith 3793db781477SPatrick Sanan .seealso: `MatRetrieveValues()` 3794be6bf707SBarry Smith 3795be6bf707SBarry Smith @*/ 37967087cfbeSBarry Smith PetscErrorCode MatStoreValues(Mat mat) 3797be6bf707SBarry Smith { 3798be6bf707SBarry Smith PetscFunctionBegin; 37990700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 380028b400f6SJacob Faibussowitsch PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 380128b400f6SJacob Faibussowitsch PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3802cac4c232SBarry Smith PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat)); 3803be6bf707SBarry Smith PetscFunctionReturn(0); 3804be6bf707SBarry Smith } 3805be6bf707SBarry Smith 38067087cfbeSBarry Smith PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat) 3807be6bf707SBarry Smith { 3808be6bf707SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 3809d0f46423SBarry Smith PetscInt nz = aij->i[mat->rmap->n]; 3810be6bf707SBarry Smith 3811be6bf707SBarry Smith PetscFunctionBegin; 381228b400f6SJacob Faibussowitsch PetscCheck(aij->nonew,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first"); 381328b400f6SJacob Faibussowitsch PetscCheck(aij->saved_values,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first"); 3814be6bf707SBarry Smith /* copy values over */ 38159566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(aij->a,aij->saved_values,nz)); 3816be6bf707SBarry Smith PetscFunctionReturn(0); 3817be6bf707SBarry Smith } 3818be6bf707SBarry Smith 3819be6bf707SBarry Smith /*@ 3820be6bf707SBarry Smith MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for 3821be6bf707SBarry Smith example, reuse of the linear part of a Jacobian, while recomputing the 3822be6bf707SBarry Smith nonlinear portion. 3823be6bf707SBarry Smith 3824be6bf707SBarry Smith Collect on Mat 3825be6bf707SBarry Smith 3826be6bf707SBarry Smith Input Parameters: 3827386f7cf9SBarry Smith . mat - the matrix (currently only AIJ matrices support this option) 3828be6bf707SBarry Smith 382915091d37SBarry Smith Level: advanced 383015091d37SBarry Smith 3831db781477SPatrick Sanan .seealso: `MatStoreValues()` 3832be6bf707SBarry Smith 3833be6bf707SBarry Smith @*/ 38347087cfbeSBarry Smith PetscErrorCode MatRetrieveValues(Mat mat) 3835be6bf707SBarry Smith { 3836be6bf707SBarry Smith PetscFunctionBegin; 38370700a824SBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 383828b400f6SJacob Faibussowitsch PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 383928b400f6SJacob Faibussowitsch PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 3840cac4c232SBarry Smith PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat)); 3841be6bf707SBarry Smith PetscFunctionReturn(0); 3842be6bf707SBarry Smith } 3843be6bf707SBarry Smith 3844be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/ 384517ab2063SBarry Smith /*@C 3846682d7d0cSBarry Smith MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format 38470d15e28bSLois Curfman McInnes (the default parallel PETSc format). For good matrix assembly performance 38486e62573dSLois Curfman McInnes the user should preallocate the matrix storage by setting the parameter nz 384951c19458SBarry Smith (or the array nnz). By setting these parameters accurately, performance 38502bd5e0b2SLois Curfman McInnes during matrix assembly can be increased by more than a factor of 50. 385117ab2063SBarry Smith 3852d083f849SBarry Smith Collective 3853db81eaa0SLois Curfman McInnes 385417ab2063SBarry Smith Input Parameters: 3855db81eaa0SLois Curfman McInnes + comm - MPI communicator, set to PETSC_COMM_SELF 385617ab2063SBarry Smith . m - number of rows 385717ab2063SBarry Smith . n - number of columns 385817ab2063SBarry Smith . nz - number of nonzeros per row (same for all rows) 385951c19458SBarry Smith - nnz - array containing the number of nonzeros in the various rows 38600298fd71SBarry Smith (possibly different for each row) or NULL 386117ab2063SBarry Smith 386217ab2063SBarry Smith Output Parameter: 3863416022c9SBarry Smith . A - the matrix 386417ab2063SBarry Smith 3865175b88e8SBarry Smith It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(), 3866f6f02116SRichard Tran Mills MatXXXXSetPreallocation() paradigm instead of this routine directly. 3867175b88e8SBarry Smith [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation] 3868175b88e8SBarry Smith 3869b259b22eSLois Curfman McInnes Notes: 387049a6f317SBarry Smith If nnz is given then nz is ignored 387149a6f317SBarry Smith 387217ab2063SBarry Smith The AIJ format (also called the Yale sparse matrix format or 387317ab2063SBarry Smith compressed row storage), is fully compatible with standard Fortran 77 38740002213bSLois Curfman McInnes storage. That is, the stored row and column indices can begin at 387544cd7ae7SLois Curfman McInnes either one (as in Fortran) or zero. See the users' manual for details. 387617ab2063SBarry Smith 387717ab2063SBarry Smith Specify the preallocated storage with either nz or nnz (not both). 38780298fd71SBarry Smith Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 38793d323bbdSBarry Smith allocation. For large problems you MUST preallocate memory or you 38806da5968aSLois Curfman McInnes will get TERRIBLE performance, see the users' manual chapter on matrices. 388117ab2063SBarry Smith 3882682d7d0cSBarry Smith By default, this format uses inodes (identical nodes) when possible, to 38834fca80b9SLois Curfman McInnes improve numerical efficiency of matrix-vector products and solves. We 3884682d7d0cSBarry Smith search for consecutive rows with the same nonzero structure, thereby 38856c7ebb05SLois Curfman McInnes reusing matrix information to achieve increased efficiency. 38866c7ebb05SLois Curfman McInnes 38876c7ebb05SLois Curfman McInnes Options Database Keys: 3888698d4c6aSKris Buschelman + -mat_no_inode - Do not use inodes 38899db58ca8SBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 389017ab2063SBarry Smith 3891027ccd11SLois Curfman McInnes Level: intermediate 3892027ccd11SLois Curfman McInnes 3893db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()` 389436db0b34SBarry Smith 389517ab2063SBarry Smith @*/ 38967087cfbeSBarry Smith PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A) 389717ab2063SBarry Smith { 38983a40ed3dSBarry Smith PetscFunctionBegin; 38999566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,A)); 39009566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A,m,n,m,n)); 39019566063dSJacob Faibussowitsch PetscCall(MatSetType(*A,MATSEQAIJ)); 39029566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz)); 3903273d9f13SBarry Smith PetscFunctionReturn(0); 3904273d9f13SBarry Smith } 3905273d9f13SBarry Smith 3906273d9f13SBarry Smith /*@C 3907273d9f13SBarry Smith MatSeqAIJSetPreallocation - For good matrix assembly performance 3908273d9f13SBarry Smith the user should preallocate the matrix storage by setting the parameter nz 3909273d9f13SBarry Smith (or the array nnz). By setting these parameters accurately, performance 3910273d9f13SBarry Smith during matrix assembly can be increased by more than a factor of 50. 3911273d9f13SBarry Smith 3912d083f849SBarry Smith Collective 3913273d9f13SBarry Smith 3914273d9f13SBarry Smith Input Parameters: 39151c4f3114SJed Brown + B - The matrix 3916273d9f13SBarry Smith . nz - number of nonzeros per row (same for all rows) 3917273d9f13SBarry Smith - nnz - array containing the number of nonzeros in the various rows 39180298fd71SBarry Smith (possibly different for each row) or NULL 3919273d9f13SBarry Smith 3920273d9f13SBarry Smith Notes: 392149a6f317SBarry Smith If nnz is given then nz is ignored 392249a6f317SBarry Smith 3923273d9f13SBarry Smith The AIJ format (also called the Yale sparse matrix format or 3924273d9f13SBarry Smith compressed row storage), is fully compatible with standard Fortran 77 3925273d9f13SBarry Smith storage. That is, the stored row and column indices can begin at 3926273d9f13SBarry Smith either one (as in Fortran) or zero. See the users' manual for details. 3927273d9f13SBarry Smith 3928273d9f13SBarry Smith Specify the preallocated storage with either nz or nnz (not both). 39290298fd71SBarry Smith Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory 3930273d9f13SBarry Smith allocation. For large problems you MUST preallocate memory or you 3931273d9f13SBarry Smith will get TERRIBLE performance, see the users' manual chapter on matrices. 3932273d9f13SBarry Smith 3933aa95bbe8SBarry Smith You can call MatGetInfo() to get information on how effective the preallocation was; 3934aa95bbe8SBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 3935aa95bbe8SBarry Smith You can also run with the option -info and look for messages with the string 3936aa95bbe8SBarry Smith malloc in them to see if additional memory allocation was needed. 3937aa95bbe8SBarry Smith 3938a96a251dSBarry Smith Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix 3939a96a251dSBarry Smith entries or columns indices 3940a96a251dSBarry Smith 3941273d9f13SBarry Smith By default, this format uses inodes (identical nodes) when possible, to 3942273d9f13SBarry Smith improve numerical efficiency of matrix-vector products and solves. We 3943273d9f13SBarry Smith search for consecutive rows with the same nonzero structure, thereby 3944273d9f13SBarry Smith reusing matrix information to achieve increased efficiency. 3945273d9f13SBarry Smith 3946273d9f13SBarry Smith Options Database Keys: 3947698d4c6aSKris Buschelman + -mat_no_inode - Do not use inodes 394847b2e64bSBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 3949273d9f13SBarry Smith 3950273d9f13SBarry Smith Level: intermediate 3951273d9f13SBarry Smith 3952db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatSetValues()`, `MatSeqAIJSetColumnIndices()`, `MatCreateSeqAIJWithArrays()`, `MatGetInfo()`, 3953db781477SPatrick Sanan `MatSeqAIJSetTotalPreallocation()` 3954273d9f13SBarry Smith 3955273d9f13SBarry Smith @*/ 39567087cfbeSBarry Smith PetscErrorCode MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[]) 3957273d9f13SBarry Smith { 3958a23d5eceSKris Buschelman PetscFunctionBegin; 39596ba663aaSJed Brown PetscValidHeaderSpecific(B,MAT_CLASSID,1); 39606ba663aaSJed Brown PetscValidType(B,1); 3961cac4c232SBarry Smith PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz)); 3962a23d5eceSKris Buschelman PetscFunctionReturn(0); 3963a23d5eceSKris Buschelman } 3964a23d5eceSKris Buschelman 39657087cfbeSBarry Smith PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz) 3966a23d5eceSKris Buschelman { 3967273d9f13SBarry Smith Mat_SeqAIJ *b; 39682576faa2SJed Brown PetscBool skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE; 396997f1f81fSBarry Smith PetscInt i; 3970273d9f13SBarry Smith 3971273d9f13SBarry Smith PetscFunctionBegin; 39722576faa2SJed Brown if (nz >= 0 || nnz) realalloc = PETSC_TRUE; 3973a96a251dSBarry Smith if (nz == MAT_SKIP_ALLOCATION) { 3974c461c341SBarry Smith skipallocation = PETSC_TRUE; 3975c461c341SBarry Smith nz = 0; 3976c461c341SBarry Smith } 39779566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 39789566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 3979899cda47SBarry Smith 3980435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5; 398108401ef6SPierre Jolivet PetscCheck(nz >= 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %" PetscInt_FMT,nz); 3982cf9c20a2SJed Brown if (PetscUnlikelyDebug(nnz)) { 3983d0f46423SBarry Smith for (i=0; i<B->rmap->n; i++) { 398408401ef6SPierre 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]); 398508401ef6SPierre 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); 3986b73539f3SBarry Smith } 3987b73539f3SBarry Smith } 3988b73539f3SBarry Smith 3989273d9f13SBarry Smith B->preallocated = PETSC_TRUE; 39902205254eSKarl Rupp 3991273d9f13SBarry Smith b = (Mat_SeqAIJ*)B->data; 3992273d9f13SBarry Smith 3993ab93d7beSBarry Smith if (!skipallocation) { 39942ee49352SLisandro Dalcin if (!b->imax) { 39959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n,&b->imax)); 39969566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt))); 3997071fcb05SBarry Smith } 3998071fcb05SBarry Smith if (!b->ilen) { 3999071fcb05SBarry Smith /* b->ilen will count nonzeros in each row so far. */ 40009566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(B->rmap->n,&b->ilen)); 40019566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt))); 4002071fcb05SBarry Smith } else { 40039566063dSJacob Faibussowitsch PetscCall(PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt))); 40042ee49352SLisandro Dalcin } 4005846b4da1SFande Kong if (!b->ipre) { 40069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n,&b->ipre)); 40079566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt))); 4008846b4da1SFande Kong } 4009273d9f13SBarry Smith if (!nnz) { 4010435da068SBarry Smith if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10; 4011c62bd62aSJed Brown else if (nz < 0) nz = 1; 40125d2a9ed1SStefano Zampini nz = PetscMin(nz,B->cmap->n); 4013d0f46423SBarry Smith for (i=0; i<B->rmap->n; i++) b->imax[i] = nz; 4014d0f46423SBarry Smith nz = nz*B->rmap->n; 4015273d9f13SBarry Smith } else { 4016c73702f5SBarry Smith PetscInt64 nz64 = 0; 4017c73702f5SBarry Smith for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];} 40189566063dSJacob Faibussowitsch PetscCall(PetscIntCast(nz64,&nz)); 4019273d9f13SBarry Smith } 4020ab93d7beSBarry Smith 4021273d9f13SBarry Smith /* allocate the matrix space */ 402253dd7562SDmitry Karpeev /* FIXME: should B's old memory be unlogged? */ 40239566063dSJacob Faibussowitsch PetscCall(MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i)); 4024396832f4SHong Zhang if (B->structure_only) { 40259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nz,&b->j)); 40269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n+1,&b->i)); 40279566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt))); 4028396832f4SHong Zhang } else { 40299566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i)); 40309566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)))); 4031396832f4SHong Zhang } 4032bfeeae90SHong Zhang b->i[0] = 0; 4033d0f46423SBarry Smith for (i=1; i<B->rmap->n+1; i++) { 40345da197adSKris Buschelman b->i[i] = b->i[i-1] + b->imax[i-1]; 40355da197adSKris Buschelman } 4036396832f4SHong Zhang if (B->structure_only) { 4037396832f4SHong Zhang b->singlemalloc = PETSC_FALSE; 4038396832f4SHong Zhang b->free_a = PETSC_FALSE; 4039396832f4SHong Zhang } else { 4040273d9f13SBarry Smith b->singlemalloc = PETSC_TRUE; 4041e6b907acSBarry Smith b->free_a = PETSC_TRUE; 4042396832f4SHong Zhang } 4043e6b907acSBarry Smith b->free_ij = PETSC_TRUE; 4044c461c341SBarry Smith } else { 4045e6b907acSBarry Smith b->free_a = PETSC_FALSE; 4046e6b907acSBarry Smith b->free_ij = PETSC_FALSE; 4047c461c341SBarry Smith } 4048273d9f13SBarry Smith 4049846b4da1SFande Kong if (b->ipre && nnz != b->ipre && b->imax) { 4050846b4da1SFande Kong /* reserve user-requested sparsity */ 40519566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->ipre,b->imax,B->rmap->n)); 4052846b4da1SFande Kong } 4053846b4da1SFande Kong 4054273d9f13SBarry Smith b->nz = 0; 4055273d9f13SBarry Smith b->maxnz = nz; 4056273d9f13SBarry Smith B->info.nz_unneeded = (double)b->maxnz; 40572205254eSKarl Rupp if (realalloc) { 40589566063dSJacob Faibussowitsch PetscCall(MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE)); 40592205254eSKarl Rupp } 4060cb7b82ddSBarry Smith B->was_assembled = PETSC_FALSE; 4061cb7b82ddSBarry Smith B->assembled = PETSC_FALSE; 4062273d9f13SBarry Smith PetscFunctionReturn(0); 4063273d9f13SBarry Smith } 4064273d9f13SBarry Smith 4065846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A) 4066846b4da1SFande Kong { 4067846b4da1SFande Kong Mat_SeqAIJ *a; 4068a5bbaf83SFande Kong PetscInt i; 4069846b4da1SFande Kong 4070846b4da1SFande Kong PetscFunctionBegin; 4071846b4da1SFande Kong PetscValidHeaderSpecific(A,MAT_CLASSID,1); 407214d0e64fSAlex Lindsay 407314d0e64fSAlex Lindsay /* Check local size. If zero, then return */ 407414d0e64fSAlex Lindsay if (!A->rmap->n) PetscFunctionReturn(0); 407514d0e64fSAlex Lindsay 4076846b4da1SFande Kong a = (Mat_SeqAIJ*)A->data; 40772c814fdeSFande Kong /* if no saved info, we error out */ 407828b400f6SJacob Faibussowitsch PetscCheck(a->ipre,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info "); 40792c814fdeSFande Kong 4080aed4548fSBarry 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 "); 40812c814fdeSFande Kong 40829566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->imax,a->ipre,A->rmap->n)); 40839566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(a->ilen,A->rmap->n)); 4084846b4da1SFande Kong a->i[0] = 0; 4085846b4da1SFande Kong for (i=1; i<A->rmap->n+1; i++) { 4086846b4da1SFande Kong a->i[i] = a->i[i-1] + a->imax[i-1]; 4087846b4da1SFande Kong } 4088846b4da1SFande Kong A->preallocated = PETSC_TRUE; 4089846b4da1SFande Kong a->nz = 0; 4090846b4da1SFande Kong a->maxnz = a->i[A->rmap->n]; 4091846b4da1SFande Kong A->info.nz_unneeded = (double)a->maxnz; 4092846b4da1SFande Kong A->was_assembled = PETSC_FALSE; 4093846b4da1SFande Kong A->assembled = PETSC_FALSE; 4094846b4da1SFande Kong PetscFunctionReturn(0); 4095846b4da1SFande Kong } 4096846b4da1SFande Kong 409758d36128SBarry Smith /*@ 4098a1661176SMatthew Knepley MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format. 4099a1661176SMatthew Knepley 4100a1661176SMatthew Knepley Input Parameters: 4101a1661176SMatthew Knepley + B - the matrix 4102a1661176SMatthew Knepley . i - the indices into j for the start of each row (starts with zero) 4103a1661176SMatthew Knepley . j - the column indices for each row (starts with zero) these must be sorted for each row 4104a1661176SMatthew Knepley - v - optional values in the matrix 4105a1661176SMatthew Knepley 4106a1661176SMatthew Knepley Level: developer 4107a1661176SMatthew Knepley 41086a9b8d82SBarry Smith Notes: 410958d36128SBarry Smith The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays() 411058d36128SBarry Smith 41116a9b8d82SBarry Smith This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero 41126a9b8d82SBarry Smith structure will be the union of all the previous nonzero structures. 41136a9b8d82SBarry Smith 41146a9b8d82SBarry Smith Developer Notes: 41156a9b8d82SBarry 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 41166a9b8d82SBarry Smith then just copies the v values directly with PetscMemcpy(). 41176a9b8d82SBarry Smith 41186a9b8d82SBarry Smith This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them. 41196a9b8d82SBarry Smith 4120db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateSeqAIJ()`, `MatSetValues()`, `MatSeqAIJSetPreallocation()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MatResetPreallocation()` 4121a1661176SMatthew Knepley @*/ 4122a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[]) 4123a1661176SMatthew Knepley { 4124a1661176SMatthew Knepley PetscFunctionBegin; 41250700a824SBarry Smith PetscValidHeaderSpecific(B,MAT_CLASSID,1); 41266ba663aaSJed Brown PetscValidType(B,1); 4127cac4c232SBarry Smith PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v)); 4128a1661176SMatthew Knepley PetscFunctionReturn(0); 4129a1661176SMatthew Knepley } 4130a1661176SMatthew Knepley 41317087cfbeSBarry Smith PetscErrorCode MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[]) 4132a1661176SMatthew Knepley { 4133a1661176SMatthew Knepley PetscInt i; 4134a1661176SMatthew Knepley PetscInt m,n; 4135a1661176SMatthew Knepley PetscInt nz; 41366a9b8d82SBarry Smith PetscInt *nnz; 4137a1661176SMatthew Knepley 4138a1661176SMatthew Knepley PetscFunctionBegin; 4139aed4548fSBarry Smith PetscCheck(Ii[0] == 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %" PetscInt_FMT, Ii[0]); 4140779a8d59SSatish Balay 41419566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->rmap)); 41429566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(B->cmap)); 4143779a8d59SSatish Balay 41449566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &m, &n)); 41459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m+1, &nnz)); 4146a1661176SMatthew Knepley for (i = 0; i < m; i++) { 4147b7940d39SSatish Balay nz = Ii[i+1]- Ii[i]; 414808401ef6SPierre 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); 4149a1661176SMatthew Knepley nnz[i] = nz; 4150a1661176SMatthew Knepley } 41519566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, nnz)); 41529566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 4153a1661176SMatthew Knepley 4154a1661176SMatthew Knepley for (i = 0; i < m; i++) { 41559566063dSJacob Faibussowitsch PetscCall(MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES)); 4156a1661176SMatthew Knepley } 4157a1661176SMatthew Knepley 41589566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 41599566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 4160a1661176SMatthew Knepley 41619566063dSJacob Faibussowitsch PetscCall(MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE)); 4162a1661176SMatthew Knepley PetscFunctionReturn(0); 4163a1661176SMatthew Knepley } 4164a1661176SMatthew Knepley 4165ad7e164aSPierre Jolivet /*@ 4166ad7e164aSPierre Jolivet MatSeqAIJKron - Computes C, the Kronecker product of A and B. 4167ad7e164aSPierre Jolivet 4168ad7e164aSPierre Jolivet Input Parameters: 4169ad7e164aSPierre Jolivet + A - left-hand side matrix 4170ad7e164aSPierre Jolivet . B - right-hand side matrix 4171ad7e164aSPierre Jolivet - reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 4172ad7e164aSPierre Jolivet 4173ad7e164aSPierre Jolivet Output Parameter: 4174ad7e164aSPierre Jolivet . C - Kronecker product of A and B 4175ad7e164aSPierre Jolivet 4176ad7e164aSPierre Jolivet Level: intermediate 4177ad7e164aSPierre Jolivet 4178ad7e164aSPierre Jolivet Notes: 4179ad7e164aSPierre 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(). 4180ad7e164aSPierre Jolivet 4181db781477SPatrick Sanan .seealso: `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATKAIJ`, `MatReuse` 4182ad7e164aSPierre Jolivet @*/ 4183ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron(Mat A,Mat B,MatReuse reuse,Mat *C) 4184ad7e164aSPierre Jolivet { 4185ad7e164aSPierre Jolivet PetscFunctionBegin; 4186ad7e164aSPierre Jolivet PetscValidHeaderSpecific(A,MAT_CLASSID,1); 4187ad7e164aSPierre Jolivet PetscValidType(A,1); 4188ad7e164aSPierre Jolivet PetscValidHeaderSpecific(B,MAT_CLASSID,2); 4189ad7e164aSPierre Jolivet PetscValidType(B,2); 4190ad7e164aSPierre Jolivet PetscValidPointer(C,4); 4191ad7e164aSPierre Jolivet if (reuse == MAT_REUSE_MATRIX) { 4192ad7e164aSPierre Jolivet PetscValidHeaderSpecific(*C,MAT_CLASSID,4); 4193ad7e164aSPierre Jolivet PetscValidType(*C,4); 4194ad7e164aSPierre Jolivet } 4195cac4c232SBarry Smith PetscTryMethod(A,"MatSeqAIJKron_C",(Mat,Mat,MatReuse,Mat*),(A,B,reuse,C)); 4196ad7e164aSPierre Jolivet PetscFunctionReturn(0); 4197ad7e164aSPierre Jolivet } 4198ad7e164aSPierre Jolivet 4199ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A,Mat B,MatReuse reuse,Mat *C) 4200ad7e164aSPierre Jolivet { 4201ad7e164aSPierre Jolivet Mat newmat; 4202ad7e164aSPierre Jolivet Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 4203ad7e164aSPierre Jolivet Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 4204ad7e164aSPierre Jolivet PetscScalar *v; 4205fff043a9SJunchao Zhang const PetscScalar *aa,*ba; 4206ad7e164aSPierre 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; 4207ad7e164aSPierre Jolivet PetscBool flg; 4208ad7e164aSPierre Jolivet 4209ad7e164aSPierre Jolivet PetscFunctionBegin; 421028b400f6SJacob Faibussowitsch PetscCheck(!A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 421128b400f6SJacob Faibussowitsch PetscCheck(A->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 421228b400f6SJacob Faibussowitsch PetscCheck(!B->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 421328b400f6SJacob Faibussowitsch PetscCheck(B->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 42149566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&flg)); 421528b400f6SJacob Faibussowitsch PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatType %s",((PetscObject)B)->type_name); 4216aed4548fSBarry Smith PetscCheck(reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatReuse %d",(int)reuse); 4217ad7e164aSPierre Jolivet if (reuse == MAT_INITIAL_MATRIX) { 42189566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(am*bm+1,&i,a->i[am]*b->i[bm],&j)); 42199566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF,&newmat)); 42209566063dSJacob Faibussowitsch PetscCall(MatSetSizes(newmat,am*bm,an*bn,am*bm,an*bn)); 42219566063dSJacob Faibussowitsch PetscCall(MatSetType(newmat,MATAIJ)); 4222ad7e164aSPierre Jolivet i[0] = 0; 4223ad7e164aSPierre Jolivet for (m = 0; m < am; ++m) { 4224ad7e164aSPierre Jolivet for (p = 0; p < bm; ++p) { 4225ad7e164aSPierre Jolivet i[m*bm + p + 1] = i[m*bm + p] + (a->i[m+1] - a->i[m]) * (b->i[p+1] - b->i[p]); 4226ad7e164aSPierre Jolivet for (n = a->i[m]; n < a->i[m+1]; ++n) { 4227ad7e164aSPierre Jolivet for (q = b->i[p]; q < b->i[p+1]; ++q) { 4228ad7e164aSPierre Jolivet j[nnz++] = a->j[n]*bn + b->j[q]; 4229ad7e164aSPierre Jolivet } 4230ad7e164aSPierre Jolivet } 4231ad7e164aSPierre Jolivet } 4232ad7e164aSPierre Jolivet } 42339566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(newmat,i,j,NULL)); 4234ad7e164aSPierre Jolivet *C = newmat; 42359566063dSJacob Faibussowitsch PetscCall(PetscFree2(i,j)); 4236ad7e164aSPierre Jolivet nnz = 0; 4237ad7e164aSPierre Jolivet } 42389566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(*C,&v)); 42399566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 42409566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B,&ba)); 4241ad7e164aSPierre Jolivet for (m = 0; m < am; ++m) { 4242ad7e164aSPierre Jolivet for (p = 0; p < bm; ++p) { 4243ad7e164aSPierre Jolivet for (n = a->i[m]; n < a->i[m+1]; ++n) { 4244ad7e164aSPierre Jolivet for (q = b->i[p]; q < b->i[p+1]; ++q) { 4245fff043a9SJunchao Zhang v[nnz++] = aa[n] * ba[q]; 4246ad7e164aSPierre Jolivet } 4247ad7e164aSPierre Jolivet } 4248ad7e164aSPierre Jolivet } 4249ad7e164aSPierre Jolivet } 42509566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(*C,&v)); 42519566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 42529566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B,&ba)); 4253ad7e164aSPierre Jolivet PetscFunctionReturn(0); 4254ad7e164aSPierre Jolivet } 4255ad7e164aSPierre Jolivet 4256c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h> 4257af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h> 4258170fe5c8SBarry Smith 4259170fe5c8SBarry Smith /* 4260170fe5c8SBarry Smith Computes (B'*A')' since computing B*A directly is untenable 4261170fe5c8SBarry Smith 4262170fe5c8SBarry Smith n p p 42632da392ccSBarry Smith [ ] [ ] [ ] 42642da392ccSBarry Smith m [ A ] * n [ B ] = m [ C ] 42652da392ccSBarry Smith [ ] [ ] [ ] 4266170fe5c8SBarry Smith 4267170fe5c8SBarry Smith */ 4268170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C) 4269170fe5c8SBarry Smith { 4270170fe5c8SBarry Smith Mat_SeqDense *sub_a = (Mat_SeqDense*)A->data; 4271170fe5c8SBarry Smith Mat_SeqAIJ *sub_b = (Mat_SeqAIJ*)B->data; 4272170fe5c8SBarry Smith Mat_SeqDense *sub_c = (Mat_SeqDense*)C->data; 427386214ceeSStefano Zampini PetscInt i,j,n,m,q,p; 4274170fe5c8SBarry Smith const PetscInt *ii,*idx; 4275170fe5c8SBarry Smith const PetscScalar *b,*a,*a_q; 4276170fe5c8SBarry Smith PetscScalar *c,*c_q; 427786214ceeSStefano Zampini PetscInt clda = sub_c->lda; 427886214ceeSStefano Zampini PetscInt alda = sub_a->lda; 4279170fe5c8SBarry Smith 4280170fe5c8SBarry Smith PetscFunctionBegin; 4281d0f46423SBarry Smith m = A->rmap->n; 4282d0f46423SBarry Smith n = A->cmap->n; 4283d0f46423SBarry Smith p = B->cmap->n; 4284170fe5c8SBarry Smith a = sub_a->v; 4285170fe5c8SBarry Smith b = sub_b->a; 4286170fe5c8SBarry Smith c = sub_c->v; 428786214ceeSStefano Zampini if (clda == m) { 42889566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c,m*p)); 428986214ceeSStefano Zampini } else { 429086214ceeSStefano Zampini for (j=0;j<p;j++) 429186214ceeSStefano Zampini for (i=0;i<m;i++) 429286214ceeSStefano Zampini c[j*clda + i] = 0.0; 429386214ceeSStefano Zampini } 4294170fe5c8SBarry Smith ii = sub_b->i; 4295170fe5c8SBarry Smith idx = sub_b->j; 4296170fe5c8SBarry Smith for (i=0; i<n; i++) { 4297170fe5c8SBarry Smith q = ii[i+1] - ii[i]; 4298170fe5c8SBarry Smith while (q-->0) { 429986214ceeSStefano Zampini c_q = c + clda*(*idx); 430086214ceeSStefano Zampini a_q = a + alda*i; 4301854c7f52SBarry Smith PetscKernelAXPY(c_q,*b,a_q,m); 4302170fe5c8SBarry Smith idx++; 4303170fe5c8SBarry Smith b++; 4304170fe5c8SBarry Smith } 4305170fe5c8SBarry Smith } 4306170fe5c8SBarry Smith PetscFunctionReturn(0); 4307170fe5c8SBarry Smith } 4308170fe5c8SBarry Smith 43094222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C) 4310170fe5c8SBarry Smith { 4311d0f46423SBarry Smith PetscInt m=A->rmap->n,n=B->cmap->n; 431286214ceeSStefano Zampini PetscBool cisdense; 4313170fe5c8SBarry Smith 4314170fe5c8SBarry Smith PetscFunctionBegin; 431508401ef6SPierre 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); 43169566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C,m,n,m,n)); 43179566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(C,A,B)); 43189566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"")); 431986214ceeSStefano Zampini if (!cisdense) { 43209566063dSJacob Faibussowitsch PetscCall(MatSetType(C,MATDENSE)); 432186214ceeSStefano Zampini } 43229566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 4323d73949e8SHong Zhang 43244222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ; 4325170fe5c8SBarry Smith PetscFunctionReturn(0); 4326170fe5c8SBarry Smith } 4327170fe5c8SBarry Smith 4328170fe5c8SBarry Smith /* ----------------------------------------------------------------*/ 43290bad9183SKris Buschelman /*MC 4330fafad747SKris Buschelman MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices, 43310bad9183SKris Buschelman based on compressed sparse row format. 43320bad9183SKris Buschelman 43330bad9183SKris Buschelman Options Database Keys: 43340bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions() 43350bad9183SKris Buschelman 43360bad9183SKris Buschelman Level: beginner 43370bad9183SKris Buschelman 43380cd7f59aSBarry Smith Notes: 43390cd7f59aSBarry Smith MatSetValues() may be called for this matrix type with a NULL argument for the numerical values, 43400cd7f59aSBarry Smith in this case the values associated with the rows and columns one passes in are set to zero 43410cd7f59aSBarry Smith in the matrix 43420cd7f59aSBarry Smith 43430cd7f59aSBarry Smith MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no 43440cd7f59aSBarry Smith space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored 43450cd7f59aSBarry Smith 43460cd7f59aSBarry Smith Developer Notes: 43470cd7f59aSBarry Smith It would be nice if all matrix formats supported passing NULL in for the numerical values 43480cd7f59aSBarry Smith 4349db781477SPatrick Sanan .seealso: `MatCreateSeqAIJ()`, `MatSetFromOptions()`, `MatSetType()`, `MatCreate()`, `MatType`, `MATSELL`, `MATSEQSELL`, `MATMPISELL` 43500bad9183SKris Buschelman M*/ 43510bad9183SKris Buschelman 4352ccd284c7SBarry Smith /*MC 4353ccd284c7SBarry Smith MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices. 4354ccd284c7SBarry Smith 4355ccd284c7SBarry Smith This matrix type is identical to MATSEQAIJ when constructed with a single process communicator, 4356ccd284c7SBarry Smith and MATMPIAIJ otherwise. As a result, for single process communicators, 4357ed73aabaSBarry Smith MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported 4358ccd284c7SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 4359ccd284c7SBarry Smith the above preallocation routines for simplicity. 4360ccd284c7SBarry Smith 4361ccd284c7SBarry Smith Options Database Keys: 4362ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions() 4363ccd284c7SBarry Smith 436495452b02SPatrick Sanan Developer Notes: 4365ca9cdca7SRichard Tran Mills Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when 4366ccd284c7SBarry Smith enough exist. 4367ccd284c7SBarry Smith 4368ccd284c7SBarry Smith Level: beginner 4369ccd284c7SBarry Smith 4370db781477SPatrick Sanan .seealso: `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MATSEQAIJ`, `MATMPIAIJ`, `MATSELL`, `MATSEQSELL`, `MATMPISELL` 4371ccd284c7SBarry Smith M*/ 4372ccd284c7SBarry Smith 4373ccd284c7SBarry Smith /*MC 4374ccd284c7SBarry Smith MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices. 4375ccd284c7SBarry Smith 4376ccd284c7SBarry Smith This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator, 4377ccd284c7SBarry Smith and MATMPIAIJCRL otherwise. As a result, for single process communicators, 4378ccd284c7SBarry Smith MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported 4379ccd284c7SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 4380ccd284c7SBarry Smith the above preallocation routines for simplicity. 4381ccd284c7SBarry Smith 4382ccd284c7SBarry Smith Options Database Keys: 4383ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions() 4384ccd284c7SBarry Smith 4385ccd284c7SBarry Smith Level: beginner 4386ccd284c7SBarry Smith 4387*c2e3fba1SPatrick Sanan .seealso: `MatCreateMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL`, `MATSEQAIJCRL`, `MATMPIAIJCRL` 4388ccd284c7SBarry Smith M*/ 4389ccd284c7SBarry Smith 43907906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*); 43917906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 43927906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*); 43937906f579SHong Zhang #endif 4394d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 4395d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*); 4396d24d4204SJose E. Roman #endif 43977906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE) 43987906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*); 43997906f579SHong Zhang #endif 44007906f579SHong Zhang 4401d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*); 4402c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*); 44034222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat); 44047906f579SHong Zhang 44058c778c55SBarry Smith /*@C 44068f1ea47aSStefano Zampini MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored 44078c778c55SBarry Smith 44088c778c55SBarry Smith Not Collective 44098c778c55SBarry Smith 44108c778c55SBarry Smith Input Parameter: 4411579dbff0SBarry Smith . mat - a MATSEQAIJ matrix 44128c778c55SBarry Smith 44138c778c55SBarry Smith Output Parameter: 44148c778c55SBarry Smith . array - pointer to the data 44158c778c55SBarry Smith 44168c778c55SBarry Smith Level: intermediate 44178c778c55SBarry Smith 4418db781477SPatrick Sanan .seealso: `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()` 44198c778c55SBarry Smith @*/ 44208c778c55SBarry Smith PetscErrorCode MatSeqAIJGetArray(Mat A,PetscScalar **array) 44218c778c55SBarry Smith { 4422d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 44238c778c55SBarry Smith 44248c778c55SBarry Smith PetscFunctionBegin; 4425d67d9f35SJunchao Zhang if (aij->ops->getarray) { 44269566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarray)(A,array)); 4427d67d9f35SJunchao Zhang } else { 4428d67d9f35SJunchao Zhang *array = aij->a; 4429d67d9f35SJunchao Zhang } 4430d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4431d67d9f35SJunchao Zhang } 4432d67d9f35SJunchao Zhang 4433d67d9f35SJunchao Zhang /*@C 4434d67d9f35SJunchao Zhang MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray() 4435d67d9f35SJunchao Zhang 4436d67d9f35SJunchao Zhang Not Collective 4437d67d9f35SJunchao Zhang 4438d67d9f35SJunchao Zhang Input Parameters: 4439d67d9f35SJunchao Zhang + mat - a MATSEQAIJ matrix 4440d67d9f35SJunchao Zhang - array - pointer to the data 4441d67d9f35SJunchao Zhang 4442d67d9f35SJunchao Zhang Level: intermediate 4443d67d9f35SJunchao Zhang 4444db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayF90()` 4445d67d9f35SJunchao Zhang @*/ 4446d67d9f35SJunchao Zhang PetscErrorCode MatSeqAIJRestoreArray(Mat A,PetscScalar **array) 4447d67d9f35SJunchao Zhang { 4448d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 4449d67d9f35SJunchao Zhang 4450d67d9f35SJunchao Zhang PetscFunctionBegin; 4451d67d9f35SJunchao Zhang if (aij->ops->restorearray) { 44529566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearray)(A,array)); 4453d67d9f35SJunchao Zhang } else { 4454d67d9f35SJunchao Zhang *array = NULL; 4455d67d9f35SJunchao Zhang } 44569566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 44579566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 44588c778c55SBarry Smith PetscFunctionReturn(0); 44598c778c55SBarry Smith } 44608c778c55SBarry Smith 446121e72a00SBarry Smith /*@C 44628f1ea47aSStefano Zampini MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored 44638f1ea47aSStefano Zampini 44648f1ea47aSStefano Zampini Not Collective 44658f1ea47aSStefano Zampini 44668f1ea47aSStefano Zampini Input Parameter: 44678f1ea47aSStefano Zampini . mat - a MATSEQAIJ matrix 44688f1ea47aSStefano Zampini 44698f1ea47aSStefano Zampini Output Parameter: 44708f1ea47aSStefano Zampini . array - pointer to the data 44718f1ea47aSStefano Zampini 44728f1ea47aSStefano Zampini Level: intermediate 44738f1ea47aSStefano Zampini 4474db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()` 44758f1ea47aSStefano Zampini @*/ 44768f1ea47aSStefano Zampini PetscErrorCode MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array) 44778f1ea47aSStefano Zampini { 4478d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 44798f1ea47aSStefano Zampini 44808f1ea47aSStefano Zampini PetscFunctionBegin; 4481d67d9f35SJunchao Zhang if (aij->ops->getarrayread) { 44829566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarrayread)(A,array)); 4483d67d9f35SJunchao Zhang } else { 4484d67d9f35SJunchao Zhang *array = aij->a; 4485d67d9f35SJunchao Zhang } 44868f1ea47aSStefano Zampini PetscFunctionReturn(0); 44878f1ea47aSStefano Zampini } 44888f1ea47aSStefano Zampini 44898f1ea47aSStefano Zampini /*@C 44908f1ea47aSStefano Zampini MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead 44918f1ea47aSStefano Zampini 44928f1ea47aSStefano Zampini Not Collective 44938f1ea47aSStefano Zampini 44948f1ea47aSStefano Zampini Input Parameter: 44958f1ea47aSStefano Zampini . mat - a MATSEQAIJ matrix 44968f1ea47aSStefano Zampini 44978f1ea47aSStefano Zampini Output Parameter: 44988f1ea47aSStefano Zampini . array - pointer to the data 44998f1ea47aSStefano Zampini 45008f1ea47aSStefano Zampini Level: intermediate 45018f1ea47aSStefano Zampini 4502db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 45038f1ea47aSStefano Zampini @*/ 45048f1ea47aSStefano Zampini PetscErrorCode MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array) 45058f1ea47aSStefano Zampini { 4506d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 45078f1ea47aSStefano Zampini 45088f1ea47aSStefano Zampini PetscFunctionBegin; 4509d67d9f35SJunchao Zhang if (aij->ops->restorearrayread) { 45109566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearrayread)(A,array)); 4511d67d9f35SJunchao Zhang } else { 4512d67d9f35SJunchao Zhang *array = NULL; 4513d67d9f35SJunchao Zhang } 4514d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4515d67d9f35SJunchao Zhang } 4516d67d9f35SJunchao Zhang 4517d67d9f35SJunchao Zhang /*@C 4518d67d9f35SJunchao Zhang MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a MATSEQAIJ matrix is stored 4519d67d9f35SJunchao Zhang 4520d67d9f35SJunchao Zhang Not Collective 4521d67d9f35SJunchao Zhang 4522d67d9f35SJunchao Zhang Input Parameter: 4523d67d9f35SJunchao Zhang . mat - a MATSEQAIJ matrix 4524d67d9f35SJunchao Zhang 4525d67d9f35SJunchao Zhang Output Parameter: 4526d67d9f35SJunchao Zhang . array - pointer to the data 4527d67d9f35SJunchao Zhang 4528d67d9f35SJunchao Zhang Level: intermediate 4529d67d9f35SJunchao Zhang 4530db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArrayRead()` 4531d67d9f35SJunchao Zhang @*/ 4532d67d9f35SJunchao Zhang PetscErrorCode MatSeqAIJGetArrayWrite(Mat A,PetscScalar **array) 4533d67d9f35SJunchao Zhang { 4534d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 4535d67d9f35SJunchao Zhang 4536d67d9f35SJunchao Zhang PetscFunctionBegin; 4537d67d9f35SJunchao Zhang if (aij->ops->getarraywrite) { 45389566063dSJacob Faibussowitsch PetscCall((*aij->ops->getarraywrite)(A,array)); 4539d67d9f35SJunchao Zhang } else { 4540d67d9f35SJunchao Zhang *array = aij->a; 4541d67d9f35SJunchao Zhang } 45429566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal(A)); 45439566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 4544d67d9f35SJunchao Zhang PetscFunctionReturn(0); 4545d67d9f35SJunchao Zhang } 4546d67d9f35SJunchao Zhang 4547d67d9f35SJunchao Zhang /*@C 4548d67d9f35SJunchao Zhang MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead 4549d67d9f35SJunchao Zhang 4550d67d9f35SJunchao Zhang Not Collective 4551d67d9f35SJunchao Zhang 4552d67d9f35SJunchao Zhang Input Parameter: 4553d67d9f35SJunchao Zhang . mat - a MATSEQAIJ matrix 4554d67d9f35SJunchao Zhang 4555d67d9f35SJunchao Zhang Output Parameter: 4556d67d9f35SJunchao Zhang . array - pointer to the data 4557d67d9f35SJunchao Zhang 4558d67d9f35SJunchao Zhang Level: intermediate 4559d67d9f35SJunchao Zhang 4560db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 4561d67d9f35SJunchao Zhang @*/ 4562d67d9f35SJunchao Zhang PetscErrorCode MatSeqAIJRestoreArrayWrite(Mat A,PetscScalar **array) 4563d67d9f35SJunchao Zhang { 4564d67d9f35SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 4565d67d9f35SJunchao Zhang 4566d67d9f35SJunchao Zhang PetscFunctionBegin; 4567d67d9f35SJunchao Zhang if (aij->ops->restorearraywrite) { 45689566063dSJacob Faibussowitsch PetscCall((*aij->ops->restorearraywrite)(A,array)); 4569d67d9f35SJunchao Zhang } else { 4570d67d9f35SJunchao Zhang *array = NULL; 4571d67d9f35SJunchao Zhang } 45728f1ea47aSStefano Zampini PetscFunctionReturn(0); 45738f1ea47aSStefano Zampini } 45748f1ea47aSStefano Zampini 45758f1ea47aSStefano Zampini /*@C 45767ee59b9bSJunchao Zhang MatSeqAIJGetCSRAndMemType - Get the CSR arrays and the memory type of the SEQAIJ matrix 45777ee59b9bSJunchao Zhang 45787ee59b9bSJunchao Zhang Not Collective 45797ee59b9bSJunchao Zhang 45807ee59b9bSJunchao Zhang Input Parameter: 45817ee59b9bSJunchao Zhang . mat - a matrix of type MATSEQAIJ or its subclasses 45827ee59b9bSJunchao Zhang 45837ee59b9bSJunchao Zhang Output Parameters: 45847ee59b9bSJunchao Zhang + i - row map array of the matrix 45857ee59b9bSJunchao Zhang . j - column index array of the matrix 45867ee59b9bSJunchao Zhang . a - data array of the matrix 45877ee59b9bSJunchao Zhang - memtype - memory type of the arrays 45887ee59b9bSJunchao Zhang 45897ee59b9bSJunchao Zhang Notes: 45907ee59b9bSJunchao Zhang Any of the output parameters can be NULL, in which case the corresponding value is not returned. 45917ee59b9bSJunchao Zhang If mat is a device matrix, the arrays are on the device. Otherwise, they are on the host. 45927ee59b9bSJunchao Zhang 45937ee59b9bSJunchao Zhang One can call this routine on a preallocated but not assembled matrix to just get the memory of the CSR underneath the matrix. 45947ee59b9bSJunchao Zhang If the matrix is assembled, the data array 'a' is guaranteed to have the latest values of the matrix. 45957ee59b9bSJunchao Zhang 45967ee59b9bSJunchao Zhang Level: Developer 45977ee59b9bSJunchao Zhang 4598db781477SPatrick Sanan .seealso: `MatSeqAIJGetArray()`, `MatSeqAIJGetArrayRead()` 45997ee59b9bSJunchao Zhang @*/ 46007ee59b9bSJunchao Zhang PetscErrorCode MatSeqAIJGetCSRAndMemType(Mat mat,const PetscInt **i,const PetscInt **j,PetscScalar **a,PetscMemType *mtype) 46017ee59b9bSJunchao Zhang { 46027ee59b9bSJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data; 46037ee59b9bSJunchao Zhang 46047ee59b9bSJunchao Zhang PetscFunctionBegin; 46057ee59b9bSJunchao Zhang PetscCheck(mat->preallocated,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"matrix is not preallocated"); 46067ee59b9bSJunchao Zhang if (aij->ops->getcsrandmemtype) { 46077ee59b9bSJunchao Zhang PetscCall((*aij->ops->getcsrandmemtype)(mat,i,j,a,mtype)); 46087ee59b9bSJunchao Zhang } else { 46097ee59b9bSJunchao Zhang if (i) *i = aij->i; 46107ee59b9bSJunchao Zhang if (j) *j = aij->j; 46117ee59b9bSJunchao Zhang if (a) *a = aij->a; 46127ee59b9bSJunchao Zhang if (mtype) *mtype = PETSC_MEMTYPE_HOST; 46137ee59b9bSJunchao Zhang } 46147ee59b9bSJunchao Zhang PetscFunctionReturn(0); 46157ee59b9bSJunchao Zhang } 46167ee59b9bSJunchao Zhang 46177ee59b9bSJunchao Zhang /*@C 461821e72a00SBarry Smith MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row 461921e72a00SBarry Smith 462021e72a00SBarry Smith Not Collective 462121e72a00SBarry Smith 462221e72a00SBarry Smith Input Parameter: 4623579dbff0SBarry Smith . mat - a MATSEQAIJ matrix 462421e72a00SBarry Smith 462521e72a00SBarry Smith Output Parameter: 462621e72a00SBarry Smith . nz - the maximum number of nonzeros in any row 462721e72a00SBarry Smith 462821e72a00SBarry Smith Level: intermediate 462921e72a00SBarry Smith 4630db781477SPatrick Sanan .seealso: `MatSeqAIJRestoreArray()`, `MatSeqAIJGetArrayF90()` 463121e72a00SBarry Smith @*/ 463221e72a00SBarry Smith PetscErrorCode MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz) 463321e72a00SBarry Smith { 463421e72a00SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)A->data; 463521e72a00SBarry Smith 463621e72a00SBarry Smith PetscFunctionBegin; 463721e72a00SBarry Smith *nz = aij->rmax; 463821e72a00SBarry Smith PetscFunctionReturn(0); 463921e72a00SBarry Smith } 464021e72a00SBarry Smith 4641394ed5ebSJunchao Zhang PetscErrorCode MatSetPreallocationCOO_SeqAIJ(Mat mat, PetscCount coo_n, const PetscInt coo_i[], const PetscInt coo_j[]) 4642394ed5ebSJunchao Zhang { 4643394ed5ebSJunchao Zhang MPI_Comm comm; 4644394ed5ebSJunchao Zhang PetscInt *i,*j; 4645394ed5ebSJunchao Zhang PetscInt M,N,row; 4646394ed5ebSJunchao Zhang PetscCount k,p,q,nneg,nnz,start,end; /* Index the coo array, so use PetscCount as their type */ 4647394ed5ebSJunchao Zhang PetscInt *Ai; /* Change to PetscCount once we use it for row pointers */ 4648394ed5ebSJunchao Zhang PetscInt *Aj; 4649394ed5ebSJunchao Zhang PetscScalar *Aa; 4650cbc6b225SStefano Zampini Mat_SeqAIJ *seqaij = (Mat_SeqAIJ*)(mat->data); 4651cbc6b225SStefano Zampini MatType rtype; 4652394ed5ebSJunchao Zhang PetscCount *perm,*jmap; 4653394ed5ebSJunchao Zhang 4654394ed5ebSJunchao Zhang PetscFunctionBegin; 46559566063dSJacob Faibussowitsch PetscCall(MatResetPreallocationCOO_SeqAIJ(mat)); 46569566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat,&comm)); 46579566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat,&M,&N)); 46589566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(coo_n,&i,coo_n,&j)); 46599566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(i,coo_i,coo_n)); /* Make a copy since we'll modify it */ 46609566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(j,coo_j,coo_n)); 46619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n,&perm)); 4662394ed5ebSJunchao Zhang for (k=0; k<coo_n; k++) { /* Ignore entries with negative row or col indices */ 4663394ed5ebSJunchao Zhang if (j[k] < 0) i[k] = -1; 4664394ed5ebSJunchao Zhang perm[k] = k; 4665394ed5ebSJunchao Zhang } 4666394ed5ebSJunchao Zhang 4667394ed5ebSJunchao Zhang /* Sort by row */ 46689566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithIntCountArrayPair(coo_n,i,j,perm)); 4669394ed5ebSJunchao Zhang for (k=0; k<coo_n; k++) {if (i[k] >= 0) break;} /* Advance k to the first row with a non-negative index */ 4670394ed5ebSJunchao Zhang nneg = k; 46719566063dSJacob 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 */ 4672394ed5ebSJunchao Zhang nnz = 0; /* Total number of unique nonzeros to be counted */ 4673394ed5ebSJunchao Zhang jmap++; /* Inc jmap by 1 for convinience */ 4674394ed5ebSJunchao Zhang 46759566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(M+1,&Ai)); /* CSR of A */ 46769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n-nneg,&Aj)); /* We have at most coo_n-nneg unique nonzeros */ 4677394ed5ebSJunchao Zhang 4678394ed5ebSJunchao Zhang /* In each row, sort by column, then unique column indices to get row length */ 4679394ed5ebSJunchao Zhang Ai++; /* Inc by 1 for convinience */ 4680394ed5ebSJunchao Zhang q = 0; /* q-th unique nonzero, with q starting from 0 */ 4681394ed5ebSJunchao Zhang while (k<coo_n) { 4682394ed5ebSJunchao Zhang row = i[k]; 4683394ed5ebSJunchao Zhang start = k; /* [start,end) indices for this row */ 4684394ed5ebSJunchao Zhang while (k<coo_n && i[k] == row) k++; 4685394ed5ebSJunchao Zhang end = k; 46869566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithCountArray(end-start,j+start,perm+start)); 4687394ed5ebSJunchao Zhang /* Find number of unique col entries in this row */ 4688394ed5ebSJunchao Zhang Aj[q] = j[start]; /* Log the first nonzero in this row */ 4689394ed5ebSJunchao Zhang jmap[q] = 1; /* Number of repeats of this nozero entry */ 4690394ed5ebSJunchao Zhang Ai[row] = 1; 4691394ed5ebSJunchao Zhang nnz++; 4692394ed5ebSJunchao Zhang 4693394ed5ebSJunchao Zhang for (p=start+1; p<end; p++) { /* Scan remaining nonzero in this row */ 4694394ed5ebSJunchao Zhang if (j[p] != j[p-1]) { /* Meet a new nonzero */ 4695394ed5ebSJunchao Zhang q++; 4696394ed5ebSJunchao Zhang jmap[q] = 1; 4697394ed5ebSJunchao Zhang Aj[q] = j[p]; 4698394ed5ebSJunchao Zhang Ai[row]++; 4699394ed5ebSJunchao Zhang nnz++; 4700394ed5ebSJunchao Zhang } else { 4701394ed5ebSJunchao Zhang jmap[q]++; 4702394ed5ebSJunchao Zhang } 4703394ed5ebSJunchao Zhang } 4704394ed5ebSJunchao Zhang q++; /* Move to next row and thus next unique nonzero */ 4705394ed5ebSJunchao Zhang } 47069566063dSJacob Faibussowitsch PetscCall(PetscFree2(i,j)); 4707394ed5ebSJunchao Zhang 4708394ed5ebSJunchao Zhang Ai--; /* Back to the beginning of Ai[] */ 4709394ed5ebSJunchao Zhang for (k=0; k<M; k++) Ai[k+1] += Ai[k]; 4710394ed5ebSJunchao Zhang jmap--; /* Back to the beginning of jmap[] */ 4711394ed5ebSJunchao Zhang jmap[0] = 0; 4712394ed5ebSJunchao Zhang for (k=0; k<nnz; k++) jmap[k+1] += jmap[k]; 4713394ed5ebSJunchao Zhang if (nnz < coo_n-nneg) { /* Realloc with actual number of unique nonzeros */ 4714394ed5ebSJunchao Zhang PetscCount *jmap_new; 4715394ed5ebSJunchao Zhang PetscInt *Aj_new; 4716394ed5ebSJunchao Zhang 47179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz+1,&jmap_new)); 47189566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(jmap_new,jmap,nnz+1)); 47199566063dSJacob Faibussowitsch PetscCall(PetscFree(jmap)); 4720394ed5ebSJunchao Zhang jmap = jmap_new; 4721394ed5ebSJunchao Zhang 47229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz,&Aj_new)); 47239566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(Aj_new,Aj,nnz)); 47249566063dSJacob Faibussowitsch PetscCall(PetscFree(Aj)); 4725394ed5ebSJunchao Zhang Aj = Aj_new; 4726394ed5ebSJunchao Zhang } 4727394ed5ebSJunchao Zhang 4728394ed5ebSJunchao Zhang if (nneg) { /* Discard heading entries with negative indices in perm[], as we'll access it from index 0 in MatSetValuesCOO */ 4729394ed5ebSJunchao Zhang PetscCount *perm_new; 4730cbc6b225SStefano Zampini 47319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coo_n-nneg,&perm_new)); 47329566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(perm_new,perm+nneg,coo_n-nneg)); 47339566063dSJacob Faibussowitsch PetscCall(PetscFree(perm)); 4734394ed5ebSJunchao Zhang perm = perm_new; 4735394ed5ebSJunchao Zhang } 4736394ed5ebSJunchao Zhang 47379566063dSJacob Faibussowitsch PetscCall(MatGetRootType_Private(mat,&rtype)); 47389566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nnz,&Aa)); /* Zero the matrix */ 47399566063dSJacob Faibussowitsch PetscCall(MatSetSeqAIJWithArrays_private(PETSC_COMM_SELF,M,N,Ai,Aj,Aa,rtype,mat)); 4740394ed5ebSJunchao Zhang 4741394ed5ebSJunchao Zhang seqaij->singlemalloc = PETSC_FALSE; /* Ai, Aj and Aa are not allocated in one big malloc */ 4742394ed5ebSJunchao Zhang seqaij->free_a = seqaij->free_ij = PETSC_TRUE; /* Let newmat own Ai, Aj and Aa */ 4743394ed5ebSJunchao Zhang /* Record COO fields */ 4744394ed5ebSJunchao Zhang seqaij->coo_n = coo_n; 4745394ed5ebSJunchao Zhang seqaij->Atot = coo_n-nneg; /* Annz is seqaij->nz, so no need to record that again */ 4746394ed5ebSJunchao Zhang seqaij->jmap = jmap; /* of length nnz+1 */ 4747394ed5ebSJunchao Zhang seqaij->perm = perm; 4748394ed5ebSJunchao Zhang PetscFunctionReturn(0); 4749394ed5ebSJunchao Zhang } 4750394ed5ebSJunchao Zhang 4751394ed5ebSJunchao Zhang static PetscErrorCode MatSetValuesCOO_SeqAIJ(Mat A,const PetscScalar v[],InsertMode imode) 4752394ed5ebSJunchao Zhang { 4753394ed5ebSJunchao Zhang Mat_SeqAIJ *aseq = (Mat_SeqAIJ*)A->data; 4754394ed5ebSJunchao Zhang PetscCount i,j,Annz = aseq->nz; 4755394ed5ebSJunchao Zhang PetscCount *perm = aseq->perm,*jmap = aseq->jmap; 4756394ed5ebSJunchao Zhang PetscScalar *Aa; 4757394ed5ebSJunchao Zhang 4758394ed5ebSJunchao Zhang PetscFunctionBegin; 47599566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A,&Aa)); 4760394ed5ebSJunchao Zhang for (i=0; i<Annz; i++) { 4761b6c38306SJunchao Zhang PetscScalar sum = 0.0; 4762b6c38306SJunchao Zhang for (j=jmap[i]; j<jmap[i+1]; j++) sum += v[perm[j]]; 4763b6c38306SJunchao Zhang Aa[i] = (imode == INSERT_VALUES? 0.0 : Aa[i]) + sum; 4764394ed5ebSJunchao Zhang } 47659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A,&Aa)); 4766394ed5ebSJunchao Zhang PetscFunctionReturn(0); 4767394ed5ebSJunchao Zhang } 4768394ed5ebSJunchao Zhang 476934b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA) 47705063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat,MatType,MatReuse,Mat*); 477102fe1965SBarry Smith #endif 47723d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 47735063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat,MatType,MatReuse,Mat*); 47743d0639e7SStefano Zampini #endif 477502fe1965SBarry Smith 47768cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B) 4777273d9f13SBarry Smith { 4778273d9f13SBarry Smith Mat_SeqAIJ *b; 477938baddfdSBarry Smith PetscMPIInt size; 4780273d9f13SBarry Smith 4781273d9f13SBarry Smith PetscFunctionBegin; 47829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B),&size)); 478308401ef6SPierre Jolivet PetscCheck(size <= 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1"); 4784273d9f13SBarry Smith 47859566063dSJacob Faibussowitsch PetscCall(PetscNewLog(B,&b)); 47862205254eSKarl Rupp 4787b0a32e0cSBarry Smith B->data = (void*)b; 47882205254eSKarl Rupp 47899566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps))); 4790071fcb05SBarry Smith if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull; 47912205254eSKarl Rupp 4792f4259b30SLisandro Dalcin b->row = NULL; 4793f4259b30SLisandro Dalcin b->col = NULL; 4794f4259b30SLisandro Dalcin b->icol = NULL; 4795b810aeb4SBarry Smith b->reallocs = 0; 479636db0b34SBarry Smith b->ignorezeroentries = PETSC_FALSE; 4797f1e2ffcdSBarry Smith b->roworiented = PETSC_TRUE; 4798416022c9SBarry Smith b->nonew = 0; 4799f4259b30SLisandro Dalcin b->diag = NULL; 4800f4259b30SLisandro Dalcin b->solve_work = NULL; 4801f4259b30SLisandro Dalcin B->spptr = NULL; 4802f4259b30SLisandro Dalcin b->saved_values = NULL; 4803f4259b30SLisandro Dalcin b->idiag = NULL; 4804f4259b30SLisandro Dalcin b->mdiag = NULL; 4805f4259b30SLisandro Dalcin b->ssor_work = NULL; 480671f1c65dSBarry Smith b->omega = 1.0; 480771f1c65dSBarry Smith b->fshift = 0.0; 480871f1c65dSBarry Smith b->idiagvalid = PETSC_FALSE; 4809bbead8a2SBarry Smith b->ibdiagvalid = PETSC_FALSE; 4810a9817697SBarry Smith b->keepnonzeropattern = PETSC_FALSE; 481117ab2063SBarry Smith 48129566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ)); 48138c778c55SBarry Smith 4814b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE) 48159566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ)); 48169566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ)); 4817b3866ffcSBarry Smith #endif 481817f1a0eaSHong Zhang 48199566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ)); 48209566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ)); 48219566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ)); 48229566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ)); 48239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ)); 48249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM)); 48259566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL)); 48269779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 48279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL)); 4828191b95cbSRichard Tran Mills #endif 482934b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA) 48309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE)); 48319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ)); 48329566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",MatProductSetFromOptions_SeqAIJ)); 483302fe1965SBarry Smith #endif 48343d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 48359566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijkokkos_C",MatConvert_SeqAIJ_SeqAIJKokkos)); 48363d0639e7SStefano Zampini #endif 48379566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL)); 4838af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 48399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental)); 4840af8000cdSHong Zhang #endif 4841d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK) 48429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK)); 4843d24d4204SJose E. Roman #endif 484463c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 48459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE)); 48469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ)); 484763c07aadSStefano Zampini #endif 48489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense)); 48499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL)); 48509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS)); 48519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ)); 48529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ)); 48539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ)); 48549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ)); 48559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ)); 48569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ)); 48579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ)); 48589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ)); 48599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ)); 48609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJKron_C",MatSeqAIJKron_SeqAIJ)); 48619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSetPreallocationCOO_C",MatSetPreallocationCOO_SeqAIJ)); 48629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatSetValuesCOO_C",MatSetValuesCOO_SeqAIJ)); 48639566063dSJacob Faibussowitsch PetscCall(MatCreate_SeqAIJ_Inode(B)); 48649566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ)); 48659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetTypeFromOptions(B)); /* this allows changing the matrix subtype to say MATSEQAIJPERM */ 48663a40ed3dSBarry Smith PetscFunctionReturn(0); 486717ab2063SBarry Smith } 486817ab2063SBarry Smith 4869b24902e0SBarry Smith /* 4870b24902e0SBarry Smith Given a matrix generated with MatGetFactor() duplicates all the information in A into B 4871b24902e0SBarry Smith */ 4872ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace) 487317ab2063SBarry Smith { 48742a350339SBarry Smith Mat_SeqAIJ *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data; 4875071fcb05SBarry Smith PetscInt m = A->rmap->n,i; 487617ab2063SBarry Smith 48773a40ed3dSBarry Smith PetscFunctionBegin; 4878aed4548fSBarry Smith PetscCheck(A->assembled || cpvalues == MAT_DO_NOT_COPY_VALUES,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix"); 4879273d9f13SBarry Smith 4880d5f3da31SBarry Smith C->factortype = A->factortype; 4881f4259b30SLisandro Dalcin c->row = NULL; 4882f4259b30SLisandro Dalcin c->col = NULL; 4883f4259b30SLisandro Dalcin c->icol = NULL; 48846ad4291fSHong Zhang c->reallocs = 0; 488517ab2063SBarry Smith 488669272f91SPierre Jolivet C->assembled = A->assembled; 488769272f91SPierre Jolivet C->preallocated = A->preallocated; 488817ab2063SBarry Smith 488969272f91SPierre Jolivet if (A->preallocated) { 48909566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->rmap,&C->rmap)); 48919566063dSJacob Faibussowitsch PetscCall(PetscLayoutReference(A->cmap,&C->cmap)); 4892eec197d1SBarry Smith 48939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m,&c->imax)); 48949566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt))); 48959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m,&c->ilen)); 48969566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt))); 48979566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt))); 489817ab2063SBarry Smith 489917ab2063SBarry Smith /* allocate the matrix space */ 4900f77e22a1SHong Zhang if (mallocmatspace) { 49019566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i)); 49029566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt))); 49032205254eSKarl Rupp 4904f1e2ffcdSBarry Smith c->singlemalloc = PETSC_TRUE; 49052205254eSKarl Rupp 49069566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->i,a->i,m+1)); 490717ab2063SBarry Smith if (m > 0) { 49089566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->j,a->j,a->i[m])); 4909be6bf707SBarry Smith if (cpvalues == MAT_COPY_VALUES) { 49102e5835c6SStefano Zampini const PetscScalar *aa; 49112e5835c6SStefano Zampini 49129566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 49139566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->a,aa,a->i[m])); 49149566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 4915be6bf707SBarry Smith } else { 49169566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(c->a,a->i[m])); 491717ab2063SBarry Smith } 491808480c60SBarry Smith } 4919f77e22a1SHong Zhang } 492017ab2063SBarry Smith 49216ad4291fSHong Zhang c->ignorezeroentries = a->ignorezeroentries; 4922416022c9SBarry Smith c->roworiented = a->roworiented; 4923416022c9SBarry Smith c->nonew = a->nonew; 4924416022c9SBarry Smith if (a->diag) { 49259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m+1,&c->diag)); 49269566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt))); 49279566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt))); 4928071fcb05SBarry Smith } else c->diag = NULL; 49292205254eSKarl Rupp 4930f4259b30SLisandro Dalcin c->solve_work = NULL; 4931f4259b30SLisandro Dalcin c->saved_values = NULL; 4932f4259b30SLisandro Dalcin c->idiag = NULL; 4933f4259b30SLisandro Dalcin c->ssor_work = NULL; 4934a9817697SBarry Smith c->keepnonzeropattern = a->keepnonzeropattern; 4935e6b907acSBarry Smith c->free_a = PETSC_TRUE; 4936e6b907acSBarry Smith c->free_ij = PETSC_TRUE; 49376ad4291fSHong Zhang 4938893ad86cSHong Zhang c->rmax = a->rmax; 4939416022c9SBarry Smith c->nz = a->nz; 49408ed568f8SMatthew G Knepley c->maxnz = a->nz; /* Since we allocate exactly the right amount */ 4941754ec7b1SSatish Balay 49426ad4291fSHong Zhang c->compressedrow.use = a->compressedrow.use; 49436ad4291fSHong Zhang c->compressedrow.nrows = a->compressedrow.nrows; 4944cd6b891eSBarry Smith if (a->compressedrow.use) { 49456ad4291fSHong Zhang i = a->compressedrow.nrows; 49469566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex)); 49479566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1)); 49489566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i)); 494927ea64f8SHong Zhang } else { 495027ea64f8SHong Zhang c->compressedrow.use = PETSC_FALSE; 49510298fd71SBarry Smith c->compressedrow.i = NULL; 49520298fd71SBarry Smith c->compressedrow.rindex = NULL; 49536ad4291fSHong Zhang } 4954ea632784SBarry Smith c->nonzerorowcnt = a->nonzerorowcnt; 4955e56f5c9eSBarry Smith C->nonzerostate = A->nonzerostate; 49564846f1f5SKris Buschelman 49579566063dSJacob Faibussowitsch PetscCall(MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C)); 495869272f91SPierre Jolivet } 49599566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist)); 49603a40ed3dSBarry Smith PetscFunctionReturn(0); 496117ab2063SBarry Smith } 496217ab2063SBarry Smith 4963b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B) 4964b24902e0SBarry Smith { 4965b24902e0SBarry Smith PetscFunctionBegin; 49669566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),B)); 49679566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n)); 4968cfd3f464SBarry Smith if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) { 49699566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(*B,A,A)); 4970cfd3f464SBarry Smith } 49719566063dSJacob Faibussowitsch PetscCall(MatSetType(*B,((PetscObject)A)->type_name)); 49729566063dSJacob Faibussowitsch PetscCall(MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE)); 4973b24902e0SBarry Smith PetscFunctionReturn(0); 4974b24902e0SBarry Smith } 4975b24902e0SBarry Smith 4976112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer) 4977fbdbba38SShri Abhyankar { 497852f91c60SVaclav Hapla PetscBool isbinary, ishdf5; 497952f91c60SVaclav Hapla 498052f91c60SVaclav Hapla PetscFunctionBegin; 498152f91c60SVaclav Hapla PetscValidHeaderSpecific(newMat,MAT_CLASSID,1); 498252f91c60SVaclav Hapla PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 4983c27b3999SVaclav Hapla /* force binary viewer to load .info file if it has not yet done so */ 49849566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 49859566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary)); 49869566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5, &ishdf5)); 498752f91c60SVaclav Hapla if (isbinary) { 49889566063dSJacob Faibussowitsch PetscCall(MatLoad_SeqAIJ_Binary(newMat,viewer)); 498952f91c60SVaclav Hapla } else if (ishdf5) { 499052f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5) 49919566063dSJacob Faibussowitsch PetscCall(MatLoad_AIJ_HDF5(newMat,viewer)); 499252f91c60SVaclav Hapla #else 499352f91c60SVaclav Hapla SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 499452f91c60SVaclav Hapla #endif 499552f91c60SVaclav Hapla } else { 499698921bdaSJacob 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); 499752f91c60SVaclav Hapla } 499852f91c60SVaclav Hapla PetscFunctionReturn(0); 499952f91c60SVaclav Hapla } 500052f91c60SVaclav Hapla 50013ea6fe3dSLisandro Dalcin PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer) 500252f91c60SVaclav Hapla { 50033ea6fe3dSLisandro Dalcin Mat_SeqAIJ *a = (Mat_SeqAIJ*)mat->data; 50043ea6fe3dSLisandro Dalcin PetscInt header[4],*rowlens,M,N,nz,sum,rows,cols,i; 5005fbdbba38SShri Abhyankar 5006fbdbba38SShri Abhyankar PetscFunctionBegin; 50079566063dSJacob Faibussowitsch PetscCall(PetscViewerSetUp(viewer)); 5008bbead8a2SBarry Smith 50093ea6fe3dSLisandro Dalcin /* read in matrix header */ 50109566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT)); 501108401ef6SPierre Jolivet PetscCheck(header[0] == MAT_FILE_CLASSID,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file"); 5012fbdbba38SShri Abhyankar M = header[1]; N = header[2]; nz = header[3]; 501308401ef6SPierre Jolivet PetscCheck(M >= 0,PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%" PetscInt_FMT ") in file is negative",M); 501408401ef6SPierre Jolivet PetscCheck(N >= 0,PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%" PetscInt_FMT ") in file is negative",N); 501508401ef6SPierre Jolivet PetscCheck(nz >= 0,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ"); 5016fbdbba38SShri Abhyankar 50173ea6fe3dSLisandro Dalcin /* set block sizes from the viewer's .info file */ 50189566063dSJacob Faibussowitsch PetscCall(MatLoad_Binary_BlockSizes(mat,viewer)); 50193ea6fe3dSLisandro Dalcin /* set local and global sizes if not set already */ 50203ea6fe3dSLisandro Dalcin if (mat->rmap->n < 0) mat->rmap->n = M; 50213ea6fe3dSLisandro Dalcin if (mat->cmap->n < 0) mat->cmap->n = N; 50223ea6fe3dSLisandro Dalcin if (mat->rmap->N < 0) mat->rmap->N = M; 50233ea6fe3dSLisandro Dalcin if (mat->cmap->N < 0) mat->cmap->N = N; 50249566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->rmap)); 50259566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->cmap)); 50263ea6fe3dSLisandro Dalcin 50273ea6fe3dSLisandro Dalcin /* check if the matrix sizes are correct */ 50289566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat,&rows,&cols)); 5029aed4548fSBarry 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); 50303ea6fe3dSLisandro Dalcin 5031fbdbba38SShri Abhyankar /* read in row lengths */ 50329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(M,&rowlens)); 50339566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT)); 50343ea6fe3dSLisandro Dalcin /* check if sum(rowlens) is same as nz */ 50353ea6fe3dSLisandro Dalcin sum = 0; for (i=0; i<M; i++) sum += rowlens[i]; 503608401ef6SPierre 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); 50373ea6fe3dSLisandro Dalcin /* preallocate and check sizes */ 50389566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens)); 50399566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat,&rows,&cols)); 5040aed4548fSBarry 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); 50413ea6fe3dSLisandro Dalcin /* store row lengths */ 50429566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(a->ilen,rowlens,M)); 50439566063dSJacob Faibussowitsch PetscCall(PetscFree(rowlens)); 5044fbdbba38SShri Abhyankar 50453ea6fe3dSLisandro Dalcin /* fill in "i" row pointers */ 50463ea6fe3dSLisandro Dalcin a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i]; 50473ea6fe3dSLisandro Dalcin /* read in "j" column indices */ 50489566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT)); 50493ea6fe3dSLisandro Dalcin /* read in "a" nonzero values */ 50509566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR)); 5051fbdbba38SShri Abhyankar 50529566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY)); 50539566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY)); 5054fbdbba38SShri Abhyankar PetscFunctionReturn(0); 5055fbdbba38SShri Abhyankar } 5056fbdbba38SShri Abhyankar 5057ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg) 50587264ac53SSatish Balay { 50597264ac53SSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data; 5060fff043a9SJunchao Zhang const PetscScalar *aa,*ba; 5061eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX) 5062eeffb40dSHong Zhang PetscInt k; 5063eeffb40dSHong Zhang #endif 50647264ac53SSatish Balay 50653a40ed3dSBarry Smith PetscFunctionBegin; 5066bfeeae90SHong Zhang /* If the matrix dimensions are not equal,or no of nonzeros */ 5067d0f46423SBarry Smith if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) { 5068ca44d042SBarry Smith *flg = PETSC_FALSE; 5069ca44d042SBarry Smith PetscFunctionReturn(0); 5070bcd2baecSBarry Smith } 50717264ac53SSatish Balay 50727264ac53SSatish Balay /* if the a->i are the same */ 50739566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(a->i,b->i,A->rmap->n+1,flg)); 5074abc0a331SBarry Smith if (!*flg) PetscFunctionReturn(0); 50757264ac53SSatish Balay 50767264ac53SSatish Balay /* if a->j are the same */ 50779566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(a->j,b->j,a->nz,flg)); 5078abc0a331SBarry Smith if (!*flg) PetscFunctionReturn(0); 5079bcd2baecSBarry Smith 50809566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A,&aa)); 50819566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(B,&ba)); 5082bcd2baecSBarry Smith /* if a->a are the same */ 5083eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX) 5084eeffb40dSHong Zhang for (k=0; k<a->nz; k++) { 5085fff043a9SJunchao Zhang if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) { 5086eeffb40dSHong Zhang *flg = PETSC_FALSE; 50873a40ed3dSBarry Smith PetscFunctionReturn(0); 5088eeffb40dSHong Zhang } 5089eeffb40dSHong Zhang } 5090eeffb40dSHong Zhang #else 50919566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(aa,ba,a->nz,flg)); 5092eeffb40dSHong Zhang #endif 50939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A,&aa)); 50949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(B,&ba)); 5095eeffb40dSHong Zhang PetscFunctionReturn(0); 50967264ac53SSatish Balay } 509736db0b34SBarry Smith 509805869f15SSatish Balay /*@ 509936db0b34SBarry Smith MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format) 510036db0b34SBarry Smith provided by the user. 510136db0b34SBarry Smith 5102d083f849SBarry Smith Collective 510336db0b34SBarry Smith 510436db0b34SBarry Smith Input Parameters: 510536db0b34SBarry Smith + comm - must be an MPI communicator of size 1 510636db0b34SBarry Smith . m - number of rows 510736db0b34SBarry Smith . n - number of columns 5108483a2f95SBarry Smith . i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix 510936db0b34SBarry Smith . j - column indices 511036db0b34SBarry Smith - a - matrix values 511136db0b34SBarry Smith 511236db0b34SBarry Smith Output Parameter: 511336db0b34SBarry Smith . mat - the matrix 511436db0b34SBarry Smith 511536db0b34SBarry Smith Level: intermediate 511636db0b34SBarry Smith 511736db0b34SBarry Smith Notes: 51180551d7c0SBarry Smith The i, j, and a arrays are not copied by this routine, the user must free these arrays 5119292fb18eSBarry Smith once the matrix is destroyed and not before 512036db0b34SBarry Smith 512136db0b34SBarry Smith You cannot set new nonzero locations into this matrix, that will generate an error. 512236db0b34SBarry Smith 5123bfeeae90SHong Zhang The i and j indices are 0 based 512436db0b34SBarry Smith 5125a4552177SSatish Balay The format which is used for the sparse matrix input, is equivalent to a 5126a4552177SSatish Balay row-major ordering.. i.e for the following matrix, the input data expected is 51278eef79e4SBarry Smith as shown 5128a4552177SSatish Balay 51298eef79e4SBarry Smith $ 1 0 0 51308eef79e4SBarry Smith $ 2 0 3 51318eef79e4SBarry Smith $ 4 5 6 51328eef79e4SBarry Smith $ 51338eef79e4SBarry Smith $ i = {0,1,3,6} [size = nrow+1 = 3+1] 51348eef79e4SBarry Smith $ j = {0,0,2,0,1,2} [size = 6]; values must be sorted for each row 51358eef79e4SBarry Smith $ v = {1,2,3,4,5,6} [size = 6] 5136a4552177SSatish Balay 5137db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateMPIAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()` 513836db0b34SBarry Smith 513936db0b34SBarry Smith @*/ 5140c3c607ccSBarry Smith PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat) 514136db0b34SBarry Smith { 5142cbcfb4deSHong Zhang PetscInt ii; 514336db0b34SBarry Smith Mat_SeqAIJ *aij; 5144cbcfb4deSHong Zhang PetscInt jj; 514536db0b34SBarry Smith 514636db0b34SBarry Smith PetscFunctionBegin; 5147aed4548fSBarry Smith PetscCheck(m <= 0 || i[0] == 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 51489566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,mat)); 51499566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat,m,n,m,n)); 51509566063dSJacob Faibussowitsch /* PetscCall(MatSetBlockSizes(*mat,,)); */ 51519566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat,MATSEQAIJ)); 51529566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL)); 5153ab93d7beSBarry Smith aij = (Mat_SeqAIJ*)(*mat)->data; 51549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m,&aij->imax)); 51559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m,&aij->ilen)); 5156ab93d7beSBarry Smith 515736db0b34SBarry Smith aij->i = i; 515836db0b34SBarry Smith aij->j = j; 515936db0b34SBarry Smith aij->a = a; 516036db0b34SBarry Smith aij->singlemalloc = PETSC_FALSE; 516136db0b34SBarry Smith aij->nonew = -1; /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/ 5162e6b907acSBarry Smith aij->free_a = PETSC_FALSE; 5163e6b907acSBarry Smith aij->free_ij = PETSC_FALSE; 516436db0b34SBarry Smith 5165cbc6b225SStefano Zampini for (ii=0,aij->nonzerorowcnt=0,aij->rmax=0; ii<m; ii++) { 516636db0b34SBarry Smith aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii]; 516776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 5168aed4548fSBarry 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]); 51699985e31cSBarry Smith for (jj=i[ii]+1; jj<i[ii+1]; jj++) { 517008401ef6SPierre 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); 517108401ef6SPierre 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); 51729985e31cSBarry Smith } 517336db0b34SBarry Smith } 517476bd3646SJed Brown } 517576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 517636db0b34SBarry Smith for (ii=0; ii<aij->i[m]; ii++) { 517708401ef6SPierre 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]); 5178aed4548fSBarry 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]); 517936db0b34SBarry Smith } 518076bd3646SJed Brown } 518136db0b34SBarry Smith 51829566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY)); 51839566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY)); 518436db0b34SBarry Smith PetscFunctionReturn(0); 518536db0b34SBarry Smith } 5186cbc6b225SStefano Zampini 5187f62e3866SBarry Smith /*@ 5188d021a1c5SVictor Minden MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format) 51898a0b0e6bSVictor Minden provided by the user. 51908a0b0e6bSVictor Minden 5191d083f849SBarry Smith Collective 51928a0b0e6bSVictor Minden 51938a0b0e6bSVictor Minden Input Parameters: 51948a0b0e6bSVictor Minden + comm - must be an MPI communicator of size 1 51958a0b0e6bSVictor Minden . m - number of rows 51968a0b0e6bSVictor Minden . n - number of columns 51978a0b0e6bSVictor Minden . i - row indices 51988a0b0e6bSVictor Minden . j - column indices 51991230e6d1SVictor Minden . a - matrix values 52001230e6d1SVictor Minden . nz - number of nonzeros 5201f62e3866SBarry Smith - idx - if the i and j indices start with 1 use PETSC_TRUE otherwise use PETSC_FALSE 52028a0b0e6bSVictor Minden 52038a0b0e6bSVictor Minden Output Parameter: 52048a0b0e6bSVictor Minden . mat - the matrix 52058a0b0e6bSVictor Minden 52068a0b0e6bSVictor Minden Level: intermediate 52078a0b0e6bSVictor Minden 5208f62e3866SBarry Smith Example: 5209f62e3866SBarry Smith For the following matrix, the input data expected is as shown (using 0 based indexing) 52109e99939fSJunchao Zhang .vb 52118a0b0e6bSVictor Minden 1 0 0 52128a0b0e6bSVictor Minden 2 0 3 52138a0b0e6bSVictor Minden 4 5 6 52148a0b0e6bSVictor Minden 52158a0b0e6bSVictor Minden i = {0,1,1,2,2,2} 52168a0b0e6bSVictor Minden j = {0,0,2,0,1,2} 52178a0b0e6bSVictor Minden v = {1,2,3,4,5,6} 52189e99939fSJunchao Zhang .ve 52198a0b0e6bSVictor Minden 5220db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateAIJ()`, `MatCreateSeqAIJ()`, `MatCreateSeqAIJWithArrays()`, `MatMPIAIJSetPreallocationCSR()`, `MatSetValuesCOO()` 52218a0b0e6bSVictor Minden 52228a0b0e6bSVictor Minden @*/ 5223c3c607ccSBarry Smith PetscErrorCode MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx) 52248a0b0e6bSVictor Minden { 5225d021a1c5SVictor Minden PetscInt ii, *nnz, one = 1,row,col; 52268a0b0e6bSVictor Minden 52278a0b0e6bSVictor Minden PetscFunctionBegin; 52289566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m,&nnz)); 52291230e6d1SVictor Minden for (ii = 0; ii < nz; ii++) { 5230c8d679ebSHong Zhang nnz[i[ii] - !!idx] += 1; 52311230e6d1SVictor Minden } 52329566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,mat)); 52339566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat,m,n,m,n)); 52349566063dSJacob Faibussowitsch PetscCall(MatSetType(*mat,MATSEQAIJ)); 52359566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz)); 52361230e6d1SVictor Minden for (ii = 0; ii < nz; ii++) { 52371230e6d1SVictor Minden if (idx) { 52381230e6d1SVictor Minden row = i[ii] - 1; 52391230e6d1SVictor Minden col = j[ii] - 1; 52401230e6d1SVictor Minden } else { 52411230e6d1SVictor Minden row = i[ii]; 52421230e6d1SVictor Minden col = j[ii]; 52438a0b0e6bSVictor Minden } 52449566063dSJacob Faibussowitsch PetscCall(MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES)); 52458a0b0e6bSVictor Minden } 52469566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY)); 52479566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY)); 52489566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 52498a0b0e6bSVictor Minden PetscFunctionReturn(0); 52508a0b0e6bSVictor Minden } 525136db0b34SBarry Smith 5252acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A) 5253acf2f550SJed Brown { 5254acf2f550SJed Brown Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data; 5255acf2f550SJed Brown 5256acf2f550SJed Brown PetscFunctionBegin; 5257acf2f550SJed Brown a->idiagvalid = PETSC_FALSE; 5258acf2f550SJed Brown a->ibdiagvalid = PETSC_FALSE; 52592205254eSKarl Rupp 52609566063dSJacob Faibussowitsch PetscCall(MatSeqAIJInvalidateDiagonal_Inode(A)); 5261acf2f550SJed Brown PetscFunctionReturn(0); 5262acf2f550SJed Brown } 5263acf2f550SJed Brown 52649c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat) 52659c8f2541SHong Zhang { 52668761c3d6SHong Zhang PetscMPIInt size; 52679c8f2541SHong Zhang 52689c8f2541SHong Zhang PetscFunctionBegin; 52699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm,&size)); 52707bbdc51dSHong Zhang if (size == 1) { 52717bbdc51dSHong Zhang if (scall == MAT_INITIAL_MATRIX) { 52729566063dSJacob Faibussowitsch PetscCall(MatDuplicate(inmat,MAT_COPY_VALUES,outmat)); 52737bbdc51dSHong Zhang } else { 52749566063dSJacob Faibussowitsch PetscCall(MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN)); 52757bbdc51dSHong Zhang } 52768761c3d6SHong Zhang } else { 52779566063dSJacob Faibussowitsch PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat)); 52788761c3d6SHong Zhang } 52799c8f2541SHong Zhang PetscFunctionReturn(0); 52809c8f2541SHong Zhang } 52819c8f2541SHong Zhang 528281824310SBarry Smith /* 528353dd7562SDmitry Karpeev Permute A into C's *local* index space using rowemb,colemb. 528453dd7562SDmitry Karpeev The embedding are supposed to be injections and the above implies that the range of rowemb is a subset 528553dd7562SDmitry Karpeev of [0,m), colemb is in [0,n). 528653dd7562SDmitry Karpeev If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A. 528753dd7562SDmitry Karpeev */ 528853dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B) 528953dd7562SDmitry Karpeev { 529053dd7562SDmitry Karpeev /* If making this function public, change the error returned in this function away from _PLIB. */ 529153dd7562SDmitry Karpeev Mat_SeqAIJ *Baij; 529253dd7562SDmitry Karpeev PetscBool seqaij; 529353dd7562SDmitry Karpeev PetscInt m,n,*nz,i,j,count; 529453dd7562SDmitry Karpeev PetscScalar v; 529553dd7562SDmitry Karpeev const PetscInt *rowindices,*colindices; 529653dd7562SDmitry Karpeev 529753dd7562SDmitry Karpeev PetscFunctionBegin; 529853dd7562SDmitry Karpeev if (!B) PetscFunctionReturn(0); 529953dd7562SDmitry Karpeev /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */ 53009566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij)); 530128b400f6SJacob Faibussowitsch PetscCheck(seqaij,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type"); 530253dd7562SDmitry Karpeev if (rowemb) { 53039566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(rowemb,&m)); 530408401ef6SPierre 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); 530553dd7562SDmitry Karpeev } else { 530608401ef6SPierre Jolivet PetscCheck(C->rmap->n == B->rmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix"); 530753dd7562SDmitry Karpeev } 530853dd7562SDmitry Karpeev if (colemb) { 53099566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(colemb,&n)); 531008401ef6SPierre 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); 531153dd7562SDmitry Karpeev } else { 531208401ef6SPierre Jolivet PetscCheck(C->cmap->n == B->cmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix"); 531353dd7562SDmitry Karpeev } 531453dd7562SDmitry Karpeev 531553dd7562SDmitry Karpeev Baij = (Mat_SeqAIJ*)(B->data); 531653dd7562SDmitry Karpeev if (pattern == DIFFERENT_NONZERO_PATTERN) { 53179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(B->rmap->n,&nz)); 531853dd7562SDmitry Karpeev for (i=0; i<B->rmap->n; i++) { 531953dd7562SDmitry Karpeev nz[i] = Baij->i[i+1] - Baij->i[i]; 532053dd7562SDmitry Karpeev } 53219566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(C,0,nz)); 53229566063dSJacob Faibussowitsch PetscCall(PetscFree(nz)); 532353dd7562SDmitry Karpeev } 532453dd7562SDmitry Karpeev if (pattern == SUBSET_NONZERO_PATTERN) { 53259566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(C)); 532653dd7562SDmitry Karpeev } 532753dd7562SDmitry Karpeev count = 0; 532853dd7562SDmitry Karpeev rowindices = NULL; 532953dd7562SDmitry Karpeev colindices = NULL; 533053dd7562SDmitry Karpeev if (rowemb) { 53319566063dSJacob Faibussowitsch PetscCall(ISGetIndices(rowemb,&rowindices)); 533253dd7562SDmitry Karpeev } 533353dd7562SDmitry Karpeev if (colemb) { 53349566063dSJacob Faibussowitsch PetscCall(ISGetIndices(colemb,&colindices)); 533553dd7562SDmitry Karpeev } 533653dd7562SDmitry Karpeev for (i=0; i<B->rmap->n; i++) { 533753dd7562SDmitry Karpeev PetscInt row; 533853dd7562SDmitry Karpeev row = i; 533953dd7562SDmitry Karpeev if (rowindices) row = rowindices[i]; 534053dd7562SDmitry Karpeev for (j=Baij->i[i]; j<Baij->i[i+1]; j++) { 534153dd7562SDmitry Karpeev PetscInt col; 534253dd7562SDmitry Karpeev col = Baij->j[count]; 534353dd7562SDmitry Karpeev if (colindices) col = colindices[col]; 534453dd7562SDmitry Karpeev v = Baij->a[count]; 53459566063dSJacob Faibussowitsch PetscCall(MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES)); 534653dd7562SDmitry Karpeev ++count; 534753dd7562SDmitry Karpeev } 534853dd7562SDmitry Karpeev } 534953dd7562SDmitry Karpeev /* FIXME: set C's nonzerostate correctly. */ 535053dd7562SDmitry Karpeev /* Assembly for C is necessary. */ 535153dd7562SDmitry Karpeev C->preallocated = PETSC_TRUE; 535253dd7562SDmitry Karpeev C->assembled = PETSC_TRUE; 535353dd7562SDmitry Karpeev C->was_assembled = PETSC_FALSE; 535453dd7562SDmitry Karpeev PetscFunctionReturn(0); 535553dd7562SDmitry Karpeev } 535653dd7562SDmitry Karpeev 53574099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL; 53584099cc6bSBarry Smith 53594099cc6bSBarry Smith /*@C 53604099cc6bSBarry Smith MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype 53614099cc6bSBarry Smith 53624099cc6bSBarry Smith Collective on Mat 53634099cc6bSBarry Smith 53644099cc6bSBarry Smith Input Parameters: 53654099cc6bSBarry Smith + mat - the matrix object 53664099cc6bSBarry Smith - matype - matrix type 53674099cc6bSBarry Smith 53684099cc6bSBarry Smith Options Database Key: 53694099cc6bSBarry Smith . -mat_seqai_type <method> - for example seqaijcrl 53704099cc6bSBarry Smith 53714099cc6bSBarry Smith Level: intermediate 53724099cc6bSBarry Smith 5373db781477SPatrick Sanan .seealso: `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`, `Mat` 53744099cc6bSBarry Smith @*/ 53754099cc6bSBarry Smith PetscErrorCode MatSeqAIJSetType(Mat mat, MatType matype) 53764099cc6bSBarry Smith { 53774099cc6bSBarry Smith PetscBool sametype; 53785f80ce2aSJacob Faibussowitsch PetscErrorCode (*r)(Mat,MatType,MatReuse,Mat*); 53794099cc6bSBarry Smith 53804099cc6bSBarry Smith PetscFunctionBegin; 53814099cc6bSBarry Smith PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 53829566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat,matype,&sametype)); 53834099cc6bSBarry Smith if (sametype) PetscFunctionReturn(0); 53844099cc6bSBarry Smith 53859566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(MatSeqAIJList,matype,&r)); 53865f80ce2aSJacob Faibussowitsch PetscCheck(r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype); 53879566063dSJacob Faibussowitsch PetscCall((*r)(mat,matype,MAT_INPLACE_MATRIX,&mat)); 53884099cc6bSBarry Smith PetscFunctionReturn(0); 53894099cc6bSBarry Smith } 53904099cc6bSBarry Smith 53914099cc6bSBarry Smith /*@C 53924099cc6bSBarry Smith MatSeqAIJRegister - - Adds a new sub-matrix type for sequential AIJ matrices 53934099cc6bSBarry Smith 53944099cc6bSBarry Smith Not Collective 53954099cc6bSBarry Smith 53964099cc6bSBarry Smith Input Parameters: 53974099cc6bSBarry Smith + name - name of a new user-defined matrix type, for example MATSEQAIJCRL 53984099cc6bSBarry Smith - function - routine to convert to subtype 53994099cc6bSBarry Smith 54004099cc6bSBarry Smith Notes: 54014099cc6bSBarry Smith MatSeqAIJRegister() may be called multiple times to add several user-defined solvers. 54024099cc6bSBarry Smith 54034099cc6bSBarry Smith Then, your matrix can be chosen with the procedural interface at runtime via the option 54044099cc6bSBarry Smith $ -mat_seqaij_type my_mat 54054099cc6bSBarry Smith 54064099cc6bSBarry Smith Level: advanced 54074099cc6bSBarry Smith 5408db781477SPatrick Sanan .seealso: `MatSeqAIJRegisterAll()` 54094099cc6bSBarry Smith 54104099cc6bSBarry Smith Level: advanced 54114099cc6bSBarry Smith @*/ 5412388d47a6SSatish Balay PetscErrorCode MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *)) 54134099cc6bSBarry Smith { 54144099cc6bSBarry Smith PetscFunctionBegin; 54159566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 54169566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&MatSeqAIJList,sname,function)); 54174099cc6bSBarry Smith PetscFunctionReturn(0); 54184099cc6bSBarry Smith } 54194099cc6bSBarry Smith 54204099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE; 54214099cc6bSBarry Smith 54224099cc6bSBarry Smith /*@C 54234099cc6bSBarry Smith MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ 54244099cc6bSBarry Smith 54254099cc6bSBarry Smith Not Collective 54264099cc6bSBarry Smith 54274099cc6bSBarry Smith Level: advanced 54284099cc6bSBarry Smith 5429db781477SPatrick Sanan .seealso: `MatRegisterAll()`, `MatSeqAIJRegister()` 54304099cc6bSBarry Smith @*/ 54314099cc6bSBarry Smith PetscErrorCode MatSeqAIJRegisterAll(void) 54324099cc6bSBarry Smith { 54334099cc6bSBarry Smith PetscFunctionBegin; 54344099cc6bSBarry Smith if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0); 54354099cc6bSBarry Smith MatSeqAIJRegisterAllCalled = PETSC_TRUE; 54364099cc6bSBarry Smith 54379566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJCRL, MatConvert_SeqAIJ_SeqAIJCRL)); 54389566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJPERM, MatConvert_SeqAIJ_SeqAIJPERM)); 54399566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJSELL, MatConvert_SeqAIJ_SeqAIJSELL)); 54409779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 54419566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJMKL, MatConvert_SeqAIJ_SeqAIJMKL)); 5442485f9817SRichard Tran Mills #endif 54435063d097SStefano Zampini #if defined(PETSC_HAVE_CUDA) 54449566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE)); 54455063d097SStefano Zampini #endif 54465063d097SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS) 54479566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATSEQAIJKOKKOS, MatConvert_SeqAIJ_SeqAIJKokkos)); 54485063d097SStefano Zampini #endif 54494099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA) 54509566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL)); 54514099cc6bSBarry Smith #endif 54524099cc6bSBarry Smith PetscFunctionReturn(0); 54534099cc6bSBarry Smith } 545453dd7562SDmitry Karpeev 545553dd7562SDmitry Karpeev /* 545681824310SBarry Smith Special version for direct calls from Fortran 545781824310SBarry Smith */ 5458af0996ceSBarry Smith #include <petsc/private/fortranimpl.h> 545981824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS) 546081824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ 546181824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 546281824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij 546381824310SBarry Smith #endif 546481824310SBarry Smith 546581824310SBarry Smith /* Change these macros so can be used in void function */ 546698921bdaSJacob Faibussowitsch 546798921bdaSJacob Faibussowitsch /* Change these macros so can be used in void function */ 54689566063dSJacob Faibussowitsch /* Identical to PetscCallVoid, except it assigns to *_ierr */ 54699566063dSJacob Faibussowitsch #undef PetscCall 54709566063dSJacob Faibussowitsch #define PetscCall(...) do { \ 54715f80ce2aSJacob Faibussowitsch PetscErrorCode ierr_msv_mpiaij = __VA_ARGS__; \ 547298921bdaSJacob Faibussowitsch if (PetscUnlikely(ierr_msv_mpiaij)) { \ 547398921bdaSJacob Faibussowitsch *_ierr = PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,ierr_msv_mpiaij,PETSC_ERROR_REPEAT," "); \ 547498921bdaSJacob Faibussowitsch return; \ 547598921bdaSJacob Faibussowitsch } \ 547698921bdaSJacob Faibussowitsch } while (0) 547798921bdaSJacob Faibussowitsch 547898921bdaSJacob Faibussowitsch #undef SETERRQ 547998921bdaSJacob Faibussowitsch #define SETERRQ(comm,ierr,...) do { \ 548098921bdaSJacob Faibussowitsch *_ierr = PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,ierr,PETSC_ERROR_INITIAL,__VA_ARGS__); \ 548198921bdaSJacob Faibussowitsch return; \ 548298921bdaSJacob Faibussowitsch } while (0) 548381824310SBarry Smith 548419caf8f3SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr) 548581824310SBarry Smith { 548681824310SBarry Smith Mat A = *AA; 548781824310SBarry Smith PetscInt m = *mm, n = *nn; 548881824310SBarry Smith InsertMode is = *isis; 548981824310SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 549081824310SBarry Smith PetscInt *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N; 549181824310SBarry Smith PetscInt *imax,*ai,*ailen; 549281824310SBarry Smith PetscInt *aj,nonew = a->nonew,lastcol = -1; 549354f21887SBarry Smith MatScalar *ap,value,*aa; 5494ace3abfcSBarry Smith PetscBool ignorezeroentries = a->ignorezeroentries; 5495ace3abfcSBarry Smith PetscBool roworiented = a->roworiented; 549681824310SBarry Smith 549781824310SBarry Smith PetscFunctionBegin; 54984994cf47SJed Brown MatCheckPreallocated(A,1); 549981824310SBarry Smith imax = a->imax; 550081824310SBarry Smith ai = a->i; 550181824310SBarry Smith ailen = a->ilen; 550281824310SBarry Smith aj = a->j; 550381824310SBarry Smith aa = a->a; 550481824310SBarry Smith 550581824310SBarry Smith for (k=0; k<m; k++) { /* loop over added rows */ 550681824310SBarry Smith row = im[k]; 550781824310SBarry Smith if (row < 0) continue; 55085f80ce2aSJacob Faibussowitsch PetscCheck(row < A->rmap->n,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large"); 550981824310SBarry Smith rp = aj + ai[row]; ap = aa + ai[row]; 551081824310SBarry Smith rmax = imax[row]; nrow = ailen[row]; 551181824310SBarry Smith low = 0; 551281824310SBarry Smith high = nrow; 551381824310SBarry Smith for (l=0; l<n; l++) { /* loop over added columns */ 551481824310SBarry Smith if (in[l] < 0) continue; 55155f80ce2aSJacob Faibussowitsch PetscCheck(in[l] < A->cmap->n,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large"); 551681824310SBarry Smith col = in[l]; 55172205254eSKarl Rupp if (roworiented) value = v[l + k*n]; 55182205254eSKarl Rupp else value = v[k + l*m]; 55192205254eSKarl Rupp 552081824310SBarry Smith if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue; 552181824310SBarry Smith 55222205254eSKarl Rupp if (col <= lastcol) low = 0; 55232205254eSKarl Rupp else high = nrow; 552481824310SBarry Smith lastcol = col; 552581824310SBarry Smith while (high-low > 5) { 552681824310SBarry Smith t = (low+high)/2; 552781824310SBarry Smith if (rp[t] > col) high = t; 552881824310SBarry Smith else low = t; 552981824310SBarry Smith } 553081824310SBarry Smith for (i=low; i<high; i++) { 553181824310SBarry Smith if (rp[i] > col) break; 553281824310SBarry Smith if (rp[i] == col) { 553381824310SBarry Smith if (is == ADD_VALUES) ap[i] += value; 553481824310SBarry Smith else ap[i] = value; 553581824310SBarry Smith goto noinsert; 553681824310SBarry Smith } 553781824310SBarry Smith } 553881824310SBarry Smith if (value == 0.0 && ignorezeroentries) goto noinsert; 553981824310SBarry Smith if (nonew == 1) goto noinsert; 55405f80ce2aSJacob Faibussowitsch PetscCheck(nonew != -1,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix"); 5541fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar); 554281824310SBarry Smith N = nrow++ - 1; a->nz++; high++; 554381824310SBarry Smith /* shift up all the later entries in this row */ 554481824310SBarry Smith for (ii=N; ii>=i; ii--) { 554581824310SBarry Smith rp[ii+1] = rp[ii]; 554681824310SBarry Smith ap[ii+1] = ap[ii]; 554781824310SBarry Smith } 554881824310SBarry Smith rp[i] = col; 554981824310SBarry Smith ap[i] = value; 5550e56f5c9eSBarry Smith A->nonzerostate++; 555181824310SBarry Smith noinsert:; 555281824310SBarry Smith low = i + 1; 555381824310SBarry Smith } 555481824310SBarry Smith ailen[row] = nrow; 555581824310SBarry Smith } 555681824310SBarry Smith PetscFunctionReturnVoid(); 555781824310SBarry Smith } 555898921bdaSJacob Faibussowitsch /* Undefining these here since they were redefined from their original definition above! No 555998921bdaSJacob Faibussowitsch * other PETSc functions should be defined past this point, as it is impossible to recover the 556098921bdaSJacob Faibussowitsch * original definitions */ 55619566063dSJacob Faibussowitsch #undef PetscCall 556298921bdaSJacob Faibussowitsch #undef SETERRQ 5563