Liebe Gitlab-Nutzer, lieber Gitlab-Nutzer, es ist nun möglich sich mittels des ZIH-Logins/LDAP an unserem Dienst anzumelden. Ein Anmelden über dieses erzeugt ein neues Konto. Das alte Konto ist über den Reiter "Standard" erreichbar. Die Administratoren

Dear Gitlab user, it is now possible to log in to our service using the ZIH login/LDAP. Logging in via this will create a new account. The old account can be accessed via the "Standard" tab. The administrators

Commit 2bec218f authored by Thomas Witkowski's avatar Thomas Witkowski
Browse files

Added more nullspace support.

parent 30aa72ea
...@@ -402,11 +402,9 @@ namespace AMDiS { ...@@ -402,11 +402,9 @@ namespace AMDiS {
/// Adds a macro element to the mesh /// Adds a macro element to the mesh
void addMacroElement(MacroElement* me); void addMacroElement(MacroElement* me);
/* \brief /// Removes a set of macro elements from the mesh. This works only for the
* Removes a set of macro elements from the mesh. This works only for the /// case, that there are no global or local refinements, i.e., all macro
* case, that there are no global or local refinements, i.e., all macro /// elements have no children.
* elements have no children.
*/
void removeMacroElements(std::set<MacroElement*>& macros, void removeMacroElements(std::set<MacroElement*>& macros,
vector<const FiniteElemSpace*>& feSpaces); vector<const FiniteElemSpace*>& feSpaces);
...@@ -484,10 +482,8 @@ namespace AMDiS { ...@@ -484,10 +482,8 @@ namespace AMDiS {
} }
/** \brief /// This function is equal to \ref getDofIndexCoords as defined above, but
* This function is equal to \ref getDofIndexCoords as defined above, but takes /// takes a DOF index instead of a DOF pointer.
* a DOF index instead of a DOF pointer.
*/
bool getDofIndexCoords(DegreeOfFreedom dof, bool getDofIndexCoords(DegreeOfFreedom dof,
const FiniteElemSpace* feSpace, const FiniteElemSpace* feSpace,
WorldVector<double>& coords); WorldVector<double>& coords);
......
...@@ -49,11 +49,9 @@ namespace AMDiS { ...@@ -49,11 +49,9 @@ namespace AMDiS {
}; };
/** \brief /// This class defines the stationary problem definition in sequential
* This class defines the stationary problem definition in sequential /// computations. For parallel computations, see
* computations. For parallel computations, see /// \ref ParallelProblemStatBase.
* \ref ParallelProblemStatBase.
*/
class ProblemStatSeq : public ProblemStatBase, class ProblemStatSeq : public ProblemStatBase,
public StandardProblemIteration public StandardProblemIteration
{ {
...@@ -149,11 +147,9 @@ namespace AMDiS { ...@@ -149,11 +147,9 @@ namespace AMDiS {
void dualAssemble(AdaptInfo *adaptInfo, Flag flag, void dualAssemble(AdaptInfo *adaptInfo, Flag flag,
bool asmMatrix = true, bool asmVector = true); bool asmMatrix = true, bool asmVector = true);
/** \brief /// Determines the execution order of the single adaption steps. If adapt is
* Determines the execution order of the single adaption steps. If adapt is /// true, mesh adaption will be performed. This allows to avoid mesh adaption,
* true, mesh adaption will be performed. This allows to avoid mesh adaption, /// e.g. in timestep adaption loops of timestep adaptive strategies.
* e.g. in timestep adaption loops of timestep adaptive strategies.
*/
virtual Flag oneIteration(AdaptInfo *adaptInfo, Flag toDo = FULL_ITERATION); virtual Flag oneIteration(AdaptInfo *adaptInfo, Flag toDo = FULL_ITERATION);
/// Returns number of managed problems /// Returns number of managed problems
...@@ -168,10 +164,8 @@ namespace AMDiS { ...@@ -168,10 +164,8 @@ namespace AMDiS {
return nComponents; return nComponents;
} }
/** \brief /// Returns the problem with the given number. If only one problem
* Returns the problem with the given number. If only one problem /// is managed by this master problem, the number hasn't to be given.
* is managed by this master problem, the number hasn't to be given.
*/
virtual ProblemStatBase *getProblem(int number = 0) virtual ProblemStatBase *getProblem(int number = 0)
{ {
return this; return this;
...@@ -260,10 +254,8 @@ namespace AMDiS { ...@@ -260,10 +254,8 @@ namespace AMDiS {
addBoundaryVectorOperator(type, &op, row); addBoundaryVectorOperator(type, &op, row);
} }
/** \brief /// This function assembles a DOFMatrix and a DOFVector for the case,
* This function assembles a DOFMatrix and a DOFVector for the case, /// the meshes from row and col FE-space are equal.
* the meshes from row and col FE-space are equal.
*/
void assembleOnOneMesh(FiniteElemSpace *feSpace, void assembleOnOneMesh(FiniteElemSpace *feSpace,
Flag assembleFlag, Flag assembleFlag,
DOFMatrix *matrix, DOFVector<double> *vector); DOFMatrix *matrix, DOFVector<double> *vector);
...@@ -533,10 +525,8 @@ namespace AMDiS { ...@@ -533,10 +525,8 @@ namespace AMDiS {
} }
/** \} */ /** \} */
/** \brief /// Outputs the mesh of the given component, but the values are taken from
* Outputs the mesh of the given component, but the values are taken from the /// the residual error estimator.
* residual error estimator.
*/
void writeResidualMesh(int comp, AdaptInfo *adaptInfo, string name); void writeResidualMesh(int comp, AdaptInfo *adaptInfo, string name);
/// Function that implements the serialization procedure. /// Function that implements the serialization procedure.
...@@ -553,10 +543,8 @@ namespace AMDiS { ...@@ -553,10 +543,8 @@ namespace AMDiS {
} }
protected: protected:
/** \brief /// If the exact solution is known, the problem can compute the exact
* If the exact solution is known, the problem can compute the exact /// error instead of the error estimation. This is done in this function.
* error instead of the error estimation. This is done in this function.
*/
void computeError(AdaptInfo *adaptInfo); void computeError(AdaptInfo *adaptInfo);
protected: protected:
...@@ -571,11 +559,9 @@ namespace AMDiS { ...@@ -571,11 +559,9 @@ namespace AMDiS {
/// vectors, \ref solution. /// vectors, \ref solution.
vector<string> componentNames; vector<string> componentNames;
/** \brief /// Number of problem meshes. If all components are defined on the same mesh,
* Number of problem meshes. If all components are defined on the same mesh, /// this number is 1. Otherwise, this variable is the number of different meshes
* this number is 1. Otherwise, this variable is the number of different meshes /// within the problem.
* within the problem.
*/
int nMeshes; int nMeshes;
/// FE spaces of this problem. /// FE spaces of this problem.
...@@ -590,11 +576,9 @@ namespace AMDiS { ...@@ -590,11 +576,9 @@ namespace AMDiS {
/// Pointer to the meshes for the different problem components /// Pointer to the meshes for the different problem components
vector<Mesh*> componentMeshes; vector<Mesh*> componentMeshes;
/** \brief /// Stores information about which meshes must be traversed to assemble the
* Stores information about which meshes must be traversed to assemble the /// specific components. I.e., it was implemented to make use of different
* specific components. I.e., it was implemented to make use of different /// meshes for different components.
* meshes for different components.
*/
ComponentTraverseInfo traverseInfo; ComponentTraverseInfo traverseInfo;
/// Responsible for element marking. /// Responsible for element marking.
...@@ -618,21 +602,17 @@ namespace AMDiS { ...@@ -618,21 +602,17 @@ namespace AMDiS {
/// Composed system matrix /// Composed system matrix
SolverMatrix<Matrix<DOFMatrix*> > solverMatrix; SolverMatrix<Matrix<DOFMatrix*> > solverMatrix;
/** \brief /// Some DOFMatrices of the systemMatrix may be assembled only once (for
* Some DOFMatrices of the systemMatrix may be assembled only once (for /// example if they are independent of the time or older solutions). If
* example if they are independent of the time or older solutions). If /// [i][j] of this field is set to true, the corresponding DOFMatrix will
* [i][j] of this field is set to true, the corresponding DOFMatrix will /// be assembled only once. All other matrices will be assembled at every
* be assembled only once. All other matrices will be assembled at every /// time step.
* time step.
*/
vector<vector<bool> > assembleMatrixOnlyOnce; vector<vector<bool> > assembleMatrixOnlyOnce;
/** \brief /// If [i][j] of this field is set to true, the corresponding DOFMatrix of
* If [i][j] of this field is set to true, the corresponding DOFMatrix of /// the systemMatrix has been assembled at least once. This field is used
* the systemMatrix has been assembled at least once. This field is used /// to determine, if assembling of a matrix can be ommitted, if it is set
* to determine, if assembling of a matrix can be ommitted, if it is set /// to be assembled only once.
* to be assembled only once.
*/
vector<vector<bool> > assembledMatrix; vector<vector<bool> > assembledMatrix;
/// Determines whether domain boundaries should be considered at assembling. /// Determines whether domain boundaries should be considered at assembling.
...@@ -641,47 +621,40 @@ namespace AMDiS { ...@@ -641,47 +621,40 @@ namespace AMDiS {
/// Writes the meshes and solution after the adaption loop. /// Writes the meshes and solution after the adaption loop.
vector<FileWriterInterface*> fileWriters; vector<FileWriterInterface*> fileWriters;
/** \brief /// All actions of mesh refinement are performed by refinementManager.
* All actions of mesh refinement are performed by refinementManager. /// If new refinement algorithms should be realized, one has to override
* If new refinement algorithms should be realized, one has to override /// RefinementManager and give one instance of it to AdaptStationary.
* RefinementManager and give one instance of it to AdaptStationary.
*/
RefinementManager *refinementManager; RefinementManager *refinementManager;
/** \brief /// All actions of mesh coarsening are performed by coarseningManager.
* All actions of mesh coarsening are performed by coarseningManager. /// If new coarsening algorithms should be realized, one has to override
* If new coarsening algorithms should be realized, one has to override /// CoarseningManager and give one instance of it to AdaptStationary.
* CoarseningManager and give one instance of it to AdaptStationary.
*/
CoarseningManager *coarseningManager; CoarseningManager *coarseningManager;
/// Info level. /// Info level.
int info; int info;
/// If true, the stationary problem was deserialized from some serialization file. /// If true, the stationary problem was deserialized from some serialization
/// file.
bool deserialized; bool deserialized;
/** \brief /// This vectors stores pointers to functions defining the exact solution of
* This vectors stores pointers to functions defining the exact solution of /// the problem. This may be used to compute the real error of the computed
* the problem. This may be used to compute the real error of the computed /// solution.
* solution.
*/
vector<AbstractFunction<double, WorldVector<double> >*> exactSolutionFcts; vector<AbstractFunction<double, WorldVector<double> >*> exactSolutionFcts;
/** \brief /// If true, the error is not estimated but computed from the exact solution
* If true, the error is not estimated but computed from the exact solution /// defined by \ref exactSolutionFcts.
* defined by \ref exactSolutionFcts.
*/
bool computeExactError; bool computeExactError;
/** \brief /// If at least on boundary condition is set, this variable is true. It is
* If at least on boundary condition is set, this variable is true. It is used /// used to ensure that no operators are added after boundary condition were
* to ensure that no operators are added after boundary condition were set. If /// set. If this would happen, boundary conditions could set wrong on off
* this would happen, boundary conditions could set wrong on off diagonal matrices. /// diagonal matrices.
*/
bool boundaryConditionSet; bool boundaryConditionSet;
/// If true, AMDiS prints information about the assembling procedure to the screen. /// If true, AMDiS prints information about the assembling procedure to
/// the screen.
bool writeAsmInfo; bool writeAsmInfo;
map<Operator*, vector<OperatorPos> > operators; map<Operator*, vector<OperatorPos> > operators;
......
...@@ -243,6 +243,7 @@ namespace AMDiS { ...@@ -243,6 +243,7 @@ namespace AMDiS {
("Should not happen (%d)!\n", multPeriodicDof2.size()); ("Should not happen (%d)!\n", multPeriodicDof2.size());
TEST_EXIT_DBG(multPeriodicDof3.size() == 0)("Should not happen!\n"); TEST_EXIT_DBG(multPeriodicDof3.size() == 0)("Should not happen!\n");
} }
if (mesh->getDim() == 3) { if (mesh->getDim() == 3) {
TEST_EXIT_DBG(multPeriodicDof3.size() == 0 || TEST_EXIT_DBG(multPeriodicDof3.size() == 0 ||
multPeriodicDof3.size() == 8) multPeriodicDof3.size() == 8)
......
...@@ -295,6 +295,14 @@ namespace AMDiS { ...@@ -295,6 +295,14 @@ namespace AMDiS {
return levelData; return levelData;
} }
void updateLocalGlobalNumbering();
/// Updates the local and global DOF numbering after the mesh has been
/// changed.
void updateLocalGlobalNumbering(ParallelDofMapping &dmap,
DofComm &dcom,
const FiniteElemSpace *feSpace);
protected: protected:
void addProblemStat(ProblemStatSeq *probStat); void addProblemStat(ProblemStatSeq *probStat);
...@@ -308,14 +316,6 @@ namespace AMDiS { ...@@ -308,14 +316,6 @@ namespace AMDiS {
/// partition. /// partition.
void removeMacroElements(); void removeMacroElements();
void updateLocalGlobalNumbering();
/// Updates the local and global DOF numbering after the mesh has been
/// changed.
void updateLocalGlobalNumbering(ParallelDofMapping &dmap,
DofComm &dcom,
const FiniteElemSpace *feSpace);
/// Calls \ref createPeriodicMap(feSpace) for all FE spaces that are /// Calls \ref createPeriodicMap(feSpace) for all FE spaces that are
/// handled by the mesh distributor. /// handled by the mesh distributor.
void createPeriodicMap(); void createPeriodicMap();
......
...@@ -37,6 +37,8 @@ namespace AMDiS { ...@@ -37,6 +37,8 @@ namespace AMDiS {
Parameters::get("parallel->remove rhs null space", removeRhsNullspace); Parameters::get("parallel->remove rhs null space", removeRhsNullspace);
Parameters::get("parallel->has constant null space", hasConstantNullspace); Parameters::get("parallel->has constant null space", hasConstantNullspace);
Parameters::get("parallel->nullspace->const in comp",
constNullspaceComponent);
} }
......
...@@ -256,6 +256,8 @@ namespace AMDiS { ...@@ -256,6 +256,8 @@ namespace AMDiS {
bool removeRhsNullspace; bool removeRhsNullspace;
bool hasConstantNullspace; bool hasConstantNullspace;
vector<int> constNullspaceComponent;
}; };
......
...@@ -119,9 +119,8 @@ namespace AMDiS { ...@@ -119,9 +119,8 @@ namespace AMDiS {
KSPSetType(kspInterior, KSPBCGS); KSPSetType(kspInterior, KSPBCGS);
KSPSetOptionsPrefix(kspInterior, kspPrefix.c_str()); KSPSetOptionsPrefix(kspInterior, kspPrefix.c_str());
KSPSetFromOptions(kspInterior); KSPSetFromOptions(kspInterior);
PCSetFromOptions(pcInterior);
createFieldSplit(pcInterior); initPreconditioner(pcInterior);
// Do not delete the solution vector, use it for the initial guess. // Do not delete the solution vector, use it for the initial guess.
if (!zeroStartVector) if (!zeroStartVector)
...@@ -131,6 +130,14 @@ namespace AMDiS { ...@@ -131,6 +130,14 @@ namespace AMDiS {
} }
void PetscSolverGlobalMatrix::fillPetscMatrix(DOFMatrix *mat)
{
Matrix<DOFMatrix*> m(1, 1);
m[0][0] = mat;
fillPetscMatrix(&m);
}
void PetscSolverGlobalMatrix::fillPetscMatrixWithCoarseSpace(Matrix<DOFMatrix*> *mat) void PetscSolverGlobalMatrix::fillPetscMatrixWithCoarseSpace(Matrix<DOFMatrix*> *mat)
{ {
FUNCNAME("PetscSolverGlobalMatrix::fillPetscMatrixWithCoarseSpace()"); FUNCNAME("PetscSolverGlobalMatrix::fillPetscMatrixWithCoarseSpace()");
...@@ -317,7 +324,6 @@ namespace AMDiS { ...@@ -317,7 +324,6 @@ namespace AMDiS {
KSPSetOperators(kspInterior, matIntInt, matIntInt, SAME_NONZERO_PATTERN); KSPSetOperators(kspInterior, matIntInt, matIntInt, SAME_NONZERO_PATTERN);
KSPSetOptionsPrefix(kspInterior, "interior_"); KSPSetOptionsPrefix(kspInterior, "interior_");
KSPSetType(kspInterior, KSPPREONLY); KSPSetType(kspInterior, KSPPREONLY);
PC pcInterior;
KSPGetPC(kspInterior, &pcInterior); KSPGetPC(kspInterior, &pcInterior);
PCSetType(pcInterior, PCLU); PCSetType(pcInterior, PCLU);
if (subdomainLevel == 0) if (subdomainLevel == 0)
...@@ -393,9 +399,21 @@ namespace AMDiS { ...@@ -393,9 +399,21 @@ namespace AMDiS {
MatNullSpace matNullspace; MatNullSpace matNullspace;
Vec nullspaceBasis; Vec nullspaceBasis;
if (nullspace.size() > 0 || hasConstantNullspace) { if (nullspace.size() > 0 ||
hasConstantNullspace ||
constNullspaceComponent.size() > 0) {
TEST_EXIT_DBG(nullspace.size() <= 1)("Not yet implemented!\n"); TEST_EXIT_DBG(nullspace.size() <= 1)("Not yet implemented!\n");
if (constNullspaceComponent.size() > 0) {
nullspace.clear();
SystemVector *basisVec = new SystemVector(vec);
basisVec->set(0.0);
for (unsigned int i = 0; i < constNullspaceComponent.size(); i++)
basisVec->getDOFVector(constNullspaceComponent[i])->set(1.0);
nullspace.push_back(basisVec);
}
if (nullspace.size() > 0) { if (nullspace.size() > 0) {
VecDuplicate(petscSolVec, &nullspaceBasis); VecDuplicate(petscSolVec, &nullspaceBasis);
for (int i = 0; i < nComponents; i++) for (int i = 0; i < nComponents; i++)
...@@ -403,6 +421,8 @@ namespace AMDiS { ...@@ -403,6 +421,8 @@ namespace AMDiS {
VecAssemblyBegin(nullspaceBasis); VecAssemblyBegin(nullspaceBasis);
VecAssemblyEnd(nullspaceBasis); VecAssemblyEnd(nullspaceBasis);
VecNormalize(nullspaceBasis, PETSC_NULL);
MatNullSpaceCreate(mpiCommGlobal, (hasConstantNullspace ? PETSC_TRUE : PETSC_FALSE), MatNullSpaceCreate(mpiCommGlobal, (hasConstantNullspace ? PETSC_TRUE : PETSC_FALSE),
1, &nullspaceBasis, &matNullspace); 1, &nullspaceBasis, &matNullspace);
...@@ -415,6 +435,7 @@ namespace AMDiS { ...@@ -415,6 +435,7 @@ namespace AMDiS {
MatNullSpaceCreate(mpiCommGlobal, PETSC_TRUE, 0, PETSC_NULL, &matNullspace); MatNullSpaceCreate(mpiCommGlobal, PETSC_TRUE, 0, PETSC_NULL, &matNullspace);
} }
MatSetNullSpace(matIntInt, matNullspace);
KSPSetNullSpace(kspInterior, matNullspace); KSPSetNullSpace(kspInterior, matNullspace);
// === Remove null space, if requested. === // === Remove null space, if requested. ===
...@@ -455,11 +476,6 @@ namespace AMDiS { ...@@ -455,11 +476,6 @@ namespace AMDiS {
} }
VecRestoreArray(petscSolVec, &vecPointer); VecRestoreArray(petscSolVec, &vecPointer);
// === Synchronize DOFs at common DOFs, i.e., DOFs that correspond to ===
// === more than one partition. ===
meshDistributor->synchVector(vec);
} }
...@@ -517,6 +533,8 @@ namespace AMDiS { ...@@ -517,6 +533,8 @@ namespace AMDiS {
{ {
FUNCNAME("PetscSolverGlobalMatrix::destroyMatrixData()"); FUNCNAME("PetscSolverGlobalMatrix::destroyMatrixData()");
exitPreconditioner(pcInterior);
MatDestroy(&matIntInt); MatDestroy(&matIntInt);
KSPDestroy(&kspInterior); KSPDestroy(&kspInterior);
...@@ -580,6 +598,21 @@ namespace AMDiS { ...@@ -580,6 +598,21 @@ namespace AMDiS {
} }
void PetscSolverGlobalMatrix::initPreconditioner(PC pc)
{
FUNCNAME("PetscSolverGlobalMatrix::initPreconditioner()");
PCSetFromOptions(pc);
createFieldSplit(pc);
}
void PetscSolverGlobalMatrix::exitPreconditioner(PC pc)
{
FUNCNAME("PetscSolverGlobalMatrix::exitPreconditioner()");
}
void PetscSolverGlobalMatrix::setDofMatrix(DOFMatrix* mat, void PetscSolverGlobalMatrix::setDofMatrix(DOFMatrix* mat,
int nRowMat, int nColMat) int nRowMat, int nColMat)
{ {
...@@ -766,7 +799,6 @@ namespace AMDiS { ...@@ -766,7 +799,6 @@ namespace AMDiS {
else else
perColDof = entry[i].second; perColDof = entry[i].second;
entry.push_back(make_pair(perRowDof, perColDof)); entry.push_back(make_pair(perRowDof, perColDof));
} }
} }
...@@ -815,6 +847,7 @@ namespace AMDiS { ...@@ -815,6 +847,7 @@ namespace AMDiS {
// Traverse all used DOFs in the dof vector. // Traverse all used DOFs in the dof vector.
DOFVector<double>::Iterator dofIt(vec, USED_DOFS); DOFVector<double>::Iterator dofIt(vec, USED_DOFS);
for (dofIt.reset(); !dofIt.end(); ++dofIt) { for (dofIt.reset(); !dofIt.end(); ++dofIt) {
if (rankOnly && !(*interiorMap)[feSpace].isRankDof(dofIt.getDOFIndex())) if (rankOnly && !(*interiorMap)[feSpace].isRankDof(dofIt.getDOFIndex()))
continue; continue;
...@@ -836,7 +869,7 @@ namespace AMDiS { ...@@ -836,7 +869,7 @@ namespace AMDiS {
else else
index = index =
interiorMap->getMatIndex(nRowVec, dofIt.getDOFIndex()) + rStartInterior; interiorMap->getMatIndex(nRowVec, dofIt.getDOFIndex()) + rStartInterior;
if (perMap.isPeriodic(feSpace, globalRowDof)) { if (perMap.isPeriodic(feSpace, globalRowDof)) {
std::set<int>& perAsc = perMap.getAssociations(feSpace, globalRowDof); std::set<int>& perAsc = perMap.getAssociations(feSpace, globalRowDof);
double value = *dofIt / (perAsc.size() + 1.0); double value = *dofIt / (perAsc.size() + 1.0);
...@@ -846,6 +879,7 @@ namespace AMDiS { ...@@ -846,6 +879,7 @@ namespace AMDiS {
perIt != perAsc.end(); ++perIt) { perIt != perAsc.end(); ++perIt) {
int mappedDof = perMap.map(feSpace, *perIt, globalRowDof); int mappedDof = perMap.map(feSpace, *perIt, globalRowDof);
int mappedIndex = interiorMap->getMatIndex(nRowVec, mappedDof); int mappedIndex = interiorMap->getMatIndex(nRowVec, mappedDof);
VecSetValue(vecInterior, mappedIndex, value, ADD_VALUES); VecSetValue(vecInterior, mappedIndex, value, ADD_VALUES);
} }
} else { } else {
......
...@@ -50,6 +50,10 @@ namespace AMDiS { ...@@ -50,6 +50,10 @@ namespace AMDiS {
void fillPetscMatrix(Matrix<DOFMatrix*> *mat); void fillPetscMatrix(Matrix<DOFMatrix*> *mat);
/// This function is just a small wrapper that creates a 1x1 matrix that
/// contains exactly one DOFMatrix and than calls \ref fillPetscMatrix
void fillPetscMatrix(DOFMatrix *mat);
void fillPetscMatrixWithCoarseSpace(Matrix<DOFMatrix*> *mat); void fillPetscMatrixWithCoarseSpace(Matrix<DOFMatrix*> *mat);
void fillPetscRhs(SystemVector *vec); void fillPetscRhs(SystemVector *vec);
...@@ -62,9 +66,13 @@ namespace AMDiS { ...@@ -62,9 +66,13 @@ namespace AMDiS {
void destroyVectorData(); void destroyVectorData();
protected:
void createFieldSplit(PC pc); void createFieldSplit(PC pc);
protected: virtual void initPreconditioner(PC pc);
virtual void exitPreconditioner(PC pc);
/// Creates a new non zero pattern structure for the PETSc matrix.