static PetscErrorCode PCPreSolve_Eisenstat(PC pc,KSP ksp,Vec b,Vec x) { PC_Eisenstat *eis = (PC_Eisenstat*)pc->data; PetscBool nonzero; PetscErrorCode ierr; PetscFunctionBegin; if (pc->presolvedone < 2) { if (pc->mat != pc->pmat) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Cannot have different mat and pmat"); /* swap shell matrix and true matrix */ eis->A = pc->mat; pc->mat = eis->shell; } if (!eis->b[pc->presolvedone-1]) { ierr = VecDuplicate(b,&eis->b[pc->presolvedone-1]);CHKERRQ(ierr); ierr = PetscLogObjectParent(pc,eis->b[pc->presolvedone-1]);CHKERRQ(ierr); } /* if nonzero initial guess, modify x */ ierr = KSPGetInitialGuessNonzero(ksp,&nonzero);CHKERRQ(ierr); if (nonzero) { ierr = VecCopy(x,eis->b[pc->presolvedone-1]);CHKERRQ(ierr); ierr = MatSOR(eis->A,eis->b[pc->presolvedone-1],eis->omega,SOR_APPLY_UPPER,0.0,1,1,x);CHKERRQ(ierr); } /* save true b, other option is to swap pointers */ ierr = VecCopy(b,eis->b[pc->presolvedone-1]);CHKERRQ(ierr); /* modify b by (L + D/omega)^{-1} */ ierr = MatSOR(eis->A,eis->b[pc->presolvedone-1],eis->omega,(MatSORType)(SOR_ZERO_INITIAL_GUESS | SOR_LOCAL_FORWARD_SWEEP),0.0,1,1,b);CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc,char **args) { Mat C; Vec u,x,b,e; PetscInt i,n = 10,midx[3]; PetscErrorCode ierr; PetscScalar v[3]; PetscReal omega = 1.0,norm; PetscInitialize(&argc,&args,(char*)0,help); ierr = PetscOptionsGetReal(NULL,"-omega",&omega,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,"-n",&n,NULL);CHKERRQ(ierr); ierr = MatCreate(PETSC_COMM_SELF,&C);CHKERRQ(ierr); ierr = MatSetSizes(C,n,n,n,n);CHKERRQ(ierr); ierr = MatSetType(C,MATSEQDENSE);CHKERRQ(ierr); ierr = MatSetUp(C);CHKERRQ(ierr); ierr = VecCreateSeq(PETSC_COMM_SELF,n,&b);CHKERRQ(ierr); ierr = VecCreateSeq(PETSC_COMM_SELF,n,&x);CHKERRQ(ierr); ierr = VecCreateSeq(PETSC_COMM_SELF,n,&u);CHKERRQ(ierr); ierr = VecCreateSeq(PETSC_COMM_SELF,n,&e);CHKERRQ(ierr); ierr = VecSet(u,1.0);CHKERRQ(ierr); ierr = VecSet(x,0.0);CHKERRQ(ierr); v[0] = -1.; v[1] = 2.; v[2] = -1.; for (i=1; i<n-1; i++) { midx[0] = i-1; midx[1] = i; midx[2] = i+1; ierr = MatSetValues(C,1,&i,3,midx,v,INSERT_VALUES);CHKERRQ(ierr); } i = 0; midx[0] = 0; midx[1] = 1; v[0] = 2.0; v[1] = -1.; ierr = MatSetValues(C,1,&i,2,midx,v,INSERT_VALUES);CHKERRQ(ierr); i = n-1; midx[0] = n-2; midx[1] = n-1; v[0] = -1.0; v[1] = 2.; ierr = MatSetValues(C,1,&i,2,midx,v,INSERT_VALUES);CHKERRQ(ierr); ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatMult(C,u,b);CHKERRQ(ierr); for (i=0; i<n; i++) { ierr = MatSOR(C,b,omega,SOR_FORWARD_SWEEP,0.0,1,1,x);CHKERRQ(ierr); ierr = VecWAXPY(e,-1.0,x,u);CHKERRQ(ierr); ierr = VecNorm(e,NORM_2,&norm);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_SELF,"2-norm of error %g\n",(double)norm);CHKERRQ(ierr); } ierr = MatDestroy(&C);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = VecDestroy(&e);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
static PetscErrorCode PCMult_Eisenstat(Mat mat,Vec b,Vec x) { PetscErrorCode ierr; PC pc; PC_Eisenstat *eis; PetscFunctionBegin; ierr = MatShellGetContext(mat,(void **)&pc);CHKERRQ(ierr); eis = (PC_Eisenstat*)pc->data; ierr = MatSOR(eis->A,b,eis->omega,SOR_EISENSTAT,0.0,1,1,x);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode PCPostSolve_Eisenstat(PC pc,KSP ksp,Vec b,Vec x) { PC_Eisenstat *eis = (PC_Eisenstat*)pc->data; PetscErrorCode ierr; PetscFunctionBegin; /* modify x by (U + D/omega)^{-1} */ ierr = MatSOR(eis->A,x,eis->omega,(MatSORType)(SOR_ZERO_INITIAL_GUESS | SOR_LOCAL_BACKWARD_SWEEP),0.0,1,1,x);CHKERRQ(ierr); pc->mat = eis->A; /* get back true b */ ierr = VecCopy(eis->b,b);CHKERRQ(ierr); PetscFunctionReturn(0); }