1dba47a55SKris Buschelman #define PETSCKSP_DLL 2ab718edeSHong Zhang 35582bec1SHong Zhang /* 4759e7b9cSHong Zhang Provides an interface to the ML 5.0 smoothed Aggregation 55582bec1SHong Zhang */ 66356e834SBarry Smith #include "private/pcimpl.h" /*I "petscpc.h" I*/ 75582bec1SHong Zhang #include "src/ksp/pc/impls/mg/mgimpl.h" /*I "petscmg.h" I*/ 85582bec1SHong Zhang #include "src/mat/impls/aij/seq/aij.h" 95582bec1SHong Zhang #include "src/mat/impls/aij/mpi/mpiaij.h" 10cb5d8e9eSHong Zhang 115582bec1SHong Zhang #include <math.h> 122cf39c26SSatish Balay EXTERN_C_BEGIN 132cf39c26SSatish Balay #include "ml_config.h" 145582bec1SHong Zhang #include "ml_include.h" 155582bec1SHong Zhang EXTERN_C_END 165582bec1SHong Zhang 175582bec1SHong Zhang /* The context (data structure) at each grid level */ 185582bec1SHong Zhang typedef struct { 195582bec1SHong Zhang Vec x,b,r; /* global vectors */ 205582bec1SHong Zhang Mat A,P,R; 215582bec1SHong Zhang KSP ksp; 225582bec1SHong Zhang } GridCtx; 235582bec1SHong Zhang 245582bec1SHong Zhang /* The context used to input PETSc matrix into ML at fine grid */ 255582bec1SHong Zhang typedef struct { 26573998d7SHong Zhang Mat A; /* Petsc matrix in aij format */ 27573998d7SHong Zhang Mat Aloc; /* local portion of A to be used by ML */ 2824a42b14SHong Zhang Vec x,y; 295582bec1SHong Zhang ML_Operator *mlmat; 305582bec1SHong Zhang PetscScalar *pwork; /* tmp array used by PetscML_comm() */ 315582bec1SHong Zhang } FineGridCtx; 325582bec1SHong Zhang 335582bec1SHong Zhang /* The context associates a ML matrix with a PETSc shell matrix */ 345582bec1SHong Zhang typedef struct { 355582bec1SHong Zhang Mat A; /* PETSc shell matrix associated with mlmat */ 365582bec1SHong Zhang ML_Operator *mlmat; /* ML matrix assorciated with A */ 375582bec1SHong Zhang Vec y; 385582bec1SHong Zhang } Mat_MLShell; 395582bec1SHong Zhang 405582bec1SHong Zhang /* Private context for the ML preconditioner */ 415582bec1SHong Zhang typedef struct { 425582bec1SHong Zhang ML *ml_object; 435582bec1SHong Zhang ML_Aggregate *agg_object; 445582bec1SHong Zhang GridCtx *gridctx; 455582bec1SHong Zhang FineGridCtx *PetscMLdata; 46573998d7SHong Zhang PetscInt Nlevels,MaxNlevels,MaxCoarseSize,CoarsenScheme; 475582bec1SHong Zhang PetscReal Threshold,DampingFactor; 485582bec1SHong Zhang PetscTruth SpectralNormScheme_Anorm; 49573998d7SHong Zhang PetscMPIInt size; /* size of communicator for pc->pmat */ 505582bec1SHong Zhang PetscErrorCode (*PCSetUp)(PC); 515582bec1SHong Zhang PetscErrorCode (*PCDestroy)(PC); 525582bec1SHong Zhang } PC_ML; 5341ca0015SHong Zhang 5441ca0015SHong Zhang extern int PetscML_getrow(ML_Operator *ML_data,int N_requested_rows,int requested_rows[], 555582bec1SHong Zhang int allocated_space,int columns[],double values[],int row_lengths[]); 5641ca0015SHong Zhang extern int PetscML_matvec(ML_Operator *ML_data, int in_length, double p[], int out_length,double ap[]); 575582bec1SHong Zhang extern int PetscML_comm(double x[], void *ML_data); 585582bec1SHong Zhang extern PetscErrorCode MatMult_ML(Mat,Vec,Vec); 595582bec1SHong Zhang extern PetscErrorCode MatMultAdd_ML(Mat,Vec,Vec,Vec); 6075179d2cSHong Zhang extern PetscErrorCode MatConvert_MPIAIJ_ML(Mat,MatType,MatReuse,Mat*); 615582bec1SHong Zhang extern PetscErrorCode MatDestroy_ML(Mat); 62573998d7SHong Zhang extern PetscErrorCode MatWrapML_SeqAIJ(ML_Operator*,MatReuse,Mat*); 63eef31507SHong Zhang extern PetscErrorCode MatWrapML_MPIAIJ(ML_Operator*,Mat*); 64573998d7SHong Zhang extern PetscErrorCode MatWrapML_SHELL(ML_Operator*,MatReuse,Mat*); 65573998d7SHong Zhang extern PetscErrorCode PetscContainerDestroy_PC_ML(void *); 665582bec1SHong Zhang 675582bec1SHong Zhang /* -------------------------------------------------------------------------- */ 685582bec1SHong Zhang /* 695582bec1SHong Zhang PCSetUp_ML - Prepares for the use of the ML preconditioner 705582bec1SHong Zhang by setting data structures and options. 715582bec1SHong Zhang 725582bec1SHong Zhang Input Parameter: 735582bec1SHong Zhang . pc - the preconditioner context 745582bec1SHong Zhang 755582bec1SHong Zhang Application Interface Routine: PCSetUp() 765582bec1SHong Zhang 775582bec1SHong Zhang Notes: 785582bec1SHong Zhang The interface routine PCSetUp() is not usually called directly by 795582bec1SHong Zhang the user, but instead is called by PCApply() if necessary. 805582bec1SHong Zhang */ 816ca4d86aSHong Zhang extern PetscErrorCode PCSetFromOptions_MG(PC); 825582bec1SHong Zhang #undef __FUNCT__ 835582bec1SHong Zhang #define __FUNCT__ "PCSetUp_ML" 846ca4d86aSHong Zhang PetscErrorCode PCSetUp_ML(PC pc) 855582bec1SHong Zhang { 865582bec1SHong Zhang PetscErrorCode ierr; 87eef31507SHong Zhang PetscMPIInt size; 885582bec1SHong Zhang FineGridCtx *PetscMLdata; 895582bec1SHong Zhang ML *ml_object; 905582bec1SHong Zhang ML_Aggregate *agg_object; 915582bec1SHong Zhang ML_Operator *mlmat; 92ac346b81SHong Zhang PetscInt nlocal_allcols,Nlevels,mllevel,level,level1,m,fine_level; 935582bec1SHong Zhang Mat A,Aloc; 945582bec1SHong Zhang GridCtx *gridctx; 955582bec1SHong Zhang PC_ML *pc_ml=PETSC_NULL; 96776b82aeSLisandro Dalcin PetscContainer container; 97573998d7SHong Zhang MatReuse reuse = MAT_INITIAL_MATRIX; 985582bec1SHong Zhang 995582bec1SHong Zhang PetscFunctionBegin; 1005582bec1SHong Zhang ierr = PetscObjectQuery((PetscObject)pc,"PC_ML",(PetscObject *)&container);CHKERRQ(ierr); 1015582bec1SHong Zhang if (container) { 102776b82aeSLisandro Dalcin ierr = PetscContainerGetPointer(container,(void **)&pc_ml);CHKERRQ(ierr); 1035582bec1SHong Zhang } else { 1045582bec1SHong Zhang SETERRQ(PETSC_ERR_ARG_NULL,"Container does not exit"); 1055582bec1SHong Zhang } 1065582bec1SHong Zhang 107573998d7SHong Zhang if (pc->setupcalled){ 108573998d7SHong Zhang if (pc->flag == SAME_NONZERO_PATTERN){ 109573998d7SHong Zhang reuse = MAT_REUSE_MATRIX; 110573998d7SHong Zhang PetscMLdata = pc_ml->PetscMLdata; 111573998d7SHong Zhang gridctx = pc_ml->gridctx; 112573998d7SHong Zhang /* ML objects cannot be reused */ 113573998d7SHong Zhang ML_Destroy(&pc_ml->ml_object); 114573998d7SHong Zhang ML_Aggregate_Destroy(&pc_ml->agg_object); 115573998d7SHong Zhang } else { 116573998d7SHong Zhang PC_ML *pc_ml_new = PETSC_NULL; 117573998d7SHong Zhang PetscContainer container_new; 11838f2d2fdSLisandro Dalcin ierr = PetscNewLog(pc,PC_ML,&pc_ml_new);CHKERRQ(ierr); 119573998d7SHong Zhang ierr = PetscContainerCreate(PETSC_COMM_SELF,&container_new);CHKERRQ(ierr); 120573998d7SHong Zhang ierr = PetscContainerSetPointer(container_new,pc_ml_new);CHKERRQ(ierr); 121573998d7SHong Zhang ierr = PetscContainerSetUserDestroy(container_new,PetscContainerDestroy_PC_ML);CHKERRQ(ierr); 122573998d7SHong Zhang ierr = PetscObjectCompose((PetscObject)pc,"PC_ML",(PetscObject)container_new);CHKERRQ(ierr); 123573998d7SHong Zhang 124573998d7SHong Zhang ierr = PetscMemcpy(pc_ml_new,pc_ml,sizeof(PC_ML));CHKERRQ(ierr); 125573998d7SHong Zhang ierr = PetscContainerDestroy(container);CHKERRQ(ierr); 126573998d7SHong Zhang pc_ml = pc_ml_new; 127573998d7SHong Zhang } 128573998d7SHong Zhang } 129573998d7SHong Zhang 1305582bec1SHong Zhang /* setup special features of PCML */ 1315582bec1SHong Zhang /*--------------------------------*/ 1325582bec1SHong Zhang /* covert A to Aloc to be used by ML at fine grid */ 1335582bec1SHong Zhang A = pc->pmat; 1347adad957SLisandro Dalcin ierr = MPI_Comm_size(((PetscObject)A)->comm,&size);CHKERRQ(ierr); 1355582bec1SHong Zhang pc_ml->size = size; 1365582bec1SHong Zhang if (size > 1){ 137573998d7SHong Zhang if (reuse) Aloc = PetscMLdata->Aloc; 138573998d7SHong Zhang ierr = MatConvert_MPIAIJ_ML(A,PETSC_NULL,reuse,&Aloc);CHKERRQ(ierr); 1395582bec1SHong Zhang } else { 1405582bec1SHong Zhang Aloc = A; 1415582bec1SHong Zhang } 1425582bec1SHong Zhang 1435582bec1SHong Zhang /* create and initialize struct 'PetscMLdata' */ 144573998d7SHong Zhang if (!reuse){ 14538f2d2fdSLisandro Dalcin ierr = PetscNewLog(pc,FineGridCtx,&PetscMLdata);CHKERRQ(ierr); 1465582bec1SHong Zhang pc_ml->PetscMLdata = PetscMLdata; 147573998d7SHong Zhang ierr = PetscMalloc((Aloc->cmap.n+1)*sizeof(PetscScalar),&PetscMLdata->pwork);CHKERRQ(ierr); 1485582bec1SHong Zhang 14924a42b14SHong Zhang ierr = VecCreate(PETSC_COMM_SELF,&PetscMLdata->x);CHKERRQ(ierr); 150a803a431SHong Zhang ierr = VecSetSizes(PetscMLdata->x,Aloc->cmap.n,Aloc->cmap.n);CHKERRQ(ierr); 15124a42b14SHong Zhang ierr = VecSetType(PetscMLdata->x,VECSEQ);CHKERRQ(ierr); 15224a42b14SHong Zhang 15324a42b14SHong Zhang ierr = VecCreate(PETSC_COMM_SELF,&PetscMLdata->y);CHKERRQ(ierr); 154a803a431SHong Zhang ierr = VecSetSizes(PetscMLdata->y,A->rmap.n,PETSC_DECIDE);CHKERRQ(ierr); 15524a42b14SHong Zhang ierr = VecSetType(PetscMLdata->y,VECSEQ);CHKERRQ(ierr); 156573998d7SHong Zhang } 157573998d7SHong Zhang PetscMLdata->A = A; 158573998d7SHong Zhang PetscMLdata->Aloc = Aloc; 15924a42b14SHong Zhang 1605582bec1SHong Zhang /* create ML discretization matrix at fine grid */ 16145cf47abSHong Zhang /* ML requires input of fine-grid matrix. It determines nlevels. */ 1625582bec1SHong Zhang ierr = MatGetSize(Aloc,&m,&nlocal_allcols);CHKERRQ(ierr); 1635582bec1SHong Zhang ML_Create(&ml_object,pc_ml->MaxNlevels); 164573998d7SHong Zhang pc_ml->ml_object = ml_object; 1655582bec1SHong Zhang ML_Init_Amatrix(ml_object,0,m,m,PetscMLdata); 1665582bec1SHong Zhang ML_Set_Amatrix_Getrow(ml_object,0,PetscML_getrow,PetscML_comm,nlocal_allcols); 1675582bec1SHong Zhang ML_Set_Amatrix_Matvec(ml_object,0,PetscML_matvec); 1685582bec1SHong Zhang 1695582bec1SHong Zhang /* aggregation */ 1705582bec1SHong Zhang ML_Aggregate_Create(&agg_object); 171573998d7SHong Zhang pc_ml->agg_object = agg_object; 172573998d7SHong Zhang 1735582bec1SHong Zhang ML_Aggregate_Set_MaxCoarseSize(agg_object,pc_ml->MaxCoarseSize); 1745582bec1SHong Zhang /* set options */ 1755582bec1SHong Zhang switch (pc_ml->CoarsenScheme) { 1765582bec1SHong Zhang case 1: 1775582bec1SHong Zhang ML_Aggregate_Set_CoarsenScheme_Coupled(agg_object);break; 1785582bec1SHong Zhang case 2: 1795582bec1SHong Zhang ML_Aggregate_Set_CoarsenScheme_MIS(agg_object);break; 1805582bec1SHong Zhang case 3: 1815582bec1SHong Zhang ML_Aggregate_Set_CoarsenScheme_METIS(agg_object);break; 1825582bec1SHong Zhang } 1835582bec1SHong Zhang ML_Aggregate_Set_Threshold(agg_object,pc_ml->Threshold); 1845582bec1SHong Zhang ML_Aggregate_Set_DampingFactor(agg_object,pc_ml->DampingFactor); 1855582bec1SHong Zhang if (pc_ml->SpectralNormScheme_Anorm){ 1865582bec1SHong Zhang ML_Aggregate_Set_SpectralNormScheme_Anorm(agg_object); 1875582bec1SHong Zhang } 1885582bec1SHong Zhang 1895582bec1SHong Zhang Nlevels = ML_Gen_MGHierarchy_UsingAggregation(ml_object,0,ML_INCREASING,agg_object); 1905582bec1SHong Zhang if (Nlevels<=0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Nlevels %d must > 0",Nlevels); 191573998d7SHong Zhang if (pc->setupcalled && pc_ml->Nlevels != Nlevels) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"previous Nlevels %D and current Nlevels %d must be same", pc_ml->Nlevels,Nlevels); 192573998d7SHong Zhang pc_ml->Nlevels = Nlevels; 193573998d7SHong Zhang if (!pc->setupcalled){ 19497177400SBarry Smith ierr = PCMGSetLevels(pc,Nlevels,PETSC_NULL);CHKERRQ(ierr); 19597177400SBarry Smith ierr = PCSetFromOptions_MG(pc);CHKERRQ(ierr); /* should be called in PCSetFromOptions_ML(), but cannot be called prior to PCMGSetLevels() */ 196573998d7SHong Zhang } 1975582bec1SHong Zhang 198573998d7SHong Zhang if (!reuse){ 1995582bec1SHong Zhang ierr = PetscMalloc(Nlevels*sizeof(GridCtx),&gridctx);CHKERRQ(ierr); 2005582bec1SHong Zhang pc_ml->gridctx = gridctx; 201573998d7SHong Zhang } 202573998d7SHong Zhang fine_level = Nlevels - 1; 2035582bec1SHong Zhang 2045582bec1SHong Zhang /* wrap ML matrices by PETSc shell matrices at coarsened grids. 2055582bec1SHong Zhang Level 0 is the finest grid for ML, but coarsest for PETSc! */ 206e14861a4SHong Zhang gridctx[fine_level].A = A; 207573998d7SHong Zhang 208e14861a4SHong Zhang level = fine_level - 1; 209ab718edeSHong Zhang if (size == 1){ /* convert ML P, R and A into seqaij format */ 2105582bec1SHong Zhang for (mllevel=1; mllevel<Nlevels; mllevel++){ 211e14861a4SHong Zhang mlmat = &(ml_object->Pmat[mllevel]); 212573998d7SHong Zhang ierr = MatWrapML_SeqAIJ(mlmat,reuse,&gridctx[level].P);CHKERRQ(ierr); 213e14861a4SHong Zhang mlmat = &(ml_object->Rmat[mllevel-1]); 214573998d7SHong Zhang ierr = MatWrapML_SeqAIJ(mlmat,reuse,&gridctx[level].R);CHKERRQ(ierr); 215573998d7SHong Zhang 216573998d7SHong Zhang mlmat = &(ml_object->Amat[mllevel]); 217573998d7SHong Zhang if (reuse){ 218573998d7SHong Zhang /* ML matrix A changes sparse pattern although PETSc A doesn't, thus gridctx[level].A must be recreated! */ 219573998d7SHong Zhang ierr = MatDestroy(gridctx[level].A);CHKERRQ(ierr); 220573998d7SHong Zhang } 221573998d7SHong Zhang ierr = MatWrapML_SeqAIJ(mlmat,MAT_INITIAL_MATRIX,&gridctx[level].A);CHKERRQ(ierr); 2225582bec1SHong Zhang level--; 2235582bec1SHong Zhang } 224ab718edeSHong Zhang } else { /* convert ML P and R into shell format, ML A into mpiaij format */ 2255582bec1SHong Zhang for (mllevel=1; mllevel<Nlevels; mllevel++){ 2265582bec1SHong Zhang mlmat = &(ml_object->Pmat[mllevel]); 227573998d7SHong Zhang ierr = MatWrapML_SHELL(mlmat,reuse,&gridctx[level].P);CHKERRQ(ierr); 228ab718edeSHong Zhang mlmat = &(ml_object->Rmat[mllevel-1]); 229573998d7SHong Zhang ierr = MatWrapML_SHELL(mlmat,reuse,&gridctx[level].R);CHKERRQ(ierr); 230573998d7SHong Zhang 2315582bec1SHong Zhang mlmat = &(ml_object->Amat[mllevel]); 232573998d7SHong Zhang if (reuse){ 233573998d7SHong Zhang ierr = MatDestroy(gridctx[level].A);CHKERRQ(ierr); 234573998d7SHong Zhang } 235eef31507SHong Zhang ierr = MatWrapML_MPIAIJ(mlmat,&gridctx[level].A);CHKERRQ(ierr); 2365582bec1SHong Zhang level--; 2375582bec1SHong Zhang } 2385582bec1SHong Zhang } 2395582bec1SHong Zhang 240573998d7SHong Zhang /* create vectors and ksp at all levels */ 241573998d7SHong Zhang if (!reuse){ 242ac346b81SHong Zhang for (level=0; level<fine_level; level++){ 243573998d7SHong Zhang level1 = level + 1; 244*e64afeacSLisandro Dalcin ierr = VecCreate(((PetscObject)gridctx[level].A)->comm,&gridctx[level].x);CHKERRQ(ierr); 245a803a431SHong Zhang ierr = VecSetSizes(gridctx[level].x,gridctx[level].A->cmap.n,PETSC_DECIDE);CHKERRQ(ierr); 2465582bec1SHong Zhang ierr = VecSetType(gridctx[level].x,VECMPI);CHKERRQ(ierr); 24797177400SBarry Smith ierr = PCMGSetX(pc,level,gridctx[level].x);CHKERRQ(ierr); 2485582bec1SHong Zhang 249*e64afeacSLisandro Dalcin ierr = VecCreate(((PetscObject)gridctx[level].A)->comm,&gridctx[level].b);CHKERRQ(ierr); 250a803a431SHong Zhang ierr = VecSetSizes(gridctx[level].b,gridctx[level].A->rmap.n,PETSC_DECIDE);CHKERRQ(ierr); 2515582bec1SHong Zhang ierr = VecSetType(gridctx[level].b,VECMPI);CHKERRQ(ierr); 25297177400SBarry Smith ierr = PCMGSetRhs(pc,level,gridctx[level].b);CHKERRQ(ierr); 253ac346b81SHong Zhang 254*e64afeacSLisandro Dalcin ierr = VecCreate(((PetscObject)gridctx[level1].A)->comm,&gridctx[level1].r);CHKERRQ(ierr); 255a803a431SHong Zhang ierr = VecSetSizes(gridctx[level1].r,gridctx[level1].A->rmap.n,PETSC_DECIDE);CHKERRQ(ierr); 256ac346b81SHong Zhang ierr = VecSetType(gridctx[level1].r,VECMPI);CHKERRQ(ierr); 25797177400SBarry Smith ierr = PCMGSetR(pc,level1,gridctx[level1].r);CHKERRQ(ierr); 258ac346b81SHong Zhang 2595582bec1SHong Zhang if (level == 0){ 26097177400SBarry Smith ierr = PCMGGetCoarseSolve(pc,&gridctx[level].ksp);CHKERRQ(ierr); 2615582bec1SHong Zhang } else { 26297177400SBarry Smith ierr = PCMGGetSmoother(pc,level,&gridctx[level].ksp);CHKERRQ(ierr); 263573998d7SHong Zhang } 264573998d7SHong Zhang } 265573998d7SHong Zhang ierr = PCMGGetSmoother(pc,fine_level,&gridctx[fine_level].ksp);CHKERRQ(ierr); 266573998d7SHong Zhang } 267573998d7SHong Zhang 268573998d7SHong Zhang /* create coarse level and the interpolation between the levels */ 269573998d7SHong Zhang for (level=0; level<fine_level; level++){ 270573998d7SHong Zhang level1 = level + 1; 271aea2a34eSBarry Smith ierr = PCMGSetInterpolation(pc,level1,gridctx[level].P);CHKERRQ(ierr); 272573998d7SHong Zhang ierr = PCMGSetRestriction(pc,level1,gridctx[level].R);CHKERRQ(ierr); 273573998d7SHong Zhang if (level > 0){ 27497177400SBarry Smith ierr = PCMGSetResidual(pc,level,PCMGDefaultResidual,gridctx[level].A);CHKERRQ(ierr); 2755582bec1SHong Zhang } 2765582bec1SHong Zhang ierr = KSPSetOperators(gridctx[level].ksp,gridctx[level].A,gridctx[level].A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 2775582bec1SHong Zhang } 27897177400SBarry Smith ierr = PCMGSetResidual(pc,fine_level,PCMGDefaultResidual,gridctx[fine_level].A);CHKERRQ(ierr); 279ac346b81SHong Zhang ierr = KSPSetOperators(gridctx[fine_level].ksp,gridctx[level].A,gridctx[fine_level].A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 2805582bec1SHong Zhang 2815582bec1SHong Zhang /* now call PCSetUp_MG() */ 282573998d7SHong Zhang /*-------------------------------*/ 2835582bec1SHong Zhang ierr = (*pc_ml->PCSetUp)(pc);CHKERRQ(ierr); 2845582bec1SHong Zhang PetscFunctionReturn(0); 2855582bec1SHong Zhang } 2865582bec1SHong Zhang 2875582bec1SHong Zhang #undef __FUNCT__ 288776b82aeSLisandro Dalcin #define __FUNCT__ "PetscContainerDestroy_PC_ML" 289776b82aeSLisandro Dalcin PetscErrorCode PetscContainerDestroy_PC_ML(void *ptr) 2905582bec1SHong Zhang { 2915582bec1SHong Zhang PetscErrorCode ierr; 2925582bec1SHong Zhang PC_ML *pc_ml = (PC_ML*)ptr; 293573998d7SHong Zhang PetscInt level,fine_level=pc_ml->Nlevels-1; 2945582bec1SHong Zhang 2955582bec1SHong Zhang PetscFunctionBegin; 2965582bec1SHong Zhang ML_Aggregate_Destroy(&pc_ml->agg_object); 2975582bec1SHong Zhang ML_Destroy(&pc_ml->ml_object); 2985582bec1SHong Zhang 29938f2d2fdSLisandro Dalcin if (pc_ml->PetscMLdata) { 3005582bec1SHong Zhang ierr = PetscFree(pc_ml->PetscMLdata->pwork);CHKERRQ(ierr); 30138f2d2fdSLisandro Dalcin if (pc_ml->size > 1) {ierr = MatDestroy(pc_ml->PetscMLdata->Aloc);CHKERRQ(ierr);} 302ac346b81SHong Zhang if (pc_ml->PetscMLdata->x){ierr = VecDestroy(pc_ml->PetscMLdata->x);CHKERRQ(ierr);} 303ac346b81SHong Zhang if (pc_ml->PetscMLdata->y){ierr = VecDestroy(pc_ml->PetscMLdata->y);CHKERRQ(ierr);} 30438f2d2fdSLisandro Dalcin } 3055582bec1SHong Zhang ierr = PetscFree(pc_ml->PetscMLdata);CHKERRQ(ierr); 3065582bec1SHong Zhang 307573998d7SHong Zhang for (level=0; level<fine_level; level++){ 308ac346b81SHong Zhang if (pc_ml->gridctx[level].A){ierr = MatDestroy(pc_ml->gridctx[level].A);CHKERRQ(ierr);} 309ac346b81SHong Zhang if (pc_ml->gridctx[level].P){ierr = MatDestroy(pc_ml->gridctx[level].P);CHKERRQ(ierr);} 310ac346b81SHong Zhang if (pc_ml->gridctx[level].R){ierr = MatDestroy(pc_ml->gridctx[level].R);CHKERRQ(ierr);} 311ac346b81SHong Zhang if (pc_ml->gridctx[level].x){ierr = VecDestroy(pc_ml->gridctx[level].x);CHKERRQ(ierr);} 312ac346b81SHong Zhang if (pc_ml->gridctx[level].b){ierr = VecDestroy(pc_ml->gridctx[level].b);CHKERRQ(ierr);} 313ac346b81SHong Zhang if (pc_ml->gridctx[level+1].r){ierr = VecDestroy(pc_ml->gridctx[level+1].r);CHKERRQ(ierr);} 3145582bec1SHong Zhang } 3155582bec1SHong Zhang ierr = PetscFree(pc_ml->gridctx);CHKERRQ(ierr); 3165582bec1SHong Zhang ierr = PetscFree(pc_ml);CHKERRQ(ierr); 3175582bec1SHong Zhang PetscFunctionReturn(0); 3185582bec1SHong Zhang } 3195582bec1SHong Zhang /* -------------------------------------------------------------------------- */ 3205582bec1SHong Zhang /* 3215582bec1SHong Zhang PCDestroy_ML - Destroys the private context for the ML preconditioner 3225582bec1SHong Zhang that was created with PCCreate_ML(). 3235582bec1SHong Zhang 3245582bec1SHong Zhang Input Parameter: 3255582bec1SHong Zhang . pc - the preconditioner context 3265582bec1SHong Zhang 3275582bec1SHong Zhang Application Interface Routine: PCDestroy() 3285582bec1SHong Zhang */ 3295582bec1SHong Zhang #undef __FUNCT__ 3305582bec1SHong Zhang #define __FUNCT__ "PCDestroy_ML" 3316ca4d86aSHong Zhang PetscErrorCode PCDestroy_ML(PC pc) 3325582bec1SHong Zhang { 3335582bec1SHong Zhang PetscErrorCode ierr; 3345582bec1SHong Zhang PC_ML *pc_ml=PETSC_NULL; 335776b82aeSLisandro Dalcin PetscContainer container; 3365582bec1SHong Zhang 3375582bec1SHong Zhang PetscFunctionBegin; 3385582bec1SHong Zhang ierr = PetscObjectQuery((PetscObject)pc,"PC_ML",(PetscObject *)&container);CHKERRQ(ierr); 3395582bec1SHong Zhang if (container) { 340776b82aeSLisandro Dalcin ierr = PetscContainerGetPointer(container,(void **)&pc_ml);CHKERRQ(ierr); 3415582bec1SHong Zhang pc->ops->destroy = pc_ml->PCDestroy; 3425582bec1SHong Zhang } else { 3435582bec1SHong Zhang SETERRQ(PETSC_ERR_ARG_NULL,"Container does not exit"); 3445582bec1SHong Zhang } 3459cb0ec93SHong Zhang /* detach pc and PC_ML and dereference container */ 34638f2d2fdSLisandro Dalcin ierr = PetscContainerDestroy(container);CHKERRQ(ierr); 3475582bec1SHong Zhang ierr = PetscObjectCompose((PetscObject)pc,"PC_ML",0);CHKERRQ(ierr); 34838f2d2fdSLisandro Dalcin if (pc->ops->destroy) { 3495582bec1SHong Zhang ierr = (*pc->ops->destroy)(pc);CHKERRQ(ierr); 35038f2d2fdSLisandro Dalcin } 3515582bec1SHong Zhang PetscFunctionReturn(0); 3525582bec1SHong Zhang } 3535582bec1SHong Zhang 3545582bec1SHong Zhang #undef __FUNCT__ 3555582bec1SHong Zhang #define __FUNCT__ "PCSetFromOptions_ML" 3566ca4d86aSHong Zhang PetscErrorCode PCSetFromOptions_ML(PC pc) 3575582bec1SHong Zhang { 3585582bec1SHong Zhang PetscErrorCode ierr; 35938f2d2fdSLisandro Dalcin PetscInt indx,m,PrintLevel; 3605582bec1SHong Zhang PetscTruth flg; 3615582bec1SHong Zhang const char *scheme[] = {"Uncoupled","Coupled","MIS","METIS"}; 3625582bec1SHong Zhang PC_ML *pc_ml=PETSC_NULL; 363776b82aeSLisandro Dalcin PetscContainer container; 3649dcbbd2bSBarry Smith PCMGType mgtype; 3655582bec1SHong Zhang 3665582bec1SHong Zhang PetscFunctionBegin; 3675582bec1SHong Zhang ierr = PetscObjectQuery((PetscObject)pc,"PC_ML",(PetscObject *)&container);CHKERRQ(ierr); 3685582bec1SHong Zhang if (container) { 369776b82aeSLisandro Dalcin ierr = PetscContainerGetPointer(container,(void **)&pc_ml);CHKERRQ(ierr); 3705582bec1SHong Zhang } else { 3715582bec1SHong Zhang SETERRQ(PETSC_ERR_ARG_NULL,"Container does not exit"); 3725582bec1SHong Zhang } 3736ca4d86aSHong Zhang 3745582bec1SHong Zhang /* inherited MG options */ 3756ca4d86aSHong Zhang ierr = PetscOptionsHead("Multigrid options(inherited)");CHKERRQ(ierr); 3765582bec1SHong Zhang ierr = PetscOptionsInt("-pc_mg_cycles","1 for V cycle, 2 for W-cycle","MGSetCycles",1,&m,&flg);CHKERRQ(ierr); 3775582bec1SHong Zhang ierr = PetscOptionsInt("-pc_mg_smoothup","Number of post-smoothing steps","MGSetNumberSmoothUp",1,&m,&flg);CHKERRQ(ierr); 3785582bec1SHong Zhang ierr = PetscOptionsInt("-pc_mg_smoothdown","Number of pre-smoothing steps","MGSetNumberSmoothDown",1,&m,&flg);CHKERRQ(ierr); 3799dcbbd2bSBarry Smith ierr = PetscOptionsEnum("-pc_mg_type","Multigrid type","PCMGSetType",PCMGTypes,(PetscEnum)PC_MG_MULTIPLICATIVE,(PetscEnum*)&mgtype,&flg);CHKERRQ(ierr); 3805582bec1SHong Zhang ierr = PetscOptionsTail();CHKERRQ(ierr); 3815582bec1SHong Zhang 3825582bec1SHong Zhang /* ML options */ 3835582bec1SHong Zhang ierr = PetscOptionsHead("ML options");CHKERRQ(ierr); 3845582bec1SHong Zhang /* set defaults */ 3855582bec1SHong Zhang PrintLevel = 0; 3865582bec1SHong Zhang indx = 0; 3875582bec1SHong Zhang ierr = PetscOptionsInt("-pc_ml_PrintLevel","Print level","ML_Set_PrintLevel",PrintLevel,&PrintLevel,PETSC_NULL);CHKERRQ(ierr); 3885582bec1SHong Zhang ML_Set_PrintLevel(PrintLevel); 389573998d7SHong Zhang ierr = PetscOptionsInt("-pc_ml_maxNlevels","Maximum number of levels","None",pc_ml->MaxNlevels,&pc_ml->MaxNlevels,PETSC_NULL);CHKERRQ(ierr); 390573998d7SHong Zhang ierr = PetscOptionsInt("-pc_ml_maxCoarseSize","Maximum coarsest mesh size","ML_Aggregate_Set_MaxCoarseSize",pc_ml->MaxCoarseSize,&pc_ml->MaxCoarseSize,PETSC_NULL);CHKERRQ(ierr); 391573998d7SHong Zhang ierr = PetscOptionsEList("-pc_ml_CoarsenScheme","Aggregate Coarsen Scheme","ML_Aggregate_Set_CoarsenScheme_*",scheme,4,scheme[0],&indx,PETSC_NULL);CHKERRQ(ierr); /* ??? */ 3925582bec1SHong Zhang pc_ml->CoarsenScheme = indx; 3935582bec1SHong Zhang 394573998d7SHong Zhang ierr = PetscOptionsReal("-pc_ml_DampingFactor","P damping factor","ML_Aggregate_Set_DampingFactor",pc_ml->DampingFactor,&pc_ml->DampingFactor,PETSC_NULL);CHKERRQ(ierr); 3955582bec1SHong Zhang 396573998d7SHong Zhang ierr = PetscOptionsReal("-pc_ml_Threshold","Smoother drop tol","ML_Aggregate_Set_Threshold",pc_ml->Threshold,&pc_ml->Threshold,PETSC_NULL);CHKERRQ(ierr); 3975582bec1SHong Zhang 398573998d7SHong Zhang ierr = PetscOptionsTruth("-pc_ml_SpectralNormScheme_Anorm","Method used for estimating spectral radius","ML_Aggregate_Set_SpectralNormScheme_Anorm",pc_ml->SpectralNormScheme_Anorm,&pc_ml->SpectralNormScheme_Anorm,PETSC_NULL); 3995582bec1SHong Zhang 4005582bec1SHong Zhang ierr = PetscOptionsTail();CHKERRQ(ierr); 4015582bec1SHong Zhang PetscFunctionReturn(0); 4025582bec1SHong Zhang } 4035582bec1SHong Zhang 4045582bec1SHong Zhang /* -------------------------------------------------------------------------- */ 4055582bec1SHong Zhang /* 4065582bec1SHong Zhang PCCreate_ML - Creates a ML preconditioner context, PC_ML, 4075582bec1SHong Zhang and sets this as the private data within the generic preconditioning 4085582bec1SHong Zhang context, PC, that was created within PCCreate(). 4095582bec1SHong Zhang 4105582bec1SHong Zhang Input Parameter: 4115582bec1SHong Zhang . pc - the preconditioner context 4125582bec1SHong Zhang 4135582bec1SHong Zhang Application Interface Routine: PCCreate() 4145582bec1SHong Zhang */ 4155582bec1SHong Zhang 4165582bec1SHong Zhang /*MC 4171e5ab15bSHong Zhang PCML - Use algebraic multigrid preconditioning. This preconditioner requires you provide 4185582bec1SHong Zhang fine grid discretization matrix. The coarser grid matrices and restriction/interpolation 4196ca4d86aSHong Zhang operators are computed by ML, with the matrices coverted to PETSc matrices in aij format 4206ca4d86aSHong Zhang and the restriction/interpolation operators wrapped as PETSc shell matrices. 4215582bec1SHong Zhang 4226ca4d86aSHong Zhang Options Database Key: 4236ca4d86aSHong Zhang Multigrid options(inherited) 4246ca4d86aSHong Zhang + -pc_mg_cycles <1>: 1 for V cycle, 2 for W-cycle (MGSetCycles) 4256ca4d86aSHong Zhang . -pc_mg_smoothup <1>: Number of post-smoothing steps (MGSetNumberSmoothUp) 4266ca4d86aSHong Zhang . -pc_mg_smoothdown <1>: Number of pre-smoothing steps (MGSetNumberSmoothDown) 427f41ab451SVictor Eijkhout - -pc_mg_type <multiplicative>: (one of) additive multiplicative full cascade kascade 4286ca4d86aSHong Zhang 42951f519a2SBarry Smith ML options: 4306ca4d86aSHong Zhang + -pc_ml_PrintLevel <0>: Print level (ML_Set_PrintLevel) 4316ca4d86aSHong Zhang . -pc_ml_maxNlevels <10>: Maximum number of levels (None) 4326ca4d86aSHong Zhang . -pc_ml_maxCoarseSize <1>: Maximum coarsest mesh size (ML_Aggregate_Set_MaxCoarseSize) 433f41ab451SVictor Eijkhout . -pc_ml_CoarsenScheme <Uncoupled>: (one of) Uncoupled Coupled MIS METIS 4346ca4d86aSHong Zhang . -pc_ml_DampingFactor <1.33333>: P damping factor (ML_Aggregate_Set_DampingFactor) 4356ca4d86aSHong Zhang . -pc_ml_Threshold <0>: Smoother drop tol (ML_Aggregate_Set_Threshold) 436f41ab451SVictor Eijkhout - -pc_ml_SpectralNormScheme_Anorm <false>: Method used for estimating spectral radius (ML_Aggregate_Set_SpectralNormScheme_Anorm) 4375582bec1SHong Zhang 4385582bec1SHong Zhang Level: intermediate 4395582bec1SHong Zhang 4405582bec1SHong Zhang Concepts: multigrid 4415582bec1SHong Zhang 4425582bec1SHong Zhang .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, PCMGType, 44397177400SBarry Smith PCMGSetLevels(), PCMGGetLevels(), PCMGSetType(), MPSetCycles(), PCMGSetNumberSmoothDown(), 44497177400SBarry Smith PCMGSetNumberSmoothUp(), PCMGGetCoarseSolve(), PCMGSetResidual(), PCMGSetInterpolation(), 44597177400SBarry Smith PCMGSetRestriction(), PCMGGetSmoother(), PCMGGetSmootherUp(), PCMGGetSmootherDown(), 44697177400SBarry Smith PCMGSetCyclesOnLevel(), PCMGSetRhs(), PCMGSetX(), PCMGSetR() 4475582bec1SHong Zhang M*/ 4485582bec1SHong Zhang 4495582bec1SHong Zhang EXTERN_C_BEGIN 4505582bec1SHong Zhang #undef __FUNCT__ 4515582bec1SHong Zhang #define __FUNCT__ "PCCreate_ML" 452dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_ML(PC pc) 4535582bec1SHong Zhang { 4545582bec1SHong Zhang PetscErrorCode ierr; 4555582bec1SHong Zhang PC_ML *pc_ml; 456776b82aeSLisandro Dalcin PetscContainer container; 4575582bec1SHong Zhang 4585582bec1SHong Zhang PetscFunctionBegin; 459573998d7SHong Zhang /* PCML is an inherited class of PCMG. Initialize pc as PCMG */ 4605582bec1SHong Zhang ierr = PCSetType(pc,PCMG);CHKERRQ(ierr); /* calls PCCreate_MG() and MGCreate_Private() */ 4615582bec1SHong Zhang 4625582bec1SHong Zhang /* create a supporting struct and attach it to pc */ 46338f2d2fdSLisandro Dalcin ierr = PetscNewLog(pc,PC_ML,&pc_ml);CHKERRQ(ierr); 464776b82aeSLisandro Dalcin ierr = PetscContainerCreate(PETSC_COMM_SELF,&container);CHKERRQ(ierr); 465776b82aeSLisandro Dalcin ierr = PetscContainerSetPointer(container,pc_ml);CHKERRQ(ierr); 466776b82aeSLisandro Dalcin ierr = PetscContainerSetUserDestroy(container,PetscContainerDestroy_PC_ML);CHKERRQ(ierr); 4675582bec1SHong Zhang ierr = PetscObjectCompose((PetscObject)pc,"PC_ML",(PetscObject)container);CHKERRQ(ierr); 4685582bec1SHong Zhang 469573998d7SHong Zhang pc_ml->ml_object = 0; 470573998d7SHong Zhang pc_ml->agg_object = 0; 471573998d7SHong Zhang pc_ml->gridctx = 0; 472573998d7SHong Zhang pc_ml->PetscMLdata = 0; 473573998d7SHong Zhang pc_ml->Nlevels = -1; 474573998d7SHong Zhang pc_ml->MaxNlevels = 10; 475573998d7SHong Zhang pc_ml->MaxCoarseSize = 1; 476573998d7SHong Zhang pc_ml->CoarsenScheme = 1; /* ??? */ 477573998d7SHong Zhang pc_ml->Threshold = 0.0; 478573998d7SHong Zhang pc_ml->DampingFactor = 4.0/3.0; 479573998d7SHong Zhang pc_ml->SpectralNormScheme_Anorm = PETSC_FALSE; 480573998d7SHong Zhang pc_ml->size = 0; 481573998d7SHong Zhang 4825582bec1SHong Zhang pc_ml->PCSetUp = pc->ops->setup; 4835582bec1SHong Zhang pc_ml->PCDestroy = pc->ops->destroy; 4845582bec1SHong Zhang 4855582bec1SHong Zhang /* overwrite the pointers of PCMG by the functions of PCML */ 4865582bec1SHong Zhang pc->ops->setfromoptions = PCSetFromOptions_ML; 4875582bec1SHong Zhang pc->ops->setup = PCSetUp_ML; 4885582bec1SHong Zhang pc->ops->destroy = PCDestroy_ML; 4895582bec1SHong Zhang PetscFunctionReturn(0); 4905582bec1SHong Zhang } 4915582bec1SHong Zhang EXTERN_C_END 4925582bec1SHong Zhang 49341ca0015SHong Zhang int PetscML_getrow(ML_Operator *ML_data, int N_requested_rows, int requested_rows[], 4945582bec1SHong Zhang int allocated_space, int columns[], double values[], int row_lengths[]) 4955582bec1SHong Zhang { 4965582bec1SHong Zhang PetscErrorCode ierr; 4975582bec1SHong Zhang Mat Aloc; 4985582bec1SHong Zhang Mat_SeqAIJ *a; 4995582bec1SHong Zhang PetscInt m,i,j,k=0,row,*aj; 5005582bec1SHong Zhang PetscScalar *aa; 50141ca0015SHong Zhang FineGridCtx *ml=(FineGridCtx*)ML_Get_MyGetrowData(ML_data); 5025582bec1SHong Zhang 5035582bec1SHong Zhang Aloc = ml->Aloc; 5045582bec1SHong Zhang a = (Mat_SeqAIJ*)Aloc->data; 5055582bec1SHong Zhang ierr = MatGetSize(Aloc,&m,PETSC_NULL);CHKERRQ(ierr); 5065582bec1SHong Zhang 5075582bec1SHong Zhang for (i = 0; i<N_requested_rows; i++) { 5085582bec1SHong Zhang row = requested_rows[i]; 5095582bec1SHong Zhang row_lengths[i] = a->ilen[row]; 5105582bec1SHong Zhang if (allocated_space < k+row_lengths[i]) return(0); 5115582bec1SHong Zhang if ( (row >= 0) || (row <= (m-1)) ) { 5125582bec1SHong Zhang aj = a->j + a->i[row]; 5135582bec1SHong Zhang aa = a->a + a->i[row]; 5145582bec1SHong Zhang for (j=0; j<row_lengths[i]; j++){ 5155582bec1SHong Zhang columns[k] = aj[j]; 5165582bec1SHong Zhang values[k++] = aa[j]; 5175582bec1SHong Zhang } 5185582bec1SHong Zhang } 5195582bec1SHong Zhang } 5205582bec1SHong Zhang return(1); 5215582bec1SHong Zhang } 5225582bec1SHong Zhang 52341ca0015SHong Zhang int PetscML_matvec(ML_Operator *ML_data,int in_length,double p[],int out_length,double ap[]) 5245582bec1SHong Zhang { 5255582bec1SHong Zhang PetscErrorCode ierr; 52641ca0015SHong Zhang FineGridCtx *ml=(FineGridCtx*)ML_Get_MyMatvecData(ML_data); 5275582bec1SHong Zhang Mat A=ml->A, Aloc=ml->Aloc; 5285582bec1SHong Zhang PetscMPIInt size; 5295582bec1SHong Zhang PetscScalar *pwork=ml->pwork; 5305582bec1SHong Zhang PetscInt i; 5315582bec1SHong Zhang 5327adad957SLisandro Dalcin ierr = MPI_Comm_size(((PetscObject)A)->comm,&size);CHKERRQ(ierr); 5335582bec1SHong Zhang if (size == 1){ 53424a42b14SHong Zhang ierr = VecPlaceArray(ml->x,p);CHKERRQ(ierr); 5355582bec1SHong Zhang } else { 5365582bec1SHong Zhang for (i=0; i<in_length; i++) pwork[i] = p[i]; 5375582bec1SHong Zhang PetscML_comm(pwork,ml); 53824a42b14SHong Zhang ierr = VecPlaceArray(ml->x,pwork);CHKERRQ(ierr); 5395582bec1SHong Zhang } 54024a42b14SHong Zhang ierr = VecPlaceArray(ml->y,ap);CHKERRQ(ierr); 54124a42b14SHong Zhang ierr = MatMult(Aloc,ml->x,ml->y);CHKERRQ(ierr); 542957c941cSHong Zhang ierr = VecResetArray(ml->x);CHKERRQ(ierr); 543957c941cSHong Zhang ierr = VecResetArray(ml->y);CHKERRQ(ierr); 5445582bec1SHong Zhang return 0; 5455582bec1SHong Zhang } 5465582bec1SHong Zhang 5475582bec1SHong Zhang int PetscML_comm(double p[],void *ML_data) 5485582bec1SHong Zhang { 5495582bec1SHong Zhang PetscErrorCode ierr; 5505582bec1SHong Zhang FineGridCtx *ml=(FineGridCtx*)ML_data; 5515582bec1SHong Zhang Mat A=ml->A; 5525582bec1SHong Zhang Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 5535582bec1SHong Zhang PetscMPIInt size; 554a803a431SHong Zhang PetscInt i,in_length=A->rmap.n,out_length=ml->Aloc->cmap.n; 5555582bec1SHong Zhang PetscScalar *array; 5565582bec1SHong Zhang 5577adad957SLisandro Dalcin ierr = MPI_Comm_size(((PetscObject)A)->comm,&size);CHKERRQ(ierr); 5585582bec1SHong Zhang if (size == 1) return 0; 55924a42b14SHong Zhang 56024a42b14SHong Zhang ierr = VecPlaceArray(ml->y,p);CHKERRQ(ierr); 561ca9f406cSSatish Balay ierr = VecScatterBegin(a->Mvctx,ml->y,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 562ca9f406cSSatish Balay ierr = VecScatterEnd(a->Mvctx,ml->y,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5637d15518fSHong Zhang ierr = VecResetArray(ml->y);CHKERRQ(ierr); 5645582bec1SHong Zhang ierr = VecGetArray(a->lvec,&array);CHKERRQ(ierr); 5655582bec1SHong Zhang for (i=in_length; i<out_length; i++){ 5665582bec1SHong Zhang p[i] = array[i-in_length]; 5675582bec1SHong Zhang } 5687d15518fSHong Zhang ierr = VecRestoreArray(a->lvec,&array);CHKERRQ(ierr); 5695582bec1SHong Zhang return 0; 5705582bec1SHong Zhang } 5715582bec1SHong Zhang #undef __FUNCT__ 5725582bec1SHong Zhang #define __FUNCT__ "MatMult_ML" 5735582bec1SHong Zhang PetscErrorCode MatMult_ML(Mat A,Vec x,Vec y) 5745582bec1SHong Zhang { 5755582bec1SHong Zhang PetscErrorCode ierr; 5765582bec1SHong Zhang Mat_MLShell *shell; 5775582bec1SHong Zhang PetscScalar *xarray,*yarray; 5785582bec1SHong Zhang PetscInt x_length,y_length; 5795582bec1SHong Zhang 5805582bec1SHong Zhang PetscFunctionBegin; 581a146b4dcSHong Zhang ierr = MatShellGetContext(A,(void **)&shell);CHKERRQ(ierr); 5825582bec1SHong Zhang ierr = VecGetArray(x,&xarray);CHKERRQ(ierr); 5835582bec1SHong Zhang ierr = VecGetArray(y,&yarray);CHKERRQ(ierr); 5845582bec1SHong Zhang x_length = shell->mlmat->invec_leng; 5855582bec1SHong Zhang y_length = shell->mlmat->outvec_leng; 5865582bec1SHong Zhang 5875582bec1SHong Zhang ML_Operator_Apply(shell->mlmat,x_length,xarray,y_length,yarray); 5885582bec1SHong Zhang 5895582bec1SHong Zhang ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr); 5905582bec1SHong Zhang ierr = VecRestoreArray(y,&yarray);CHKERRQ(ierr); 5915582bec1SHong Zhang PetscFunctionReturn(0); 5925582bec1SHong Zhang } 5935582bec1SHong Zhang /* MatMultAdd_ML - Compute y = w + A*x */ 5945582bec1SHong Zhang #undef __FUNCT__ 5955582bec1SHong Zhang #define __FUNCT__ "MatMultAdd_ML" 5965582bec1SHong Zhang PetscErrorCode MatMultAdd_ML(Mat A,Vec x,Vec w,Vec y) 5975582bec1SHong Zhang { 5985582bec1SHong Zhang PetscErrorCode ierr; 5995582bec1SHong Zhang Mat_MLShell *shell; 6005582bec1SHong Zhang PetscScalar *xarray,*yarray; 6015582bec1SHong Zhang PetscInt x_length,y_length; 6025582bec1SHong Zhang 6035582bec1SHong Zhang PetscFunctionBegin; 604a146b4dcSHong Zhang ierr = MatShellGetContext(A,(void **)&shell);CHKERRQ(ierr); 6055582bec1SHong Zhang ierr = VecGetArray(x,&xarray);CHKERRQ(ierr); 6065582bec1SHong Zhang ierr = VecGetArray(y,&yarray);CHKERRQ(ierr); 6075582bec1SHong Zhang 6085582bec1SHong Zhang x_length = shell->mlmat->invec_leng; 6095582bec1SHong Zhang y_length = shell->mlmat->outvec_leng; 6105582bec1SHong Zhang 6115582bec1SHong Zhang ML_Operator_Apply(shell->mlmat,x_length,xarray,y_length,yarray); 6125582bec1SHong Zhang 6135582bec1SHong Zhang ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr); 6145582bec1SHong Zhang ierr = VecRestoreArray(y,&yarray);CHKERRQ(ierr); 615efb30889SBarry Smith ierr = VecAXPY(y,1.0,w);CHKERRQ(ierr); 6165582bec1SHong Zhang 6175582bec1SHong Zhang PetscFunctionReturn(0); 6185582bec1SHong Zhang } 6195582bec1SHong Zhang 6205582bec1SHong Zhang /* newtype is ignored because "ml" is not listed under Petsc MatType yet */ 6215582bec1SHong Zhang #undef __FUNCT__ 6225582bec1SHong Zhang #define __FUNCT__ "MatConvert_MPIAIJ_ML" 62375179d2cSHong Zhang PetscErrorCode MatConvert_MPIAIJ_ML(Mat A,MatType newtype,MatReuse scall,Mat *Aloc) 6245582bec1SHong Zhang { 6255582bec1SHong Zhang PetscErrorCode ierr; 6265582bec1SHong Zhang Mat_MPIAIJ *mpimat=(Mat_MPIAIJ*)A->data; 6275582bec1SHong Zhang Mat_SeqAIJ *mat,*a=(Mat_SeqAIJ*)(mpimat->A)->data,*b=(Mat_SeqAIJ*)(mpimat->B)->data; 6285582bec1SHong Zhang PetscInt *ai=a->i,*aj=a->j,*bi=b->i,*bj=b->j; 6295582bec1SHong Zhang PetscScalar *aa=a->a,*ba=b->a,*ca; 630a803a431SHong Zhang PetscInt am=A->rmap.n,an=A->cmap.n,i,j,k; 6315582bec1SHong Zhang PetscInt *ci,*cj,ncols; 6325582bec1SHong Zhang 6335582bec1SHong Zhang PetscFunctionBegin; 6345582bec1SHong Zhang if (am != an) SETERRQ2(PETSC_ERR_ARG_WRONG,"A must have a square diagonal portion, am: %d != an: %d",am,an); 6355582bec1SHong Zhang 6365582bec1SHong Zhang if (scall == MAT_INITIAL_MATRIX){ 6375582bec1SHong Zhang ierr = PetscMalloc((1+am)*sizeof(PetscInt),&ci);CHKERRQ(ierr); 6385582bec1SHong Zhang ci[0] = 0; 6395582bec1SHong Zhang for (i=0; i<am; i++){ 6405582bec1SHong Zhang ci[i+1] = ci[i] + (ai[i+1] - ai[i]) + (bi[i+1] - bi[i]); 6415582bec1SHong Zhang } 6425582bec1SHong Zhang ierr = PetscMalloc((1+ci[am])*sizeof(PetscInt),&cj);CHKERRQ(ierr); 6435582bec1SHong Zhang ierr = PetscMalloc((1+ci[am])*sizeof(PetscScalar),&ca);CHKERRQ(ierr); 6445582bec1SHong Zhang 6455582bec1SHong Zhang k = 0; 6465582bec1SHong Zhang for (i=0; i<am; i++){ 6475582bec1SHong Zhang /* diagonal portion of A */ 6485582bec1SHong Zhang ncols = ai[i+1] - ai[i]; 6495582bec1SHong Zhang for (j=0; j<ncols; j++) { 6505582bec1SHong Zhang cj[k] = *aj++; 6515582bec1SHong Zhang ca[k++] = *aa++; 6525582bec1SHong Zhang } 6535582bec1SHong Zhang /* off-diagonal portion of A */ 6545582bec1SHong Zhang ncols = bi[i+1] - bi[i]; 6555582bec1SHong Zhang for (j=0; j<ncols; j++) { 6565582bec1SHong Zhang cj[k] = an + (*bj); bj++; 6575582bec1SHong Zhang ca[k++] = *ba++; 6585582bec1SHong Zhang } 6595582bec1SHong Zhang } 6605582bec1SHong Zhang if (k != ci[am]) SETERRQ2(PETSC_ERR_ARG_WRONG,"k: %d != ci[am]: %d",k,ci[am]); 6615582bec1SHong Zhang 6625582bec1SHong Zhang /* put together the new matrix */ 663a803a431SHong Zhang an = mpimat->A->cmap.n+mpimat->B->cmap.n; 6645582bec1SHong Zhang ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,am,an,ci,cj,ca,Aloc);CHKERRQ(ierr); 6655582bec1SHong Zhang 6665582bec1SHong Zhang /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */ 6675582bec1SHong Zhang /* Since these are PETSc arrays, change flags to free them as necessary. */ 6685582bec1SHong Zhang mat = (Mat_SeqAIJ*)(*Aloc)->data; 6693756052fSSatish Balay mat->free_a = PETSC_TRUE; 6703756052fSSatish Balay mat->free_ij = PETSC_TRUE; 6713756052fSSatish Balay 6725582bec1SHong Zhang mat->nonew = 0; 6735582bec1SHong Zhang } else if (scall == MAT_REUSE_MATRIX){ 6745582bec1SHong Zhang mat=(Mat_SeqAIJ*)(*Aloc)->data; 6755582bec1SHong Zhang ci = mat->i; cj = mat->j; ca = mat->a; 6765582bec1SHong Zhang for (i=0; i<am; i++) { 6775582bec1SHong Zhang /* diagonal portion of A */ 6785582bec1SHong Zhang ncols = ai[i+1] - ai[i]; 6795582bec1SHong Zhang for (j=0; j<ncols; j++) *ca++ = *aa++; 6805582bec1SHong Zhang /* off-diagonal portion of A */ 6815582bec1SHong Zhang ncols = bi[i+1] - bi[i]; 6825582bec1SHong Zhang for (j=0; j<ncols; j++) *ca++ = *ba++; 6835582bec1SHong Zhang } 6845582bec1SHong Zhang } else { 6855582bec1SHong Zhang SETERRQ1(PETSC_ERR_ARG_WRONG,"Invalid MatReuse %d",(int)scall); 6865582bec1SHong Zhang } 6875582bec1SHong Zhang PetscFunctionReturn(0); 6885582bec1SHong Zhang } 6895582bec1SHong Zhang extern PetscErrorCode MatDestroy_Shell(Mat); 6905582bec1SHong Zhang #undef __FUNCT__ 6915582bec1SHong Zhang #define __FUNCT__ "MatDestroy_ML" 6925582bec1SHong Zhang PetscErrorCode MatDestroy_ML(Mat A) 6935582bec1SHong Zhang { 6945582bec1SHong Zhang PetscErrorCode ierr; 6955582bec1SHong Zhang Mat_MLShell *shell; 6965582bec1SHong Zhang 6975582bec1SHong Zhang PetscFunctionBegin; 698a146b4dcSHong Zhang ierr = MatShellGetContext(A,(void **)&shell);CHKERRQ(ierr); 6995582bec1SHong Zhang ierr = VecDestroy(shell->y);CHKERRQ(ierr); 7005582bec1SHong Zhang ierr = PetscFree(shell);CHKERRQ(ierr); 7015582bec1SHong Zhang ierr = MatDestroy_Shell(A);CHKERRQ(ierr); 702dbd8c25aSHong Zhang ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 7035582bec1SHong Zhang PetscFunctionReturn(0); 7045582bec1SHong Zhang } 7055582bec1SHong Zhang 7065582bec1SHong Zhang #undef __FUNCT__ 707eef31507SHong Zhang #define __FUNCT__ "MatWrapML_SeqAIJ" 708573998d7SHong Zhang PetscErrorCode MatWrapML_SeqAIJ(ML_Operator *mlmat,MatReuse reuse,Mat *newmat) 7095582bec1SHong Zhang { 710e14861a4SHong Zhang struct ML_CSR_MSRdata *matdata = (struct ML_CSR_MSRdata *)mlmat->data; 7115582bec1SHong Zhang PetscErrorCode ierr; 7123e826d7bSSatish Balay PetscInt m=mlmat->outvec_leng,n=mlmat->invec_leng,*nnz,nz_max; 713e14861a4SHong Zhang PetscInt *ml_cols=matdata->columns,*aj,i,j,k; 714e14861a4SHong Zhang PetscScalar *ml_vals=matdata->values,*aa; 7155582bec1SHong Zhang 7165582bec1SHong Zhang PetscFunctionBegin; 717e14861a4SHong Zhang if ( mlmat->getrow == NULL) SETERRQ(PETSC_ERR_ARG_NULL,"mlmat->getrow = NULL"); 718ab718edeSHong Zhang if (m != n){ /* ML Pmat and Rmat are in CSR format. Pass array pointers into SeqAIJ matrix */ 719573998d7SHong Zhang if (reuse){ 720573998d7SHong Zhang Mat_SeqAIJ *aij= (Mat_SeqAIJ*)(*newmat)->data; 721573998d7SHong Zhang aij->i = matdata->rowptr; 722573998d7SHong Zhang aij->j = ml_cols; 723573998d7SHong Zhang aij->a = ml_vals; 724573998d7SHong Zhang } else { 725e14861a4SHong Zhang ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,m,n,matdata->rowptr,ml_cols,ml_vals,newmat);CHKERRQ(ierr); 726573998d7SHong Zhang } 72724a42b14SHong Zhang PetscFunctionReturn(0); 72824a42b14SHong Zhang } 7295582bec1SHong Zhang 730e14861a4SHong Zhang /* ML Amat is in MSR format. Copy its data into SeqAIJ matrix */ 731f69a0ea3SMatthew Knepley ierr = MatCreate(PETSC_COMM_SELF,newmat);CHKERRQ(ierr); 732f69a0ea3SMatthew Knepley ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 7335582bec1SHong Zhang ierr = MatSetType(*newmat,MATSEQAIJ);CHKERRQ(ierr); 734e14861a4SHong Zhang 735573998d7SHong Zhang ierr = PetscMalloc((m+1)*sizeof(PetscInt),&nnz); 736573998d7SHong Zhang nz_max = 1; 7375582bec1SHong Zhang for (i=0; i<m; i++) { 738e14861a4SHong Zhang nnz[i] = ml_cols[i+1] - ml_cols[i] + 1; 739573998d7SHong Zhang if (nnz[i] > nz_max) nz_max += nnz[i]; 7405582bec1SHong Zhang } 7415582bec1SHong Zhang 742573998d7SHong Zhang ierr = MatSeqAIJSetPreallocation(*newmat,0,nnz);CHKERRQ(ierr); 7437c307921SBarry Smith ierr = PetscMalloc(nz_max*(sizeof(PetscInt)+sizeof(PetscScalar)),&aj);CHKERRQ(ierr); 744e14861a4SHong Zhang aa = (PetscScalar*)(aj + nz_max); 74524a42b14SHong Zhang 7465582bec1SHong Zhang for (i=0; i<m; i++){ 747e14861a4SHong Zhang k = 0; 748e14861a4SHong Zhang /* diagonal entry */ 749e14861a4SHong Zhang aj[k] = i; aa[k++] = ml_vals[i]; 750e14861a4SHong Zhang /* off diagonal entries */ 751e14861a4SHong Zhang for (j=ml_cols[i]; j<ml_cols[i+1]; j++){ 752e14861a4SHong Zhang aj[k] = ml_cols[j]; aa[k++] = ml_vals[j]; 75324a42b14SHong Zhang } 754ab718edeSHong Zhang /* sort aj and aa */ 755e14861a4SHong Zhang ierr = PetscSortIntWithScalarArray(nnz[i],aj,aa);CHKERRQ(ierr); 756e14861a4SHong Zhang ierr = MatSetValues(*newmat,1,&i,nnz[i],aj,aa,INSERT_VALUES);CHKERRQ(ierr); 7575582bec1SHong Zhang } 7585582bec1SHong Zhang ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 7595582bec1SHong Zhang ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 760573998d7SHong Zhang 761e14861a4SHong Zhang ierr = PetscFree(aj);CHKERRQ(ierr); 7623e826d7bSSatish Balay ierr = PetscFree(nnz);CHKERRQ(ierr); 7635582bec1SHong Zhang PetscFunctionReturn(0); 7645582bec1SHong Zhang } 7655582bec1SHong Zhang 7665582bec1SHong Zhang #undef __FUNCT__ 767eef31507SHong Zhang #define __FUNCT__ "MatWrapML_SHELL" 768573998d7SHong Zhang PetscErrorCode MatWrapML_SHELL(ML_Operator *mlmat,MatReuse reuse,Mat *newmat) 7695582bec1SHong Zhang { 7705582bec1SHong Zhang PetscErrorCode ierr; 7715582bec1SHong Zhang PetscInt m,n; 7725582bec1SHong Zhang ML_Comm *MLcomm; 7735582bec1SHong Zhang Mat_MLShell *shellctx; 7745582bec1SHong Zhang 7755582bec1SHong Zhang PetscFunctionBegin; 7765582bec1SHong Zhang m = mlmat->outvec_leng; 7775582bec1SHong Zhang n = mlmat->invec_leng; 7785582bec1SHong Zhang if (!m || !n){ 7795582bec1SHong Zhang newmat = PETSC_NULL; 780573998d7SHong Zhang PetscFunctionReturn(0); 781573998d7SHong Zhang } 782573998d7SHong Zhang 783573998d7SHong Zhang if (reuse){ 784573998d7SHong Zhang ierr = MatShellGetContext(*newmat,(void **)&shellctx);CHKERRQ(ierr); 785573998d7SHong Zhang shellctx->mlmat = mlmat; 786573998d7SHong Zhang PetscFunctionReturn(0); 787573998d7SHong Zhang } 788573998d7SHong Zhang 7895582bec1SHong Zhang MLcomm = mlmat->comm; 7905582bec1SHong Zhang ierr = PetscNew(Mat_MLShell,&shellctx);CHKERRQ(ierr); 7915582bec1SHong Zhang ierr = MatCreateShell(MLcomm->USR_comm,m,n,PETSC_DETERMINE,PETSC_DETERMINE,shellctx,newmat);CHKERRQ(ierr); 7923e826d7bSSatish Balay ierr = MatShellSetOperation(*newmat,MATOP_MULT,(void(*)(void))MatMult_ML);CHKERRQ(ierr); 7933e826d7bSSatish Balay ierr = MatShellSetOperation(*newmat,MATOP_MULT_ADD,(void(*)(void))MatMultAdd_ML);CHKERRQ(ierr); 7945582bec1SHong Zhang shellctx->A = *newmat; 7955582bec1SHong Zhang shellctx->mlmat = mlmat; 7965582bec1SHong Zhang ierr = VecCreate(PETSC_COMM_WORLD,&shellctx->y);CHKERRQ(ierr); 7975582bec1SHong Zhang ierr = VecSetSizes(shellctx->y,m,PETSC_DECIDE);CHKERRQ(ierr); 7985582bec1SHong Zhang ierr = VecSetFromOptions(shellctx->y);CHKERRQ(ierr); 7995582bec1SHong Zhang (*newmat)->ops->destroy = MatDestroy_ML; 8005582bec1SHong Zhang PetscFunctionReturn(0); 8015582bec1SHong Zhang } 802e14861a4SHong Zhang 803e14861a4SHong Zhang #undef __FUNCT__ 804eef31507SHong Zhang #define __FUNCT__ "MatWrapML_MPIAIJ" 805eef31507SHong Zhang PetscErrorCode MatWrapML_MPIAIJ(ML_Operator *mlmat,Mat *newmat) 806e14861a4SHong Zhang { 807ab718edeSHong Zhang struct ML_CSR_MSRdata *matdata = (struct ML_CSR_MSRdata *)mlmat->data; 808ab718edeSHong Zhang PetscInt *ml_cols=matdata->columns,*aj; 809ab718edeSHong Zhang PetscScalar *ml_vals=matdata->values,*aa; 810e14861a4SHong Zhang PetscErrorCode ierr; 811ab718edeSHong Zhang PetscInt i,j,k,*gordering; 8123e826d7bSSatish Balay PetscInt m=mlmat->outvec_leng,n,*nnzA,*nnzB,*nnz,nz_max,row; 813ab718edeSHong Zhang Mat A; 814e14861a4SHong Zhang 815e14861a4SHong Zhang PetscFunctionBegin; 816ab718edeSHong Zhang if (mlmat->getrow == NULL) SETERRQ(PETSC_ERR_ARG_NULL,"mlmat->getrow = NULL"); 817ab718edeSHong Zhang n = mlmat->invec_leng; 818e14861a4SHong Zhang if (m != n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"m %d must equal to n %d",m,n); 819e14861a4SHong Zhang 820f69a0ea3SMatthew Knepley ierr = MatCreate(mlmat->comm->USR_comm,&A);CHKERRQ(ierr); 821f69a0ea3SMatthew Knepley ierr = MatSetSizes(A,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 822ab718edeSHong Zhang ierr = MatSetType(A,MATMPIAIJ);CHKERRQ(ierr); 8233e826d7bSSatish Balay ierr = PetscMalloc3(m,PetscInt,&nnzA,m,PetscInt,&nnzB,m,PetscInt,&nnz);CHKERRQ(ierr); 8243e826d7bSSatish Balay 825e14861a4SHong Zhang nz_max = 0; 826e14861a4SHong Zhang for (i=0; i<m; i++){ 827ab718edeSHong Zhang nnz[i] = ml_cols[i+1] - ml_cols[i] + 1; 828e14861a4SHong Zhang if (nz_max < nnz[i]) nz_max = nnz[i]; 829ab718edeSHong Zhang nnzA[i] = 1; /* diag */ 830ab718edeSHong Zhang for (j=ml_cols[i]; j<ml_cols[i+1]; j++){ 831ab718edeSHong Zhang if (ml_cols[j] < m) nnzA[i]++; 832e14861a4SHong Zhang } 833e14861a4SHong Zhang nnzB[i] = nnz[i] - nnzA[i]; 834e14861a4SHong Zhang } 835ab718edeSHong Zhang ierr = MatMPIAIJSetPreallocation(A,0,nnzA,0,nnzB);CHKERRQ(ierr); 836e14861a4SHong Zhang 837ab718edeSHong Zhang /* insert mat values -- remap row and column indices */ 838ab718edeSHong Zhang nz_max++; 8397c307921SBarry Smith ierr = PetscMalloc(nz_max*(sizeof(PetscInt)+sizeof(PetscScalar)),&aj);CHKERRQ(ierr); 840ab718edeSHong Zhang aa = (PetscScalar*)(aj + nz_max); 841510c6b62SHong Zhang /* create global row numbering for a ML_Operator */ 842510c6b62SHong Zhang ML_build_global_numbering(mlmat,&gordering,"rows"); 843e14861a4SHong Zhang for (i=0; i<m; i++){ 844e14861a4SHong Zhang row = gordering[i]; 845ab718edeSHong Zhang k = 0; 846ab718edeSHong Zhang /* diagonal entry */ 847ab718edeSHong Zhang aj[k] = row; aa[k++] = ml_vals[i]; 848ab718edeSHong Zhang /* off diagonal entries */ 849ab718edeSHong Zhang for (j=ml_cols[i]; j<ml_cols[i+1]; j++){ 850ab718edeSHong Zhang aj[k] = gordering[ml_cols[j]]; aa[k++] = ml_vals[j]; 851e14861a4SHong Zhang } 852ab718edeSHong Zhang ierr = MatSetValues(A,1,&row,nnz[i],aj,aa,INSERT_VALUES);CHKERRQ(ierr); 853e14861a4SHong Zhang } 854ab718edeSHong Zhang ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 855ab718edeSHong Zhang ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 856ab718edeSHong Zhang *newmat = A; 857e14861a4SHong Zhang 8583e826d7bSSatish Balay ierr = PetscFree3(nnzA,nnzB,nnz); 859ab718edeSHong Zhang ierr = PetscFree(aj);CHKERRQ(ierr); 860e14861a4SHong Zhang PetscFunctionReturn(0); 861e14861a4SHong Zhang } 862