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" );
}
Ejemplo n.º 2
0
/*@
   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);
}
Ejemplo n.º 3
0
Archivo: mg.c Proyecto: ziolai/petsc
/*@
   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);
}
Ejemplo n.º 4
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 );
	}
}