1aaa7dc30SBarry Smith #include <../src/mat/impls/nest/matnestimpl.h> /*I "petscmat.h" I*/ 2b68353e5Sstefano_zampini #include <../src/mat/impls/aij/seq/aij.h> 30c312b8eSJed Brown #include <petscsf.h> 4d8588912SDave May 5c8883902SJed Brown static PetscErrorCode MatSetUp_NestIS_Private(Mat,PetscInt,const IS[],PetscInt,const IS[]); 606a1af2fSStefano Zampini static PetscErrorCode MatCreateVecs_Nest(Mat,Vec*,Vec*); 706a1af2fSStefano Zampini static PetscErrorCode MatReset_Nest(Mat); 806a1af2fSStefano Zampini 95e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat,MatType,MatReuse,Mat*); 10c8883902SJed Brown 11d8588912SDave May /* private functions */ 128188e55aSJed Brown static PetscErrorCode MatNestGetSizes_Private(Mat A,PetscInt *m,PetscInt *n,PetscInt *M,PetscInt *N) 13d8588912SDave May { 14d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 158188e55aSJed Brown PetscInt i,j; 16d8588912SDave May 17d8588912SDave May PetscFunctionBegin; 188188e55aSJed Brown *m = *n = *M = *N = 0; 198188e55aSJed Brown for (i=0; i<bA->nr; i++) { /* rows */ 208188e55aSJed Brown PetscInt sm,sM; 219566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(bA->isglobal.row[i],&sm)); 229566063dSJacob Faibussowitsch PetscCall(ISGetSize(bA->isglobal.row[i],&sM)); 238188e55aSJed Brown *m += sm; 248188e55aSJed Brown *M += sM; 25d8588912SDave May } 268188e55aSJed Brown for (j=0; j<bA->nc; j++) { /* cols */ 278188e55aSJed Brown PetscInt sn,sN; 289566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(bA->isglobal.col[j],&sn)); 299566063dSJacob Faibussowitsch PetscCall(ISGetSize(bA->isglobal.col[j],&sN)); 308188e55aSJed Brown *n += sn; 318188e55aSJed Brown *N += sN; 32d8588912SDave May } 33d8588912SDave May PetscFunctionReturn(0); 34d8588912SDave May } 35d8588912SDave May 36d8588912SDave May /* operations */ 37207556f9SJed Brown static PetscErrorCode MatMult_Nest(Mat A,Vec x,Vec y) 38d8588912SDave May { 39d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 40207556f9SJed Brown Vec *bx = bA->right,*by = bA->left; 41207556f9SJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 42d8588912SDave May 43d8588912SDave May PetscFunctionBegin; 449566063dSJacob Faibussowitsch for (i=0; i<nr; i++) PetscCall(VecGetSubVector(y,bA->isglobal.row[i],&by[i])); 459566063dSJacob Faibussowitsch for (i=0; i<nc; i++) PetscCall(VecGetSubVector(x,bA->isglobal.col[i],&bx[i])); 46207556f9SJed Brown for (i=0; i<nr; i++) { 479566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(by[i])); 48207556f9SJed Brown for (j=0; j<nc; j++) { 49207556f9SJed Brown if (!bA->m[i][j]) continue; 50d8588912SDave May /* y[i] <- y[i] + A[i][j] * x[j] */ 519566063dSJacob Faibussowitsch PetscCall(MatMultAdd(bA->m[i][j],bx[j],by[i],by[i])); 52d8588912SDave May } 53d8588912SDave May } 549566063dSJacob Faibussowitsch for (i=0; i<nr; i++) PetscCall(VecRestoreSubVector(y,bA->isglobal.row[i],&by[i])); 559566063dSJacob Faibussowitsch for (i=0; i<nc; i++) PetscCall(VecRestoreSubVector(x,bA->isglobal.col[i],&bx[i])); 56d8588912SDave May PetscFunctionReturn(0); 57d8588912SDave May } 58d8588912SDave May 599194d70fSJed Brown static PetscErrorCode MatMultAdd_Nest(Mat A,Vec x,Vec y,Vec z) 609194d70fSJed Brown { 619194d70fSJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 629194d70fSJed Brown Vec *bx = bA->right,*bz = bA->left; 639194d70fSJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 649194d70fSJed Brown 659194d70fSJed Brown PetscFunctionBegin; 669566063dSJacob Faibussowitsch for (i=0; i<nr; i++) PetscCall(VecGetSubVector(z,bA->isglobal.row[i],&bz[i])); 679566063dSJacob Faibussowitsch for (i=0; i<nc; i++) PetscCall(VecGetSubVector(x,bA->isglobal.col[i],&bx[i])); 689194d70fSJed Brown for (i=0; i<nr; i++) { 699194d70fSJed Brown if (y != z) { 709194d70fSJed Brown Vec by; 719566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(y,bA->isglobal.row[i],&by)); 729566063dSJacob Faibussowitsch PetscCall(VecCopy(by,bz[i])); 739566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(y,bA->isglobal.row[i],&by)); 749194d70fSJed Brown } 759194d70fSJed Brown for (j=0; j<nc; j++) { 769194d70fSJed Brown if (!bA->m[i][j]) continue; 779194d70fSJed Brown /* y[i] <- y[i] + A[i][j] * x[j] */ 789566063dSJacob Faibussowitsch PetscCall(MatMultAdd(bA->m[i][j],bx[j],bz[i],bz[i])); 799194d70fSJed Brown } 809194d70fSJed Brown } 819566063dSJacob Faibussowitsch for (i=0; i<nr; i++) PetscCall(VecRestoreSubVector(z,bA->isglobal.row[i],&bz[i])); 829566063dSJacob Faibussowitsch for (i=0; i<nc; i++) PetscCall(VecRestoreSubVector(x,bA->isglobal.col[i],&bx[i])); 839194d70fSJed Brown PetscFunctionReturn(0); 849194d70fSJed Brown } 859194d70fSJed Brown 8652c5f739Sprj- typedef struct { 8752c5f739Sprj- Mat *workC; /* array of Mat with specific containers depending on the underlying MatMatMult implementation */ 8852c5f739Sprj- PetscScalar *tarray; /* buffer for storing all temporary products A[i][j] B[j] */ 8952c5f739Sprj- PetscInt *dm,*dn,k; /* displacements and number of submatrices */ 9052c5f739Sprj- } Nest_Dense; 9152c5f739Sprj- 926718818eSStefano Zampini PETSC_INTERN PetscErrorCode MatProductNumeric_Nest_Dense(Mat C) 9352c5f739Sprj- { 946718818eSStefano Zampini Mat_Nest *bA; 9552c5f739Sprj- Nest_Dense *contents; 966718818eSStefano Zampini Mat viewB,viewC,productB,workC; 9752c5f739Sprj- const PetscScalar *barray; 9852c5f739Sprj- PetscScalar *carray; 996718818eSStefano Zampini PetscInt i,j,M,N,nr,nc,ldb,ldc; 1006718818eSStefano Zampini Mat A,B; 10152c5f739Sprj- 10252c5f739Sprj- PetscFunctionBegin; 1036718818eSStefano Zampini MatCheckProduct(C,3); 1046718818eSStefano Zampini A = C->product->A; 1056718818eSStefano Zampini B = C->product->B; 1069566063dSJacob Faibussowitsch PetscCall(MatGetSize(B,NULL,&N)); 1076718818eSStefano Zampini if (!N) { 1089566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY)); 1099566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY)); 1106718818eSStefano Zampini PetscFunctionReturn(0); 1116718818eSStefano Zampini } 1126718818eSStefano Zampini contents = (Nest_Dense*)C->product->data; 11328b400f6SJacob Faibussowitsch PetscCheck(contents,PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Product data empty"); 1146718818eSStefano Zampini bA = (Mat_Nest*)A->data; 1156718818eSStefano Zampini nr = bA->nr; 1166718818eSStefano Zampini nc = bA->nc; 1179566063dSJacob Faibussowitsch PetscCall(MatDenseGetLDA(B,&ldb)); 1189566063dSJacob Faibussowitsch PetscCall(MatDenseGetLDA(C,&ldc)); 1199566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(C)); 1209566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(B,&barray)); 1219566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(C,&carray)); 12252c5f739Sprj- for (i=0; i<nr; i++) { 1239566063dSJacob Faibussowitsch PetscCall(ISGetSize(bA->isglobal.row[i],&M)); 1249566063dSJacob Faibussowitsch PetscCall(MatCreateDense(PetscObjectComm((PetscObject)A),contents->dm[i+1]-contents->dm[i],PETSC_DECIDE,M,N,carray+contents->dm[i],&viewC)); 1259566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(viewC,ldc)); 12652c5f739Sprj- for (j=0; j<nc; j++) { 12752c5f739Sprj- if (!bA->m[i][j]) continue; 1289566063dSJacob Faibussowitsch PetscCall(ISGetSize(bA->isglobal.col[j],&M)); 1299566063dSJacob Faibussowitsch PetscCall(MatCreateDense(PetscObjectComm((PetscObject)A),contents->dn[j+1]-contents->dn[j],PETSC_DECIDE,M,N,(PetscScalar*)(barray+contents->dn[j]),&viewB)); 1309566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(viewB,ldb)); 1314222ddf1SHong Zhang 1324222ddf1SHong Zhang /* MatMatMultNumeric(bA->m[i][j],viewB,contents->workC[i*nc + j]); */ 1334222ddf1SHong Zhang workC = contents->workC[i*nc + j]; 1344222ddf1SHong Zhang productB = workC->product->B; 1354222ddf1SHong Zhang workC->product->B = viewB; /* use newly created dense matrix viewB */ 1369566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(workC)); 1379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&viewB)); 1384222ddf1SHong Zhang workC->product->B = productB; /* resume original B */ 1394222ddf1SHong Zhang 14052c5f739Sprj- /* C[i] <- workC + C[i] */ 1419566063dSJacob Faibussowitsch PetscCall(MatAXPY(viewC,1.0,contents->workC[i*nc + j],SAME_NONZERO_PATTERN)); 14252c5f739Sprj- } 1439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&viewC)); 14452c5f739Sprj- } 1459566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(C,&carray)); 1469566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(B,&barray)); 1474222ddf1SHong Zhang 1489566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY)); 1499566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY)); 15052c5f739Sprj- PetscFunctionReturn(0); 15152c5f739Sprj- } 15252c5f739Sprj- 15352c5f739Sprj- PetscErrorCode MatNest_DenseDestroy(void *ctx) 15452c5f739Sprj- { 15552c5f739Sprj- Nest_Dense *contents = (Nest_Dense*)ctx; 15652c5f739Sprj- PetscInt i; 15752c5f739Sprj- 15852c5f739Sprj- PetscFunctionBegin; 1599566063dSJacob Faibussowitsch PetscCall(PetscFree(contents->tarray)); 16052c5f739Sprj- for (i=0; i<contents->k; i++) { 1619566063dSJacob Faibussowitsch PetscCall(MatDestroy(contents->workC + i)); 16252c5f739Sprj- } 1639566063dSJacob Faibussowitsch PetscCall(PetscFree3(contents->dm,contents->dn,contents->workC)); 1649566063dSJacob Faibussowitsch PetscCall(PetscFree(contents)); 16552c5f739Sprj- PetscFunctionReturn(0); 16652c5f739Sprj- } 16752c5f739Sprj- 1686718818eSStefano Zampini PETSC_INTERN PetscErrorCode MatProductSymbolic_Nest_Dense(Mat C) 16952c5f739Sprj- { 1706718818eSStefano Zampini Mat_Nest *bA; 1716718818eSStefano Zampini Mat viewB,workC; 17252c5f739Sprj- const PetscScalar *barray; 1736718818eSStefano Zampini PetscInt i,j,M,N,m,n,nr,nc,maxm = 0,ldb; 1744222ddf1SHong Zhang Nest_Dense *contents=NULL; 1756718818eSStefano Zampini PetscBool cisdense; 1766718818eSStefano Zampini Mat A,B; 1776718818eSStefano Zampini PetscReal fill; 17852c5f739Sprj- 17952c5f739Sprj- PetscFunctionBegin; 1806718818eSStefano Zampini MatCheckProduct(C,4); 18128b400f6SJacob Faibussowitsch PetscCheck(!C->product->data,PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Product data not empty"); 1826718818eSStefano Zampini A = C->product->A; 1836718818eSStefano Zampini B = C->product->B; 1846718818eSStefano Zampini fill = C->product->fill; 1856718818eSStefano Zampini bA = (Mat_Nest*)A->data; 1866718818eSStefano Zampini nr = bA->nr; 1876718818eSStefano Zampini nc = bA->nc; 1889566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(C,&m,&n)); 1899566063dSJacob Faibussowitsch PetscCall(MatGetSize(C,&M,&N)); 1900572eedcSPierre Jolivet if (m == PETSC_DECIDE || n == PETSC_DECIDE || M == PETSC_DECIDE || N == PETSC_DECIDE) { 1919566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(B,NULL,&n)); 1929566063dSJacob Faibussowitsch PetscCall(MatGetSize(B,NULL,&N)); 1939566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A,&m,NULL)); 1949566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&M,NULL)); 1959566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C,m,n,M,N)); 1960572eedcSPierre Jolivet } 1979566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATMPIDENSE,MATSEQDENSECUDA,MATMPIDENSECUDA,"")); 1986718818eSStefano Zampini if (!cisdense) { 1999566063dSJacob Faibussowitsch PetscCall(MatSetType(C,((PetscObject)B)->type_name)); 2006718818eSStefano Zampini } 2019566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 2026718818eSStefano Zampini if (!N) { 2036718818eSStefano Zampini C->ops->productnumeric = MatProductNumeric_Nest_Dense; 2046718818eSStefano Zampini PetscFunctionReturn(0); 20552c5f739Sprj- } 20652c5f739Sprj- 2079566063dSJacob Faibussowitsch PetscCall(PetscNew(&contents)); 2086718818eSStefano Zampini C->product->data = contents; 2096718818eSStefano Zampini C->product->destroy = MatNest_DenseDestroy; 2109566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(nr+1,&contents->dm,nc+1,&contents->dn,nr*nc,&contents->workC)); 21152c5f739Sprj- contents->k = nr*nc; 21252c5f739Sprj- for (i=0; i<nr; i++) { 2139566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(bA->isglobal.row[i],contents->dm + i+1)); 21452c5f739Sprj- maxm = PetscMax(maxm,contents->dm[i+1]); 21552c5f739Sprj- contents->dm[i+1] += contents->dm[i]; 21652c5f739Sprj- } 21752c5f739Sprj- for (i=0; i<nc; i++) { 2189566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(bA->isglobal.col[i],contents->dn + i+1)); 21952c5f739Sprj- contents->dn[i+1] += contents->dn[i]; 22052c5f739Sprj- } 2219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxm*N,&contents->tarray)); 2229566063dSJacob Faibussowitsch PetscCall(MatDenseGetLDA(B,&ldb)); 2239566063dSJacob Faibussowitsch PetscCall(MatGetSize(B,NULL,&N)); 2249566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(B,&barray)); 22552c5f739Sprj- /* loops are permuted compared to MatMatMultNumeric so that viewB is created only once per column of A */ 22652c5f739Sprj- for (j=0; j<nc; j++) { 2279566063dSJacob Faibussowitsch PetscCall(ISGetSize(bA->isglobal.col[j],&M)); 2289566063dSJacob Faibussowitsch PetscCall(MatCreateDense(PetscObjectComm((PetscObject)A),contents->dn[j+1]-contents->dn[j],PETSC_DECIDE,M,N,(PetscScalar*)(barray+contents->dn[j]),&viewB)); 2299566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(viewB,ldb)); 23052c5f739Sprj- for (i=0; i<nr; i++) { 23152c5f739Sprj- if (!bA->m[i][j]) continue; 23252c5f739Sprj- /* MatMatMultSymbolic may attach a specific container (depending on MatType of bA->m[i][j]) to workC[i][j] */ 2334222ddf1SHong Zhang 2349566063dSJacob Faibussowitsch PetscCall(MatProductCreate(bA->m[i][j],viewB,NULL,&contents->workC[i*nc + j])); 2354222ddf1SHong Zhang workC = contents->workC[i*nc + j]; 2369566063dSJacob Faibussowitsch PetscCall(MatProductSetType(workC,MATPRODUCT_AB)); 2379566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(workC,"default")); 2389566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(workC,fill)); 2399566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(workC)); 2409566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(workC)); 2414222ddf1SHong Zhang 2426718818eSStefano Zampini /* since tarray will be shared by all Mat */ 2439566063dSJacob Faibussowitsch PetscCall(MatSeqDenseSetPreallocation(workC,contents->tarray)); 2449566063dSJacob Faibussowitsch PetscCall(MatMPIDenseSetPreallocation(workC,contents->tarray)); 24552c5f739Sprj- } 2469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&viewB)); 24752c5f739Sprj- } 2489566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(B,&barray)); 24952c5f739Sprj- 2506718818eSStefano Zampini C->ops->productnumeric = MatProductNumeric_Nest_Dense; 25152c5f739Sprj- PetscFunctionReturn(0); 25252c5f739Sprj- } 25352c5f739Sprj- 2544222ddf1SHong Zhang /* --------------------------------------------------------- */ 2554222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_Nest_Dense_AB(Mat C) 2564222ddf1SHong Zhang { 2574222ddf1SHong Zhang PetscFunctionBegin; 2586718818eSStefano Zampini C->ops->productsymbolic = MatProductSymbolic_Nest_Dense; 2594222ddf1SHong Zhang PetscFunctionReturn(0); 2604222ddf1SHong Zhang } 2614222ddf1SHong Zhang 2624222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Nest_Dense(Mat C) 26352c5f739Sprj- { 2644222ddf1SHong Zhang Mat_Product *product = C->product; 26552c5f739Sprj- 26652c5f739Sprj- PetscFunctionBegin; 2674222ddf1SHong Zhang if (product->type == MATPRODUCT_AB) { 2689566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions_Nest_Dense_AB(C)); 2696718818eSStefano Zampini } 27052c5f739Sprj- PetscFunctionReturn(0); 27152c5f739Sprj- } 2724222ddf1SHong Zhang /* --------------------------------------------------------- */ 27352c5f739Sprj- 274207556f9SJed Brown static PetscErrorCode MatMultTranspose_Nest(Mat A,Vec x,Vec y) 275d8588912SDave May { 276d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 277207556f9SJed Brown Vec *bx = bA->left,*by = bA->right; 278207556f9SJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 279d8588912SDave May 280d8588912SDave May PetscFunctionBegin; 2819566063dSJacob Faibussowitsch for (i=0; i<nr; i++) PetscCall(VecGetSubVector(x,bA->isglobal.row[i],&bx[i])); 2829566063dSJacob Faibussowitsch for (i=0; i<nc; i++) PetscCall(VecGetSubVector(y,bA->isglobal.col[i],&by[i])); 283207556f9SJed Brown for (j=0; j<nc; j++) { 2849566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(by[j])); 285609e31cbSJed Brown for (i=0; i<nr; i++) { 2866c75ac25SJed Brown if (!bA->m[i][j]) continue; 287609e31cbSJed Brown /* y[j] <- y[j] + (A[i][j])^T * x[i] */ 2889566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(bA->m[i][j],bx[i],by[j],by[j])); 289d8588912SDave May } 290d8588912SDave May } 2919566063dSJacob Faibussowitsch for (i=0; i<nr; i++) PetscCall(VecRestoreSubVector(x,bA->isglobal.row[i],&bx[i])); 2929566063dSJacob Faibussowitsch for (i=0; i<nc; i++) PetscCall(VecRestoreSubVector(y,bA->isglobal.col[i],&by[i])); 293d8588912SDave May PetscFunctionReturn(0); 294d8588912SDave May } 295d8588912SDave May 2969194d70fSJed Brown static PetscErrorCode MatMultTransposeAdd_Nest(Mat A,Vec x,Vec y,Vec z) 2979194d70fSJed Brown { 2989194d70fSJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 2999194d70fSJed Brown Vec *bx = bA->left,*bz = bA->right; 3009194d70fSJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 3019194d70fSJed Brown 3029194d70fSJed Brown PetscFunctionBegin; 3039566063dSJacob Faibussowitsch for (i=0; i<nr; i++) PetscCall(VecGetSubVector(x,bA->isglobal.row[i],&bx[i])); 3049566063dSJacob Faibussowitsch for (i=0; i<nc; i++) PetscCall(VecGetSubVector(z,bA->isglobal.col[i],&bz[i])); 3059194d70fSJed Brown for (j=0; j<nc; j++) { 3069194d70fSJed Brown if (y != z) { 3079194d70fSJed Brown Vec by; 3089566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(y,bA->isglobal.col[j],&by)); 3099566063dSJacob Faibussowitsch PetscCall(VecCopy(by,bz[j])); 3109566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(y,bA->isglobal.col[j],&by)); 3119194d70fSJed Brown } 3129194d70fSJed Brown for (i=0; i<nr; i++) { 3136c75ac25SJed Brown if (!bA->m[i][j]) continue; 3149194d70fSJed Brown /* z[j] <- y[j] + (A[i][j])^T * x[i] */ 3159566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(bA->m[i][j],bx[i],bz[j],bz[j])); 3169194d70fSJed Brown } 3179194d70fSJed Brown } 3189566063dSJacob Faibussowitsch for (i=0; i<nr; i++) PetscCall(VecRestoreSubVector(x,bA->isglobal.row[i],&bx[i])); 3199566063dSJacob Faibussowitsch for (i=0; i<nc; i++) PetscCall(VecRestoreSubVector(z,bA->isglobal.col[i],&bz[i])); 3209194d70fSJed Brown PetscFunctionReturn(0); 3219194d70fSJed Brown } 3229194d70fSJed Brown 323f8170845SAlex Fikl static PetscErrorCode MatTranspose_Nest(Mat A,MatReuse reuse,Mat *B) 324f8170845SAlex Fikl { 325f8170845SAlex Fikl Mat_Nest *bA = (Mat_Nest*)A->data, *bC; 326f8170845SAlex Fikl Mat C; 327f8170845SAlex Fikl PetscInt i,j,nr = bA->nr,nc = bA->nc; 328f8170845SAlex Fikl 329f8170845SAlex Fikl PetscFunctionBegin; 330*7fb60732SBarry Smith if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A,*B)); 331aed4548fSBarry Smith PetscCheck(reuse != MAT_INPLACE_MATRIX || nr == nc,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Square nested matrix only for in-place"); 332f8170845SAlex Fikl 333cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) { 334f8170845SAlex Fikl Mat *subs; 335f8170845SAlex Fikl IS *is_row,*is_col; 336f8170845SAlex Fikl 3379566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nr * nc,&subs)); 3389566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nr,&is_row,nc,&is_col)); 3399566063dSJacob Faibussowitsch PetscCall(MatNestGetISs(A,is_row,is_col)); 340cf37664fSBarry Smith if (reuse == MAT_INPLACE_MATRIX) { 341ddeb9bd8SAlex Fikl for (i=0; i<nr; i++) { 342ddeb9bd8SAlex Fikl for (j=0; j<nc; j++) { 343ddeb9bd8SAlex Fikl subs[i + nr * j] = bA->m[i][j]; 344ddeb9bd8SAlex Fikl } 345ddeb9bd8SAlex Fikl } 346ddeb9bd8SAlex Fikl } 347ddeb9bd8SAlex Fikl 3489566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PetscObjectComm((PetscObject)A),nc,is_col,nr,is_row,subs,&C)); 3499566063dSJacob Faibussowitsch PetscCall(PetscFree(subs)); 3509566063dSJacob Faibussowitsch PetscCall(PetscFree2(is_row,is_col)); 351f8170845SAlex Fikl } else { 352f8170845SAlex Fikl C = *B; 353f8170845SAlex Fikl } 354f8170845SAlex Fikl 355f8170845SAlex Fikl bC = (Mat_Nest*)C->data; 356f8170845SAlex Fikl for (i=0; i<nr; i++) { 357f8170845SAlex Fikl for (j=0; j<nc; j++) { 358f8170845SAlex Fikl if (bA->m[i][j]) { 3599566063dSJacob Faibussowitsch PetscCall(MatTranspose(bA->m[i][j], reuse, &(bC->m[j][i]))); 360f8170845SAlex Fikl } else { 361f8170845SAlex Fikl bC->m[j][i] = NULL; 362f8170845SAlex Fikl } 363f8170845SAlex Fikl } 364f8170845SAlex Fikl } 365f8170845SAlex Fikl 366cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) { 367f8170845SAlex Fikl *B = C; 368f8170845SAlex Fikl } else { 3699566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(A, &C)); 370f8170845SAlex Fikl } 371f8170845SAlex Fikl PetscFunctionReturn(0); 372f8170845SAlex Fikl } 373f8170845SAlex Fikl 374e2d7f03fSJed Brown static PetscErrorCode MatNestDestroyISList(PetscInt n,IS **list) 375e2d7f03fSJed Brown { 376e2d7f03fSJed Brown IS *lst = *list; 377e2d7f03fSJed Brown PetscInt i; 378e2d7f03fSJed Brown 379e2d7f03fSJed Brown PetscFunctionBegin; 380e2d7f03fSJed Brown if (!lst) PetscFunctionReturn(0); 3819566063dSJacob Faibussowitsch for (i=0; i<n; i++) if (lst[i]) PetscCall(ISDestroy(&lst[i])); 3829566063dSJacob Faibussowitsch PetscCall(PetscFree(lst)); 3830298fd71SBarry Smith *list = NULL; 384e2d7f03fSJed Brown PetscFunctionReturn(0); 385e2d7f03fSJed Brown } 386e2d7f03fSJed Brown 38706a1af2fSStefano Zampini static PetscErrorCode MatReset_Nest(Mat A) 388d8588912SDave May { 389d8588912SDave May Mat_Nest *vs = (Mat_Nest*)A->data; 390d8588912SDave May PetscInt i,j; 391d8588912SDave May 392d8588912SDave May PetscFunctionBegin; 393d8588912SDave May /* release the matrices and the place holders */ 3949566063dSJacob Faibussowitsch PetscCall(MatNestDestroyISList(vs->nr,&vs->isglobal.row)); 3959566063dSJacob Faibussowitsch PetscCall(MatNestDestroyISList(vs->nc,&vs->isglobal.col)); 3969566063dSJacob Faibussowitsch PetscCall(MatNestDestroyISList(vs->nr,&vs->islocal.row)); 3979566063dSJacob Faibussowitsch PetscCall(MatNestDestroyISList(vs->nc,&vs->islocal.col)); 398d8588912SDave May 3999566063dSJacob Faibussowitsch PetscCall(PetscFree(vs->row_len)); 4009566063dSJacob Faibussowitsch PetscCall(PetscFree(vs->col_len)); 4019566063dSJacob Faibussowitsch PetscCall(PetscFree(vs->nnzstate)); 402d8588912SDave May 4039566063dSJacob Faibussowitsch PetscCall(PetscFree2(vs->left,vs->right)); 404207556f9SJed Brown 405d8588912SDave May /* release the matrices and the place holders */ 406d8588912SDave May if (vs->m) { 407d8588912SDave May for (i=0; i<vs->nr; i++) { 408d8588912SDave May for (j=0; j<vs->nc; j++) { 4099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&vs->m[i][j])); 410d8588912SDave May } 4119566063dSJacob Faibussowitsch PetscCall(PetscFree(vs->m[i])); 412d8588912SDave May } 4139566063dSJacob Faibussowitsch PetscCall(PetscFree(vs->m)); 414d8588912SDave May } 41506a1af2fSStefano Zampini 41606a1af2fSStefano Zampini /* restore defaults */ 41706a1af2fSStefano Zampini vs->nr = 0; 41806a1af2fSStefano Zampini vs->nc = 0; 41906a1af2fSStefano Zampini vs->splitassembly = PETSC_FALSE; 42006a1af2fSStefano Zampini PetscFunctionReturn(0); 42106a1af2fSStefano Zampini } 42206a1af2fSStefano Zampini 42306a1af2fSStefano Zampini static PetscErrorCode MatDestroy_Nest(Mat A) 42406a1af2fSStefano Zampini { 425362febeeSStefano Zampini PetscFunctionBegin; 4269566063dSJacob Faibussowitsch PetscCall(MatReset_Nest(A)); 4279566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 4289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMat_C",NULL)); 4299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMat_C",NULL)); 4309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMats_C",NULL)); 4319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatNestGetSize_C",NULL)); 4329566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatNestGetISs_C",NULL)); 4339566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatNestGetLocalISs_C",NULL)); 4349566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatNestSetVecType_C",NULL)); 4359566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMats_C",NULL)); 4369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_mpiaij_C",NULL)); 4379566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_seqaij_C",NULL)); 4389566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_aij_C",NULL)); 4399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_is_C",NULL)); 4409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_mpidense_C",NULL)); 4419566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_seqdense_C",NULL)); 4429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_nest_seqdense_C",NULL)); 4439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_nest_mpidense_C",NULL)); 4449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_nest_dense_C",NULL)); 445d8588912SDave May PetscFunctionReturn(0); 446d8588912SDave May } 447d8588912SDave May 448381b8e50SStefano Zampini static PetscErrorCode MatMissingDiagonal_Nest(Mat mat,PetscBool *missing,PetscInt *dd) 449381b8e50SStefano Zampini { 450381b8e50SStefano Zampini Mat_Nest *vs = (Mat_Nest*)mat->data; 451381b8e50SStefano Zampini PetscInt i; 452381b8e50SStefano Zampini 453381b8e50SStefano Zampini PetscFunctionBegin; 454381b8e50SStefano Zampini if (dd) *dd = 0; 455381b8e50SStefano Zampini if (!vs->nr) { 456381b8e50SStefano Zampini *missing = PETSC_TRUE; 457381b8e50SStefano Zampini PetscFunctionReturn(0); 458381b8e50SStefano Zampini } 459381b8e50SStefano Zampini *missing = PETSC_FALSE; 460381b8e50SStefano Zampini for (i = 0; i < vs->nr && !(*missing); i++) { 461381b8e50SStefano Zampini *missing = PETSC_TRUE; 462381b8e50SStefano Zampini if (vs->m[i][i]) { 4639566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal(vs->m[i][i],missing,NULL)); 46408401ef6SPierre Jolivet PetscCheck(!*missing || !dd,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"First missing entry not yet implemented"); 465381b8e50SStefano Zampini } 466381b8e50SStefano Zampini } 467381b8e50SStefano Zampini PetscFunctionReturn(0); 468381b8e50SStefano Zampini } 469381b8e50SStefano Zampini 470207556f9SJed Brown static PetscErrorCode MatAssemblyBegin_Nest(Mat A,MatAssemblyType type) 471d8588912SDave May { 472d8588912SDave May Mat_Nest *vs = (Mat_Nest*)A->data; 473d8588912SDave May PetscInt i,j; 47406a1af2fSStefano Zampini PetscBool nnzstate = PETSC_FALSE; 475d8588912SDave May 476d8588912SDave May PetscFunctionBegin; 477d8588912SDave May for (i=0; i<vs->nr; i++) { 478d8588912SDave May for (j=0; j<vs->nc; j++) { 47906a1af2fSStefano Zampini PetscObjectState subnnzstate = 0; 480e7c19651SJed Brown if (vs->m[i][j]) { 4819566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(vs->m[i][j],type)); 482e7c19651SJed Brown if (!vs->splitassembly) { 483e7c19651SJed Brown /* Note: split assembly will fail if the same block appears more than once (even indirectly through a nested 484e7c19651SJed Brown * sub-block). This could be fixed by adding a flag to Mat so that there was a way to check if a Mat was 485e7c19651SJed Brown * already performing an assembly, but the result would by more complicated and appears to offer less 486e7c19651SJed Brown * potential for diagnostics and correctness checking. Split assembly should be fixed once there is an 487e7c19651SJed Brown * interface for libraries to make asynchronous progress in "user-defined non-blocking collectives". 488e7c19651SJed Brown */ 4899566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(vs->m[i][j],type)); 4909566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroState(vs->m[i][j],&subnnzstate)); 491e7c19651SJed Brown } 492e7c19651SJed Brown } 49306a1af2fSStefano Zampini nnzstate = (PetscBool)(nnzstate || vs->nnzstate[i*vs->nc+j] != subnnzstate); 49406a1af2fSStefano Zampini vs->nnzstate[i*vs->nc+j] = subnnzstate; 495d8588912SDave May } 496d8588912SDave May } 49706a1af2fSStefano Zampini if (nnzstate) A->nonzerostate++; 498d8588912SDave May PetscFunctionReturn(0); 499d8588912SDave May } 500d8588912SDave May 501207556f9SJed Brown static PetscErrorCode MatAssemblyEnd_Nest(Mat A, MatAssemblyType type) 502d8588912SDave May { 503d8588912SDave May Mat_Nest *vs = (Mat_Nest*)A->data; 504d8588912SDave May PetscInt i,j; 505d8588912SDave May 506d8588912SDave May PetscFunctionBegin; 507d8588912SDave May for (i=0; i<vs->nr; i++) { 508d8588912SDave May for (j=0; j<vs->nc; j++) { 509e7c19651SJed Brown if (vs->m[i][j]) { 510e7c19651SJed Brown if (vs->splitassembly) { 5119566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(vs->m[i][j],type)); 512e7c19651SJed Brown } 513e7c19651SJed Brown } 514d8588912SDave May } 515d8588912SDave May } 516d8588912SDave May PetscFunctionReturn(0); 517d8588912SDave May } 518d8588912SDave May 519f349c1fdSJed Brown static PetscErrorCode MatNestFindNonzeroSubMatRow(Mat A,PetscInt row,Mat *B) 520d8588912SDave May { 521f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 522f349c1fdSJed Brown PetscInt j; 523f349c1fdSJed Brown Mat sub; 524d8588912SDave May 525d8588912SDave May PetscFunctionBegin; 5260298fd71SBarry Smith sub = (row < vs->nc) ? vs->m[row][row] : (Mat)NULL; /* Prefer to find on the diagonal */ 527f349c1fdSJed Brown for (j=0; !sub && j<vs->nc; j++) sub = vs->m[row][j]; 5289566063dSJacob Faibussowitsch if (sub) PetscCall(MatSetUp(sub)); /* Ensure that the sizes are available */ 529f349c1fdSJed Brown *B = sub; 530f349c1fdSJed Brown PetscFunctionReturn(0); 531d8588912SDave May } 532d8588912SDave May 533f349c1fdSJed Brown static PetscErrorCode MatNestFindNonzeroSubMatCol(Mat A,PetscInt col,Mat *B) 534f349c1fdSJed Brown { 535f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 536f349c1fdSJed Brown PetscInt i; 537f349c1fdSJed Brown Mat sub; 538f349c1fdSJed Brown 539f349c1fdSJed Brown PetscFunctionBegin; 5400298fd71SBarry Smith sub = (col < vs->nr) ? vs->m[col][col] : (Mat)NULL; /* Prefer to find on the diagonal */ 541f349c1fdSJed Brown for (i=0; !sub && i<vs->nr; i++) sub = vs->m[i][col]; 5429566063dSJacob Faibussowitsch if (sub) PetscCall(MatSetUp(sub)); /* Ensure that the sizes are available */ 543f349c1fdSJed Brown *B = sub; 544f349c1fdSJed Brown PetscFunctionReturn(0); 545d8588912SDave May } 546d8588912SDave May 54718d228c0SPierre Jolivet static PetscErrorCode MatNestFindISRange(Mat A,PetscInt n,const IS list[],IS is,PetscInt *begin,PetscInt *end) 548f349c1fdSJed Brown { 54918d228c0SPierre Jolivet PetscInt i,j,size,m; 550f349c1fdSJed Brown PetscBool flg; 55118d228c0SPierre Jolivet IS out,concatenate[2]; 552f349c1fdSJed Brown 553f349c1fdSJed Brown PetscFunctionBegin; 554f349c1fdSJed Brown PetscValidPointer(list,3); 555f349c1fdSJed Brown PetscValidHeaderSpecific(is,IS_CLASSID,4); 55618d228c0SPierre Jolivet if (begin) { 55718d228c0SPierre Jolivet PetscValidIntPointer(begin,5); 55818d228c0SPierre Jolivet *begin = -1; 55918d228c0SPierre Jolivet } 56018d228c0SPierre Jolivet if (end) { 56118d228c0SPierre Jolivet PetscValidIntPointer(end,6); 56218d228c0SPierre Jolivet *end = -1; 56318d228c0SPierre Jolivet } 564f349c1fdSJed Brown for (i=0; i<n; i++) { 565207556f9SJed Brown if (!list[i]) continue; 5669566063dSJacob Faibussowitsch PetscCall(ISEqualUnsorted(list[i],is,&flg)); 567f349c1fdSJed Brown if (flg) { 56818d228c0SPierre Jolivet if (begin) *begin = i; 56918d228c0SPierre Jolivet if (end) *end = i+1; 570f349c1fdSJed Brown PetscFunctionReturn(0); 571f349c1fdSJed Brown } 572f349c1fdSJed Brown } 5739566063dSJacob Faibussowitsch PetscCall(ISGetSize(is,&size)); 57418d228c0SPierre Jolivet for (i=0; i<n-1; i++) { 57518d228c0SPierre Jolivet if (!list[i]) continue; 57618d228c0SPierre Jolivet m = 0; 5779566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PetscObjectComm((PetscObject)A),2,list+i,&out)); 5789566063dSJacob Faibussowitsch PetscCall(ISGetSize(out,&m)); 57918d228c0SPierre Jolivet for (j=i+2; j<n && m<size; j++) { 58018d228c0SPierre Jolivet if (list[j]) { 58118d228c0SPierre Jolivet concatenate[0] = out; 58218d228c0SPierre Jolivet concatenate[1] = list[j]; 5839566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PetscObjectComm((PetscObject)A),2,concatenate,&out)); 5849566063dSJacob Faibussowitsch PetscCall(ISDestroy(concatenate)); 5859566063dSJacob Faibussowitsch PetscCall(ISGetSize(out,&m)); 58618d228c0SPierre Jolivet } 58718d228c0SPierre Jolivet } 58818d228c0SPierre Jolivet if (m == size) { 5899566063dSJacob Faibussowitsch PetscCall(ISEqualUnsorted(out,is,&flg)); 59018d228c0SPierre Jolivet if (flg) { 59118d228c0SPierre Jolivet if (begin) *begin = i; 59218d228c0SPierre Jolivet if (end) *end = j; 5939566063dSJacob Faibussowitsch PetscCall(ISDestroy(&out)); 59418d228c0SPierre Jolivet PetscFunctionReturn(0); 59518d228c0SPierre Jolivet } 59618d228c0SPierre Jolivet } 5979566063dSJacob Faibussowitsch PetscCall(ISDestroy(&out)); 59818d228c0SPierre Jolivet } 59918d228c0SPierre Jolivet PetscFunctionReturn(0); 600f349c1fdSJed Brown } 601f349c1fdSJed Brown 60218d228c0SPierre Jolivet static PetscErrorCode MatNestFillEmptyMat_Private(Mat A,PetscInt i,PetscInt j,Mat *B) 6038188e55aSJed Brown { 6048188e55aSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 60518d228c0SPierre Jolivet PetscInt lr,lc; 60618d228c0SPierre Jolivet 60718d228c0SPierre Jolivet PetscFunctionBegin; 6089566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),B)); 6099566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(vs->isglobal.row[i],&lr)); 6109566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(vs->isglobal.col[j],&lc)); 6119566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B,lr,lc,PETSC_DECIDE,PETSC_DECIDE)); 6129566063dSJacob Faibussowitsch PetscCall(MatSetType(*B,MATAIJ)); 6139566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(*B,0,NULL)); 6149566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(*B,0,NULL,0,NULL)); 6159566063dSJacob Faibussowitsch PetscCall(MatSetUp(*B)); 6169566063dSJacob Faibussowitsch PetscCall(MatSetOption(*B,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE)); 6179566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY)); 6189566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY)); 61918d228c0SPierre Jolivet PetscFunctionReturn(0); 62018d228c0SPierre Jolivet } 62118d228c0SPierre Jolivet 62218d228c0SPierre Jolivet static PetscErrorCode MatNestGetBlock_Private(Mat A,PetscInt rbegin,PetscInt rend,PetscInt cbegin,PetscInt cend,Mat *B) 62318d228c0SPierre Jolivet { 62418d228c0SPierre Jolivet Mat_Nest *vs = (Mat_Nest*)A->data; 62518d228c0SPierre Jolivet Mat *a; 62618d228c0SPierre Jolivet PetscInt i,j,k,l,nr=rend-rbegin,nc=cend-cbegin; 6278188e55aSJed Brown char keyname[256]; 62818d228c0SPierre Jolivet PetscBool *b; 62918d228c0SPierre Jolivet PetscBool flg; 6308188e55aSJed Brown 6318188e55aSJed Brown PetscFunctionBegin; 6320298fd71SBarry Smith *B = NULL; 6339566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(keyname,sizeof(keyname),"NestBlock_%" PetscInt_FMT "-%" PetscInt_FMT "x%" PetscInt_FMT "-%" PetscInt_FMT,rbegin,rend,cbegin,cend)); 6349566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)A,keyname,(PetscObject*)B)); 6358188e55aSJed Brown if (*B) PetscFunctionReturn(0); 6368188e55aSJed Brown 6379566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nr*nc,&a,nr*nc,&b)); 63818d228c0SPierre Jolivet for (i=0; i<nr; i++) { 63918d228c0SPierre Jolivet for (j=0; j<nc; j++) { 64018d228c0SPierre Jolivet a[i*nc + j] = vs->m[rbegin+i][cbegin+j]; 64118d228c0SPierre Jolivet b[i*nc + j] = PETSC_FALSE; 64218d228c0SPierre Jolivet } 64318d228c0SPierre Jolivet } 64418d228c0SPierre Jolivet if (nc!=vs->nc&&nr!=vs->nr) { 64518d228c0SPierre Jolivet for (i=0; i<nr; i++) { 64618d228c0SPierre Jolivet for (j=0; j<nc; j++) { 64718d228c0SPierre Jolivet flg = PETSC_FALSE; 64818d228c0SPierre Jolivet for (k=0; (k<nr&&!flg); k++) { 64918d228c0SPierre Jolivet if (a[j + k*nc]) flg = PETSC_TRUE; 65018d228c0SPierre Jolivet } 65118d228c0SPierre Jolivet if (flg) { 65218d228c0SPierre Jolivet flg = PETSC_FALSE; 65318d228c0SPierre Jolivet for (l=0; (l<nc&&!flg); l++) { 65418d228c0SPierre Jolivet if (a[i*nc + l]) flg = PETSC_TRUE; 65518d228c0SPierre Jolivet } 65618d228c0SPierre Jolivet } 65718d228c0SPierre Jolivet if (!flg) { 65818d228c0SPierre Jolivet b[i*nc + j] = PETSC_TRUE; 6599566063dSJacob Faibussowitsch PetscCall(MatNestFillEmptyMat_Private(A,rbegin+i,cbegin+j,a + i*nc + j)); 66018d228c0SPierre Jolivet } 66118d228c0SPierre Jolivet } 66218d228c0SPierre Jolivet } 66318d228c0SPierre Jolivet } 6649566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PetscObjectComm((PetscObject)A),nr,nr!=vs->nr?NULL:vs->isglobal.row,nc,nc!=vs->nc?NULL:vs->isglobal.col,a,B)); 66518d228c0SPierre Jolivet for (i=0; i<nr; i++) { 66618d228c0SPierre Jolivet for (j=0; j<nc; j++) { 66718d228c0SPierre Jolivet if (b[i*nc + j]) { 6689566063dSJacob Faibussowitsch PetscCall(MatDestroy(a + i*nc + j)); 66918d228c0SPierre Jolivet } 67018d228c0SPierre Jolivet } 67118d228c0SPierre Jolivet } 6729566063dSJacob Faibussowitsch PetscCall(PetscFree2(a,b)); 6738188e55aSJed Brown (*B)->assembled = A->assembled; 6749566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A,keyname,(PetscObject)*B)); 6759566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)*B)); /* Leave the only remaining reference in the composition */ 6768188e55aSJed Brown PetscFunctionReturn(0); 6778188e55aSJed Brown } 6788188e55aSJed Brown 679f349c1fdSJed Brown static PetscErrorCode MatNestFindSubMat(Mat A,struct MatNestISPair *is,IS isrow,IS iscol,Mat *B) 680f349c1fdSJed Brown { 681f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 68218d228c0SPierre Jolivet PetscInt rbegin,rend,cbegin,cend; 683f349c1fdSJed Brown 684f349c1fdSJed Brown PetscFunctionBegin; 6859566063dSJacob Faibussowitsch PetscCall(MatNestFindISRange(A,vs->nr,is->row,isrow,&rbegin,&rend)); 6869566063dSJacob Faibussowitsch PetscCall(MatNestFindISRange(A,vs->nc,is->col,iscol,&cbegin,&cend)); 68718d228c0SPierre Jolivet if (rend == rbegin + 1 && cend == cbegin + 1) { 68818d228c0SPierre Jolivet if (!vs->m[rbegin][cbegin]) { 6899566063dSJacob Faibussowitsch PetscCall(MatNestFillEmptyMat_Private(A,rbegin,cbegin,vs->m[rbegin] + cbegin)); 69077019fcaSJed Brown } 69118d228c0SPierre Jolivet *B = vs->m[rbegin][cbegin]; 69218d228c0SPierre Jolivet } else if (rbegin != -1 && cbegin != -1) { 6939566063dSJacob Faibussowitsch PetscCall(MatNestGetBlock_Private(A,rbegin,rend,cbegin,cend,B)); 69418d228c0SPierre Jolivet } else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Could not find index set"); 695f349c1fdSJed Brown PetscFunctionReturn(0); 696f349c1fdSJed Brown } 697f349c1fdSJed Brown 69806a1af2fSStefano Zampini /* 69906a1af2fSStefano Zampini TODO: This does not actually returns a submatrix we can modify 70006a1af2fSStefano Zampini */ 7017dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_Nest(Mat A,IS isrow,IS iscol,MatReuse reuse,Mat *B) 702f349c1fdSJed Brown { 703f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 704f349c1fdSJed Brown Mat sub; 705f349c1fdSJed Brown 706f349c1fdSJed Brown PetscFunctionBegin; 7079566063dSJacob Faibussowitsch PetscCall(MatNestFindSubMat(A,&vs->isglobal,isrow,iscol,&sub)); 708f349c1fdSJed Brown switch (reuse) { 709f349c1fdSJed Brown case MAT_INITIAL_MATRIX: 7109566063dSJacob Faibussowitsch if (sub) PetscCall(PetscObjectReference((PetscObject)sub)); 711f349c1fdSJed Brown *B = sub; 712f349c1fdSJed Brown break; 713f349c1fdSJed Brown case MAT_REUSE_MATRIX: 71408401ef6SPierre Jolivet PetscCheck(sub == *B,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Submatrix was not used before in this call"); 715f349c1fdSJed Brown break; 716f349c1fdSJed Brown case MAT_IGNORE_MATRIX: /* Nothing to do */ 717f349c1fdSJed Brown break; 718511c6705SHong Zhang case MAT_INPLACE_MATRIX: /* Nothing to do */ 719511c6705SHong Zhang SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX is not supported yet"); 720f349c1fdSJed Brown } 721f349c1fdSJed Brown PetscFunctionReturn(0); 722f349c1fdSJed Brown } 723f349c1fdSJed Brown 724f349c1fdSJed Brown PetscErrorCode MatGetLocalSubMatrix_Nest(Mat A,IS isrow,IS iscol,Mat *B) 725f349c1fdSJed Brown { 726f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 727f349c1fdSJed Brown Mat sub; 728f349c1fdSJed Brown 729f349c1fdSJed Brown PetscFunctionBegin; 7309566063dSJacob Faibussowitsch PetscCall(MatNestFindSubMat(A,&vs->islocal,isrow,iscol,&sub)); 731f349c1fdSJed Brown /* We allow the submatrix to be NULL, perhaps it would be better for the user to return an empty matrix instead */ 7329566063dSJacob Faibussowitsch if (sub) PetscCall(PetscObjectReference((PetscObject)sub)); 733f349c1fdSJed Brown *B = sub; 734d8588912SDave May PetscFunctionReturn(0); 735d8588912SDave May } 736d8588912SDave May 737207556f9SJed Brown static PetscErrorCode MatRestoreLocalSubMatrix_Nest(Mat A,IS isrow,IS iscol,Mat *B) 738d8588912SDave May { 739f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 740f349c1fdSJed Brown Mat sub; 741d8588912SDave May 742d8588912SDave May PetscFunctionBegin; 7439566063dSJacob Faibussowitsch PetscCall(MatNestFindSubMat(A,&vs->islocal,isrow,iscol,&sub)); 74408401ef6SPierre Jolivet PetscCheck(*B == sub,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Local submatrix has not been gotten"); 745f349c1fdSJed Brown if (sub) { 746aed4548fSBarry Smith PetscCheck(((PetscObject)sub)->refct > 1,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Local submatrix has had reference count decremented too many times"); 7479566063dSJacob Faibussowitsch PetscCall(MatDestroy(B)); 748d8588912SDave May } 749d8588912SDave May PetscFunctionReturn(0); 750d8588912SDave May } 751d8588912SDave May 7527874fa86SDave May static PetscErrorCode MatGetDiagonal_Nest(Mat A,Vec v) 7537874fa86SDave May { 7547874fa86SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 7557874fa86SDave May PetscInt i; 7567874fa86SDave May 7577874fa86SDave May PetscFunctionBegin; 7587874fa86SDave May for (i=0; i<bA->nr; i++) { 759429bac76SJed Brown Vec bv; 7609566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(v,bA->isglobal.row[i],&bv)); 7617874fa86SDave May if (bA->m[i][i]) { 7629566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(bA->m[i][i],bv)); 7637874fa86SDave May } else { 7649566063dSJacob Faibussowitsch PetscCall(VecSet(bv,0.0)); 7657874fa86SDave May } 7669566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(v,bA->isglobal.row[i],&bv)); 7677874fa86SDave May } 7687874fa86SDave May PetscFunctionReturn(0); 7697874fa86SDave May } 7707874fa86SDave May 7717874fa86SDave May static PetscErrorCode MatDiagonalScale_Nest(Mat A,Vec l,Vec r) 7727874fa86SDave May { 7737874fa86SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 774429bac76SJed Brown Vec bl,*br; 7757874fa86SDave May PetscInt i,j; 7767874fa86SDave May 7777874fa86SDave May PetscFunctionBegin; 7789566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(bA->nc,&br)); 7792e6472ebSElliott Sales de Andrade if (r) { 7809566063dSJacob Faibussowitsch for (j=0; j<bA->nc; j++) PetscCall(VecGetSubVector(r,bA->isglobal.col[j],&br[j])); 7812e6472ebSElliott Sales de Andrade } 7822e6472ebSElliott Sales de Andrade bl = NULL; 7837874fa86SDave May for (i=0; i<bA->nr; i++) { 7842e6472ebSElliott Sales de Andrade if (l) { 7859566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(l,bA->isglobal.row[i],&bl)); 7862e6472ebSElliott Sales de Andrade } 7877874fa86SDave May for (j=0; j<bA->nc; j++) { 7887874fa86SDave May if (bA->m[i][j]) { 7899566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(bA->m[i][j],bl,br[j])); 7907874fa86SDave May } 7917874fa86SDave May } 7922e6472ebSElliott Sales de Andrade if (l) { 7939566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(l,bA->isglobal.row[i],&bl)); 7947874fa86SDave May } 7952e6472ebSElliott Sales de Andrade } 7962e6472ebSElliott Sales de Andrade if (r) { 7979566063dSJacob Faibussowitsch for (j=0; j<bA->nc; j++) PetscCall(VecRestoreSubVector(r,bA->isglobal.col[j],&br[j])); 7982e6472ebSElliott Sales de Andrade } 7999566063dSJacob Faibussowitsch PetscCall(PetscFree(br)); 8007874fa86SDave May PetscFunctionReturn(0); 8017874fa86SDave May } 8027874fa86SDave May 803a061e289SJed Brown static PetscErrorCode MatScale_Nest(Mat A,PetscScalar a) 804a061e289SJed Brown { 805a061e289SJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 806a061e289SJed Brown PetscInt i,j; 807a061e289SJed Brown 808a061e289SJed Brown PetscFunctionBegin; 809a061e289SJed Brown for (i=0; i<bA->nr; i++) { 810a061e289SJed Brown for (j=0; j<bA->nc; j++) { 811a061e289SJed Brown if (bA->m[i][j]) { 8129566063dSJacob Faibussowitsch PetscCall(MatScale(bA->m[i][j],a)); 813a061e289SJed Brown } 814a061e289SJed Brown } 815a061e289SJed Brown } 816a061e289SJed Brown PetscFunctionReturn(0); 817a061e289SJed Brown } 818a061e289SJed Brown 819a061e289SJed Brown static PetscErrorCode MatShift_Nest(Mat A,PetscScalar a) 820a061e289SJed Brown { 821a061e289SJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 822a061e289SJed Brown PetscInt i; 82306a1af2fSStefano Zampini PetscBool nnzstate = PETSC_FALSE; 824a061e289SJed Brown 825a061e289SJed Brown PetscFunctionBegin; 826a061e289SJed Brown for (i=0; i<bA->nr; i++) { 82706a1af2fSStefano Zampini PetscObjectState subnnzstate = 0; 82808401ef6SPierre Jolivet PetscCheck(bA->m[i][i],PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for shifting an empty diagonal block, insert a matrix in block (%" PetscInt_FMT ",%" PetscInt_FMT ")",i,i); 8299566063dSJacob Faibussowitsch PetscCall(MatShift(bA->m[i][i],a)); 8309566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroState(bA->m[i][i],&subnnzstate)); 83106a1af2fSStefano Zampini nnzstate = (PetscBool)(nnzstate || bA->nnzstate[i*bA->nc+i] != subnnzstate); 83206a1af2fSStefano Zampini bA->nnzstate[i*bA->nc+i] = subnnzstate; 833a061e289SJed Brown } 83406a1af2fSStefano Zampini if (nnzstate) A->nonzerostate++; 835a061e289SJed Brown PetscFunctionReturn(0); 836a061e289SJed Brown } 837a061e289SJed Brown 83813135bc6SAlex Fikl static PetscErrorCode MatDiagonalSet_Nest(Mat A,Vec D,InsertMode is) 83913135bc6SAlex Fikl { 84013135bc6SAlex Fikl Mat_Nest *bA = (Mat_Nest*)A->data; 84113135bc6SAlex Fikl PetscInt i; 84206a1af2fSStefano Zampini PetscBool nnzstate = PETSC_FALSE; 84313135bc6SAlex Fikl 84413135bc6SAlex Fikl PetscFunctionBegin; 84513135bc6SAlex Fikl for (i=0; i<bA->nr; i++) { 84606a1af2fSStefano Zampini PetscObjectState subnnzstate = 0; 84713135bc6SAlex Fikl Vec bv; 8489566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(D,bA->isglobal.row[i],&bv)); 84913135bc6SAlex Fikl if (bA->m[i][i]) { 8509566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(bA->m[i][i],bv,is)); 8519566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroState(bA->m[i][i],&subnnzstate)); 85213135bc6SAlex Fikl } 8539566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(D,bA->isglobal.row[i],&bv)); 85406a1af2fSStefano Zampini nnzstate = (PetscBool)(nnzstate || bA->nnzstate[i*bA->nc+i] != subnnzstate); 85506a1af2fSStefano Zampini bA->nnzstate[i*bA->nc+i] = subnnzstate; 85613135bc6SAlex Fikl } 85706a1af2fSStefano Zampini if (nnzstate) A->nonzerostate++; 85813135bc6SAlex Fikl PetscFunctionReturn(0); 85913135bc6SAlex Fikl } 86013135bc6SAlex Fikl 861f8170845SAlex Fikl static PetscErrorCode MatSetRandom_Nest(Mat A,PetscRandom rctx) 862f8170845SAlex Fikl { 863f8170845SAlex Fikl Mat_Nest *bA = (Mat_Nest*)A->data; 864f8170845SAlex Fikl PetscInt i,j; 865f8170845SAlex Fikl 866f8170845SAlex Fikl PetscFunctionBegin; 867f8170845SAlex Fikl for (i=0; i<bA->nr; i++) { 868f8170845SAlex Fikl for (j=0; j<bA->nc; j++) { 869f8170845SAlex Fikl if (bA->m[i][j]) { 8709566063dSJacob Faibussowitsch PetscCall(MatSetRandom(bA->m[i][j],rctx)); 871f8170845SAlex Fikl } 872f8170845SAlex Fikl } 873f8170845SAlex Fikl } 874f8170845SAlex Fikl PetscFunctionReturn(0); 875f8170845SAlex Fikl } 876f8170845SAlex Fikl 8772a7a6963SBarry Smith static PetscErrorCode MatCreateVecs_Nest(Mat A,Vec *right,Vec *left) 878d8588912SDave May { 879d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 880d8588912SDave May Vec *L,*R; 881d8588912SDave May MPI_Comm comm; 882d8588912SDave May PetscInt i,j; 883d8588912SDave May 884d8588912SDave May PetscFunctionBegin; 8859566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A,&comm)); 886d8588912SDave May if (right) { 887d8588912SDave May /* allocate R */ 8889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bA->nc, &R)); 889d8588912SDave May /* Create the right vectors */ 890d8588912SDave May for (j=0; j<bA->nc; j++) { 891d8588912SDave May for (i=0; i<bA->nr; i++) { 892d8588912SDave May if (bA->m[i][j]) { 8939566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(bA->m[i][j],&R[j],NULL)); 894d8588912SDave May break; 895d8588912SDave May } 896d8588912SDave May } 89708401ef6SPierre Jolivet PetscCheck(i!=bA->nr,PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Mat(Nest) contains a null column."); 898d8588912SDave May } 8999566063dSJacob Faibussowitsch PetscCall(VecCreateNest(comm,bA->nc,bA->isglobal.col,R,right)); 900d8588912SDave May /* hand back control to the nest vector */ 901d8588912SDave May for (j=0; j<bA->nc; j++) { 9029566063dSJacob Faibussowitsch PetscCall(VecDestroy(&R[j])); 903d8588912SDave May } 9049566063dSJacob Faibussowitsch PetscCall(PetscFree(R)); 905d8588912SDave May } 906d8588912SDave May 907d8588912SDave May if (left) { 908d8588912SDave May /* allocate L */ 9099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bA->nr, &L)); 910d8588912SDave May /* Create the left vectors */ 911d8588912SDave May for (i=0; i<bA->nr; i++) { 912d8588912SDave May for (j=0; j<bA->nc; j++) { 913d8588912SDave May if (bA->m[i][j]) { 9149566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(bA->m[i][j],NULL,&L[i])); 915d8588912SDave May break; 916d8588912SDave May } 917d8588912SDave May } 91808401ef6SPierre Jolivet PetscCheck(j!=bA->nc,PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Mat(Nest) contains a null row."); 919d8588912SDave May } 920d8588912SDave May 9219566063dSJacob Faibussowitsch PetscCall(VecCreateNest(comm,bA->nr,bA->isglobal.row,L,left)); 922d8588912SDave May for (i=0; i<bA->nr; i++) { 9239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&L[i])); 924d8588912SDave May } 925d8588912SDave May 9269566063dSJacob Faibussowitsch PetscCall(PetscFree(L)); 927d8588912SDave May } 928d8588912SDave May PetscFunctionReturn(0); 929d8588912SDave May } 930d8588912SDave May 931207556f9SJed Brown static PetscErrorCode MatView_Nest(Mat A,PetscViewer viewer) 932d8588912SDave May { 933d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 93429e60adbSStefano Zampini PetscBool isascii,viewSub = PETSC_FALSE; 935d8588912SDave May PetscInt i,j; 936d8588912SDave May 937d8588912SDave May PetscFunctionBegin; 9389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii)); 939d8588912SDave May if (isascii) { 940d8588912SDave May 9419566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)A)->options,((PetscObject)A)->prefix,"-mat_view_nest_sub",&viewSub,NULL)); 9429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"Matrix object: \n")); 9439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 9449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "type=nest, rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT " \n",bA->nr,bA->nc)); 945d8588912SDave May 9469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"MatNest structure: \n")); 947d8588912SDave May for (i=0; i<bA->nr; i++) { 948d8588912SDave May for (j=0; j<bA->nc; j++) { 94919fd82e9SBarry Smith MatType type; 950270f95d7SJed Brown char name[256] = "",prefix[256] = ""; 951d8588912SDave May PetscInt NR,NC; 952d8588912SDave May PetscBool isNest = PETSC_FALSE; 953d8588912SDave May 954d8588912SDave May if (!bA->m[i][j]) { 9559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "(%" PetscInt_FMT ",%" PetscInt_FMT ") : NULL \n",i,j)); 956d8588912SDave May continue; 957d8588912SDave May } 9589566063dSJacob Faibussowitsch PetscCall(MatGetSize(bA->m[i][j],&NR,&NC)); 9599566063dSJacob Faibussowitsch PetscCall(MatGetType(bA->m[i][j], &type)); 9609566063dSJacob Faibussowitsch if (((PetscObject)bA->m[i][j])->name) PetscCall(PetscSNPrintf(name,sizeof(name),"name=\"%s\", ",((PetscObject)bA->m[i][j])->name)); 9619566063dSJacob Faibussowitsch if (((PetscObject)bA->m[i][j])->prefix) PetscCall(PetscSNPrintf(prefix,sizeof(prefix),"prefix=\"%s\", ",((PetscObject)bA->m[i][j])->prefix)); 9629566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)bA->m[i][j],MATNEST,&isNest)); 963d8588912SDave May 9649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"(%" PetscInt_FMT ",%" PetscInt_FMT ") : %s%stype=%s, rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT " \n",i,j,name,prefix,type,NR,NC)); 965d8588912SDave May 96629e60adbSStefano Zampini if (isNest || viewSub) { 9679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); /* push1 */ 9689566063dSJacob Faibussowitsch PetscCall(MatView(bA->m[i][j],viewer)); 9699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); /* pop1 */ 970d8588912SDave May } 971d8588912SDave May } 972d8588912SDave May } 9739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); /* pop0 */ 974d8588912SDave May } 975d8588912SDave May PetscFunctionReturn(0); 976d8588912SDave May } 977d8588912SDave May 978207556f9SJed Brown static PetscErrorCode MatZeroEntries_Nest(Mat A) 979d8588912SDave May { 980d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 981d8588912SDave May PetscInt i,j; 982d8588912SDave May 983d8588912SDave May PetscFunctionBegin; 984d8588912SDave May for (i=0; i<bA->nr; i++) { 985d8588912SDave May for (j=0; j<bA->nc; j++) { 986d8588912SDave May if (!bA->m[i][j]) continue; 9879566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(bA->m[i][j])); 988d8588912SDave May } 989d8588912SDave May } 990d8588912SDave May PetscFunctionReturn(0); 991d8588912SDave May } 992d8588912SDave May 993c222c20dSDavid Ham static PetscErrorCode MatCopy_Nest(Mat A,Mat B,MatStructure str) 994c222c20dSDavid Ham { 995c222c20dSDavid Ham Mat_Nest *bA = (Mat_Nest*)A->data,*bB = (Mat_Nest*)B->data; 996c222c20dSDavid Ham PetscInt i,j,nr = bA->nr,nc = bA->nc; 99706a1af2fSStefano Zampini PetscBool nnzstate = PETSC_FALSE; 998c222c20dSDavid Ham 999c222c20dSDavid Ham PetscFunctionBegin; 1000aed4548fSBarry Smith PetscCheck(nr == bB->nr && nc == bB->nc,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Cannot copy a Mat_Nest of block size (%" PetscInt_FMT ",%" PetscInt_FMT ") to a Mat_Nest of block size (%" PetscInt_FMT ",%" PetscInt_FMT ")",bB->nr,bB->nc,nr,nc); 1001c222c20dSDavid Ham for (i=0; i<nr; i++) { 1002c222c20dSDavid Ham for (j=0; j<nc; j++) { 100306a1af2fSStefano Zampini PetscObjectState subnnzstate = 0; 100446a2b97cSJed Brown if (bA->m[i][j] && bB->m[i][j]) { 10059566063dSJacob Faibussowitsch PetscCall(MatCopy(bA->m[i][j],bB->m[i][j],str)); 100608401ef6SPierre Jolivet } else PetscCheck(!bA->m[i][j] && !bB->m[i][j],PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Matrix block does not exist at %" PetscInt_FMT ",%" PetscInt_FMT,i,j); 10079566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroState(bB->m[i][j],&subnnzstate)); 100806a1af2fSStefano Zampini nnzstate = (PetscBool)(nnzstate || bB->nnzstate[i*nc+j] != subnnzstate); 100906a1af2fSStefano Zampini bB->nnzstate[i*nc+j] = subnnzstate; 1010c222c20dSDavid Ham } 1011c222c20dSDavid Ham } 101206a1af2fSStefano Zampini if (nnzstate) B->nonzerostate++; 1013c222c20dSDavid Ham PetscFunctionReturn(0); 1014c222c20dSDavid Ham } 1015c222c20dSDavid Ham 10166e76ffeaSPierre Jolivet static PetscErrorCode MatAXPY_Nest(Mat Y,PetscScalar a,Mat X,MatStructure str) 10176e76ffeaSPierre Jolivet { 10186e76ffeaSPierre Jolivet Mat_Nest *bY = (Mat_Nest*)Y->data,*bX = (Mat_Nest*)X->data; 10196e76ffeaSPierre Jolivet PetscInt i,j,nr = bY->nr,nc = bY->nc; 102006a1af2fSStefano Zampini PetscBool nnzstate = PETSC_FALSE; 10216e76ffeaSPierre Jolivet 10226e76ffeaSPierre Jolivet PetscFunctionBegin; 1023aed4548fSBarry Smith PetscCheck(nr == bX->nr && nc == bX->nc,PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_INCOMP,"Cannot AXPY a MatNest of block size (%" PetscInt_FMT ",%" PetscInt_FMT ") with a MatNest of block size (%" PetscInt_FMT ",%" PetscInt_FMT ")",bX->nr,bX->nc,nr,nc); 10246e76ffeaSPierre Jolivet for (i=0; i<nr; i++) { 10256e76ffeaSPierre Jolivet for (j=0; j<nc; j++) { 102606a1af2fSStefano Zampini PetscObjectState subnnzstate = 0; 10276e76ffeaSPierre Jolivet if (bY->m[i][j] && bX->m[i][j]) { 10289566063dSJacob Faibussowitsch PetscCall(MatAXPY(bY->m[i][j],a,bX->m[i][j],str)); 1029c066aebcSStefano Zampini } else if (bX->m[i][j]) { 1030c066aebcSStefano Zampini Mat M; 1031c066aebcSStefano Zampini 103208401ef6SPierre Jolivet PetscCheck(str == DIFFERENT_NONZERO_PATTERN,PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_INCOMP,"Matrix block does not exist at %" PetscInt_FMT ",%" PetscInt_FMT ". Use DIFFERENT_NONZERO_PATTERN",i,j); 10339566063dSJacob Faibussowitsch PetscCall(MatDuplicate(bX->m[i][j],MAT_COPY_VALUES,&M)); 10349566063dSJacob Faibussowitsch PetscCall(MatNestSetSubMat(Y,i,j,M)); 10359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 1036c066aebcSStefano Zampini } 10379566063dSJacob Faibussowitsch if (bY->m[i][j]) PetscCall(MatGetNonzeroState(bY->m[i][j],&subnnzstate)); 103806a1af2fSStefano Zampini nnzstate = (PetscBool)(nnzstate || bY->nnzstate[i*nc+j] != subnnzstate); 103906a1af2fSStefano Zampini bY->nnzstate[i*nc+j] = subnnzstate; 10406e76ffeaSPierre Jolivet } 10416e76ffeaSPierre Jolivet } 104206a1af2fSStefano Zampini if (nnzstate) Y->nonzerostate++; 10436e76ffeaSPierre Jolivet PetscFunctionReturn(0); 10446e76ffeaSPierre Jolivet } 10456e76ffeaSPierre Jolivet 1046207556f9SJed Brown static PetscErrorCode MatDuplicate_Nest(Mat A,MatDuplicateOption op,Mat *B) 1047d8588912SDave May { 1048d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 1049841e96a3SJed Brown Mat *b; 1050841e96a3SJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 1051d8588912SDave May 1052d8588912SDave May PetscFunctionBegin; 10539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nr*nc,&b)); 1054841e96a3SJed Brown for (i=0; i<nr; i++) { 1055841e96a3SJed Brown for (j=0; j<nc; j++) { 1056841e96a3SJed Brown if (bA->m[i][j]) { 10579566063dSJacob Faibussowitsch PetscCall(MatDuplicate(bA->m[i][j],op,&b[i*nc+j])); 1058841e96a3SJed Brown } else { 10590298fd71SBarry Smith b[i*nc+j] = NULL; 1060d8588912SDave May } 1061d8588912SDave May } 1062d8588912SDave May } 10639566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PetscObjectComm((PetscObject)A),nr,bA->isglobal.row,nc,bA->isglobal.col,b,B)); 1064841e96a3SJed Brown /* Give the new MatNest exclusive ownership */ 1065841e96a3SJed Brown for (i=0; i<nr*nc; i++) { 10669566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b[i])); 1067d8588912SDave May } 10689566063dSJacob Faibussowitsch PetscCall(PetscFree(b)); 1069d8588912SDave May 10709566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY)); 10719566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY)); 1072d8588912SDave May PetscFunctionReturn(0); 1073d8588912SDave May } 1074d8588912SDave May 1075d8588912SDave May /* nest api */ 1076d8588912SDave May PetscErrorCode MatNestGetSubMat_Nest(Mat A,PetscInt idxm,PetscInt jdxm,Mat *mat) 1077d8588912SDave May { 1078d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 10795fd66863SKarl Rupp 1080d8588912SDave May PetscFunctionBegin; 108108401ef6SPierre Jolivet PetscCheck(idxm < bA->nr,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT,idxm,bA->nr-1); 108208401ef6SPierre Jolivet PetscCheck(jdxm < bA->nc,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Col too large: row %" PetscInt_FMT " max %" PetscInt_FMT,jdxm,bA->nc-1); 1083d8588912SDave May *mat = bA->m[idxm][jdxm]; 1084d8588912SDave May PetscFunctionReturn(0); 1085d8588912SDave May } 1086d8588912SDave May 10879ba0d327SJed Brown /*@ 1088d8588912SDave May MatNestGetSubMat - Returns a single, sub-matrix from a nest matrix. 1089d8588912SDave May 1090d8588912SDave May Not collective 1091d8588912SDave May 1092d8588912SDave May Input Parameters: 1093629881c0SJed Brown + A - nest matrix 1094d8588912SDave May . idxm - index of the matrix within the nest matrix 1095629881c0SJed Brown - jdxm - index of the matrix within the nest matrix 1096d8588912SDave May 1097d8588912SDave May Output Parameter: 1098d8588912SDave May . sub - matrix at index idxm,jdxm within the nest matrix 1099d8588912SDave May 1100d8588912SDave May Level: developer 1101d8588912SDave May 1102db781477SPatrick Sanan .seealso: `MatNestGetSize()`, `MatNestGetSubMats()`, `MatCreateNest()`, `MATNEST`, `MatNestSetSubMat()`, 1103db781477SPatrick Sanan `MatNestGetLocalISs()`, `MatNestGetISs()` 1104d8588912SDave May @*/ 11057087cfbeSBarry Smith PetscErrorCode MatNestGetSubMat(Mat A,PetscInt idxm,PetscInt jdxm,Mat *sub) 1106d8588912SDave May { 1107d8588912SDave May PetscFunctionBegin; 1108cac4c232SBarry Smith PetscUseMethod(A,"MatNestGetSubMat_C",(Mat,PetscInt,PetscInt,Mat*),(A,idxm,jdxm,sub)); 1109d8588912SDave May PetscFunctionReturn(0); 1110d8588912SDave May } 1111d8588912SDave May 11120782ca92SJed Brown PetscErrorCode MatNestSetSubMat_Nest(Mat A,PetscInt idxm,PetscInt jdxm,Mat mat) 11130782ca92SJed Brown { 11140782ca92SJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 11150782ca92SJed Brown PetscInt m,n,M,N,mi,ni,Mi,Ni; 11160782ca92SJed Brown 11170782ca92SJed Brown PetscFunctionBegin; 111808401ef6SPierre Jolivet PetscCheck(idxm < bA->nr,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT,idxm,bA->nr-1); 111908401ef6SPierre Jolivet PetscCheck(jdxm < bA->nc,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Col too large: row %" PetscInt_FMT " max %" PetscInt_FMT,jdxm,bA->nc-1); 11209566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat,&m,&n)); 11219566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat,&M,&N)); 11229566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(bA->isglobal.row[idxm],&mi)); 11239566063dSJacob Faibussowitsch PetscCall(ISGetSize(bA->isglobal.row[idxm],&Mi)); 11249566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(bA->isglobal.col[jdxm],&ni)); 11259566063dSJacob Faibussowitsch PetscCall(ISGetSize(bA->isglobal.col[jdxm],&Ni)); 1126aed4548fSBarry Smith PetscCheck(M == Mi && N == Ni,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_INCOMP,"Submatrix dimension (%" PetscInt_FMT ",%" PetscInt_FMT ") incompatible with nest block (%" PetscInt_FMT ",%" PetscInt_FMT ")",M,N,Mi,Ni); 1127aed4548fSBarry Smith PetscCheck(m == mi && n == ni,PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_INCOMP,"Submatrix local dimension (%" PetscInt_FMT ",%" PetscInt_FMT ") incompatible with nest block (%" PetscInt_FMT ",%" PetscInt_FMT ")",m,n,mi,ni); 112826fbe8dcSKarl Rupp 112906a1af2fSStefano Zampini /* do not increase object state */ 113006a1af2fSStefano Zampini if (mat == bA->m[idxm][jdxm]) PetscFunctionReturn(0); 113106a1af2fSStefano Zampini 11329566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)mat)); 11339566063dSJacob Faibussowitsch PetscCall(MatDestroy(&bA->m[idxm][jdxm])); 11340782ca92SJed Brown bA->m[idxm][jdxm] = mat; 11359566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 11369566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroState(mat,&bA->nnzstate[idxm*bA->nc+jdxm])); 113706a1af2fSStefano Zampini A->nonzerostate++; 11380782ca92SJed Brown PetscFunctionReturn(0); 11390782ca92SJed Brown } 11400782ca92SJed Brown 11419ba0d327SJed Brown /*@ 11420782ca92SJed Brown MatNestSetSubMat - Set a single submatrix in the nest matrix. 11430782ca92SJed Brown 11440782ca92SJed Brown Logically collective on the submatrix communicator 11450782ca92SJed Brown 11460782ca92SJed Brown Input Parameters: 11470782ca92SJed Brown + A - nest matrix 11480782ca92SJed Brown . idxm - index of the matrix within the nest matrix 11490782ca92SJed Brown . jdxm - index of the matrix within the nest matrix 11500782ca92SJed Brown - sub - matrix at index idxm,jdxm within the nest matrix 11510782ca92SJed Brown 11520782ca92SJed Brown Notes: 11530782ca92SJed Brown The new submatrix must have the same size and communicator as that block of the nest. 11540782ca92SJed Brown 11550782ca92SJed Brown This increments the reference count of the submatrix. 11560782ca92SJed Brown 11570782ca92SJed Brown Level: developer 11580782ca92SJed Brown 1159db781477SPatrick Sanan .seealso: `MatNestSetSubMats()`, `MatNestGetSubMats()`, `MatNestGetLocalISs()`, `MATNEST`, `MatCreateNest()`, 1160db781477SPatrick Sanan `MatNestGetSubMat()`, `MatNestGetISs()`, `MatNestGetSize()` 11610782ca92SJed Brown @*/ 11620782ca92SJed Brown PetscErrorCode MatNestSetSubMat(Mat A,PetscInt idxm,PetscInt jdxm,Mat sub) 11630782ca92SJed Brown { 11640782ca92SJed Brown PetscFunctionBegin; 1165cac4c232SBarry Smith PetscUseMethod(A,"MatNestSetSubMat_C",(Mat,PetscInt,PetscInt,Mat),(A,idxm,jdxm,sub)); 11660782ca92SJed Brown PetscFunctionReturn(0); 11670782ca92SJed Brown } 11680782ca92SJed Brown 1169d8588912SDave May PetscErrorCode MatNestGetSubMats_Nest(Mat A,PetscInt *M,PetscInt *N,Mat ***mat) 1170d8588912SDave May { 1171d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 11725fd66863SKarl Rupp 1173d8588912SDave May PetscFunctionBegin; 117426fbe8dcSKarl Rupp if (M) *M = bA->nr; 117526fbe8dcSKarl Rupp if (N) *N = bA->nc; 117626fbe8dcSKarl Rupp if (mat) *mat = bA->m; 1177d8588912SDave May PetscFunctionReturn(0); 1178d8588912SDave May } 1179d8588912SDave May 1180d8588912SDave May /*@C 1181d8588912SDave May MatNestGetSubMats - Returns the entire two dimensional array of matrices defining a nest matrix. 1182d8588912SDave May 1183d8588912SDave May Not collective 1184d8588912SDave May 1185f899ff85SJose E. Roman Input Parameter: 1186629881c0SJed Brown . A - nest matrix 1187d8588912SDave May 1188d8d19677SJose E. Roman Output Parameters: 1189629881c0SJed Brown + M - number of rows in the nest matrix 1190d8588912SDave May . N - number of cols in the nest matrix 1191629881c0SJed Brown - mat - 2d array of matrices 1192d8588912SDave May 1193d8588912SDave May Notes: 1194d8588912SDave May 1195d8588912SDave May The user should not free the array mat. 1196d8588912SDave May 1197351962e3SVincent Le Chenadec In Fortran, this routine has a calling sequence 1198351962e3SVincent Le Chenadec $ call MatNestGetSubMats(A, M, N, mat, ierr) 1199351962e3SVincent Le Chenadec where the space allocated for the optional argument mat is assumed large enough (if provided). 1200351962e3SVincent Le Chenadec 1201d8588912SDave May Level: developer 1202d8588912SDave May 1203db781477SPatrick Sanan .seealso: `MatNestGetSize()`, `MatNestGetSubMat()`, `MatNestGetLocalISs()`, `MATNEST`, `MatCreateNest()`, 1204db781477SPatrick Sanan `MatNestSetSubMats()`, `MatNestGetISs()`, `MatNestSetSubMat()` 1205d8588912SDave May @*/ 12067087cfbeSBarry Smith PetscErrorCode MatNestGetSubMats(Mat A,PetscInt *M,PetscInt *N,Mat ***mat) 1207d8588912SDave May { 1208d8588912SDave May PetscFunctionBegin; 1209cac4c232SBarry Smith PetscUseMethod(A,"MatNestGetSubMats_C",(Mat,PetscInt*,PetscInt*,Mat***),(A,M,N,mat)); 1210d8588912SDave May PetscFunctionReturn(0); 1211d8588912SDave May } 1212d8588912SDave May 12137087cfbeSBarry Smith PetscErrorCode MatNestGetSize_Nest(Mat A,PetscInt *M,PetscInt *N) 1214d8588912SDave May { 1215d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 1216d8588912SDave May 1217d8588912SDave May PetscFunctionBegin; 121826fbe8dcSKarl Rupp if (M) *M = bA->nr; 121926fbe8dcSKarl Rupp if (N) *N = bA->nc; 1220d8588912SDave May PetscFunctionReturn(0); 1221d8588912SDave May } 1222d8588912SDave May 12239ba0d327SJed Brown /*@ 1224d8588912SDave May MatNestGetSize - Returns the size of the nest matrix. 1225d8588912SDave May 1226d8588912SDave May Not collective 1227d8588912SDave May 1228f899ff85SJose E. Roman Input Parameter: 1229d8588912SDave May . A - nest matrix 1230d8588912SDave May 1231d8d19677SJose E. Roman Output Parameters: 1232629881c0SJed Brown + M - number of rows in the nested mat 1233629881c0SJed Brown - N - number of cols in the nested mat 1234d8588912SDave May 1235d8588912SDave May Notes: 1236d8588912SDave May 1237d8588912SDave May Level: developer 1238d8588912SDave May 1239db781477SPatrick Sanan .seealso: `MatNestGetSubMat()`, `MatNestGetSubMats()`, `MATNEST`, `MatCreateNest()`, `MatNestGetLocalISs()`, 1240db781477SPatrick Sanan `MatNestGetISs()` 1241d8588912SDave May @*/ 12427087cfbeSBarry Smith PetscErrorCode MatNestGetSize(Mat A,PetscInt *M,PetscInt *N) 1243d8588912SDave May { 1244d8588912SDave May PetscFunctionBegin; 1245cac4c232SBarry Smith PetscUseMethod(A,"MatNestGetSize_C",(Mat,PetscInt*,PetscInt*),(A,M,N)); 1246d8588912SDave May PetscFunctionReturn(0); 1247d8588912SDave May } 1248d8588912SDave May 1249f7a08781SBarry Smith static PetscErrorCode MatNestGetISs_Nest(Mat A,IS rows[],IS cols[]) 1250900e7ff2SJed Brown { 1251900e7ff2SJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 1252900e7ff2SJed Brown PetscInt i; 1253900e7ff2SJed Brown 1254900e7ff2SJed Brown PetscFunctionBegin; 1255900e7ff2SJed Brown if (rows) for (i=0; i<vs->nr; i++) rows[i] = vs->isglobal.row[i]; 1256900e7ff2SJed Brown if (cols) for (i=0; i<vs->nc; i++) cols[i] = vs->isglobal.col[i]; 1257900e7ff2SJed Brown PetscFunctionReturn(0); 1258900e7ff2SJed Brown } 1259900e7ff2SJed Brown 12603a4d7b9aSSatish Balay /*@C 1261900e7ff2SJed Brown MatNestGetISs - Returns the index sets partitioning the row and column spaces 1262900e7ff2SJed Brown 1263900e7ff2SJed Brown Not collective 1264900e7ff2SJed Brown 1265f899ff85SJose E. Roman Input Parameter: 1266900e7ff2SJed Brown . A - nest matrix 1267900e7ff2SJed Brown 1268d8d19677SJose E. Roman Output Parameters: 1269900e7ff2SJed Brown + rows - array of row index sets 1270900e7ff2SJed Brown - cols - array of column index sets 1271900e7ff2SJed Brown 1272900e7ff2SJed Brown Level: advanced 1273900e7ff2SJed Brown 1274900e7ff2SJed Brown Notes: 1275900e7ff2SJed Brown The user must have allocated arrays of the correct size. The reference count is not increased on the returned ISs. 1276900e7ff2SJed Brown 1277db781477SPatrick Sanan .seealso: `MatNestGetSubMat()`, `MatNestGetSubMats()`, `MatNestGetSize()`, `MatNestGetLocalISs()`, `MATNEST`, 1278db781477SPatrick Sanan `MatCreateNest()`, `MatNestGetSubMats()`, `MatNestSetSubMats()` 1279900e7ff2SJed Brown @*/ 1280900e7ff2SJed Brown PetscErrorCode MatNestGetISs(Mat A,IS rows[],IS cols[]) 1281900e7ff2SJed Brown { 1282900e7ff2SJed Brown PetscFunctionBegin; 1283900e7ff2SJed Brown PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1284cac4c232SBarry Smith PetscUseMethod(A,"MatNestGetISs_C",(Mat,IS[],IS[]),(A,rows,cols)); 1285900e7ff2SJed Brown PetscFunctionReturn(0); 1286900e7ff2SJed Brown } 1287900e7ff2SJed Brown 1288f7a08781SBarry Smith static PetscErrorCode MatNestGetLocalISs_Nest(Mat A,IS rows[],IS cols[]) 1289900e7ff2SJed Brown { 1290900e7ff2SJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 1291900e7ff2SJed Brown PetscInt i; 1292900e7ff2SJed Brown 1293900e7ff2SJed Brown PetscFunctionBegin; 1294900e7ff2SJed Brown if (rows) for (i=0; i<vs->nr; i++) rows[i] = vs->islocal.row[i]; 1295900e7ff2SJed Brown if (cols) for (i=0; i<vs->nc; i++) cols[i] = vs->islocal.col[i]; 1296900e7ff2SJed Brown PetscFunctionReturn(0); 1297900e7ff2SJed Brown } 1298900e7ff2SJed Brown 1299900e7ff2SJed Brown /*@C 1300900e7ff2SJed Brown MatNestGetLocalISs - Returns the index sets partitioning the row and column spaces 1301900e7ff2SJed Brown 1302900e7ff2SJed Brown Not collective 1303900e7ff2SJed Brown 1304f899ff85SJose E. Roman Input Parameter: 1305900e7ff2SJed Brown . A - nest matrix 1306900e7ff2SJed Brown 1307d8d19677SJose E. Roman Output Parameters: 13080298fd71SBarry Smith + rows - array of row index sets (or NULL to ignore) 13090298fd71SBarry Smith - cols - array of column index sets (or NULL to ignore) 1310900e7ff2SJed Brown 1311900e7ff2SJed Brown Level: advanced 1312900e7ff2SJed Brown 1313900e7ff2SJed Brown Notes: 1314900e7ff2SJed Brown The user must have allocated arrays of the correct size. The reference count is not increased on the returned ISs. 1315900e7ff2SJed Brown 1316db781477SPatrick Sanan .seealso: `MatNestGetSubMat()`, `MatNestGetSubMats()`, `MatNestGetSize()`, `MatNestGetISs()`, `MatCreateNest()`, 1317db781477SPatrick Sanan `MATNEST`, `MatNestSetSubMats()`, `MatNestSetSubMat()` 1318900e7ff2SJed Brown @*/ 1319900e7ff2SJed Brown PetscErrorCode MatNestGetLocalISs(Mat A,IS rows[],IS cols[]) 1320900e7ff2SJed Brown { 1321900e7ff2SJed Brown PetscFunctionBegin; 1322900e7ff2SJed Brown PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1323cac4c232SBarry Smith PetscUseMethod(A,"MatNestGetLocalISs_C",(Mat,IS[],IS[]),(A,rows,cols)); 1324900e7ff2SJed Brown PetscFunctionReturn(0); 1325900e7ff2SJed Brown } 1326900e7ff2SJed Brown 132719fd82e9SBarry Smith PetscErrorCode MatNestSetVecType_Nest(Mat A,VecType vtype) 1328207556f9SJed Brown { 1329207556f9SJed Brown PetscBool flg; 1330207556f9SJed Brown 1331207556f9SJed Brown PetscFunctionBegin; 13329566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(vtype,VECNEST,&flg)); 1333207556f9SJed Brown /* In reality, this only distinguishes VECNEST and "other" */ 13342a7a6963SBarry Smith if (flg) A->ops->getvecs = MatCreateVecs_Nest; 133512b53f24SSatish Balay else A->ops->getvecs = (PetscErrorCode (*)(Mat,Vec*,Vec*)) 0; 1336207556f9SJed Brown PetscFunctionReturn(0); 1337207556f9SJed Brown } 1338207556f9SJed Brown 1339207556f9SJed Brown /*@C 13402a7a6963SBarry Smith MatNestSetVecType - Sets the type of Vec returned by MatCreateVecs() 1341207556f9SJed Brown 1342207556f9SJed Brown Not collective 1343207556f9SJed Brown 1344207556f9SJed Brown Input Parameters: 1345207556f9SJed Brown + A - nest matrix 1346207556f9SJed Brown - vtype - type to use for creating vectors 1347207556f9SJed Brown 1348207556f9SJed Brown Notes: 1349207556f9SJed Brown 1350207556f9SJed Brown Level: developer 1351207556f9SJed Brown 1352db781477SPatrick Sanan .seealso: `MatCreateVecs()`, `MATNEST`, `MatCreateNest()` 1353207556f9SJed Brown @*/ 135419fd82e9SBarry Smith PetscErrorCode MatNestSetVecType(Mat A,VecType vtype) 1355207556f9SJed Brown { 1356207556f9SJed Brown PetscFunctionBegin; 1357cac4c232SBarry Smith PetscTryMethod(A,"MatNestSetVecType_C",(Mat,VecType),(A,vtype)); 1358207556f9SJed Brown PetscFunctionReturn(0); 1359207556f9SJed Brown } 1360207556f9SJed Brown 1361c8883902SJed Brown PetscErrorCode MatNestSetSubMats_Nest(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[]) 1362d8588912SDave May { 1363c8883902SJed Brown Mat_Nest *s = (Mat_Nest*)A->data; 1364c8883902SJed Brown PetscInt i,j,m,n,M,N; 136588ffe2e8SJose E. Roman PetscBool cong,isstd,sametype=PETSC_FALSE; 136688ffe2e8SJose E. Roman VecType vtype,type; 1367d8588912SDave May 1368d8588912SDave May PetscFunctionBegin; 13699566063dSJacob Faibussowitsch PetscCall(MatReset_Nest(A)); 137006a1af2fSStefano Zampini 1371c8883902SJed Brown s->nr = nr; 1372c8883902SJed Brown s->nc = nc; 1373d8588912SDave May 1374c8883902SJed Brown /* Create space for submatrices */ 13759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nr,&s->m)); 1376c8883902SJed Brown for (i=0; i<nr; i++) { 13779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nc,&s->m[i])); 1378d8588912SDave May } 1379c8883902SJed Brown for (i=0; i<nr; i++) { 1380c8883902SJed Brown for (j=0; j<nc; j++) { 1381c8883902SJed Brown s->m[i][j] = a[i*nc+j]; 1382c8883902SJed Brown if (a[i*nc+j]) { 13839566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)a[i*nc+j])); 1384d8588912SDave May } 1385d8588912SDave May } 1386d8588912SDave May } 13879566063dSJacob Faibussowitsch PetscCall(MatGetVecType(A,&vtype)); 13889566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(vtype,VECSTANDARD,&isstd)); 138988ffe2e8SJose E. Roman if (isstd) { 139088ffe2e8SJose E. Roman /* check if all blocks have the same vectype */ 139188ffe2e8SJose E. Roman vtype = NULL; 139288ffe2e8SJose E. Roman for (i=0; i<nr; i++) { 139388ffe2e8SJose E. Roman for (j=0; j<nc; j++) { 139488ffe2e8SJose E. Roman if (a[i*nc+j]) { 139588ffe2e8SJose E. Roman if (!vtype) { /* first visited block */ 13969566063dSJacob Faibussowitsch PetscCall(MatGetVecType(a[i*nc+j],&vtype)); 139788ffe2e8SJose E. Roman sametype = PETSC_TRUE; 139888ffe2e8SJose E. Roman } else if (sametype) { 13999566063dSJacob Faibussowitsch PetscCall(MatGetVecType(a[i*nc+j],&type)); 14009566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(vtype,type,&sametype)); 140188ffe2e8SJose E. Roman } 140288ffe2e8SJose E. Roman } 140388ffe2e8SJose E. Roman } 140488ffe2e8SJose E. Roman } 140588ffe2e8SJose E. Roman if (sametype) { /* propagate vectype */ 14069566063dSJacob Faibussowitsch PetscCall(MatSetVecType(A,vtype)); 140788ffe2e8SJose E. Roman } 140888ffe2e8SJose E. Roman } 1409d8588912SDave May 14109566063dSJacob Faibussowitsch PetscCall(MatSetUp_NestIS_Private(A,nr,is_row,nc,is_col)); 1411d8588912SDave May 14129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nr,&s->row_len)); 14139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nc,&s->col_len)); 1414c8883902SJed Brown for (i=0; i<nr; i++) s->row_len[i]=-1; 1415c8883902SJed Brown for (j=0; j<nc; j++) s->col_len[j]=-1; 1416d8588912SDave May 14179566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nr*nc,&s->nnzstate)); 141806a1af2fSStefano Zampini for (i=0; i<nr; i++) { 141906a1af2fSStefano Zampini for (j=0; j<nc; j++) { 142006a1af2fSStefano Zampini if (s->m[i][j]) { 14219566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroState(s->m[i][j],&s->nnzstate[i*nc+j])); 142206a1af2fSStefano Zampini } 142306a1af2fSStefano Zampini } 142406a1af2fSStefano Zampini } 142506a1af2fSStefano Zampini 14269566063dSJacob Faibussowitsch PetscCall(MatNestGetSizes_Private(A,&m,&n,&M,&N)); 1427d8588912SDave May 14289566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(A->rmap,M)); 14299566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(A->rmap,m)); 14309566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(A->cmap,N)); 14319566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(A->cmap,n)); 1432c8883902SJed Brown 14339566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 14349566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 1435c8883902SJed Brown 143606a1af2fSStefano Zampini /* disable operations that are not supported for non-square matrices, 143706a1af2fSStefano Zampini or matrices for which is_row != is_col */ 14389566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A,&cong)); 143906a1af2fSStefano Zampini if (cong && nr != nc) cong = PETSC_FALSE; 144006a1af2fSStefano Zampini if (cong) { 144106a1af2fSStefano Zampini for (i = 0; cong && i < nr; i++) { 14429566063dSJacob Faibussowitsch PetscCall(ISEqualUnsorted(s->isglobal.row[i],s->isglobal.col[i],&cong)); 144306a1af2fSStefano Zampini } 144406a1af2fSStefano Zampini } 144506a1af2fSStefano Zampini if (!cong) { 1446381b8e50SStefano Zampini A->ops->missingdiagonal = NULL; 144706a1af2fSStefano Zampini A->ops->getdiagonal = NULL; 144806a1af2fSStefano Zampini A->ops->shift = NULL; 144906a1af2fSStefano Zampini A->ops->diagonalset = NULL; 145006a1af2fSStefano Zampini } 145106a1af2fSStefano Zampini 14529566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nr,&s->left,nc,&s->right)); 14539566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)A)); 145406a1af2fSStefano Zampini A->nonzerostate++; 1455d8588912SDave May PetscFunctionReturn(0); 1456d8588912SDave May } 1457d8588912SDave May 1458c8883902SJed Brown /*@ 1459c8883902SJed Brown MatNestSetSubMats - Sets the nested submatrices 1460c8883902SJed Brown 1461c8883902SJed Brown Collective on Mat 1462c8883902SJed Brown 1463d8d19677SJose E. Roman Input Parameters: 1464ffd6319bSRichard Tran Mills + A - nested matrix 1465c8883902SJed Brown . nr - number of nested row blocks 14660298fd71SBarry Smith . is_row - index sets for each nested row block, or NULL to make contiguous 1467c8883902SJed Brown . nc - number of nested column blocks 14680298fd71SBarry Smith . is_col - index sets for each nested column block, or NULL to make contiguous 14690298fd71SBarry Smith - a - row-aligned array of nr*nc submatrices, empty submatrices can be passed using NULL 1470c8883902SJed Brown 147106a1af2fSStefano Zampini Notes: this always resets any submatrix information previously set 147206a1af2fSStefano Zampini 1473c8883902SJed Brown Level: advanced 1474c8883902SJed Brown 1475db781477SPatrick Sanan .seealso: `MatCreateNest()`, `MATNEST`, `MatNestSetSubMat()`, `MatNestGetSubMat()`, `MatNestGetSubMats()` 1476c8883902SJed Brown @*/ 1477c8883902SJed Brown PetscErrorCode MatNestSetSubMats(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[]) 1478c8883902SJed Brown { 147906a1af2fSStefano Zampini PetscInt i; 1480c8883902SJed Brown 1481c8883902SJed Brown PetscFunctionBegin; 1482c8883902SJed Brown PetscValidHeaderSpecific(A,MAT_CLASSID,1); 148308401ef6SPierre Jolivet PetscCheck(nr >= 0,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Number of rows cannot be negative"); 1484c8883902SJed Brown if (nr && is_row) { 1485c8883902SJed Brown PetscValidPointer(is_row,3); 1486c8883902SJed Brown for (i=0; i<nr; i++) PetscValidHeaderSpecific(is_row[i],IS_CLASSID,3); 1487c8883902SJed Brown } 148808401ef6SPierre Jolivet PetscCheck(nc >= 0,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Number of columns cannot be negative"); 14891664e352SJed Brown if (nc && is_col) { 1490c8883902SJed Brown PetscValidPointer(is_col,5); 14919b30a8f6SBarry Smith for (i=0; i<nc; i++) PetscValidHeaderSpecific(is_col[i],IS_CLASSID,5); 1492c8883902SJed Brown } 149306a1af2fSStefano Zampini if (nr*nc > 0) PetscValidPointer(a,6); 1494cac4c232SBarry Smith PetscUseMethod(A,"MatNestSetSubMats_C",(Mat,PetscInt,const IS[],PetscInt,const IS[],const Mat[]),(A,nr,is_row,nc,is_col,a)); 1495c8883902SJed Brown PetscFunctionReturn(0); 1496c8883902SJed Brown } 1497d8588912SDave May 149845b6f7e9SBarry Smith static PetscErrorCode MatNestCreateAggregateL2G_Private(Mat A,PetscInt n,const IS islocal[],const IS isglobal[],PetscBool colflg,ISLocalToGlobalMapping *ltog) 149977019fcaSJed Brown { 150077019fcaSJed Brown PetscBool flg; 150177019fcaSJed Brown PetscInt i,j,m,mi,*ix; 150277019fcaSJed Brown 150377019fcaSJed Brown PetscFunctionBegin; 1504aea6d515SStefano Zampini *ltog = NULL; 150577019fcaSJed Brown for (i=0,m=0,flg=PETSC_FALSE; i<n; i++) { 150677019fcaSJed Brown if (islocal[i]) { 15079566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(islocal[i],&mi)); 150877019fcaSJed Brown flg = PETSC_TRUE; /* We found a non-trivial entry */ 150977019fcaSJed Brown } else { 15109566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isglobal[i],&mi)); 151177019fcaSJed Brown } 151277019fcaSJed Brown m += mi; 151377019fcaSJed Brown } 1514aea6d515SStefano Zampini if (!flg) PetscFunctionReturn(0); 1515aea6d515SStefano Zampini 15169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m,&ix)); 1517165cd838SBarry Smith for (i=0,m=0; i<n; i++) { 15180298fd71SBarry Smith ISLocalToGlobalMapping smap = NULL; 1519e108cb99SStefano Zampini Mat sub = NULL; 1520f6d38dbbSStefano Zampini PetscSF sf; 1521f6d38dbbSStefano Zampini PetscLayout map; 1522aea6d515SStefano Zampini const PetscInt *ix2; 152377019fcaSJed Brown 1524165cd838SBarry Smith if (!colflg) { 15259566063dSJacob Faibussowitsch PetscCall(MatNestFindNonzeroSubMatRow(A,i,&sub)); 152677019fcaSJed Brown } else { 15279566063dSJacob Faibussowitsch PetscCall(MatNestFindNonzeroSubMatCol(A,i,&sub)); 152877019fcaSJed Brown } 1529191fd14bSBarry Smith if (sub) { 1530191fd14bSBarry Smith if (!colflg) { 15319566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(sub,&smap,NULL)); 1532191fd14bSBarry Smith } else { 15339566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(sub,NULL,&smap)); 1534191fd14bSBarry Smith } 1535191fd14bSBarry Smith } 153677019fcaSJed Brown /* 153777019fcaSJed Brown Now we need to extract the monolithic global indices that correspond to the given split global indices. 153877019fcaSJed Brown In many/most cases, we only want MatGetLocalSubMatrix() to work, in which case we only need to know the size of the local spaces. 153977019fcaSJed Brown */ 15409566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isglobal[i],&ix2)); 1541aea6d515SStefano Zampini if (islocal[i]) { 1542aea6d515SStefano Zampini PetscInt *ilocal,*iremote; 1543aea6d515SStefano Zampini PetscInt mil,nleaves; 1544aea6d515SStefano Zampini 15459566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(islocal[i],&mi)); 154628b400f6SJacob Faibussowitsch PetscCheck(smap,PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing local to global map"); 1547aea6d515SStefano Zampini for (j=0; j<mi; j++) ix[m+j] = j; 15489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(smap,mi,ix+m,ix+m)); 1549aea6d515SStefano Zampini 1550aea6d515SStefano Zampini /* PetscSFSetGraphLayout does not like negative indices */ 15519566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(mi,&ilocal,mi,&iremote)); 1552aea6d515SStefano Zampini for (j=0, nleaves = 0; j<mi; j++) { 1553aea6d515SStefano Zampini if (ix[m+j] < 0) continue; 1554aea6d515SStefano Zampini ilocal[nleaves] = j; 1555aea6d515SStefano Zampini iremote[nleaves] = ix[m+j]; 1556aea6d515SStefano Zampini nleaves++; 1557aea6d515SStefano Zampini } 15589566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isglobal[i],&mil)); 15599566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)A),&sf)); 15609566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)A),&map)); 15619566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(map,mil)); 15629566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(map)); 15639566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(sf,map,nleaves,ilocal,PETSC_USE_POINTER,iremote)); 15649566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&map)); 15659566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf,MPIU_INT,ix2,ix + m,MPI_REPLACE)); 15669566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf,MPIU_INT,ix2,ix + m,MPI_REPLACE)); 15679566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 15689566063dSJacob Faibussowitsch PetscCall(PetscFree2(ilocal,iremote)); 1569aea6d515SStefano Zampini } else { 15709566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isglobal[i],&mi)); 1571aea6d515SStefano Zampini for (j=0; j<mi; j++) ix[m+j] = ix2[i]; 1572aea6d515SStefano Zampini } 15739566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isglobal[i],&ix2)); 157477019fcaSJed Brown m += mi; 157577019fcaSJed Brown } 15769566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,m,ix,PETSC_OWN_POINTER,ltog)); 157777019fcaSJed Brown PetscFunctionReturn(0); 157877019fcaSJed Brown } 157977019fcaSJed Brown 1580d8588912SDave May /* If an IS was provided, there is nothing Nest needs to do, otherwise Nest will build a strided IS */ 1581d8588912SDave May /* 1582d8588912SDave May nprocessors = NP 1583d8588912SDave May Nest x^T = ((g_0,g_1,...g_nprocs-1), (h_0,h_1,...h_NP-1)) 1584d8588912SDave May proc 0: => (g_0,h_0,) 1585d8588912SDave May proc 1: => (g_1,h_1,) 1586d8588912SDave May ... 1587d8588912SDave May proc nprocs-1: => (g_NP-1,h_NP-1,) 1588d8588912SDave May 1589d8588912SDave May proc 0: proc 1: proc nprocs-1: 1590d8588912SDave May is[0] = (0,1,2,...,nlocal(g_0)-1) (0,1,...,nlocal(g_1)-1) (0,1,...,nlocal(g_NP-1)) 1591d8588912SDave May 1592d8588912SDave May proc 0: 1593d8588912SDave May is[1] = (nlocal(g_0),nlocal(g_0)+1,...,nlocal(g_0)+nlocal(h_0)-1) 1594d8588912SDave May proc 1: 1595d8588912SDave May is[1] = (nlocal(g_1),nlocal(g_1)+1,...,nlocal(g_1)+nlocal(h_1)-1) 1596d8588912SDave May 1597d8588912SDave May proc NP-1: 1598d8588912SDave May is[1] = (nlocal(g_NP-1),nlocal(g_NP-1)+1,...,nlocal(g_NP-1)+nlocal(h_NP-1)-1) 1599d8588912SDave May */ 1600841e96a3SJed Brown static PetscErrorCode MatSetUp_NestIS_Private(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[]) 1601d8588912SDave May { 1602e2d7f03fSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 16038188e55aSJed Brown PetscInt i,j,offset,n,nsum,bs; 16040298fd71SBarry Smith Mat sub = NULL; 1605d8588912SDave May 1606d8588912SDave May PetscFunctionBegin; 16079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nr,&vs->isglobal.row)); 16089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nc,&vs->isglobal.col)); 1609d8588912SDave May if (is_row) { /* valid IS is passed in */ 1610a5b23f4aSJose E. Roman /* refs on is[] are incremented */ 1611e2d7f03fSJed Brown for (i=0; i<vs->nr; i++) { 16129566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is_row[i])); 161326fbe8dcSKarl Rupp 1614e2d7f03fSJed Brown vs->isglobal.row[i] = is_row[i]; 1615d8588912SDave May } 16162ae74bdbSJed Brown } else { /* Create the ISs by inspecting sizes of a submatrix in each row */ 16178188e55aSJed Brown nsum = 0; 16188188e55aSJed Brown for (i=0; i<vs->nr; i++) { /* Add up the local sizes to compute the aggregate offset */ 16199566063dSJacob Faibussowitsch PetscCall(MatNestFindNonzeroSubMatRow(A,i,&sub)); 162028b400f6SJacob Faibussowitsch PetscCheck(sub,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"No nonzero submatrix in row %" PetscInt_FMT,i); 16219566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(sub,&n,NULL)); 162208401ef6SPierre Jolivet PetscCheck(n >= 0,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Sizes have not yet been set for submatrix"); 16238188e55aSJed Brown nsum += n; 16248188e55aSJed Brown } 16259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scan(&nsum,&offset,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)A))); 162630bc264bSJed Brown offset -= nsum; 1627e2d7f03fSJed Brown for (i=0; i<vs->nr; i++) { 16289566063dSJacob Faibussowitsch PetscCall(MatNestFindNonzeroSubMatRow(A,i,&sub)); 16299566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(sub,&n,NULL)); 16309566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(sub,&bs,NULL)); 16319566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)sub),n,offset,1,&vs->isglobal.row[i])); 16329566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(vs->isglobal.row[i],bs)); 16332ae74bdbSJed Brown offset += n; 1634d8588912SDave May } 1635d8588912SDave May } 1636d8588912SDave May 1637d8588912SDave May if (is_col) { /* valid IS is passed in */ 1638a5b23f4aSJose E. Roman /* refs on is[] are incremented */ 1639e2d7f03fSJed Brown for (j=0; j<vs->nc; j++) { 16409566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is_col[j])); 164126fbe8dcSKarl Rupp 1642e2d7f03fSJed Brown vs->isglobal.col[j] = is_col[j]; 1643d8588912SDave May } 16442ae74bdbSJed Brown } else { /* Create the ISs by inspecting sizes of a submatrix in each column */ 16452ae74bdbSJed Brown offset = A->cmap->rstart; 16468188e55aSJed Brown nsum = 0; 16478188e55aSJed Brown for (j=0; j<vs->nc; j++) { 16489566063dSJacob Faibussowitsch PetscCall(MatNestFindNonzeroSubMatCol(A,j,&sub)); 164928b400f6SJacob Faibussowitsch PetscCheck(sub,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"No nonzero submatrix in column %" PetscInt_FMT,i); 16509566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(sub,NULL,&n)); 165108401ef6SPierre Jolivet PetscCheck(n >= 0,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Sizes have not yet been set for submatrix"); 16528188e55aSJed Brown nsum += n; 16538188e55aSJed Brown } 16549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scan(&nsum,&offset,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)A))); 165530bc264bSJed Brown offset -= nsum; 1656e2d7f03fSJed Brown for (j=0; j<vs->nc; j++) { 16579566063dSJacob Faibussowitsch PetscCall(MatNestFindNonzeroSubMatCol(A,j,&sub)); 16589566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(sub,NULL,&n)); 16599566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(sub,NULL,&bs)); 16609566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)sub),n,offset,1,&vs->isglobal.col[j])); 16619566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(vs->isglobal.col[j],bs)); 16622ae74bdbSJed Brown offset += n; 1663d8588912SDave May } 1664d8588912SDave May } 1665e2d7f03fSJed Brown 1666e2d7f03fSJed Brown /* Set up the local ISs */ 16679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(vs->nr,&vs->islocal.row)); 16689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(vs->nc,&vs->islocal.col)); 1669e2d7f03fSJed Brown for (i=0,offset=0; i<vs->nr; i++) { 1670e2d7f03fSJed Brown IS isloc; 16710298fd71SBarry Smith ISLocalToGlobalMapping rmap = NULL; 1672e2d7f03fSJed Brown PetscInt nlocal,bs; 16739566063dSJacob Faibussowitsch PetscCall(MatNestFindNonzeroSubMatRow(A,i,&sub)); 16749566063dSJacob Faibussowitsch if (sub) PetscCall(MatGetLocalToGlobalMapping(sub,&rmap,NULL)); 1675207556f9SJed Brown if (rmap) { 16769566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(sub,&bs,NULL)); 16779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rmap,&nlocal)); 16789566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc)); 16799566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(isloc,bs)); 1680207556f9SJed Brown } else { 1681207556f9SJed Brown nlocal = 0; 16820298fd71SBarry Smith isloc = NULL; 1683207556f9SJed Brown } 1684e2d7f03fSJed Brown vs->islocal.row[i] = isloc; 1685e2d7f03fSJed Brown offset += nlocal; 1686e2d7f03fSJed Brown } 16878188e55aSJed Brown for (i=0,offset=0; i<vs->nc; i++) { 1688e2d7f03fSJed Brown IS isloc; 16890298fd71SBarry Smith ISLocalToGlobalMapping cmap = NULL; 1690e2d7f03fSJed Brown PetscInt nlocal,bs; 16919566063dSJacob Faibussowitsch PetscCall(MatNestFindNonzeroSubMatCol(A,i,&sub)); 16929566063dSJacob Faibussowitsch if (sub) PetscCall(MatGetLocalToGlobalMapping(sub,NULL,&cmap)); 1693207556f9SJed Brown if (cmap) { 16949566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(sub,NULL,&bs)); 16959566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cmap,&nlocal)); 16969566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc)); 16979566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(isloc,bs)); 1698207556f9SJed Brown } else { 1699207556f9SJed Brown nlocal = 0; 17000298fd71SBarry Smith isloc = NULL; 1701207556f9SJed Brown } 1702e2d7f03fSJed Brown vs->islocal.col[i] = isloc; 1703e2d7f03fSJed Brown offset += nlocal; 1704e2d7f03fSJed Brown } 17050189643fSJed Brown 170677019fcaSJed Brown /* Set up the aggregate ISLocalToGlobalMapping */ 170777019fcaSJed Brown { 170845b6f7e9SBarry Smith ISLocalToGlobalMapping rmap,cmap; 17099566063dSJacob Faibussowitsch PetscCall(MatNestCreateAggregateL2G_Private(A,vs->nr,vs->islocal.row,vs->isglobal.row,PETSC_FALSE,&rmap)); 17109566063dSJacob Faibussowitsch PetscCall(MatNestCreateAggregateL2G_Private(A,vs->nc,vs->islocal.col,vs->isglobal.col,PETSC_TRUE,&cmap)); 17119566063dSJacob Faibussowitsch if (rmap && cmap) PetscCall(MatSetLocalToGlobalMapping(A,rmap,cmap)); 17129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rmap)); 17139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cmap)); 171477019fcaSJed Brown } 171577019fcaSJed Brown 171676bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 17170189643fSJed Brown for (i=0; i<vs->nr; i++) { 17180189643fSJed Brown for (j=0; j<vs->nc; j++) { 17190189643fSJed Brown PetscInt m,n,M,N,mi,ni,Mi,Ni; 17200189643fSJed Brown Mat B = vs->m[i][j]; 17210189643fSJed Brown if (!B) continue; 17229566063dSJacob Faibussowitsch PetscCall(MatGetSize(B,&M,&N)); 17239566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(B,&m,&n)); 17249566063dSJacob Faibussowitsch PetscCall(ISGetSize(vs->isglobal.row[i],&Mi)); 17259566063dSJacob Faibussowitsch PetscCall(ISGetSize(vs->isglobal.col[j],&Ni)); 17269566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(vs->isglobal.row[i],&mi)); 17279566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(vs->isglobal.col[j],&ni)); 1728aed4548fSBarry Smith PetscCheck(M == Mi && N == Ni,PetscObjectComm((PetscObject)sub),PETSC_ERR_ARG_INCOMP,"Global sizes (%" PetscInt_FMT ",%" PetscInt_FMT ") of nested submatrix (%" PetscInt_FMT ",%" PetscInt_FMT ") do not agree with space defined by index sets (%" PetscInt_FMT ",%" PetscInt_FMT ")",M,N,i,j,Mi,Ni); 1729aed4548fSBarry Smith PetscCheck(m == mi && n == ni,PetscObjectComm((PetscObject)sub),PETSC_ERR_ARG_INCOMP,"Local sizes (%" PetscInt_FMT ",%" PetscInt_FMT ") of nested submatrix (%" PetscInt_FMT ",%" PetscInt_FMT ") do not agree with space defined by index sets (%" PetscInt_FMT ",%" PetscInt_FMT ")",m,n,i,j,mi,ni); 17300189643fSJed Brown } 17310189643fSJed Brown } 173276bd3646SJed Brown } 1733a061e289SJed Brown 1734a061e289SJed Brown /* Set A->assembled if all non-null blocks are currently assembled */ 1735a061e289SJed Brown for (i=0; i<vs->nr; i++) { 1736a061e289SJed Brown for (j=0; j<vs->nc; j++) { 1737a061e289SJed Brown if (vs->m[i][j] && !vs->m[i][j]->assembled) PetscFunctionReturn(0); 1738a061e289SJed Brown } 1739a061e289SJed Brown } 1740a061e289SJed Brown A->assembled = PETSC_TRUE; 1741d8588912SDave May PetscFunctionReturn(0); 1742d8588912SDave May } 1743d8588912SDave May 174445c38901SJed Brown /*@C 1745659c6bb0SJed Brown MatCreateNest - Creates a new matrix containing several nested submatrices, each stored separately 1746659c6bb0SJed Brown 1747659c6bb0SJed Brown Collective on Mat 1748659c6bb0SJed Brown 1749d8d19677SJose E. Roman Input Parameters: 1750659c6bb0SJed Brown + comm - Communicator for the new Mat 1751659c6bb0SJed Brown . nr - number of nested row blocks 17520298fd71SBarry Smith . is_row - index sets for each nested row block, or NULL to make contiguous 1753659c6bb0SJed Brown . nc - number of nested column blocks 17540298fd71SBarry Smith . is_col - index sets for each nested column block, or NULL to make contiguous 17550298fd71SBarry Smith - a - row-aligned array of nr*nc submatrices, empty submatrices can be passed using NULL 1756659c6bb0SJed Brown 1757659c6bb0SJed Brown Output Parameter: 1758659c6bb0SJed Brown . B - new matrix 1759659c6bb0SJed Brown 1760659c6bb0SJed Brown Level: advanced 1761659c6bb0SJed Brown 1762db781477SPatrick Sanan .seealso: `MatCreate()`, `VecCreateNest()`, `DMCreateMatrix()`, `MATNEST`, `MatNestSetSubMat()`, 1763db781477SPatrick Sanan `MatNestGetSubMat()`, `MatNestGetLocalISs()`, `MatNestGetSize()`, 1764db781477SPatrick Sanan `MatNestGetISs()`, `MatNestSetSubMats()`, `MatNestGetSubMats()` 1765659c6bb0SJed Brown @*/ 17667087cfbeSBarry Smith PetscErrorCode MatCreateNest(MPI_Comm comm,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[],Mat *B) 1767d8588912SDave May { 1768d8588912SDave May Mat A; 1769d8588912SDave May 1770d8588912SDave May PetscFunctionBegin; 1771f4259b30SLisandro Dalcin *B = NULL; 17729566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,&A)); 17739566063dSJacob Faibussowitsch PetscCall(MatSetType(A,MATNEST)); 177491a28eb3SBarry Smith A->preallocated = PETSC_TRUE; 17759566063dSJacob Faibussowitsch PetscCall(MatNestSetSubMats(A,nr,is_row,nc,is_col,a)); 1776d8588912SDave May *B = A; 1777d8588912SDave May PetscFunctionReturn(0); 1778d8588912SDave May } 1779659c6bb0SJed Brown 1780be705e3aSPierre Jolivet PetscErrorCode MatConvert_Nest_SeqAIJ_fast(Mat A,MatType newtype,MatReuse reuse,Mat *newmat) 1781b68353e5Sstefano_zampini { 1782b68353e5Sstefano_zampini Mat_Nest *nest = (Mat_Nest*)A->data; 178323875855Sstefano_zampini Mat *trans; 1784b68353e5Sstefano_zampini PetscScalar **avv; 1785b68353e5Sstefano_zampini PetscScalar *vv; 1786b68353e5Sstefano_zampini PetscInt **aii,**ajj; 1787b68353e5Sstefano_zampini PetscInt *ii,*jj,*ci; 1788b68353e5Sstefano_zampini PetscInt nr,nc,nnz,i,j; 1789b68353e5Sstefano_zampini PetscBool done; 1790b68353e5Sstefano_zampini 1791b68353e5Sstefano_zampini PetscFunctionBegin; 17929566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&nr,&nc)); 1793b68353e5Sstefano_zampini if (reuse == MAT_REUSE_MATRIX) { 1794b68353e5Sstefano_zampini PetscInt rnr; 1795b68353e5Sstefano_zampini 17969566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(*newmat,0,PETSC_FALSE,PETSC_FALSE,&rnr,(const PetscInt**)&ii,(const PetscInt**)&jj,&done)); 179728b400f6SJacob Faibussowitsch PetscCheck(done,PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"MatGetRowIJ"); 179808401ef6SPierre Jolivet PetscCheck(rnr == nr,PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"Cannot reuse matrix, wrong number of rows"); 17999566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(*newmat,&vv)); 1800b68353e5Sstefano_zampini } 1801b68353e5Sstefano_zampini /* extract CSR for nested SeqAIJ matrices */ 1802b68353e5Sstefano_zampini nnz = 0; 18039566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(nest->nr*nest->nc,&aii,nest->nr*nest->nc,&ajj,nest->nr*nest->nc,&avv,nest->nr*nest->nc,&trans)); 1804b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1805b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1806b68353e5Sstefano_zampini Mat B = nest->m[i][j]; 1807b68353e5Sstefano_zampini if (B) { 1808b68353e5Sstefano_zampini PetscScalar *naa; 1809b68353e5Sstefano_zampini PetscInt *nii,*njj,nnr; 181023875855Sstefano_zampini PetscBool istrans; 1811b68353e5Sstefano_zampini 18129566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&istrans)); 181323875855Sstefano_zampini if (istrans) { 181423875855Sstefano_zampini Mat Bt; 181523875855Sstefano_zampini 18169566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(B,&Bt)); 18179566063dSJacob Faibussowitsch PetscCall(MatTranspose(Bt,MAT_INITIAL_MATRIX,&trans[i*nest->nc+j])); 181823875855Sstefano_zampini B = trans[i*nest->nc+j]; 181923875855Sstefano_zampini } 18209566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(B,0,PETSC_FALSE,PETSC_FALSE,&nnr,(const PetscInt**)&nii,(const PetscInt**)&njj,&done)); 182128b400f6SJacob Faibussowitsch PetscCheck(done,PetscObjectComm((PetscObject)B),PETSC_ERR_PLIB,"MatGetRowIJ"); 18229566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(B,&naa)); 1823b68353e5Sstefano_zampini nnz += nii[nnr]; 1824b68353e5Sstefano_zampini 1825b68353e5Sstefano_zampini aii[i*nest->nc+j] = nii; 1826b68353e5Sstefano_zampini ajj[i*nest->nc+j] = njj; 1827b68353e5Sstefano_zampini avv[i*nest->nc+j] = naa; 1828b68353e5Sstefano_zampini } 1829b68353e5Sstefano_zampini } 1830b68353e5Sstefano_zampini } 1831b68353e5Sstefano_zampini if (reuse != MAT_REUSE_MATRIX) { 18329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nr+1,&ii)); 18339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz,&jj)); 18349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz,&vv)); 1835b68353e5Sstefano_zampini } else { 183608401ef6SPierre Jolivet PetscCheck(nnz == ii[nr],PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"Cannot reuse matrix, wrong number of nonzeros"); 1837b68353e5Sstefano_zampini } 1838b68353e5Sstefano_zampini 1839b68353e5Sstefano_zampini /* new row pointer */ 18409566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ii,nr+1)); 1841b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1842b68353e5Sstefano_zampini PetscInt ncr,rst; 1843b68353e5Sstefano_zampini 18449566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(nest->isglobal.row[i],&rst,NULL)); 18459566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(nest->isglobal.row[i],&ncr)); 1846b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1847b68353e5Sstefano_zampini if (aii[i*nest->nc+j]) { 1848b68353e5Sstefano_zampini PetscInt *nii = aii[i*nest->nc+j]; 1849b68353e5Sstefano_zampini PetscInt ir; 1850b68353e5Sstefano_zampini 1851b68353e5Sstefano_zampini for (ir=rst; ir<ncr+rst; ++ir) { 1852b68353e5Sstefano_zampini ii[ir+1] += nii[1]-nii[0]; 1853b68353e5Sstefano_zampini nii++; 1854b68353e5Sstefano_zampini } 1855b68353e5Sstefano_zampini } 1856b68353e5Sstefano_zampini } 1857b68353e5Sstefano_zampini } 1858b68353e5Sstefano_zampini for (i=0; i<nr; i++) ii[i+1] += ii[i]; 1859b68353e5Sstefano_zampini 1860b68353e5Sstefano_zampini /* construct CSR for the new matrix */ 18619566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nr,&ci)); 1862b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1863b68353e5Sstefano_zampini PetscInt ncr,rst; 1864b68353e5Sstefano_zampini 18659566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(nest->isglobal.row[i],&rst,NULL)); 18669566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(nest->isglobal.row[i],&ncr)); 1867b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1868b68353e5Sstefano_zampini if (aii[i*nest->nc+j]) { 1869b68353e5Sstefano_zampini PetscScalar *nvv = avv[i*nest->nc+j]; 1870b68353e5Sstefano_zampini PetscInt *nii = aii[i*nest->nc+j]; 1871b68353e5Sstefano_zampini PetscInt *njj = ajj[i*nest->nc+j]; 1872b68353e5Sstefano_zampini PetscInt ir,cst; 1873b68353e5Sstefano_zampini 18749566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(nest->isglobal.col[j],&cst,NULL)); 1875b68353e5Sstefano_zampini for (ir=rst; ir<ncr+rst; ++ir) { 1876b68353e5Sstefano_zampini PetscInt ij,rsize = nii[1]-nii[0],ist = ii[ir]+ci[ir]; 1877b68353e5Sstefano_zampini 1878b68353e5Sstefano_zampini for (ij=0;ij<rsize;ij++) { 1879b68353e5Sstefano_zampini jj[ist+ij] = *njj+cst; 1880b68353e5Sstefano_zampini vv[ist+ij] = *nvv; 1881b68353e5Sstefano_zampini njj++; 1882b68353e5Sstefano_zampini nvv++; 1883b68353e5Sstefano_zampini } 1884b68353e5Sstefano_zampini ci[ir] += rsize; 1885b68353e5Sstefano_zampini nii++; 1886b68353e5Sstefano_zampini } 1887b68353e5Sstefano_zampini } 1888b68353e5Sstefano_zampini } 1889b68353e5Sstefano_zampini } 18909566063dSJacob Faibussowitsch PetscCall(PetscFree(ci)); 1891b68353e5Sstefano_zampini 1892b68353e5Sstefano_zampini /* restore info */ 1893b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1894b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1895b68353e5Sstefano_zampini Mat B = nest->m[i][j]; 1896b68353e5Sstefano_zampini if (B) { 1897b68353e5Sstefano_zampini PetscInt nnr = 0, k = i*nest->nc+j; 189823875855Sstefano_zampini 189923875855Sstefano_zampini B = (trans[k] ? trans[k] : B); 19009566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(B,0,PETSC_FALSE,PETSC_FALSE,&nnr,(const PetscInt**)&aii[k],(const PetscInt**)&ajj[k],&done)); 190128b400f6SJacob Faibussowitsch PetscCheck(done,PetscObjectComm((PetscObject)B),PETSC_ERR_PLIB,"MatRestoreRowIJ"); 19029566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(B,&avv[k])); 19039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&trans[k])); 1904b68353e5Sstefano_zampini } 1905b68353e5Sstefano_zampini } 1906b68353e5Sstefano_zampini } 19079566063dSJacob Faibussowitsch PetscCall(PetscFree4(aii,ajj,avv,trans)); 1908b68353e5Sstefano_zampini 1909b68353e5Sstefano_zampini /* finalize newmat */ 1910b68353e5Sstefano_zampini if (reuse == MAT_INITIAL_MATRIX) { 19119566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),nr,nc,ii,jj,vv,newmat)); 1912b68353e5Sstefano_zampini } else if (reuse == MAT_INPLACE_MATRIX) { 1913b68353e5Sstefano_zampini Mat B; 1914b68353e5Sstefano_zampini 19159566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),nr,nc,ii,jj,vv,&B)); 19169566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A,&B)); 1917b68353e5Sstefano_zampini } 19189566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY)); 19199566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY)); 1920b68353e5Sstefano_zampini { 1921b68353e5Sstefano_zampini Mat_SeqAIJ *a = (Mat_SeqAIJ*)((*newmat)->data); 1922b68353e5Sstefano_zampini a->free_a = PETSC_TRUE; 1923b68353e5Sstefano_zampini a->free_ij = PETSC_TRUE; 1924b68353e5Sstefano_zampini } 1925b68353e5Sstefano_zampini PetscFunctionReturn(0); 1926b68353e5Sstefano_zampini } 1927b68353e5Sstefano_zampini 1928be705e3aSPierre Jolivet PETSC_INTERN PetscErrorCode MatAXPY_Dense_Nest(Mat Y,PetscScalar a,Mat X) 1929be705e3aSPierre Jolivet { 1930be705e3aSPierre Jolivet Mat_Nest *nest = (Mat_Nest*)X->data; 1931be705e3aSPierre Jolivet PetscInt i,j,k,rstart; 1932be705e3aSPierre Jolivet PetscBool flg; 1933be705e3aSPierre Jolivet 1934be705e3aSPierre Jolivet PetscFunctionBegin; 1935be705e3aSPierre Jolivet /* Fill by row */ 1936be705e3aSPierre Jolivet for (j=0; j<nest->nc; ++j) { 1937be705e3aSPierre Jolivet /* Using global column indices and ISAllGather() is not scalable. */ 1938be705e3aSPierre Jolivet IS bNis; 1939be705e3aSPierre Jolivet PetscInt bN; 1940be705e3aSPierre Jolivet const PetscInt *bNindices; 19419566063dSJacob Faibussowitsch PetscCall(ISAllGather(nest->isglobal.col[j], &bNis)); 19429566063dSJacob Faibussowitsch PetscCall(ISGetSize(bNis,&bN)); 19439566063dSJacob Faibussowitsch PetscCall(ISGetIndices(bNis,&bNindices)); 1944be705e3aSPierre Jolivet for (i=0; i<nest->nr; ++i) { 1945fd8a7442SPierre Jolivet Mat B=nest->m[i][j],D=NULL; 1946be705e3aSPierre Jolivet PetscInt bm,br; 1947be705e3aSPierre Jolivet const PetscInt *bmindices; 1948be705e3aSPierre Jolivet if (!B) continue; 19499566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&flg)); 1950be705e3aSPierre Jolivet if (flg) { 1951cac4c232SBarry Smith PetscTryMethod(B,"MatTransposeGetMat_C",(Mat,Mat*),(B,&D)); 1952cac4c232SBarry Smith PetscTryMethod(B,"MatHermitianTransposeGetMat_C",(Mat,Mat*),(B,&D)); 19539566063dSJacob Faibussowitsch PetscCall(MatConvert(B,((PetscObject)D)->type_name,MAT_INITIAL_MATRIX,&D)); 1954be705e3aSPierre Jolivet B = D; 1955be705e3aSPierre Jolivet } 19569566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)B,&flg,MATSEQSBAIJ,MATMPISBAIJ,"")); 1957be705e3aSPierre Jolivet if (flg) { 1958fd8a7442SPierre Jolivet if (D) PetscCall(MatConvert(D,MATBAIJ,MAT_INPLACE_MATRIX,&D)); 1959fd8a7442SPierre Jolivet else PetscCall(MatConvert(B,MATBAIJ,MAT_INITIAL_MATRIX,&D)); 1960be705e3aSPierre Jolivet B = D; 1961be705e3aSPierre Jolivet } 19629566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(nest->isglobal.row[i],&bm)); 19639566063dSJacob Faibussowitsch PetscCall(ISGetIndices(nest->isglobal.row[i],&bmindices)); 19649566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B,&rstart,NULL)); 1965be705e3aSPierre Jolivet for (br = 0; br < bm; ++br) { 1966be705e3aSPierre Jolivet PetscInt row = bmindices[br], brncols, *cols; 1967be705e3aSPierre Jolivet const PetscInt *brcols; 1968be705e3aSPierre Jolivet const PetscScalar *brcoldata; 1969be705e3aSPierre Jolivet PetscScalar *vals = NULL; 19709566063dSJacob Faibussowitsch PetscCall(MatGetRow(B,br+rstart,&brncols,&brcols,&brcoldata)); 19719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(brncols,&cols)); 1972be705e3aSPierre Jolivet for (k=0; k<brncols; k++) cols[k] = bNindices[brcols[k]]; 1973be705e3aSPierre Jolivet /* 1974be705e3aSPierre Jolivet Nest blocks are required to be nonoverlapping -- otherwise nest and monolithic index layouts wouldn't match. 1975be705e3aSPierre Jolivet Thus, we could use INSERT_VALUES, but I prefer ADD_VALUES. 1976be705e3aSPierre Jolivet */ 1977be705e3aSPierre Jolivet if (a != 1.0) { 19789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(brncols,&vals)); 1979be705e3aSPierre Jolivet for (k=0; k<brncols; k++) vals[k] = a * brcoldata[k]; 19809566063dSJacob Faibussowitsch PetscCall(MatSetValues(Y,1,&row,brncols,cols,vals,ADD_VALUES)); 19819566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 1982be705e3aSPierre Jolivet } else { 19839566063dSJacob Faibussowitsch PetscCall(MatSetValues(Y,1,&row,brncols,cols,brcoldata,ADD_VALUES)); 1984be705e3aSPierre Jolivet } 19859566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B,br+rstart,&brncols,&brcols,&brcoldata)); 19869566063dSJacob Faibussowitsch PetscCall(PetscFree(cols)); 1987be705e3aSPierre Jolivet } 1988fd8a7442SPierre Jolivet if (D) PetscCall(MatDestroy(&D)); 19899566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(nest->isglobal.row[i],&bmindices)); 1990be705e3aSPierre Jolivet } 19919566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(bNis,&bNindices)); 19929566063dSJacob Faibussowitsch PetscCall(ISDestroy(&bNis)); 1993be705e3aSPierre Jolivet } 19949566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY)); 19959566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY)); 1996be705e3aSPierre Jolivet PetscFunctionReturn(0); 1997be705e3aSPierre Jolivet } 1998be705e3aSPierre Jolivet 1999be705e3aSPierre Jolivet PetscErrorCode MatConvert_Nest_AIJ(Mat A,MatType newtype,MatReuse reuse,Mat *newmat) 2000629c3df2SDmitry Karpeev { 2001629c3df2SDmitry Karpeev Mat_Nest *nest = (Mat_Nest*)A->data; 2002be705e3aSPierre Jolivet PetscInt m,n,M,N,i,j,k,*dnnz,*onnz,rstart,cstart,cend; 2003b68353e5Sstefano_zampini PetscMPIInt size; 2004629c3df2SDmitry Karpeev Mat C; 2005629c3df2SDmitry Karpeev 2006629c3df2SDmitry Karpeev PetscFunctionBegin; 20079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A),&size)); 2008b68353e5Sstefano_zampini if (size == 1) { /* look for a special case with SeqAIJ matrices and strided-1, contiguous, blocks */ 2009b68353e5Sstefano_zampini PetscInt nf; 2010b68353e5Sstefano_zampini PetscBool fast; 2011b68353e5Sstefano_zampini 20129566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(newtype,MATAIJ,&fast)); 2013b68353e5Sstefano_zampini if (!fast) { 20149566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(newtype,MATSEQAIJ,&fast)); 2015b68353e5Sstefano_zampini } 2016b68353e5Sstefano_zampini for (i=0; i<nest->nr && fast; ++i) { 2017b68353e5Sstefano_zampini for (j=0; j<nest->nc && fast; ++j) { 2018b68353e5Sstefano_zampini Mat B = nest->m[i][j]; 2019b68353e5Sstefano_zampini if (B) { 20209566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&fast)); 202123875855Sstefano_zampini if (!fast) { 202223875855Sstefano_zampini PetscBool istrans; 202323875855Sstefano_zampini 20249566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&istrans)); 202523875855Sstefano_zampini if (istrans) { 202623875855Sstefano_zampini Mat Bt; 202723875855Sstefano_zampini 20289566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(B,&Bt)); 20299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)Bt,MATSEQAIJ,&fast)); 203023875855Sstefano_zampini } 2031b68353e5Sstefano_zampini } 2032b68353e5Sstefano_zampini } 2033b68353e5Sstefano_zampini } 2034b68353e5Sstefano_zampini } 2035b68353e5Sstefano_zampini for (i=0, nf=0; i<nest->nr && fast; ++i) { 20369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)nest->isglobal.row[i],ISSTRIDE,&fast)); 2037b68353e5Sstefano_zampini if (fast) { 2038b68353e5Sstefano_zampini PetscInt f,s; 2039b68353e5Sstefano_zampini 20409566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(nest->isglobal.row[i],&f,&s)); 2041b68353e5Sstefano_zampini if (f != nf || s != 1) { fast = PETSC_FALSE; } 2042b68353e5Sstefano_zampini else { 20439566063dSJacob Faibussowitsch PetscCall(ISGetSize(nest->isglobal.row[i],&f)); 2044b68353e5Sstefano_zampini nf += f; 2045b68353e5Sstefano_zampini } 2046b68353e5Sstefano_zampini } 2047b68353e5Sstefano_zampini } 2048b68353e5Sstefano_zampini for (i=0, nf=0; i<nest->nc && fast; ++i) { 20499566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)nest->isglobal.col[i],ISSTRIDE,&fast)); 2050b68353e5Sstefano_zampini if (fast) { 2051b68353e5Sstefano_zampini PetscInt f,s; 2052b68353e5Sstefano_zampini 20539566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(nest->isglobal.col[i],&f,&s)); 2054b68353e5Sstefano_zampini if (f != nf || s != 1) { fast = PETSC_FALSE; } 2055b68353e5Sstefano_zampini else { 20569566063dSJacob Faibussowitsch PetscCall(ISGetSize(nest->isglobal.col[i],&f)); 2057b68353e5Sstefano_zampini nf += f; 2058b68353e5Sstefano_zampini } 2059b68353e5Sstefano_zampini } 2060b68353e5Sstefano_zampini } 2061b68353e5Sstefano_zampini if (fast) { 20629566063dSJacob Faibussowitsch PetscCall(MatConvert_Nest_SeqAIJ_fast(A,newtype,reuse,newmat)); 2063b68353e5Sstefano_zampini PetscFunctionReturn(0); 2064b68353e5Sstefano_zampini } 2065b68353e5Sstefano_zampini } 20669566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&M,&N)); 20679566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A,&m,&n)); 20689566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A,&cstart,&cend)); 2069d1487292SPierre Jolivet if (reuse == MAT_REUSE_MATRIX) C = *newmat; 2070d1487292SPierre Jolivet else { 20719566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),&C)); 20729566063dSJacob Faibussowitsch PetscCall(MatSetType(C,newtype)); 20739566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C,m,n,M,N)); 2074629c3df2SDmitry Karpeev } 20759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2*m,&dnnz)); 2076629c3df2SDmitry Karpeev onnz = dnnz + m; 2077629c3df2SDmitry Karpeev for (k=0; k<m; k++) { 2078629c3df2SDmitry Karpeev dnnz[k] = 0; 2079629c3df2SDmitry Karpeev onnz[k] = 0; 2080629c3df2SDmitry Karpeev } 2081629c3df2SDmitry Karpeev for (j=0; j<nest->nc; ++j) { 2082629c3df2SDmitry Karpeev IS bNis; 2083629c3df2SDmitry Karpeev PetscInt bN; 2084629c3df2SDmitry Karpeev const PetscInt *bNindices; 2085fd8a7442SPierre Jolivet PetscBool flg; 2086629c3df2SDmitry Karpeev /* Using global column indices and ISAllGather() is not scalable. */ 20879566063dSJacob Faibussowitsch PetscCall(ISAllGather(nest->isglobal.col[j], &bNis)); 20889566063dSJacob Faibussowitsch PetscCall(ISGetSize(bNis, &bN)); 20899566063dSJacob Faibussowitsch PetscCall(ISGetIndices(bNis,&bNindices)); 2090629c3df2SDmitry Karpeev for (i=0; i<nest->nr; ++i) { 2091629c3df2SDmitry Karpeev PetscSF bmsf; 2092649b366bSFande Kong PetscSFNode *iremote; 2093fd8a7442SPierre Jolivet Mat B=nest->m[i][j],D=NULL; 2094649b366bSFande Kong PetscInt bm,*sub_dnnz,*sub_onnz,br; 2095629c3df2SDmitry Karpeev const PetscInt *bmindices; 2096629c3df2SDmitry Karpeev if (!B) continue; 20979566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(nest->isglobal.row[i],&bm)); 20989566063dSJacob Faibussowitsch PetscCall(ISGetIndices(nest->isglobal.row[i],&bmindices)); 20999566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)A), &bmsf)); 21009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bm,&iremote)); 21019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bm,&sub_dnnz)); 21029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bm,&sub_onnz)); 2103649b366bSFande Kong for (k = 0; k < bm; ++k) { 2104649b366bSFande Kong sub_dnnz[k] = 0; 2105649b366bSFande Kong sub_onnz[k] = 0; 2106649b366bSFande Kong } 2107fd8a7442SPierre Jolivet PetscCall(PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&flg)); 2108fd8a7442SPierre Jolivet if (flg) { 2109fd8a7442SPierre Jolivet PetscTryMethod(B,"MatTransposeGetMat_C",(Mat,Mat*),(B,&D)); 2110fd8a7442SPierre Jolivet PetscTryMethod(B,"MatHermitianTransposeGetMat_C",(Mat,Mat*),(B,&D)); 2111fd8a7442SPierre Jolivet PetscCall(MatConvert(B,((PetscObject)D)->type_name,MAT_INITIAL_MATRIX,&D)); 2112fd8a7442SPierre Jolivet B = D; 2113fd8a7442SPierre Jolivet } 2114fd8a7442SPierre Jolivet PetscCall(PetscObjectTypeCompareAny((PetscObject)B,&flg,MATSEQSBAIJ,MATMPISBAIJ,"")); 2115fd8a7442SPierre Jolivet if (flg) { 2116fd8a7442SPierre Jolivet if (D) PetscCall(MatConvert(D,MATBAIJ,MAT_INPLACE_MATRIX,&D)); 2117fd8a7442SPierre Jolivet else PetscCall(MatConvert(B,MATBAIJ,MAT_INITIAL_MATRIX,&D)); 2118fd8a7442SPierre Jolivet B = D; 2119fd8a7442SPierre Jolivet } 2120629c3df2SDmitry Karpeev /* 2121629c3df2SDmitry Karpeev Locate the owners for all of the locally-owned global row indices for this row block. 2122629c3df2SDmitry Karpeev These determine the roots of PetscSF used to communicate preallocation data to row owners. 2123629c3df2SDmitry Karpeev The roots correspond to the dnnz and onnz entries; thus, there are two roots per row. 2124629c3df2SDmitry Karpeev */ 21259566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(B,&rstart,NULL)); 2126629c3df2SDmitry Karpeev for (br = 0; br < bm; ++br) { 2127131c27b5Sprj- PetscInt row = bmindices[br], brncols, col; 2128629c3df2SDmitry Karpeev const PetscInt *brcols; 2129a4b3d3acSMatthew G Knepley PetscInt rowrel = 0; /* row's relative index on its owner rank */ 2130131c27b5Sprj- PetscMPIInt rowowner = 0; 21319566063dSJacob Faibussowitsch PetscCall(PetscLayoutFindOwnerIndex(A->rmap,row,&rowowner,&rowrel)); 2132649b366bSFande Kong /* how many roots */ 2133649b366bSFande Kong iremote[br].rank = rowowner; iremote[br].index = rowrel; /* edge from bmdnnz to dnnz */ 2134649b366bSFande Kong /* get nonzero pattern */ 21359566063dSJacob Faibussowitsch PetscCall(MatGetRow(B,br+rstart,&brncols,&brcols,NULL)); 2136629c3df2SDmitry Karpeev for (k=0; k<brncols; k++) { 2137629c3df2SDmitry Karpeev col = bNindices[brcols[k]]; 2138649b366bSFande Kong if (col>=A->cmap->range[rowowner] && col<A->cmap->range[rowowner+1]) { 2139649b366bSFande Kong sub_dnnz[br]++; 2140649b366bSFande Kong } else { 2141649b366bSFande Kong sub_onnz[br]++; 2142649b366bSFande Kong } 2143629c3df2SDmitry Karpeev } 21449566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(B,br+rstart,&brncols,&brcols,NULL)); 2145629c3df2SDmitry Karpeev } 2146fd8a7442SPierre Jolivet if (D) PetscCall(MatDestroy(&D)); 21479566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(nest->isglobal.row[i],&bmindices)); 2148629c3df2SDmitry Karpeev /* bsf will have to take care of disposing of bedges. */ 21499566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(bmsf,m,bm,NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER)); 21509566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(bmsf,MPIU_INT,sub_dnnz,dnnz,MPI_SUM)); 21519566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(bmsf,MPIU_INT,sub_dnnz,dnnz,MPI_SUM)); 21529566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(bmsf,MPIU_INT,sub_onnz,onnz,MPI_SUM)); 21539566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(bmsf,MPIU_INT,sub_onnz,onnz,MPI_SUM)); 21549566063dSJacob Faibussowitsch PetscCall(PetscFree(sub_dnnz)); 21559566063dSJacob Faibussowitsch PetscCall(PetscFree(sub_onnz)); 21569566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&bmsf)); 2157629c3df2SDmitry Karpeev } 21589566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(bNis,&bNindices)); 21599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&bNis)); 216065a4a0a3Sstefano_zampini } 216165a4a0a3Sstefano_zampini /* Resize preallocation if overestimated */ 216265a4a0a3Sstefano_zampini for (i=0;i<m;i++) { 216365a4a0a3Sstefano_zampini dnnz[i] = PetscMin(dnnz[i],A->cmap->n); 216465a4a0a3Sstefano_zampini onnz[i] = PetscMin(onnz[i],A->cmap->N - A->cmap->n); 2165629c3df2SDmitry Karpeev } 21669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(C,0,dnnz)); 21679566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(C,0,dnnz,0,onnz)); 21689566063dSJacob Faibussowitsch PetscCall(PetscFree(dnnz)); 21699566063dSJacob Faibussowitsch PetscCall(MatAXPY_Dense_Nest(C,1.0,A)); 2170d1487292SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) { 21719566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A,&C)); 2172d1487292SPierre Jolivet } else *newmat = C; 2173be705e3aSPierre Jolivet PetscFunctionReturn(0); 2174be705e3aSPierre Jolivet } 2175629c3df2SDmitry Karpeev 2176be705e3aSPierre Jolivet PetscErrorCode MatConvert_Nest_Dense(Mat A,MatType newtype,MatReuse reuse,Mat *newmat) 2177be705e3aSPierre Jolivet { 2178629c3df2SDmitry Karpeev Mat B; 2179be705e3aSPierre Jolivet PetscInt m,n,M,N; 2180be705e3aSPierre Jolivet 2181be705e3aSPierre Jolivet PetscFunctionBegin; 21829566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&M,&N)); 21839566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A,&m,&n)); 2184be705e3aSPierre Jolivet if (reuse == MAT_REUSE_MATRIX) { 2185be705e3aSPierre Jolivet B = *newmat; 21869566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(B)); 2187be705e3aSPierre Jolivet } else { 21889566063dSJacob Faibussowitsch PetscCall(MatCreateDense(PetscObjectComm((PetscObject)A),m,PETSC_DECIDE,M,N,NULL,&B)); 2189629c3df2SDmitry Karpeev } 21909566063dSJacob Faibussowitsch PetscCall(MatAXPY_Dense_Nest(B,1.0,A)); 2191be705e3aSPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) { 21929566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A,&B)); 2193be705e3aSPierre Jolivet } else if (reuse == MAT_INITIAL_MATRIX) *newmat = B; 2194629c3df2SDmitry Karpeev PetscFunctionReturn(0); 2195629c3df2SDmitry Karpeev } 2196629c3df2SDmitry Karpeev 21978b7d3b4bSBarry Smith PetscErrorCode MatHasOperation_Nest(Mat mat,MatOperation op,PetscBool *has) 21988b7d3b4bSBarry Smith { 21998b7d3b4bSBarry Smith Mat_Nest *bA = (Mat_Nest*)mat->data; 22003c6db4c4SPierre Jolivet MatOperation opAdd; 22018b7d3b4bSBarry Smith PetscInt i,j,nr = bA->nr,nc = bA->nc; 22028b7d3b4bSBarry Smith PetscBool flg; 220352c5f739Sprj- PetscFunctionBegin; 22048b7d3b4bSBarry Smith 220552c5f739Sprj- *has = PETSC_FALSE; 22063c6db4c4SPierre Jolivet if (op == MATOP_MULT || op == MATOP_MULT_ADD || op == MATOP_MULT_TRANSPOSE || op == MATOP_MULT_TRANSPOSE_ADD) { 22073c6db4c4SPierre Jolivet opAdd = (op == MATOP_MULT || op == MATOP_MULT_ADD ? MATOP_MULT_ADD : MATOP_MULT_TRANSPOSE_ADD); 22088b7d3b4bSBarry Smith for (j=0; j<nc; j++) { 22098b7d3b4bSBarry Smith for (i=0; i<nr; i++) { 22108b7d3b4bSBarry Smith if (!bA->m[i][j]) continue; 22119566063dSJacob Faibussowitsch PetscCall(MatHasOperation(bA->m[i][j],opAdd,&flg)); 22128b7d3b4bSBarry Smith if (!flg) PetscFunctionReturn(0); 22138b7d3b4bSBarry Smith } 22148b7d3b4bSBarry Smith } 22158b7d3b4bSBarry Smith } 22163c6db4c4SPierre Jolivet if (((void**)mat->ops)[op]) *has = PETSC_TRUE; 22178b7d3b4bSBarry Smith PetscFunctionReturn(0); 22188b7d3b4bSBarry Smith } 22198b7d3b4bSBarry Smith 2220659c6bb0SJed Brown /*MC 2221659c6bb0SJed Brown MATNEST - MATNEST = "nest" - Matrix type consisting of nested submatrices, each stored separately. 2222659c6bb0SJed Brown 2223659c6bb0SJed Brown Level: intermediate 2224659c6bb0SJed Brown 2225659c6bb0SJed Brown Notes: 2226659c6bb0SJed Brown This matrix type permits scalable use of PCFieldSplit and avoids the large memory costs of extracting submatrices. 2227659c6bb0SJed Brown It allows the use of symmetric and block formats for parts of multi-physics simulations. 2228950540a4SJed Brown It is usually used with DMComposite and DMCreateMatrix() 2229659c6bb0SJed Brown 22308b7d3b4bSBarry Smith Each of the submatrices lives on the same MPI communicator as the original nest matrix (though they can have zero 22318b7d3b4bSBarry Smith rows/columns on some processes.) Thus this is not meant for cases where the submatrices live on far fewer processes 22328b7d3b4bSBarry Smith than the nest matrix. 22338b7d3b4bSBarry Smith 2234db781477SPatrick Sanan .seealso: `MatCreate()`, `MatType`, `MatCreateNest()`, `MatNestSetSubMat()`, `MatNestGetSubMat()`, 2235db781477SPatrick Sanan `VecCreateNest()`, `DMCreateMatrix()`, `DMCOMPOSITE`, `MatNestSetVecType()`, `MatNestGetLocalISs()`, 2236db781477SPatrick Sanan `MatNestGetISs()`, `MatNestSetSubMats()`, `MatNestGetSubMats()` 2237659c6bb0SJed Brown M*/ 22388cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_Nest(Mat A) 2239c8883902SJed Brown { 2240c8883902SJed Brown Mat_Nest *s; 2241c8883902SJed Brown 2242c8883902SJed Brown PetscFunctionBegin; 22439566063dSJacob Faibussowitsch PetscCall(PetscNewLog(A,&s)); 2244c8883902SJed Brown A->data = (void*)s; 2245e7c19651SJed Brown 2246e7c19651SJed Brown s->nr = -1; 2247e7c19651SJed Brown s->nc = -1; 22480298fd71SBarry Smith s->m = NULL; 2249e7c19651SJed Brown s->splitassembly = PETSC_FALSE; 2250c8883902SJed Brown 22519566063dSJacob Faibussowitsch PetscCall(PetscMemzero(A->ops,sizeof(*A->ops))); 225226fbe8dcSKarl Rupp 2253c8883902SJed Brown A->ops->mult = MatMult_Nest; 22549194d70fSJed Brown A->ops->multadd = MatMultAdd_Nest; 2255c8883902SJed Brown A->ops->multtranspose = MatMultTranspose_Nest; 22569194d70fSJed Brown A->ops->multtransposeadd = MatMultTransposeAdd_Nest; 2257f8170845SAlex Fikl A->ops->transpose = MatTranspose_Nest; 2258c8883902SJed Brown A->ops->assemblybegin = MatAssemblyBegin_Nest; 2259c8883902SJed Brown A->ops->assemblyend = MatAssemblyEnd_Nest; 2260c8883902SJed Brown A->ops->zeroentries = MatZeroEntries_Nest; 2261c222c20dSDavid Ham A->ops->copy = MatCopy_Nest; 22626e76ffeaSPierre Jolivet A->ops->axpy = MatAXPY_Nest; 2263c8883902SJed Brown A->ops->duplicate = MatDuplicate_Nest; 22647dae84e0SHong Zhang A->ops->createsubmatrix = MatCreateSubMatrix_Nest; 2265c8883902SJed Brown A->ops->destroy = MatDestroy_Nest; 2266c8883902SJed Brown A->ops->view = MatView_Nest; 2267f4259b30SLisandro Dalcin A->ops->getvecs = NULL; /* Use VECNEST by calling MatNestSetVecType(A,VECNEST) */ 2268c8883902SJed Brown A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_Nest; 2269c8883902SJed Brown A->ops->restorelocalsubmatrix = MatRestoreLocalSubMatrix_Nest; 2270429bac76SJed Brown A->ops->getdiagonal = MatGetDiagonal_Nest; 2271429bac76SJed Brown A->ops->diagonalscale = MatDiagonalScale_Nest; 2272a061e289SJed Brown A->ops->scale = MatScale_Nest; 2273a061e289SJed Brown A->ops->shift = MatShift_Nest; 227413135bc6SAlex Fikl A->ops->diagonalset = MatDiagonalSet_Nest; 2275f8170845SAlex Fikl A->ops->setrandom = MatSetRandom_Nest; 22768b7d3b4bSBarry Smith A->ops->hasoperation = MatHasOperation_Nest; 2277381b8e50SStefano Zampini A->ops->missingdiagonal = MatMissingDiagonal_Nest; 2278c8883902SJed Brown 2279f4259b30SLisandro Dalcin A->spptr = NULL; 2280c8883902SJed Brown A->assembled = PETSC_FALSE; 2281c8883902SJed Brown 2282c8883902SJed Brown /* expose Nest api's */ 22839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMat_C", MatNestGetSubMat_Nest)); 22849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMat_C", MatNestSetSubMat_Nest)); 22859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMats_C", MatNestGetSubMats_Nest)); 22869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatNestGetSize_C", MatNestGetSize_Nest)); 22879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatNestGetISs_C", MatNestGetISs_Nest)); 22889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatNestGetLocalISs_C", MatNestGetLocalISs_Nest)); 22899566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatNestSetVecType_C", MatNestSetVecType_Nest)); 22909566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMats_C", MatNestSetSubMats_Nest)); 22919566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_mpiaij_C", MatConvert_Nest_AIJ)); 22929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_seqaij_C", MatConvert_Nest_AIJ)); 22939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_aij_C", MatConvert_Nest_AIJ)); 22949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_is_C", MatConvert_Nest_IS)); 22959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_mpidense_C",MatConvert_Nest_Dense)); 22969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_seqdense_C",MatConvert_Nest_Dense)); 22979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_nest_seqdense_C",MatProductSetFromOptions_Nest_Dense)); 22989566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_nest_mpidense_C",MatProductSetFromOptions_Nest_Dense)); 22999566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_nest_dense_C",MatProductSetFromOptions_Nest_Dense)); 2300c8883902SJed Brown 23019566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A,MATNEST)); 2302c8883902SJed Brown PetscFunctionReturn(0); 2303c8883902SJed Brown } 2304