Skip to content

Commit 5990e6e

Browse files
authored
Merge pull request #4041 from farscape-project/petscpc
Simplify set_petsc_preconditioner_type
2 parents acaf775 + fdd8a5c commit 5990e6e

2 files changed

Lines changed: 21 additions & 146 deletions

File tree

include/numerics/petsc_preconditioner.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,16 +93,6 @@ class PetscPreconditioner : public Preconditioner<T>
9393
* aren't responsible for cleaning up this one.
9494
*/
9595
Mat _mat;
96-
97-
private:
98-
/**
99-
* Some PETSc preconditioners (ILU, LU) don't work in parallel. This function
100-
* is called from set_petsc_preconditioner_type() to set additional options
101-
* for those so-called sub-preconditioners. This method ends up being static
102-
* so that it can be called from set_petsc_preconditioner_type(). Not sure
103-
* why set_petsc_preconditioner_type() needs to be static though...
104-
*/
105-
static void set_petsc_subpreconditioner_type(const PCType type, PC & pc);
10696
};
10797

10898
} // namespace libMesh

src/numerics/petsc_preconditioner.C

Lines changed: 21 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -111,98 +111,28 @@ void PetscPreconditioner<T>::set_petsc_preconditioner_type (const Preconditioner
111111
PetscErrorCode ierr = PetscObjectGetComm((PetscObject)pc, & comm);
112112
if (ierr != LIBMESH_PETSC_SUCCESS)
113113
libmesh_error_msg("Error retrieving communicator");
114-
Parallel::Communicator communicator(comm);
114+
115+
#define CasePCSetType(PreconditionerType, PCType) \
116+
case PreconditionerType: \
117+
LibmeshPetscCallA(comm, PCSetType (pc, const_cast<KSPType>(PCType))); \
118+
break;
115119

116120
switch (preconditioner_type)
117121
{
118-
case IDENTITY_PRECOND:
119-
LibmeshPetscCall2(communicator, PCSetType (pc, const_cast<KSPType>(PCNONE)));
120-
break;
121-
122-
case CHOLESKY_PRECOND:
123-
LibmeshPetscCall2(communicator, PCSetType (pc, const_cast<KSPType>(PCCHOLESKY)));
124-
break;
125-
126-
case ICC_PRECOND:
127-
LibmeshPetscCall2(communicator, PCSetType (pc, const_cast<KSPType>(PCICC)));
128-
break;
129-
130-
case ILU_PRECOND:
131-
{
132-
// In serial, just set the ILU preconditioner type
133-
if (communicator.size())
134-
LibmeshPetscCall2(communicator, PCSetType (pc, const_cast<KSPType>(PCILU)));
135-
else
136-
{
137-
// But PETSc has no truly parallel ILU, instead you have to set
138-
// an actual parallel preconditioner (e.g. block Jacobi) and then
139-
// assign ILU sub-preconditioners.
140-
LibmeshPetscCall2(communicator, PCSetType (pc, const_cast<KSPType>(PCBJACOBI)));
141-
142-
// Set ILU as the sub preconditioner type
143-
set_petsc_subpreconditioner_type(PCILU, pc);
144-
}
145-
break;
146-
}
147-
148-
case LU_PRECOND:
149-
{
150-
// In serial, just set the LU preconditioner type
151-
if (communicator.size())
152-
LibmeshPetscCall2(communicator, PCSetType (pc, const_cast<KSPType>(PCLU)));
153-
else
154-
{
155-
// But PETSc has no truly parallel LU, instead you have to set
156-
// an actual parallel preconditioner (e.g. block Jacobi) and then
157-
// assign LU sub-preconditioners.
158-
LibmeshPetscCall2(communicator, PCSetType (pc, const_cast<KSPType>(PCBJACOBI)));
159-
160-
// Set ILU as the sub preconditioner type
161-
set_petsc_subpreconditioner_type(PCLU, pc);
162-
}
163-
break;
164-
}
165-
166-
case ASM_PRECOND:
167-
{
168-
// In parallel, I think ASM uses ILU by default as the sub-preconditioner...
169-
// I tried setting a different sub-preconditioner here, but apparently the matrix
170-
// is not in the correct state (at this point) to call PCSetUp().
171-
LibmeshPetscCall2(communicator, PCSetType (pc, const_cast<KSPType>(PCASM)));
172-
break;
173-
}
174-
175-
case JACOBI_PRECOND:
176-
LibmeshPetscCall2(communicator, PCSetType (pc, const_cast<KSPType>(PCJACOBI)));
177-
break;
178-
179-
case BLOCK_JACOBI_PRECOND:
180-
LibmeshPetscCall2(communicator, PCSetType (pc, const_cast<KSPType>(PCBJACOBI)));
181-
break;
182-
183-
case SOR_PRECOND:
184-
LibmeshPetscCall2(communicator, PCSetType (pc, const_cast<KSPType>(PCSOR)));
185-
break;
186-
187-
case EISENSTAT_PRECOND:
188-
LibmeshPetscCall2(communicator, PCSetType (pc, const_cast<KSPType>(PCEISENSTAT)));
189-
break;
190-
191-
case AMG_PRECOND:
192-
LibmeshPetscCall2(communicator, PCSetType (pc, const_cast<KSPType>(PCHYPRE)));
193-
break;
194-
195-
case SVD_PRECOND:
196-
LibmeshPetscCall2(communicator, PCSetType (pc, const_cast<KSPType>(PCSVD)));
197-
break;
198-
199-
case USER_PRECOND:
200-
LibmeshPetscCall2(communicator, PCSetType (pc, const_cast<KSPType>(PCMAT)));
201-
break;
202-
203-
case SHELL_PRECOND:
204-
LibmeshPetscCall2(communicator, PCSetType (pc, const_cast<KSPType>(PCSHELL)));
205-
break;
122+
CasePCSetType(IDENTITY_PRECOND, PCNONE)
123+
CasePCSetType(CHOLESKY_PRECOND, PCCHOLESKY)
124+
CasePCSetType(ICC_PRECOND, PCICC)
125+
CasePCSetType(ILU_PRECOND, PCILU)
126+
CasePCSetType(LU_PRECOND, PCLU)
127+
CasePCSetType(ASM_PRECOND, PCASM)
128+
CasePCSetType(JACOBI_PRECOND, PCJACOBI)
129+
CasePCSetType(BLOCK_JACOBI_PRECOND, PCBJACOBI)
130+
CasePCSetType(SOR_PRECOND, PCSOR)
131+
CasePCSetType(EISENSTAT_PRECOND, PCEISENSTAT)
132+
CasePCSetType(AMG_PRECOND, PCHYPRE)
133+
CasePCSetType(SVD_PRECOND, PCSVD)
134+
CasePCSetType(USER_PRECOND, PCMAT)
135+
CasePCSetType(SHELL_PRECOND, PCSHELL)
206136

207137
default:
208138
libMesh::err << "ERROR: Unsupported PETSC Preconditioner: "
@@ -214,60 +144,15 @@ void PetscPreconditioner<T>::set_petsc_preconditioner_type (const Preconditioner
214144
// HYPRE is available
215145
#ifdef LIBMESH_HAVE_PETSC_HYPRE
216146
if (preconditioner_type == AMG_PRECOND)
217-
LibmeshPetscCall2(communicator, PCHYPRESetType(pc, "boomeramg"));
147+
LibmeshPetscCallA(comm, PCHYPRESetType(pc, "boomeramg"));
218148
#endif
219149

220150
// Let the commandline override stuff
221-
LibmeshPetscCall2(communicator, PCSetFromOptions(pc));
222-
}
223-
224-
225-
template <typename T>
226-
void PetscPreconditioner<T>::set_petsc_subpreconditioner_type(const PCType type, PC & pc)
227-
{
228-
// get the communicator from the PETSc object
229-
Parallel::communicator comm;
230-
PetscErrorCode ierr = PetscObjectGetComm((PetscObject)pc, &comm);
231-
if (ierr != LIBMESH_PETSC_SUCCESS)
232-
libmesh_error_msg("Error retrieving communicator");
233-
234-
// All docs say must call KSPSetUp or PCSetUp before calling PCBJacobiGetSubKSP.
235-
// You must call PCSetUp after the preconditioner operators have been set, otherwise you get the:
236-
//
237-
// "Object is in wrong state!"
238-
// "Matrix must be set first."
239-
//
240-
// error messages...
241-
LibmeshPetscCallA(comm, PCSetUp(pc));
242-
243-
// To store array of local KSP contexts on this processor
244-
KSP * subksps;
245-
246-
// the number of blocks on this processor
247-
PetscInt n_local;
248-
249-
// The global number of the first block on this processor.
250-
// This is not used, so we just pass null instead.
251-
// int first_local;
252-
253-
// Fill array of local KSP contexts
254-
LibmeshPetscCallA(comm, PCBJacobiGetSubKSP(pc, &n_local, LIBMESH_PETSC_NULLPTR, &subksps));
255-
256-
// Loop over sub-ksp objects, set ILU preconditioner
257-
for (PetscInt i=0; i<n_local; ++i)
258-
{
259-
// Get pointer to sub KSP object's PC
260-
PC subpc;
261-
LibmeshPetscCallA(comm, KSPGetPC(subksps[i], &subpc));
262-
263-
// Set requested type on the sub PC
264-
LibmeshPetscCallA(comm, PCSetType(subpc, type));
265-
}
151+
LibmeshPetscCallA(comm, PCSetFromOptions(pc));
266152
}
267153

268154

269155

270-
271156
//------------------------------------------------------------------
272157
// Explicit instantiations
273158
template class LIBMESH_EXPORT PetscPreconditioner<Number>;

0 commit comments

Comments
 (0)