153022affSStefano Zampini #include <petsc/private/pcimpl.h> 253022affSStefano Zampini #include <petsc/private/matimpl.h> 353022affSStefano Zampini #include <h2opusconf.h> 453022affSStefano Zampini 553022affSStefano Zampini /* Use GPU only if H2OPUS is configured for GPU */ 653022affSStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(H2OPUS_USE_GPU) 753022affSStefano Zampini #define PETSC_H2OPUS_USE_GPU 853022affSStefano Zampini #endif 953022affSStefano Zampini 1053022affSStefano Zampini typedef struct { 1153022affSStefano Zampini Mat A; 1253022affSStefano Zampini Mat M; 1353022affSStefano Zampini PetscScalar s0; 1453022affSStefano Zampini 1553022affSStefano Zampini /* sampler for Newton-Schultz */ 1653022affSStefano Zampini Mat S; 1753022affSStefano Zampini PetscInt hyperorder; 1853022affSStefano Zampini Vec wns[4]; 1953022affSStefano Zampini Mat wnsmat[4]; 2053022affSStefano Zampini 2153022affSStefano Zampini /* convergence testing */ 2253022affSStefano Zampini Mat T; 2353022affSStefano Zampini Vec w; 2453022affSStefano Zampini PetscBool testMA; 2553022affSStefano Zampini 2653022affSStefano Zampini /* Support for PCSetCoordinates */ 2753022affSStefano Zampini PetscInt sdim; 2853022affSStefano Zampini PetscInt nlocc; 2953022affSStefano Zampini PetscReal *coords; 3053022affSStefano Zampini 3153022affSStefano Zampini /* Newton-Schultz customization */ 3253022affSStefano Zampini PetscInt maxits; 3353022affSStefano Zampini PetscReal rtol,atol; 3453022affSStefano Zampini PetscBool monitor; 3553022affSStefano Zampini PetscBool useapproximatenorms; 3653022affSStefano Zampini NormType normtype; 3753022affSStefano Zampini 3853022affSStefano Zampini /* Used when pmat != MATH2OPUS */ 3953022affSStefano Zampini PetscReal eta; 4053022affSStefano Zampini PetscInt leafsize; 4153022affSStefano Zampini PetscInt max_rank; 4253022affSStefano Zampini PetscInt bs; 4353022affSStefano Zampini PetscReal mrtol; 4453022affSStefano Zampini 4553022affSStefano Zampini PetscBool boundtocpu; 4653022affSStefano Zampini } PC_H2OPUS; 4753022affSStefano Zampini 4853022affSStefano Zampini PETSC_EXTERN PetscErrorCode MatNorm_H2OPUS(Mat,NormType,PetscReal*); 4953022affSStefano Zampini 5053022affSStefano Zampini static PetscErrorCode PCReset_H2OPUS(PC pc) 5153022affSStefano Zampini { 5253022affSStefano Zampini PC_H2OPUS *pch2opus = (PC_H2OPUS*)pc->data; 5353022affSStefano Zampini 5453022affSStefano Zampini PetscFunctionBegin; 5553022affSStefano Zampini pch2opus->sdim = 0; 5653022affSStefano Zampini pch2opus->nlocc = 0; 57*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pch2opus->coords)); 58*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->A)); 59*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->M)); 60*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->T)); 61*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pch2opus->w)); 62*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->S)); 63*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pch2opus->wns[0])); 64*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pch2opus->wns[1])); 65*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pch2opus->wns[2])); 66*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pch2opus->wns[3])); 67*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->wnsmat[0])); 68*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->wnsmat[1])); 69*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->wnsmat[2])); 70*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->wnsmat[3])); 7153022affSStefano Zampini PetscFunctionReturn(0); 7253022affSStefano Zampini } 7353022affSStefano Zampini 7453022affSStefano Zampini static PetscErrorCode PCSetCoordinates_H2OPUS(PC pc, PetscInt sdim, PetscInt nlocc, PetscReal *coords) 7553022affSStefano Zampini { 7653022affSStefano Zampini PC_H2OPUS *pch2opus = (PC_H2OPUS*)pc->data; 7753022affSStefano Zampini PetscBool reset = PETSC_TRUE; 7853022affSStefano Zampini 7953022affSStefano Zampini PetscFunctionBegin; 8053022affSStefano Zampini if (pch2opus->sdim && sdim == pch2opus->sdim && nlocc == pch2opus->nlocc) { 81*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycmp(pch2opus->coords,coords,sdim*nlocc,&reset)); 8253022affSStefano Zampini reset = (PetscBool)!reset; 8353022affSStefano Zampini } 84*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(MPI_IN_PLACE,&reset,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc))); 8553022affSStefano Zampini if (reset) { 86*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCReset_H2OPUS(pc)); 87*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(sdim*nlocc,&pch2opus->coords)); 88*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(pch2opus->coords,coords,sdim*nlocc)); 8953022affSStefano Zampini pch2opus->sdim = sdim; 9053022affSStefano Zampini pch2opus->nlocc = nlocc; 9153022affSStefano Zampini } 9253022affSStefano Zampini PetscFunctionReturn(0); 9353022affSStefano Zampini } 9453022affSStefano Zampini 9553022affSStefano Zampini static PetscErrorCode PCDestroy_H2OPUS(PC pc) 9653022affSStefano Zampini { 9753022affSStefano Zampini PetscFunctionBegin; 98*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCReset_H2OPUS(pc)); 99*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL)); 100*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pc->data)); 10153022affSStefano Zampini PetscFunctionReturn(0); 10253022affSStefano Zampini } 10353022affSStefano Zampini 10453022affSStefano Zampini static PetscErrorCode PCSetFromOptions_H2OPUS(PetscOptionItems *PetscOptionsObject,PC pc) 10553022affSStefano Zampini { 10653022affSStefano Zampini PC_H2OPUS *pch2opus = (PC_H2OPUS*)pc->data; 10753022affSStefano Zampini 10853022affSStefano Zampini PetscFunctionBegin; 109*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHead(PetscOptionsObject,"H2OPUS options")); 110*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-pc_h2opus_maxits","Maximum number of iterations for Newton-Schultz",NULL,pch2opus->maxits,&pch2opus->maxits,NULL)); 111*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-pc_h2opus_monitor","Monitor Newton-Schultz convergence",NULL,pch2opus->monitor,&pch2opus->monitor,NULL)); 112*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-pc_h2opus_atol","Absolute tolerance",NULL,pch2opus->atol,&pch2opus->atol,NULL)); 113*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-pc_h2opus_rtol","Relative tolerance",NULL,pch2opus->rtol,&pch2opus->rtol,NULL)); 114*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsEnum("-pc_h2opus_norm_type","Norm type for convergence monitoring",NULL,NormTypes,(PetscEnum)pch2opus->normtype,(PetscEnum*)&pch2opus->normtype,NULL)); 115*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-pc_h2opus_hyperorder","Hyper power order of sampling",NULL,pch2opus->hyperorder,&pch2opus->hyperorder,NULL)); 116*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-pc_h2opus_leafsize","Leaf size when constructed from kernel",NULL,pch2opus->leafsize,&pch2opus->leafsize,NULL)); 117*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-pc_h2opus_eta","Admissibility condition tolerance",NULL,pch2opus->eta,&pch2opus->eta,NULL)); 118*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-pc_h2opus_maxrank","Maximum rank when constructed from matvecs",NULL,pch2opus->max_rank,&pch2opus->max_rank,NULL)); 119*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-pc_h2opus_samples","Number of samples to be taken concurrently when constructing from matvecs",NULL,pch2opus->bs,&pch2opus->bs,NULL)); 120*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-pc_h2opus_mrtol","Relative tolerance for construction from sampling",NULL,pch2opus->mrtol,&pch2opus->mrtol,NULL)); 121*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsTail()); 12253022affSStefano Zampini PetscFunctionReturn(0); 12353022affSStefano Zampini } 12453022affSStefano Zampini 12553022affSStefano Zampini typedef struct { 12653022affSStefano Zampini Mat A; 12753022affSStefano Zampini Mat M; 12853022affSStefano Zampini Vec w; 12953022affSStefano Zampini } AAtCtx; 13053022affSStefano Zampini 13153022affSStefano Zampini static PetscErrorCode MatMult_AAt(Mat A, Vec x, Vec y) 13253022affSStefano Zampini { 13353022affSStefano Zampini AAtCtx *aat; 13453022affSStefano Zampini 13553022affSStefano Zampini PetscFunctionBegin; 136*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(A,(void*)&aat)); 137*5f80ce2aSJacob Faibussowitsch /* CHKERRQ(MatMultTranspose(aat->M,x,aat->w)); */ 138*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(aat->A,x,aat->w)); 139*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(aat->A,aat->w,y)); 14053022affSStefano Zampini PetscFunctionReturn(0); 14153022affSStefano Zampini } 14253022affSStefano Zampini 14353022affSStefano Zampini static PetscErrorCode PCH2OpusSetUpInit(PC pc) 14453022affSStefano Zampini { 14553022affSStefano Zampini PC_H2OPUS *pch2opus = (PC_H2OPUS*)pc->data; 14653022affSStefano Zampini Mat A = pc->useAmat ? pc->mat : pc->pmat, AAt; 14753022affSStefano Zampini PetscInt M,m; 14853022affSStefano Zampini VecType vtype; 14953022affSStefano Zampini PetscReal n; 15053022affSStefano Zampini AAtCtx aat; 15153022affSStefano Zampini 15253022affSStefano Zampini PetscFunctionBegin; 15353022affSStefano Zampini aat.A = A; 15453022affSStefano Zampini aat.M = pch2opus->M; /* unused so far */ 155*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(A,NULL,&aat.w)); 156*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(A,&M,NULL)); 157*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(A,&m,NULL)); 158*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateShell(PetscObjectComm((PetscObject)A),m,m,M,M,&aat,&AAt)); 159*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatBindToCPU(AAt,pch2opus->boundtocpu)); 160*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(AAt,MATOP_MULT,(void (*)(void))MatMult_AAt)); 161*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(AAt,MATOP_MULT_TRANSPOSE,(void (*)(void))MatMult_AAt)); 162*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(AAt,MATOP_NORM,(void (*)(void))MatNorm_H2OPUS)); 163*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetVecType(A,&vtype)); 164*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetVecType(AAt,vtype)); 165*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatNorm(AAt,NORM_1,&n)); 16653022affSStefano Zampini pch2opus->s0 = 1./n; 167*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&aat.w)); 168*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&AAt)); 16953022affSStefano Zampini PetscFunctionReturn(0); 17053022affSStefano Zampini } 17153022affSStefano Zampini 17253022affSStefano Zampini static PetscErrorCode PCApplyKernel_H2OPUS(PC pc, Vec x, Vec y, PetscBool t) 17353022affSStefano Zampini { 17453022affSStefano Zampini PC_H2OPUS *pch2opus = (PC_H2OPUS*)pc->data; 17553022affSStefano Zampini 17653022affSStefano Zampini PetscFunctionBegin; 177*5f80ce2aSJacob Faibussowitsch if (t) CHKERRQ(MatMultTranspose(pch2opus->M,x,y)); 178*5f80ce2aSJacob Faibussowitsch else CHKERRQ(MatMult(pch2opus->M,x,y)); 17953022affSStefano Zampini PetscFunctionReturn(0); 18053022affSStefano Zampini } 18153022affSStefano Zampini 18253022affSStefano Zampini static PetscErrorCode PCApplyMatKernel_H2OPUS(PC pc, Mat X, Mat Y, PetscBool t) 18353022affSStefano Zampini { 18453022affSStefano Zampini PC_H2OPUS *pch2opus = (PC_H2OPUS*)pc->data; 18553022affSStefano Zampini 18653022affSStefano Zampini PetscFunctionBegin; 187*5f80ce2aSJacob Faibussowitsch if (t) CHKERRQ(MatTransposeMatMult(pch2opus->M,X,MAT_REUSE_MATRIX,PETSC_DEFAULT,&Y)); 188*5f80ce2aSJacob Faibussowitsch else CHKERRQ(MatMatMult(pch2opus->M,X,MAT_REUSE_MATRIX,PETSC_DEFAULT,&Y)); 18953022affSStefano Zampini PetscFunctionReturn(0); 19053022affSStefano Zampini } 19153022affSStefano Zampini 19253022affSStefano Zampini static PetscErrorCode PCApplyMat_H2OPUS(PC pc, Mat X, Mat Y) 19353022affSStefano Zampini { 19453022affSStefano Zampini PetscFunctionBegin; 195*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyMatKernel_H2OPUS(pc,X,Y,PETSC_FALSE)); 19653022affSStefano Zampini PetscFunctionReturn(0); 19753022affSStefano Zampini } 19853022affSStefano Zampini 19953022affSStefano Zampini static PetscErrorCode PCApplyTransposeMat_H2OPUS(PC pc, Mat X, Mat Y) 20053022affSStefano Zampini { 20153022affSStefano Zampini PetscFunctionBegin; 202*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyMatKernel_H2OPUS(pc,X,Y,PETSC_TRUE)); 20353022affSStefano Zampini PetscFunctionReturn(0); 20453022affSStefano Zampini } 20553022affSStefano Zampini 20653022affSStefano Zampini static PetscErrorCode PCApply_H2OPUS(PC pc, Vec x, Vec y) 20753022affSStefano Zampini { 20853022affSStefano Zampini PetscFunctionBegin; 209*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyKernel_H2OPUS(pc,x,y,PETSC_FALSE)); 21053022affSStefano Zampini PetscFunctionReturn(0); 21153022affSStefano Zampini } 21253022affSStefano Zampini 21353022affSStefano Zampini static PetscErrorCode PCApplyTranspose_H2OPUS(PC pc, Vec x, Vec y) 21453022affSStefano Zampini { 21553022affSStefano Zampini PetscFunctionBegin; 216*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyKernel_H2OPUS(pc,x,y,PETSC_TRUE)); 21753022affSStefano Zampini PetscFunctionReturn(0); 21853022affSStefano Zampini } 21953022affSStefano Zampini 22053022affSStefano Zampini /* used to test the norm of (M^-1 A - I) */ 22153022affSStefano Zampini static PetscErrorCode MatMultKernel_MAmI(Mat M, Vec x, Vec y, PetscBool t) 22253022affSStefano Zampini { 22353022affSStefano Zampini PC pc; 22453022affSStefano Zampini Mat A; 22553022affSStefano Zampini PC_H2OPUS *pch2opus; 22653022affSStefano Zampini PetscBool sideleft = PETSC_TRUE; 22753022affSStefano Zampini 22853022affSStefano Zampini PetscFunctionBegin; 229*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(M,(void*)&pc)); 23053022affSStefano Zampini pch2opus = (PC_H2OPUS*)pc->data; 231*5f80ce2aSJacob Faibussowitsch if (!pch2opus->w) CHKERRQ(MatCreateVecs(pch2opus->M,&pch2opus->w,NULL)); 23253022affSStefano Zampini A = pch2opus->A; 233*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecBindToCPU(pch2opus->w,pch2opus->boundtocpu)); 23453022affSStefano Zampini if (t) { 23553022affSStefano Zampini if (sideleft) { 236*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyTranspose_H2OPUS(pc,x,pch2opus->w)); 237*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(A,pch2opus->w,y)); 23853022affSStefano Zampini } else { 239*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(A,x,pch2opus->w)); 240*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyTranspose_H2OPUS(pc,pch2opus->w,y)); 24153022affSStefano Zampini } 24253022affSStefano Zampini } else { 24353022affSStefano Zampini if (sideleft) { 244*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(A,x,pch2opus->w)); 245*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApply_H2OPUS(pc,pch2opus->w,y)); 24653022affSStefano Zampini } else { 247*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApply_H2OPUS(pc,x,pch2opus->w)); 248*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(A,pch2opus->w,y)); 24953022affSStefano Zampini } 25053022affSStefano Zampini } 251*5f80ce2aSJacob Faibussowitsch if (!pch2opus->testMA) CHKERRQ(VecAXPY(y,-1.0,x)); 25253022affSStefano Zampini PetscFunctionReturn(0); 25353022affSStefano Zampini } 25453022affSStefano Zampini 25553022affSStefano Zampini static PetscErrorCode MatMult_MAmI(Mat A, Vec x, Vec y) 25653022affSStefano Zampini { 25753022affSStefano Zampini PetscFunctionBegin; 258*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultKernel_MAmI(A,x,y,PETSC_FALSE)); 25953022affSStefano Zampini PetscFunctionReturn(0); 26053022affSStefano Zampini } 26153022affSStefano Zampini 26253022affSStefano Zampini static PetscErrorCode MatMultTranspose_MAmI(Mat A, Vec x, Vec y) 26353022affSStefano Zampini { 26453022affSStefano Zampini PetscFunctionBegin; 265*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultKernel_MAmI(A,x,y,PETSC_TRUE)); 26653022affSStefano Zampini PetscFunctionReturn(0); 26753022affSStefano Zampini } 26853022affSStefano Zampini 26953022affSStefano Zampini /* HyperPower kernel: 27053022affSStefano Zampini Y = R = x 27153022affSStefano Zampini for i = 1 . . . l - 1 do 27253022affSStefano Zampini R = (I - A * Xk) * R 27353022affSStefano Zampini Y = Y + R 27453022affSStefano Zampini Y = Xk * Y 27553022affSStefano Zampini */ 27653022affSStefano Zampini static PetscErrorCode MatMultKernel_Hyper(Mat M, Vec x, Vec y, PetscBool t) 27753022affSStefano Zampini { 27853022affSStefano Zampini PC pc; 27953022affSStefano Zampini Mat A; 28053022affSStefano Zampini PC_H2OPUS *pch2opus; 28153022affSStefano Zampini 28253022affSStefano Zampini PetscFunctionBegin; 283*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(M,(void*)&pc)); 28453022affSStefano Zampini pch2opus = (PC_H2OPUS*)pc->data; 28553022affSStefano Zampini A = pch2opus->A; 286*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(pch2opus->M,pch2opus->wns[0] ? NULL : &pch2opus->wns[0],pch2opus->wns[1] ? NULL : &pch2opus->wns[1])); 287*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(pch2opus->M,pch2opus->wns[2] ? NULL : &pch2opus->wns[2],pch2opus->wns[3] ? NULL : &pch2opus->wns[3])); 288*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecBindToCPU(pch2opus->wns[0],pch2opus->boundtocpu)); 289*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecBindToCPU(pch2opus->wns[1],pch2opus->boundtocpu)); 290*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecBindToCPU(pch2opus->wns[2],pch2opus->boundtocpu)); 291*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecBindToCPU(pch2opus->wns[3],pch2opus->boundtocpu)); 292*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(x,pch2opus->wns[0])); 293*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(x,pch2opus->wns[3])); 29453022affSStefano Zampini if (t) { 295*5f80ce2aSJacob Faibussowitsch for (PetscInt i=0;i<pch2opus->hyperorder-1;i++) { 296*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(A,pch2opus->wns[0],pch2opus->wns[1])); 297*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyTranspose_H2OPUS(pc,pch2opus->wns[1],pch2opus->wns[2])); 298*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(pch2opus->wns[0],-1.,pch2opus->wns[2])); 299*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(pch2opus->wns[3], 1.,pch2opus->wns[0])); 30053022affSStefano Zampini } 301*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyTranspose_H2OPUS(pc,pch2opus->wns[3],y)); 30253022affSStefano Zampini } else { 303*5f80ce2aSJacob Faibussowitsch for (PetscInt i=0;i<pch2opus->hyperorder-1;i++) { 304*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApply_H2OPUS(pc,pch2opus->wns[0],pch2opus->wns[1])); 305*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(A,pch2opus->wns[1],pch2opus->wns[2])); 306*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(pch2opus->wns[0],-1.,pch2opus->wns[2])); 307*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(pch2opus->wns[3], 1.,pch2opus->wns[0])); 30853022affSStefano Zampini } 309*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApply_H2OPUS(pc,pch2opus->wns[3],y)); 31053022affSStefano Zampini } 31153022affSStefano Zampini PetscFunctionReturn(0); 31253022affSStefano Zampini } 31353022affSStefano Zampini 31453022affSStefano Zampini static PetscErrorCode MatMult_Hyper(Mat M, Vec x, Vec y) 31553022affSStefano Zampini { 31653022affSStefano Zampini PetscFunctionBegin; 317*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultKernel_Hyper(M,x,y,PETSC_FALSE)); 31853022affSStefano Zampini PetscFunctionReturn(0); 31953022affSStefano Zampini } 32053022affSStefano Zampini 32153022affSStefano Zampini static PetscErrorCode MatMultTranspose_Hyper(Mat M, Vec x, Vec y) 32253022affSStefano Zampini { 32353022affSStefano Zampini PetscFunctionBegin; 324*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultKernel_Hyper(M,x,y,PETSC_TRUE)); 32553022affSStefano Zampini PetscFunctionReturn(0); 32653022affSStefano Zampini } 32753022affSStefano Zampini 32853022affSStefano Zampini /* Hyper power kernel, MatMat version */ 32953022affSStefano Zampini static PetscErrorCode MatMatMultKernel_Hyper(Mat M, Mat X, Mat Y, PetscBool t) 33053022affSStefano Zampini { 33153022affSStefano Zampini PC pc; 33253022affSStefano Zampini Mat A; 33353022affSStefano Zampini PC_H2OPUS *pch2opus; 33453022affSStefano Zampini PetscInt i; 33553022affSStefano Zampini 33653022affSStefano Zampini PetscFunctionBegin; 337*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(M,(void*)&pc)); 33853022affSStefano Zampini pch2opus = (PC_H2OPUS*)pc->data; 33953022affSStefano Zampini A = pch2opus->A; 34053022affSStefano Zampini if (pch2opus->wnsmat[0] && pch2opus->wnsmat[0]->cmap->N != X->cmap->N) { 341*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->wnsmat[0])); 342*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->wnsmat[1])); 34353022affSStefano Zampini } 34453022affSStefano Zampini if (!pch2opus->wnsmat[0]) { 345*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(X,MAT_SHARE_NONZERO_PATTERN,&pch2opus->wnsmat[0])); 346*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(Y,MAT_SHARE_NONZERO_PATTERN,&pch2opus->wnsmat[1])); 34753022affSStefano Zampini } 34853022affSStefano Zampini if (pch2opus->wnsmat[2] && pch2opus->wnsmat[2]->cmap->N != X->cmap->N) { 349*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->wnsmat[2])); 350*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->wnsmat[3])); 35153022affSStefano Zampini } 35253022affSStefano Zampini if (!pch2opus->wnsmat[2]) { 353*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(X,MAT_SHARE_NONZERO_PATTERN,&pch2opus->wnsmat[2])); 354*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(Y,MAT_SHARE_NONZERO_PATTERN,&pch2opus->wnsmat[3])); 35553022affSStefano Zampini } 356*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCopy(X,pch2opus->wnsmat[0],SAME_NONZERO_PATTERN)); 357*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCopy(X,pch2opus->wnsmat[3],SAME_NONZERO_PATTERN)); 35853022affSStefano Zampini if (t) { 35953022affSStefano Zampini for (i=0;i<pch2opus->hyperorder-1;i++) { 360*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatTransposeMatMult(A,pch2opus->wnsmat[0],MAT_REUSE_MATRIX,PETSC_DEFAULT,&pch2opus->wnsmat[1])); 361*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyTransposeMat_H2OPUS(pc,pch2opus->wnsmat[1],pch2opus->wnsmat[2])); 362*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(pch2opus->wnsmat[0],-1.,pch2opus->wnsmat[2],SAME_NONZERO_PATTERN)); 363*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(pch2opus->wnsmat[3],1.,pch2opus->wnsmat[0],SAME_NONZERO_PATTERN)); 36453022affSStefano Zampini } 365*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyTransposeMat_H2OPUS(pc,pch2opus->wnsmat[3],Y)); 36653022affSStefano Zampini } else { 36753022affSStefano Zampini for (i=0;i<pch2opus->hyperorder-1;i++) { 368*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyMat_H2OPUS(pc,pch2opus->wnsmat[0],pch2opus->wnsmat[1])); 369*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(A,pch2opus->wnsmat[1],MAT_REUSE_MATRIX,PETSC_DEFAULT,&pch2opus->wnsmat[2])); 370*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(pch2opus->wnsmat[0],-1.,pch2opus->wnsmat[2],SAME_NONZERO_PATTERN)); 371*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(pch2opus->wnsmat[3],1.,pch2opus->wnsmat[0],SAME_NONZERO_PATTERN)); 37253022affSStefano Zampini } 373*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyMat_H2OPUS(pc,pch2opus->wnsmat[3],Y)); 37453022affSStefano Zampini } 37553022affSStefano Zampini PetscFunctionReturn(0); 37653022affSStefano Zampini } 37753022affSStefano Zampini 37853022affSStefano Zampini static PetscErrorCode MatMatMultNumeric_Hyper(Mat M, Mat X, Mat Y,void *ctx) 37953022affSStefano Zampini { 38053022affSStefano Zampini PetscFunctionBegin; 381*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMultKernel_Hyper(M,X,Y,PETSC_FALSE)); 38253022affSStefano Zampini PetscFunctionReturn(0); 38353022affSStefano Zampini } 38453022affSStefano Zampini 38553022affSStefano Zampini /* Basic Newton-Schultz sampler: (2 * I - M * A)*M */ 38653022affSStefano Zampini static PetscErrorCode MatMultKernel_NS(Mat M, Vec x, Vec y, PetscBool t) 38753022affSStefano Zampini { 38853022affSStefano Zampini PC pc; 38953022affSStefano Zampini Mat A; 39053022affSStefano Zampini PC_H2OPUS *pch2opus; 39153022affSStefano Zampini 39253022affSStefano Zampini PetscFunctionBegin; 393*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(M,(void*)&pc)); 39453022affSStefano Zampini pch2opus = (PC_H2OPUS*)pc->data; 39553022affSStefano Zampini A = pch2opus->A; 396*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(pch2opus->M,pch2opus->wns[0] ? NULL : &pch2opus->wns[0],pch2opus->wns[1] ? NULL : &pch2opus->wns[1])); 397*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecBindToCPU(pch2opus->wns[0],pch2opus->boundtocpu)); 398*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecBindToCPU(pch2opus->wns[1],pch2opus->boundtocpu)); 39953022affSStefano Zampini if (t) { 400*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyTranspose_H2OPUS(pc,x,y)); 401*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(A,y,pch2opus->wns[1])); 402*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyTranspose_H2OPUS(pc,pch2opus->wns[1],pch2opus->wns[0])); 403*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPBY(y,-1.,2.,pch2opus->wns[0])); 40453022affSStefano Zampini } else { 405*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApply_H2OPUS(pc,x,y)); 406*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(A,y,pch2opus->wns[0])); 407*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApply_H2OPUS(pc,pch2opus->wns[0],pch2opus->wns[1])); 408*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPBY(y,-1.,2.,pch2opus->wns[1])); 40953022affSStefano Zampini } 41053022affSStefano Zampini PetscFunctionReturn(0); 41153022affSStefano Zampini } 41253022affSStefano Zampini 41353022affSStefano Zampini static PetscErrorCode MatMult_NS(Mat M, Vec x, Vec y) 41453022affSStefano Zampini { 41553022affSStefano Zampini PetscFunctionBegin; 416*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultKernel_NS(M,x,y,PETSC_FALSE)); 41753022affSStefano Zampini PetscFunctionReturn(0); 41853022affSStefano Zampini } 41953022affSStefano Zampini 42053022affSStefano Zampini static PetscErrorCode MatMultTranspose_NS(Mat M, Vec x, Vec y) 42153022affSStefano Zampini { 42253022affSStefano Zampini PetscFunctionBegin; 423*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultKernel_NS(M,x,y,PETSC_TRUE)); 42453022affSStefano Zampini PetscFunctionReturn(0); 42553022affSStefano Zampini } 42653022affSStefano Zampini 42753022affSStefano Zampini /* Basic Newton-Schultz sampler: (2 * I - M * A)*M, MatMat version */ 42853022affSStefano Zampini static PetscErrorCode MatMatMultKernel_NS(Mat M, Mat X, Mat Y, PetscBool t) 42953022affSStefano Zampini { 43053022affSStefano Zampini PC pc; 43153022affSStefano Zampini Mat A; 43253022affSStefano Zampini PC_H2OPUS *pch2opus; 43353022affSStefano Zampini 43453022affSStefano Zampini PetscFunctionBegin; 435*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(M,(void*)&pc)); 43653022affSStefano Zampini pch2opus = (PC_H2OPUS*)pc->data; 43753022affSStefano Zampini A = pch2opus->A; 43853022affSStefano Zampini if (pch2opus->wnsmat[0] && pch2opus->wnsmat[0]->cmap->N != X->cmap->N) { 439*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->wnsmat[0])); 440*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->wnsmat[1])); 44153022affSStefano Zampini } 44253022affSStefano Zampini if (!pch2opus->wnsmat[0]) { 443*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(X,MAT_SHARE_NONZERO_PATTERN,&pch2opus->wnsmat[0])); 444*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(Y,MAT_SHARE_NONZERO_PATTERN,&pch2opus->wnsmat[1])); 44553022affSStefano Zampini } 44653022affSStefano Zampini if (t) { 447*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyTransposeMat_H2OPUS(pc,X,Y)); 448*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatTransposeMatMult(A,Y,MAT_REUSE_MATRIX,PETSC_DEFAULT,&pch2opus->wnsmat[1])); 449*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyTransposeMat_H2OPUS(pc,pch2opus->wnsmat[1],pch2opus->wnsmat[0])); 450*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(Y,2.)); 451*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(Y,-1.,pch2opus->wnsmat[0],SAME_NONZERO_PATTERN)); 45253022affSStefano Zampini } else { 453*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyMat_H2OPUS(pc,X,Y)); 454*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(A,Y,MAT_REUSE_MATRIX,PETSC_DEFAULT,&pch2opus->wnsmat[0])); 455*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCApplyMat_H2OPUS(pc,pch2opus->wnsmat[0],pch2opus->wnsmat[1])); 456*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(Y,2.)); 457*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(Y,-1.,pch2opus->wnsmat[1],SAME_NONZERO_PATTERN)); 45853022affSStefano Zampini } 45953022affSStefano Zampini PetscFunctionReturn(0); 46053022affSStefano Zampini } 46153022affSStefano Zampini 46253022affSStefano Zampini static PetscErrorCode MatMatMultNumeric_NS(Mat M, Mat X, Mat Y, void *ctx) 46353022affSStefano Zampini { 46453022affSStefano Zampini PetscFunctionBegin; 465*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMultKernel_NS(M,X,Y,PETSC_FALSE)); 46653022affSStefano Zampini PetscFunctionReturn(0); 46753022affSStefano Zampini } 46853022affSStefano Zampini 46953022affSStefano Zampini static PetscErrorCode PCH2OpusSetUpSampler_Private(PC pc) 47053022affSStefano Zampini { 47153022affSStefano Zampini PC_H2OPUS *pch2opus = (PC_H2OPUS*)pc->data; 47253022affSStefano Zampini Mat A = pc->useAmat ? pc->mat : pc->pmat; 47353022affSStefano Zampini 47453022affSStefano Zampini PetscFunctionBegin; 47553022affSStefano Zampini if (!pch2opus->S) { 47653022affSStefano Zampini PetscInt M,N,m,n; 47753022affSStefano Zampini 478*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(A,&M,&N)); 479*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(A,&m,&n)); 480*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateShell(PetscObjectComm((PetscObject)A),m,n,M,N,pc,&pch2opus->S)); 481*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetBlockSizesFromMats(pch2opus->S,A,A)); 48253022affSStefano Zampini #if defined(PETSC_H2OPUS_USE_GPU) 483*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetVecType(pch2opus->S,VECCUDA)); 48453022affSStefano Zampini #endif 48553022affSStefano Zampini } 48653022affSStefano Zampini if (pch2opus->hyperorder >= 2) { 487*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(pch2opus->S,MATOP_MULT,(void (*)(void))MatMult_Hyper)); 488*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(pch2opus->S,MATOP_MULT_TRANSPOSE,(void (*)(void))MatMultTranspose_Hyper)); 489*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetMatProductOperation(pch2opus->S,MATPRODUCT_AB,NULL,MatMatMultNumeric_Hyper,NULL,MATDENSE,MATDENSE)); 490*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetMatProductOperation(pch2opus->S,MATPRODUCT_AB,NULL,MatMatMultNumeric_Hyper,NULL,MATDENSECUDA,MATDENSECUDA)); 49153022affSStefano Zampini } else { 492*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(pch2opus->S,MATOP_MULT,(void (*)(void))MatMult_NS)); 493*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(pch2opus->S,MATOP_MULT_TRANSPOSE,(void (*)(void))MatMultTranspose_NS)); 494*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetMatProductOperation(pch2opus->S,MATPRODUCT_AB,NULL,MatMatMultNumeric_NS,NULL,MATDENSE,MATDENSE)); 495*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetMatProductOperation(pch2opus->S,MATPRODUCT_AB,NULL,MatMatMultNumeric_NS,NULL,MATDENSECUDA,MATDENSECUDA)); 49653022affSStefano Zampini } 497*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatPropagateSymmetryOptions(A,pch2opus->S)); 498*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatBindToCPU(pch2opus->S,pch2opus->boundtocpu)); 49953022affSStefano Zampini /* XXX */ 500*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(pch2opus->S,MAT_SYMMETRIC,PETSC_TRUE)); 50153022affSStefano Zampini PetscFunctionReturn(0); 50253022affSStefano Zampini } 50353022affSStefano Zampini 50453022affSStefano Zampini static PetscErrorCode PCSetUp_H2OPUS(PC pc) 50553022affSStefano Zampini { 50653022affSStefano Zampini PC_H2OPUS *pch2opus = (PC_H2OPUS*)pc->data; 50753022affSStefano Zampini Mat A = pc->useAmat ? pc->mat : pc->pmat; 50853022affSStefano Zampini NormType norm = pch2opus->normtype; 50953022affSStefano Zampini PetscReal initerr = 0.0,err; 51053022affSStefano Zampini PetscReal initerrMA = 0.0,errMA; 51153022affSStefano Zampini PetscBool ish2opus; 51253022affSStefano Zampini 51353022affSStefano Zampini PetscFunctionBegin; 51453022affSStefano Zampini if (!pch2opus->T) { 51553022affSStefano Zampini PetscInt M,N,m,n; 51653022affSStefano Zampini const char *prefix; 51753022affSStefano Zampini 518*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCGetOptionsPrefix(pc,&prefix)); 519*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(A,&M,&N)); 520*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(A,&m,&n)); 521*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateShell(PetscObjectComm((PetscObject)pc->pmat),m,n,M,N,pc,&pch2opus->T)); 522*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetBlockSizesFromMats(pch2opus->T,A,A)); 523*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(pch2opus->T,MATOP_MULT,(void (*)(void))MatMult_MAmI)); 524*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(pch2opus->T,MATOP_MULT_TRANSPOSE,(void (*)(void))MatMultTranspose_MAmI)); 525*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(pch2opus->T,MATOP_NORM,(void (*)(void))MatNorm_H2OPUS)); 52653022affSStefano Zampini #if defined(PETSC_H2OPUS_USE_GPU) 527*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetVecType(pch2opus->T,VECCUDA)); 52853022affSStefano Zampini #endif 529*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)pch2opus->T)); 530*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOptionsPrefix(pch2opus->T,prefix)); 531*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAppendOptionsPrefix(pch2opus->T,"pc_h2opus_est_")); 53253022affSStefano Zampini } 533*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->A)); 534*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)A,MATH2OPUS,&ish2opus)); 53553022affSStefano Zampini if (ish2opus) { 536*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject)A)); 53753022affSStefano Zampini pch2opus->A = A; 53853022affSStefano Zampini } else { 53953022affSStefano Zampini const char *prefix; 540*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateH2OpusFromMat(A,pch2opus->sdim,pch2opus->coords,PETSC_FALSE,pch2opus->eta,pch2opus->leafsize,pch2opus->max_rank,pch2opus->bs,pch2opus->mrtol,&pch2opus->A)); 54153022affSStefano Zampini /* XXX */ 542*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(pch2opus->A,MAT_SYMMETRIC,PETSC_TRUE)); 543*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCGetOptionsPrefix(pc,&prefix)); 544*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOptionsPrefix(pch2opus->A,prefix)); 545*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAppendOptionsPrefix(pch2opus->A,"pc_h2opus_init_")); 546*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetFromOptions(pch2opus->A)); 547*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(pch2opus->A,MAT_FINAL_ASSEMBLY)); 548*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(pch2opus->A,MAT_FINAL_ASSEMBLY)); 54953022affSStefano Zampini /* XXX */ 550*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(pch2opus->A,MAT_SYMMETRIC,PETSC_TRUE)); 55153022affSStefano Zampini } 55253022affSStefano Zampini #if defined(PETSC_H2OPUS_USE_GPU) 55353022affSStefano Zampini pch2opus->boundtocpu = pch2opus->A->boundtocpu; 55453022affSStefano Zampini #endif 555*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatBindToCPU(pch2opus->T,pch2opus->boundtocpu)); 55653022affSStefano Zampini if (pch2opus->M) { /* see if we can reuse M as initial guess */ 55753022affSStefano Zampini PetscReal reuse; 55853022affSStefano Zampini 559*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatBindToCPU(pch2opus->M,pch2opus->boundtocpu)); 560*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatNorm(pch2opus->T,norm,&reuse)); 561*5f80ce2aSJacob Faibussowitsch if (reuse >= 1.0) CHKERRQ(MatDestroy(&pch2opus->M)); 56253022affSStefano Zampini } 56353022affSStefano Zampini if (!pch2opus->M) { 56453022affSStefano Zampini const char *prefix; 565*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(pch2opus->A,MAT_COPY_VALUES,&pch2opus->M)); 566*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCGetOptionsPrefix(pc,&prefix)); 567*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOptionsPrefix(pch2opus->M,prefix)); 568*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAppendOptionsPrefix(pch2opus->M,"pc_h2opus_inv_")); 569*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetFromOptions(pch2opus->M)); 570*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCH2OpusSetUpInit(pc)); 571*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(pch2opus->M,pch2opus->s0)); 57253022affSStefano Zampini } 57353022affSStefano Zampini /* A and M have the same h2 matrix structure, save on reordering routines */ 574*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatH2OpusSetNativeMult(pch2opus->A,PETSC_TRUE)); 575*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatH2OpusSetNativeMult(pch2opus->M,PETSC_TRUE)); 57653022affSStefano Zampini if (norm == NORM_1 || norm == NORM_2 || norm == NORM_INFINITY) { 577*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatNorm(pch2opus->T,norm,&initerr)); 57853022affSStefano Zampini pch2opus->testMA = PETSC_TRUE; 579*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatNorm(pch2opus->T,norm,&initerrMA)); 58053022affSStefano Zampini pch2opus->testMA = PETSC_FALSE; 58153022affSStefano Zampini } 58253022affSStefano Zampini if (PetscIsInfOrNanReal(initerr)) pc->failedreason = PC_SETUP_ERROR; 58353022affSStefano Zampini err = initerr; 58453022affSStefano Zampini errMA = initerrMA; 58553022affSStefano Zampini if (pch2opus->monitor) { 586*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PetscObjectComm((PetscObject)pc),"%D: ||M*A - I|| NORM%s abs %g rel %g\n",0,NormTypes[norm],(double)err,(double)(err/initerr))); 587*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PetscObjectComm((PetscObject)pc),"%D: ||M*A|| NORM%s abs %g rel %g\n",0,NormTypes[norm],(double)errMA,(double)(errMA/initerrMA))); 58853022affSStefano Zampini } 58953022affSStefano Zampini if (initerr > pch2opus->atol && !pc->failedreason) { 59053022affSStefano Zampini PetscInt i; 59153022affSStefano Zampini 592*5f80ce2aSJacob Faibussowitsch CHKERRQ(PCH2OpusSetUpSampler_Private(pc)); 59353022affSStefano Zampini for (i = 0; i < pch2opus->maxits; i++) { 59453022affSStefano Zampini Mat M; 59553022affSStefano Zampini const char* prefix; 59653022affSStefano Zampini 597*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDuplicate(pch2opus->M,MAT_SHARE_NONZERO_PATTERN,&M)); 598*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOptionsPrefix(pch2opus->M,&prefix)); 599*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOptionsPrefix(M,prefix)); 600*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatH2OpusSetSamplingMat(M,pch2opus->S,PETSC_DECIDE,PETSC_DECIDE)); 601*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetFromOptions(M)); 602*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatH2OpusSetNativeMult(M,PETSC_TRUE)); 603*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY)); 604*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY)); 60553022affSStefano Zampini 606*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->M)); 60753022affSStefano Zampini pch2opus->M = M; 60853022affSStefano Zampini if (norm == NORM_1 || norm == NORM_2 || norm == NORM_INFINITY) { 609*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatNorm(pch2opus->T,norm,&err)); 61053022affSStefano Zampini pch2opus->testMA = PETSC_TRUE; 611*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatNorm(pch2opus->T,norm,&errMA)); 61253022affSStefano Zampini pch2opus->testMA = PETSC_FALSE; 61353022affSStefano Zampini } 61453022affSStefano Zampini if (pch2opus->monitor) { 615*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PetscObjectComm((PetscObject)pc),"%D: ||M*A - I|| NORM%s abs %g rel %g\n",i+1,NormTypes[norm],(double)err,(double)(err/initerr))); 616*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PetscObjectComm((PetscObject)pc),"%D: ||M*A|| NORM%s abs %g rel %g\n",i+1,NormTypes[norm],(double)errMA,(double)(errMA/initerrMA))); 61753022affSStefano Zampini } 61853022affSStefano Zampini if (PetscIsInfOrNanReal(err)) pc->failedreason = PC_SETUP_ERROR; 61953022affSStefano Zampini if (err < pch2opus->atol || err < pch2opus->rtol*initerr || pc->failedreason) break; 62053022affSStefano Zampini } 62153022affSStefano Zampini } 62253022affSStefano Zampini /* cleanup setup workspace */ 623*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatH2OpusSetNativeMult(pch2opus->A,PETSC_FALSE)); 624*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatH2OpusSetNativeMult(pch2opus->M,PETSC_FALSE)); 625*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pch2opus->wns[0])); 626*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pch2opus->wns[1])); 627*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pch2opus->wns[2])); 628*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pch2opus->wns[3])); 629*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->wnsmat[0])); 630*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->wnsmat[1])); 631*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->wnsmat[2])); 632*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&pch2opus->wnsmat[3])); 63353022affSStefano Zampini PetscFunctionReturn(0); 63453022affSStefano Zampini } 63553022affSStefano Zampini 63653022affSStefano Zampini static PetscErrorCode PCView_H2OPUS(PC pc, PetscViewer viewer) 63753022affSStefano Zampini { 63853022affSStefano Zampini PC_H2OPUS *pch2opus = (PC_H2OPUS*)pc->data; 63953022affSStefano Zampini PetscBool isascii; 64053022affSStefano Zampini 64153022affSStefano Zampini PetscFunctionBegin; 642*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii)); 64353022affSStefano Zampini if (isascii) { 64453022affSStefano Zampini if (pch2opus->A && pch2opus->A != pc->mat && pch2opus->A != pc->pmat) { 645*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer,"Initial approximation matrix\n")); 646*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushTab(viewer)); 647*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO_DETAIL)); 648*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(pch2opus->A,viewer)); 649*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerPopFormat(viewer)); 650*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPopTab(viewer)); 65153022affSStefano Zampini } 65253022affSStefano Zampini if (pch2opus->M) { 653*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer,"Inner matrix constructed\n")); 654*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushTab(viewer)); 655*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO_DETAIL)); 656*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatView(pch2opus->M,viewer)); 657*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerPopFormat(viewer)); 658*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPopTab(viewer)); 65953022affSStefano Zampini } 660*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer,"Initial scaling: %g\n",pch2opus->s0)); 66153022affSStefano Zampini } 66253022affSStefano Zampini PetscFunctionReturn(0); 66353022affSStefano Zampini } 66453022affSStefano Zampini 66553022affSStefano Zampini PETSC_EXTERN PetscErrorCode PCCreate_H2OPUS(PC pc) 66653022affSStefano Zampini { 66753022affSStefano Zampini PC_H2OPUS *pch2opus; 66853022affSStefano Zampini 66953022affSStefano Zampini PetscFunctionBegin; 670*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNewLog(pc,&pch2opus)); 67153022affSStefano Zampini pc->data = (void*)pch2opus; 67253022affSStefano Zampini 67353022affSStefano Zampini pch2opus->atol = 1.e-2; 67453022affSStefano Zampini pch2opus->rtol = 1.e-6; 67553022affSStefano Zampini pch2opus->maxits = 50; 67653022affSStefano Zampini pch2opus->hyperorder = 1; /* defaults to basic NewtonSchultz */ 67753022affSStefano Zampini pch2opus->normtype = NORM_2; 67853022affSStefano Zampini 67953022affSStefano Zampini /* these are needed when we are sampling the pmat */ 68053022affSStefano Zampini pch2opus->eta = PETSC_DECIDE; 68153022affSStefano Zampini pch2opus->leafsize = PETSC_DECIDE; 68253022affSStefano Zampini pch2opus->max_rank = PETSC_DECIDE; 68353022affSStefano Zampini pch2opus->bs = PETSC_DECIDE; 68453022affSStefano Zampini pch2opus->mrtol = PETSC_DECIDE; 68553022affSStefano Zampini #if defined(PETSC_H2OPUS_USE_GPU) 68653022affSStefano Zampini pch2opus->boundtocpu = PETSC_FALSE; 68753022affSStefano Zampini #else 68853022affSStefano Zampini pch2opus->boundtocpu = PETSC_TRUE; 68953022affSStefano Zampini #endif 69053022affSStefano Zampini pc->ops->destroy = PCDestroy_H2OPUS; 69153022affSStefano Zampini pc->ops->setup = PCSetUp_H2OPUS; 69253022affSStefano Zampini pc->ops->apply = PCApply_H2OPUS; 69353022affSStefano Zampini pc->ops->matapply = PCApplyMat_H2OPUS; 69453022affSStefano Zampini pc->ops->applytranspose = PCApplyTranspose_H2OPUS; 69553022affSStefano Zampini pc->ops->reset = PCReset_H2OPUS; 69653022affSStefano Zampini pc->ops->setfromoptions = PCSetFromOptions_H2OPUS; 69753022affSStefano Zampini pc->ops->view = PCView_H2OPUS; 69853022affSStefano Zampini 699*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_H2OPUS)); 70053022affSStefano Zampini PetscFunctionReturn(0); 70153022affSStefano Zampini } 702