10da83c2eSBarry Smith 20da83c2eSBarry Smith /* 30da83c2eSBarry Smith Include files needed for the variable size block PBJacobi preconditioner: 40da83c2eSBarry Smith pcimpl.h - private include file intended for use by all preconditioners 50da83c2eSBarry Smith */ 60da83c2eSBarry Smith 70da83c2eSBarry Smith #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/ 80da83c2eSBarry Smith 90da83c2eSBarry Smith /* 100da83c2eSBarry Smith Private context (data structure) for the VPBJacobi preconditioner. 110da83c2eSBarry Smith */ 120da83c2eSBarry Smith typedef struct { 130da83c2eSBarry Smith MatScalar *diag; 140da83c2eSBarry Smith } PC_VPBJacobi; 150da83c2eSBarry Smith 160da83c2eSBarry Smith 170da83c2eSBarry Smith static PetscErrorCode PCApply_VPBJacobi(PC pc,Vec x,Vec y) 180da83c2eSBarry Smith { 190da83c2eSBarry Smith PC_VPBJacobi *jac = (PC_VPBJacobi*)pc->data; 200da83c2eSBarry Smith PetscErrorCode ierr; 210da83c2eSBarry Smith PetscInt i,ncnt = 0; 220da83c2eSBarry Smith const MatScalar *diag = jac->diag; 230da83c2eSBarry Smith PetscInt ib,jb,bs; 240da83c2eSBarry Smith const PetscScalar *xx; 250da83c2eSBarry Smith PetscScalar *yy,x0,x1,x2,x3,x4,x5,x6; 260da83c2eSBarry Smith PetscInt nblocks; 270da83c2eSBarry Smith const PetscInt *bsizes; 280da83c2eSBarry Smith 290da83c2eSBarry Smith PetscFunctionBegin; 300da83c2eSBarry Smith ierr = MatGetVariableBlockSizes(pc->pmat,&nblocks,&bsizes);CHKERRQ(ierr); 310da83c2eSBarry Smith ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr); 320da83c2eSBarry Smith ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 330da83c2eSBarry Smith for (i=0; i<nblocks; i++) { 340da83c2eSBarry Smith bs = bsizes[i]; 350da83c2eSBarry Smith switch (bs) { 360da83c2eSBarry Smith case 1: 370da83c2eSBarry Smith yy[ncnt] = *diag*xx[ncnt]; 380da83c2eSBarry Smith break; 390da83c2eSBarry Smith case 2: 400da83c2eSBarry Smith x0 = xx[ncnt]; x1 = xx[ncnt+1]; 410da83c2eSBarry Smith yy[ncnt] = diag[0]*x0 + diag[2]*x1; 420da83c2eSBarry Smith yy[ncnt+1] = diag[1]*x0 + diag[3]*x1; 430da83c2eSBarry Smith break; 440da83c2eSBarry Smith case 3: 450da83c2eSBarry Smith x0 = xx[ncnt]; x1 = xx[ncnt+1]; x2 = xx[ncnt+2]; 460da83c2eSBarry Smith yy[ncnt] = diag[0]*x0 + diag[3]*x1 + diag[6]*x2; 470da83c2eSBarry Smith yy[ncnt+1] = diag[1]*x0 + diag[4]*x1 + diag[7]*x2; 480da83c2eSBarry Smith yy[ncnt+2] = diag[2]*x0 + diag[5]*x1 + diag[8]*x2; 490da83c2eSBarry Smith break; 500da83c2eSBarry Smith case 4: 510da83c2eSBarry Smith x0 = xx[ncnt]; x1 = xx[ncnt+1]; x2 = xx[ncnt+2]; x3 = xx[ncnt+3]; 520da83c2eSBarry Smith yy[ncnt] = diag[0]*x0 + diag[4]*x1 + diag[8]*x2 + diag[12]*x3; 530da83c2eSBarry Smith yy[ncnt+1] = diag[1]*x0 + diag[5]*x1 + diag[9]*x2 + diag[13]*x3; 540da83c2eSBarry Smith yy[ncnt+2] = diag[2]*x0 + diag[6]*x1 + diag[10]*x2 + diag[14]*x3; 550da83c2eSBarry Smith yy[ncnt+3] = diag[3]*x0 + diag[7]*x1 + diag[11]*x2 + diag[15]*x3; 560da83c2eSBarry Smith break; 570da83c2eSBarry Smith case 5: 580da83c2eSBarry Smith x0 = xx[ncnt]; x1 = xx[ncnt+1]; x2 = xx[ncnt+2]; x3 = xx[ncnt+3]; x4 = xx[ncnt+4]; 590da83c2eSBarry Smith yy[ncnt] = diag[0]*x0 + diag[5]*x1 + diag[10]*x2 + diag[15]*x3 + diag[20]*x4; 600da83c2eSBarry Smith yy[ncnt+1] = diag[1]*x0 + diag[6]*x1 + diag[11]*x2 + diag[16]*x3 + diag[21]*x4; 610da83c2eSBarry Smith yy[ncnt+2] = diag[2]*x0 + diag[7]*x1 + diag[12]*x2 + diag[17]*x3 + diag[22]*x4; 620da83c2eSBarry Smith yy[ncnt+3] = diag[3]*x0 + diag[8]*x1 + diag[13]*x2 + diag[18]*x3 + diag[23]*x4; 630da83c2eSBarry Smith yy[ncnt+4] = diag[4]*x0 + diag[9]*x1 + diag[14]*x2 + diag[19]*x3 + diag[24]*x4; 640da83c2eSBarry Smith break; 650da83c2eSBarry Smith case 6: 660da83c2eSBarry Smith x0 = xx[ncnt]; x1 = xx[ncnt+1]; x2 = xx[ncnt+2]; x3 = xx[ncnt+3]; x4 = xx[ncnt+4]; x5 = xx[ncnt+5]; 670da83c2eSBarry Smith yy[ncnt] = diag[0]*x0 + diag[6]*x1 + diag[12]*x2 + diag[18]*x3 + diag[24]*x4 + diag[30]*x5; 680da83c2eSBarry Smith yy[ncnt+1] = diag[1]*x0 + diag[7]*x1 + diag[13]*x2 + diag[19]*x3 + diag[25]*x4 + diag[31]*x5; 690da83c2eSBarry Smith yy[ncnt+2] = diag[2]*x0 + diag[8]*x1 + diag[14]*x2 + diag[20]*x3 + diag[26]*x4 + diag[32]*x5; 700da83c2eSBarry Smith yy[ncnt+3] = diag[3]*x0 + diag[9]*x1 + diag[15]*x2 + diag[21]*x3 + diag[27]*x4 + diag[33]*x5; 710da83c2eSBarry Smith yy[ncnt+4] = diag[4]*x0 + diag[10]*x1 + diag[16]*x2 + diag[22]*x3 + diag[28]*x4 + diag[34]*x5; 720da83c2eSBarry Smith yy[ncnt+5] = diag[5]*x0 + diag[11]*x1 + diag[17]*x2 + diag[23]*x3 + diag[29]*x4 + diag[35]*x5; 730da83c2eSBarry Smith break; 740da83c2eSBarry Smith case 7: 750da83c2eSBarry Smith x0 = xx[ncnt]; x1 = xx[ncnt+1]; x2 = xx[ncnt+2]; x3 = xx[ncnt+3]; x4 = xx[ncnt+4]; x5 = xx[ncnt+5]; x6 = xx[ncnt+6]; 760da83c2eSBarry Smith yy[ncnt] = diag[0]*x0 + diag[7]*x1 + diag[14]*x2 + diag[21]*x3 + diag[28]*x4 + diag[35]*x5 + diag[42]*x6; 770da83c2eSBarry Smith yy[ncnt+1] = diag[1]*x0 + diag[8]*x1 + diag[15]*x2 + diag[22]*x3 + diag[29]*x4 + diag[36]*x5 + diag[43]*x6; 780da83c2eSBarry Smith yy[ncnt+2] = diag[2]*x0 + diag[9]*x1 + diag[16]*x2 + diag[23]*x3 + diag[30]*x4 + diag[37]*x5 + diag[44]*x6; 790da83c2eSBarry Smith yy[ncnt+3] = diag[3]*x0 + diag[10]*x1 + diag[17]*x2 + diag[24]*x3 + diag[31]*x4 + diag[38]*x5 + diag[45]*x6; 800da83c2eSBarry Smith yy[ncnt+4] = diag[4]*x0 + diag[11]*x1 + diag[18]*x2 + diag[25]*x3 + diag[32]*x4 + diag[39]*x5 + diag[46]*x6; 810da83c2eSBarry Smith yy[ncnt+5] = diag[5]*x0 + diag[12]*x1 + diag[19]*x2 + diag[26]*x3 + diag[33]*x4 + diag[40]*x5 + diag[47]*x6; 820da83c2eSBarry Smith yy[ncnt+6] = diag[6]*x0 + diag[13]*x1 + diag[20]*x2 + diag[27]*x3 + diag[34]*x4 + diag[41]*x5 + diag[48]*x6; 830da83c2eSBarry Smith break; 840da83c2eSBarry Smith default: 850da83c2eSBarry Smith for (ib=0; ib<bs; ib++){ 860da83c2eSBarry Smith PetscScalar rowsum = 0; 870da83c2eSBarry Smith for (jb=0; jb<bs; jb++){ 880da83c2eSBarry Smith rowsum += diag[ib+jb*bs] * xx[ncnt+jb]; 890da83c2eSBarry Smith } 900da83c2eSBarry Smith yy[ncnt+ib] = rowsum; 910da83c2eSBarry Smith } 920da83c2eSBarry Smith } 930da83c2eSBarry Smith ncnt += bsizes[i]; 940da83c2eSBarry Smith diag += bsizes[i]*bsizes[i]; 950da83c2eSBarry Smith } 960da83c2eSBarry Smith ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr); 970da83c2eSBarry Smith ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 980da83c2eSBarry Smith PetscFunctionReturn(0); 990da83c2eSBarry Smith } 1000da83c2eSBarry Smith 1010da83c2eSBarry Smith 1020da83c2eSBarry Smith 1030da83c2eSBarry Smith /* -------------------------------------------------------------------------- */ 1040da83c2eSBarry Smith static PetscErrorCode PCSetUp_VPBJacobi(PC pc) 1050da83c2eSBarry Smith { 1060da83c2eSBarry Smith PC_VPBJacobi *jac = (PC_VPBJacobi*)pc->data; 1070da83c2eSBarry Smith PetscErrorCode ierr; 1080da83c2eSBarry Smith Mat A = pc->pmat; 1090da83c2eSBarry Smith MatFactorError err; 1100da83c2eSBarry Smith PetscInt i,nsize = 0,nlocal; 1110da83c2eSBarry Smith PetscInt nblocks; 1120da83c2eSBarry Smith const PetscInt *bsizes; 1130da83c2eSBarry Smith 1140da83c2eSBarry Smith PetscFunctionBegin; 1150da83c2eSBarry Smith ierr = MatGetVariableBlockSizes(pc->pmat,&nblocks,&bsizes);CHKERRQ(ierr); 1160da83c2eSBarry Smith ierr = MatGetLocalSize(pc->pmat,&nlocal,NULL);CHKERRQ(ierr); 1170da83c2eSBarry Smith if (nlocal && !nblocks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call MatSetVariableBlockSizes() before using PCVPBJACOBI"); 1180da83c2eSBarry Smith if (!jac->diag) { 1190da83c2eSBarry Smith for (i=0; i<nblocks; i++) nsize += bsizes[i]*bsizes[i]; 1200da83c2eSBarry Smith ierr = PetscMalloc1(nsize,&jac->diag);CHKERRQ(ierr); 1210da83c2eSBarry Smith } 1220da83c2eSBarry Smith ierr = MatInvertVariableBlockDiagonal(A,nblocks,bsizes,jac->diag);CHKERRQ(ierr); 1230da83c2eSBarry Smith ierr = MatFactorGetError(A,&err);CHKERRQ(ierr); 1240da83c2eSBarry Smith if (err) pc->failedreason = (PCFailedReason)err; 1250da83c2eSBarry Smith pc->ops->apply = PCApply_VPBJacobi; 1260da83c2eSBarry Smith PetscFunctionReturn(0); 1270da83c2eSBarry Smith } 1280da83c2eSBarry Smith /* -------------------------------------------------------------------------- */ 1290da83c2eSBarry Smith static PetscErrorCode PCDestroy_VPBJacobi(PC pc) 1300da83c2eSBarry Smith { 1310da83c2eSBarry Smith PC_VPBJacobi *jac = (PC_VPBJacobi*)pc->data; 1320da83c2eSBarry Smith PetscErrorCode ierr; 1330da83c2eSBarry Smith 1340da83c2eSBarry Smith PetscFunctionBegin; 1350da83c2eSBarry Smith /* 1360da83c2eSBarry Smith Free the private data structure that was hanging off the PC 1370da83c2eSBarry Smith */ 1380da83c2eSBarry Smith ierr = PetscFree(jac->diag);CHKERRQ(ierr); 1390da83c2eSBarry Smith ierr = PetscFree(pc->data);CHKERRQ(ierr); 1400da83c2eSBarry Smith PetscFunctionReturn(0); 1410da83c2eSBarry Smith } 1420da83c2eSBarry Smith 1430da83c2eSBarry Smith /* -------------------------------------------------------------------------- */ 1440da83c2eSBarry Smith /*MC 1450da83c2eSBarry Smith PCVPBJACOBI - Variable size point block Jacobi preconditioner 1460da83c2eSBarry Smith 1470da83c2eSBarry Smith 1480da83c2eSBarry Smith Notes: 1490da83c2eSBarry Smith See PCJACOBI for point Jacobi preconditioning, PCPBJACOBI for fixed point block size, and PCBJACOBI for large size blocks 1500da83c2eSBarry Smith 1510da83c2eSBarry Smith This works for AIJ matrices 1520da83c2eSBarry Smith 1530da83c2eSBarry Smith Uses dense LU factorization with partial pivoting to invert the blocks; if a zero pivot 1540da83c2eSBarry Smith is detected a PETSc error is generated. 1550da83c2eSBarry Smith 1560da83c2eSBarry Smith One must call MatSetVariableBlockSizes() to use this preconditioner 1570da83c2eSBarry Smith Developer Notes: 1580da83c2eSBarry Smith This should support the PCSetErrorIfFailure() flag set to PETSC_TRUE to allow 1590da83c2eSBarry Smith the factorization to continue even after a zero pivot is found resulting in a Nan and hence 1600da83c2eSBarry Smith terminating KSP with a KSP_DIVERGED_NANORIF allowing 1610da83c2eSBarry Smith a nonlinear solver/ODE integrator to recover without stopping the program as currently happens. 1620da83c2eSBarry Smith 1630da83c2eSBarry Smith Perhaps should provide an option that allows generation of a valid preconditioner 1640da83c2eSBarry Smith even if a block is singular as the PCJACOBI does. 1650da83c2eSBarry Smith 1660da83c2eSBarry Smith Level: beginner 1670da83c2eSBarry Smith 1680da83c2eSBarry Smith .seealso: MatSetVariableBlockSizes(), PCCreate(), PCSetType(), PCType (for list of available types), PC, PCJACOBI 1690da83c2eSBarry Smith 1700da83c2eSBarry Smith M*/ 1710da83c2eSBarry Smith 1720da83c2eSBarry Smith PETSC_EXTERN PetscErrorCode PCCreate_VPBJacobi(PC pc) 1730da83c2eSBarry Smith { 1740da83c2eSBarry Smith PC_VPBJacobi *jac; 1750da83c2eSBarry Smith PetscErrorCode ierr; 1760da83c2eSBarry Smith 1770da83c2eSBarry Smith PetscFunctionBegin; 1780da83c2eSBarry Smith /* 1790da83c2eSBarry Smith Creates the private data structure for this preconditioner and 1800da83c2eSBarry Smith attach it to the PC object. 1810da83c2eSBarry Smith */ 1820da83c2eSBarry Smith ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr); 1830da83c2eSBarry Smith pc->data = (void*)jac; 1840da83c2eSBarry Smith 1850da83c2eSBarry Smith /* 1860da83c2eSBarry Smith Initialize the pointers to vectors to ZERO; these will be used to store 1870da83c2eSBarry Smith diagonal entries of the matrix for fast preconditioner application. 1880da83c2eSBarry Smith */ 1890da83c2eSBarry Smith jac->diag = NULL; 1900da83c2eSBarry Smith 1910da83c2eSBarry Smith /* 1920da83c2eSBarry Smith Set the pointers for the functions that are provided above. 1930da83c2eSBarry Smith Now when the user-level routines (such as PCApply(), PCDestroy(), etc.) 1940da83c2eSBarry Smith are called, they will automatically call these functions. Note we 1950da83c2eSBarry Smith choose not to provide a couple of these functions since they are 1960da83c2eSBarry Smith not needed. 1970da83c2eSBarry Smith */ 1980da83c2eSBarry Smith pc->ops->apply = PCApply_VPBJacobi; 199*0a545947SLisandro Dalcin pc->ops->applytranspose = NULL; 2000da83c2eSBarry Smith pc->ops->setup = PCSetUp_VPBJacobi; 2010da83c2eSBarry Smith pc->ops->destroy = PCDestroy_VPBJacobi; 202*0a545947SLisandro Dalcin pc->ops->setfromoptions = NULL; 203*0a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 204*0a545947SLisandro Dalcin pc->ops->applysymmetricleft = NULL; 205*0a545947SLisandro Dalcin pc->ops->applysymmetricright = NULL; 2060da83c2eSBarry Smith PetscFunctionReturn(0); 2070da83c2eSBarry Smith } 2080da83c2eSBarry Smith 2090da83c2eSBarry Smith 210