void PETScMGSolver_UpdateMatrices( PETScMGSolver* self ) { Stream* stream; PETScMGSolver_Level* level; PC pc; KSP levelKSP; PetscErrorCode ec; unsigned l_i; assert( self && Stg_CheckType( self, PETScMGSolver ) ); //assert( self->matrix && Stg_CheckType( self->matrix, PETScMatrix ) ); stream = Journal_Register( InfoStream_Type, (Name)"general" ); assert( stream ); Journal_Printf( stream, "Updating MG matrices ...\n" ); ec = KSPGetPC( self->mgData->ksp, &pc ); CheckPETScError( ec ); for( l_i = self->nLevels - 1; l_i < self->nLevels; l_i-- ) { level = self->levels + l_i; if( l_i == self->nLevels - 1 ) //level->A = (PETScMatrix*)self->matrix; level->A = self->mgData->matrix; else { if( level->A ) MatPtAP( self->levels[l_i + 1].A, self->levels[l_i + 1].P, MAT_REUSE_MATRIX, 1.0, &level->A ); else MatPtAP( self->levels[l_i + 1].A, self->levels[l_i + 1].P, MAT_INITIAL_MATRIX, 1.0, &level->A ); //Matrix_PtAP( self->levels[l_i + 1].A, self->levels[l_i + 1].P, (void**)&level->A ); /* if( self->levels[l_i + 1].P ) MatPtAP( self->levels[l_i + 1].A, self->levels[l_i + 1].P, MAT_REUSE_MATRIX, 1.0, &level->A ); else MatPtAP( self->levels[l_i + 1].A, self->levels[l_i + 1].P, MAT_INITIAL_MATRIX, 1.0, &level->A ); */ } ec = PCMGGetSmootherDown( pc, l_i, &levelKSP ); CheckPETScError( ec ); //ec = Stg_KSPSetOperators( levelKSP, level->A->petscMat, level->A->petscMat, DIFFERENT_NONZERO_PATTERN ); ec = Stg_KSPSetOperators( levelKSP, level->A, level->A, DIFFERENT_NONZERO_PATTERN ); CheckPETScError( ec ); //ec = PCMGSetResidual( pc, l_i, PCMGDefaultResidual, level->A->petscMat ); ec = PCMGSetResidual( pc, l_i, Stg_PCMGDefaultResidual, level->A ); CheckPETScError( ec ); if( l_i > 0 ) { PCMGGetSmootherUp( pc, l_i, &levelKSP ); //ec = Stg_KSPSetOperators( levelKSP, level->A->petscMat, level->A->petscMat, DIFFERENT_NONZERO_PATTERN ); ec = Stg_KSPSetOperators( levelKSP, level->A, level->A, DIFFERENT_NONZERO_PATTERN ); CheckPETScError( ec ); } } Journal_Printf( stream, "done\n" ); }
/*@ PCMGGetSmootherDown - Gets the KSP context to be used as smoother before coarse grid correction (pre-smoother). Not Collective, KSP returned is parallel if PC is Input Parameters: + pc - the multigrid context - l - the level (0 is coarsest) to supply Ouput Parameters: . ksp - the smoother Level: advanced Notes: calling this will result in a different pre and post smoother so you may need to set options on the post smoother also .keywords: MG, multigrid, get, smoother, down, pre-smoother, level .seealso: PCMGGetSmootherUp(), PCMGGetSmoother() @*/ PetscErrorCode PCMGGetSmootherDown(PC pc,PetscInt l,KSP *ksp) { PetscErrorCode ierr; PC_MG *mg = (PC_MG*)pc->data; PC_MG_Levels **mglevels = mg->levels; PetscFunctionBegin; PetscValidHeaderSpecific(pc,PC_CLASSID,1); /* make sure smoother up and down are different */ if (l) { ierr = PCMGGetSmootherUp(pc,l,NULL);CHKERRQ(ierr); } *ksp = mglevels[l]->smoothd; PetscFunctionReturn(0); }
/*@ PCMGSetNumberSmoothUp - Sets the number of post-smoothing steps to use on all levels. Use PCMGGetSmootherUp() to set different numbers of post-smoothing steps on different levels. Logically Collective on PC Input Parameters: + mg - the multigrid context - n - the number of smoothing steps Options Database Key: . -pc_mg_smoothup <n> - Sets number of post-smoothing steps Level: advanced Note: this does not set a value on the coarsest grid, since we assume that there is no separate smooth up on the coarsest grid. .keywords: MG, smooth, up, post-smoothing, steps, multigrid .seealso: PCMGSetNumberSmoothDown() @*/ PetscErrorCode PCMGSetNumberSmoothUp(PC pc,PetscInt n) { PC_MG *mg = (PC_MG*)pc->data; PC_MG_Levels **mglevels = mg->levels; PetscErrorCode ierr; PetscInt i,levels; PetscFunctionBegin; PetscValidHeaderSpecific(pc,PC_CLASSID,1); if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); PetscValidLogicalCollectiveInt(pc,n,2); levels = mglevels[0]->levels; for (i=1; i<levels; i++) { /* make sure smoother up and down are different */ ierr = PCMGGetSmootherUp(pc,i,NULL);CHKERRQ(ierr); ierr = KSPSetTolerances(mglevels[i]->smoothu,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,n);CHKERRQ(ierr); mg->default_smoothu = n; } PetscFunctionReturn(0); }
PETSC_EXTERN void PETSC_STDCALL pcmggetsmootherup_(PC pc,PetscInt *l,KSP *ksp, int *__ierr ){ *__ierr = PCMGGetSmootherUp( (PC)PetscToPointer((pc) ),*l,ksp); }
void PETScMGSolver_UpdateSolvers( PETScMGSolver* self ) { PETScMGSolver_Level* level; PC pc; KSP levelKSP; PC levelPC; PetscErrorCode ec; unsigned l_i; PetscTruth smoothers_differ, flag; PetscMPIInt size; MPI_Comm comm; assert( self && Stg_CheckType( self, PETScMGSolver ) ); ec = KSPGetPC( self->mgData->ksp, &pc ); CheckPETScError( ec ); ec = PCMGSetLevels( pc, self->nLevels, PETSC_NULL ); CheckPETScError( ec ); ec = PCMGSetType( pc, PC_MG_MULTIPLICATIVE ); CheckPETScError( ec ); ec=PetscOptionsGetTruth( PETSC_NULL, "-pc_mg_different_smoothers", &smoothers_differ, &flag ); CheckPETScError(ec); ec=PetscObjectGetComm( (PetscObject)pc, &comm ); CheckPETScError(ec); MPI_Comm_size( comm, &size ); for( l_i = 1; l_i < self->nLevels; l_i++ ) { level = self->levels + l_i; printf("Configuring MG level %d \n", l_i ); ec = PCMGGetSmootherDown( pc, l_i, &levelKSP ); CheckPETScError( ec ); if(smoothers_differ==PETSC_TRUE) { ec=KSPAppendOptionsPrefix( levelKSP, "down_" ); CheckPETScError(ec); } ec = KSPSetType( levelKSP, KSPRICHARDSON ); CheckPETScError( ec ); ec = KSPGetPC( levelKSP, &levelPC ); CheckPETScError( ec ); if(size==1) { ec = PCSetType( levelPC, PCSOR ); CheckPETScError( ec ); } /* This does not work - bug with the order the operators are created I guess */ /* For parallel jobs you best bet is to use the command line args and let petsc work it out */ /* else { KSP *sub_ksp; PetscInt k, n_local, first_local; PC sub_pc; PCSetType( levelPC, PCBJACOBI ); KSPSetUp( levelKSP ); PCBJacobiGetSubKSP( levelPC, &n_local,&first_local,&sub_ksp); for(k=0;k<n_local;k++ ) { KSPSetType( sub_ksp[k], KSPFGMRES ); KSPGetPC( sub_ksp[k], &sub_pc ); PCSetType( sub_pc, PCSOR ); } } */ ec = KSPSetTolerances( levelKSP, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, level->nDownIts ); CheckPETScError( ec ); if( l_i == self->nLevels - 1 ) { ec = KSPSetInitialGuessNonzero( levelKSP, PETSC_TRUE ); CheckPETScError( ec ); } else { ec = KSPSetInitialGuessNonzero( levelKSP, PETSC_FALSE ); CheckPETScError( ec ); } ec = PCMGGetSmootherUp( pc, l_i, &levelKSP ); CheckPETScError( ec ); if(smoothers_differ==PETSC_TRUE) { ec=KSPAppendOptionsPrefix( levelKSP, "up_" ); CheckPETScError(ec); } ec = KSPSetType( levelKSP, KSPRICHARDSON ); CheckPETScError( ec ); ec = KSPGetPC( levelKSP, &levelPC ); CheckPETScError( ec ); if(size==1) { ec = PCSetType( levelPC, PCSOR ); CheckPETScError( ec ); } ec = KSPSetTolerances( levelKSP, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, level->nUpIts ); CheckPETScError( ec ); ec = KSPSetInitialGuessNonzero( levelKSP, PETSC_TRUE ); CheckPETScError( ec ); ec = PCMGSetCyclesOnLevel( pc, l_i, level->nCycles ); CheckPETScError( ec ); } }