/*@C DMMGSetNullSpace - Indicates the null space in the linear operator (this is needed by the linear solver) Collective on DMMG Input Parameter: + dmmg - the context . has_cnst - is the constant vector in the null space . n - number of null vectors (excluding the possible constant vector) - func - a function that fills an array of vectors with the null vectors (must be orthonormal), may be PETSC_NULL Level: advanced .seealso DMMGCreate(), DMMGDestroy, DMMGSetDM(), DMMGSolve(), MatNullSpaceCreate(), KSPSetNullSpace(), DMMGSetMatType() @*/ PetscErrorCode PETSCSNES_DLLEXPORT DMMGSetNullSpace(DMMG *dmmg,PetscTruth has_cnst,PetscInt n,PetscErrorCode (*func)(DMMG,Vec[])) { PetscErrorCode ierr; PetscInt i,j,nlevels = dmmg[0]->nlevels; Vec *nulls = 0; MatNullSpace nullsp; KSP iksp; PC pc,ipc; PetscTruth ismg,isred; PetscFunctionBegin; if (!dmmg) SETERRQ(PETSC_ERR_ARG_NULL,"Passing null as DMMG"); if (!dmmg[0]->ksp) SETERRQ(PETSC_ERR_ORDER,"Must call AFTER DMMGSetKSP() or DMMGSetSNES()"); if ((n && !func) || (!n && func)) SETERRQ(PETSC_ERR_ARG_INCOMP,"Both n and func() must be set together"); if (n < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Cannot have negative number of vectors in null space n = %D",n) for (i=0; i<nlevels; i++) { if (n) { ierr = VecDuplicateVecs(dmmg[i]->b,n,&nulls);CHKERRQ(ierr); ierr = (*func)(dmmg[i],nulls);CHKERRQ(ierr); } ierr = MatNullSpaceCreate(dmmg[i]->comm,has_cnst,n,nulls,&nullsp);CHKERRQ(ierr); ierr = KSPSetNullSpace(dmmg[i]->ksp,nullsp);CHKERRQ(ierr); for (j=i; j<nlevels; j++) { ierr = KSPGetPC(dmmg[j]->ksp,&pc);CHKERRQ(ierr); ierr = PetscTypeCompare((PetscObject)pc,PCMG,&ismg);CHKERRQ(ierr); if (ismg) { ierr = PCMGGetSmoother(pc,i,&iksp);CHKERRQ(ierr); ierr = KSPSetNullSpace(iksp, nullsp);CHKERRQ(ierr); } } ierr = MatNullSpaceDestroy(nullsp);CHKERRQ(ierr); if (n) { ierr = VecDestroyVecs(nulls,n);CHKERRQ(ierr); } } /* make all the coarse grid solvers have LU shift since they are singular */ for (i=0; i<nlevels; i++) { ierr = KSPGetPC(dmmg[i]->ksp,&pc);CHKERRQ(ierr); ierr = PetscTypeCompare((PetscObject)pc,PCMG,&ismg);CHKERRQ(ierr); if (ismg) { ierr = PCMGGetSmoother(pc,0,&iksp);CHKERRQ(ierr); ierr = KSPGetPC(iksp,&ipc);CHKERRQ(ierr); ierr = PetscTypeCompare((PetscObject)ipc,PCREDUNDANT,&isred);CHKERRQ(ierr); if (isred) { ierr = PCRedundantGetPC(ipc,&ipc);CHKERRQ(ierr); } ierr = PCFactorSetShiftType(ipc,MAT_SHIFT_POSITIVE_DEFINITE);CHKERRQ(ierr); } } PetscFunctionReturn(0); }
MGSolver_PETScData* MultigridSolver_CreateCoarseSolver( MultigridSolver* self, Mat matrix ) { //MatrixSolver* coarseSolver; MGSolver_PETScData* courseSolver; unsigned nProcs; PC pc; MPI_Comm_size( self->mgData->comm, (int*)&nProcs ); /* coarseSolver = (MatrixSolver*)PETScMatrixSolver_New( "" ); PETScMatrixSolver_SetKSPType( coarseSolver, PETScMatrixSolver_KSPType_PreOnly ); if( nProcs == 1 ) { PETScMatrixSolver_SetPCType( coarseSolver, PETScMatrixSolver_PCType_LU ); } else { PETScMatrixSolver_SetPCType( coarseSolver, PETScMatrixSolver_PCType_RedundantLU ); } MatrixSolver_SetMatrix( coarseSolver, matrix ); */ if( nProcs == 1 ){ KSPCreate( MPI_COMM_WORLD, &courseSolver->ksp ); KSPSetType( courseSolver->ksp, KSPPREONLY ); KSPGetPC( courseSolver->ksp, &pc ); PCSetType( pc, PCLU ); } else { PCSetType( pc, PCREDUNDANT ); #if ((PETSC_VERSION_MAJOR>=3) && (PETSC_VERSION_MINOR>=2) ) PCCreate( MPI_COMM_WORLD, &pc); PCRedundantGetKSP( pc, &courseSolver->ksp ); #else KSPCreate( MPI_COMM_WORLD, &courseSolver->ksp ); KSPSetType( courseSolver->ksp, KSPPREONLY ); KSPGetPC( courseSolver->ksp, &pc ); PCRedundantGetPC( pc, &pc ); #endif PCSetType( pc, PCLU ); } if( courseSolver->matrix != PETSC_NULL ){ Stg_MatDestroy(&courseSolver->matrix );} courseSolver->matrix = matrix; Stg_KSPSetOperators( courseSolver->ksp, matrix, matrix, DIFFERENT_NONZERO_PATTERN ); return courseSolver; }
void PETSC_STDCALL pcredundantgetpc_(PC pc,PC *innerpc, int *__ierr ){ *__ierr = PCRedundantGetPC( (PC)PetscToPointer((pc) ),innerpc); }