G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
ieti2_example.cpp

This example is a variation of the example file ieti_example.cpp, please see the documentation for that file.

There are two main differences:

  • The file at hand used a gsAssembler based assembler, while the example file ieti_example.cpp uses the gsExprAssembler.
  • The file at hand uses a MINRES solver to solve the saddle point formulation of the IETI system, which is of particular interest for inexact variants of IETI. The example file ieti_example.cpp uses CG for solving the Schur complement formulation.

Annotated source file

Here is the full file examples/ieti2_example.cpp. Clicking on a function or class name will lead you to its reference documentation.

#include <ctime>
#include <gismo.h>
using namespace gismo;
int main(int argc, char *argv[])
{
/************** Define command line options *************/
std::string geometry("domain2d/yeti_mp2.xml");
index_t splitPatches = 1;
real_t stretchGeometry = 1;
index_t refinements = 1;
index_t degree = 2;
std::string boundaryConditions("d");
real_t tolerance = 1.e-8;
index_t maxIterations = 100;
std::string out;
bool plot = false;
gsCmdLine cmd("Solves a PDE with an isogeometric discretization using an isogeometric tearing and interconnecting (IETI) solver.");
cmd.addString("g", "Geometry", "Geometry file", geometry);
cmd.addInt ("", "SplitPatches", "Split every patch that many times in 2^d patches", splitPatches);
cmd.addReal ("", "StretchGeometry", "Stretch geometry in x-direction by the given factor", stretchGeometry);
cmd.addInt ("r", "Refinements", "Number of uniform h-refinement steps to perform before solving", refinements);
cmd.addInt ("p", "Degree", "Degree of the B-spline discretization space", degree);
cmd.addString("b", "BoundaryConditions", "Boundary conditions", boundaryConditions);
cmd.addReal ("t", "Solver.Tolerance", "Stopping criterion for linear solver", tolerance);
cmd.addInt ("", "Solver.MaxIterations", "Stopping criterion for linear solver", maxIterations);
cmd.addString("", "out", "Write solution and used options to file", out);
cmd.addSwitch( "plot", "Plot the result with Paraview", plot);
try { cmd.getValues(argc,argv); } catch (int rv) { return rv; }
if ( ! gsFileManager::fileExists(geometry) )
{
gsInfo << "Geometry file could not be found.\n";
gsInfo << "I was searching in the current directory and in: " << gsFileManager::getSearchPaths() << "\n";
return EXIT_FAILURE;
}
gsInfo << "Run ieti_example with options:\n" << cmd << std::endl;
/******************* Define geometry ********************/
gsInfo << "Define geometry... " << std::flush;
if (!mpPtr)
{
gsInfo << "No geometry found in file " << geometry << ".\n";
return EXIT_FAILURE;
}
gsMultiPatch<>& mp = *mpPtr;
for (index_t i=0; i<splitPatches; ++i)
{
gsInfo << "split patches uniformly... " << std::flush;
mp = mp.uniformSplit();
}
if (stretchGeometry!=1)
{
gsInfo << "and stretch it... " << std::flush;
for (size_t i=0; i!=mp.nPatches(); ++i)
const_cast<gsGeometry<>&>(mp[i]).scale(stretchGeometry,0);
// Const cast is allowed since the object itself is not const. Stretching the
// overall domain keeps its topology.
}
gsInfo << "done.\n";
/************** Define boundary conditions **************/
gsInfo << "Define right-hand-side and boundary conditions... " << std::flush;
// Right-hand-side
gsFunctionExpr<> f( "2*sin(x)*cos(y)", mp.geoDim() );
// Dirichlet function
gsFunctionExpr<> gD( "sin(x)*cos(y)", mp.geoDim() );
// Neumann
gsConstantFunction<> gN( 1.0, mp.geoDim() );
{
const index_t len = boundaryConditions.length();
index_t i = 0;
for (gsMultiPatch<>::const_biterator it = mp.bBegin(); it < mp.bEnd(); ++it)
{
char b_local;
if ( len == 1 )
b_local = boundaryConditions[0];
else if ( i < len )
b_local = boundaryConditions[i];
else
{
gsInfo << "\nNot enough boundary conditions given.\n";
return EXIT_FAILURE;
}
if ( b_local == 'd' )
else if ( b_local == 'n' )
else
{
gsInfo << "\nInvalid boundary condition given; only 'd' (Dirichlet) and 'n' (Neumann) are supported.\n";
return EXIT_FAILURE;
}
++i;
}
if ( len > i )
gsInfo << "\nToo many boundary conditions have been specified. Ignoring the remaining ones.\n";
gsInfo << "done. "<<i<<" boundary conditions set.\n";
}
/************ Setup bases and adjust degree *************/
gsInfo << "Setup bases and adjust degree... " << std::flush;
for ( size_t i = 0; i < mb.nBases(); ++ i )
mb[i].setDegreePreservingMultiplicity(degree);
for ( index_t i = 0; i < refinements; ++i )
mb.uniformRefine();
gsInfo << "done.\n";
/********* Setup assembler and assemble matrix **********/
gsInfo << "Setup assembler and assemble matrix... " << std::flush;
const index_t nPatches = mp.nPatches();
gsIetiMapper<> ietiMapper;
// We start by setting up a global FeSpace that allows us to
// obtain a dof mapper and the Dirichlet data
{
mp,
mb,
bc,
f,
dirichlet::elimination,
iFace::glue
);
assembler.computeDirichletDofs();
ietiMapper.init( mb, assembler.system().rowMapper(0), assembler.fixedDofs() );
}
// Compute the jump matrices
bool fullyRedundant = true,
noLagrangeMultipliersForCorners = true;
ietiMapper.computeJumpMatrices(fullyRedundant, noLagrangeMultipliersForCorners);
// We tell the ieti mapper which primal constraints we want; calling
// more than one such function is possible.
ietiMapper.cornersAsPrimals();
// The ieti system does not have a special treatment for the
// primal dofs. They are just one more subdomain
ieti.reserve(nPatches+1);
// The scaled Dirichlet preconditioner is independent of the
// primal dofs.
prec.reserve(nPatches);
// Setup the primal system, which needs to know the number of primal dofs.
gsPrimalSystem<> primal(ietiMapper.nPrimalDofs());
// Setup of the block-diagonal preconditioner for the saddle point problem
// First, we need to know its size
const index_t bdPrecSz = nPatches + 1 + (ietiMapper.nPrimalDofs()>0?1:0);
gsBlockOp<>::Ptr bdPrec = gsBlockOp<>::make(bdPrecSz,bdPrecSz);
for (index_t k=0; k<nPatches; ++k)
{
// We use the local variants of everything
bc.getConditionsForPatch(k,bc_local);
gsMultiPatch<> mp_local = mp[k];
gsMultiBasis<> mb_local = mb[k];
// Setup assembler
mp_local,
mb_local,
bc_local,
f,
dirichlet::elimination,
iFace::glue
);
// This provides a new dof mapper and the Dirichlet data
// This is necessary since it might happen that a 2d-patch touches the
// Dirichlet boundary just with a corner or that a 3d-patch touches the
// Dirichlet boundary with a corner or an edge. These cases are not
// covered by bc.getConditionsForPatch
gsDofMapper tmp = ietiMapper.dofMapperLocal(k);
assembler.system() = gsSparseSystem<>(tmp); // gsSparseSystem takes per reference and steals contets
assembler.setFixedDofVector(ietiMapper.fixedPart(k));
// Assemble
assembler.assemble();
// Fetch data
gsSparseMatrix<real_t, RowMajor> jumpMatrix = ietiMapper.jumpMatrix(k);
gsSparseMatrix<> localMatrix = assembler.matrix();
gsMatrix<> localRhs = assembler.rhs();
// Add the patch to the scaled Dirichlet preconditioner
//
// This can be done using gsScaledDirichletPrec<>::restrictToSkeleton
// as in ieti_example. Here, we call the underlying commands directly
// to show how one can choose an alternative solver.
std::vector<index_t> skeletonDofs = ietiMapper.skeletonDofs(k);
= gsScaledDirichletPrec<>::matrixBlocks(localMatrix, skeletonDofs);
prec.restrictJumpMatrix(jumpMatrix, skeletonDofs).moveToPtr(),
gsScaledDirichletPrec<>::schurComplement( blocks, makeSparseCholeskySolver(blocks.A11) )
);
// Now, we handle the primal constraints.
//
// This can be done using primal.handleConstraints as in ieti_example.
// Here, we call the underlying commands directly to show how one can
// choose an alternative solver.
gsSparseMatrix<> modifiedLocalMatrix, localEmbedding, embeddingForBasis;
gsMatrix<> rhsForBasis;
const bool eliminatePointwiseDofs = true;
ietiMapper.primalConstraints(k),
eliminatePointwiseDofs,
localMatrix,
modifiedLocalMatrix,
localEmbedding,
embeddingForBasis,
rhsForBasis
);
gsLinearOperator<>::Ptr localSolver = makeSparseLUSolver(modifiedLocalMatrix);
primal.addContribution(
jumpMatrix, localMatrix, localRhs,
localSolver, embeddingForBasis, rhsForBasis, ietiMapper.primalDofIndices(k), primal.nPrimalDofs()
)
);
gsMatrix<> modifiedLocalRhs = localEmbedding.transpose() * localRhs;
gsSparseMatrix<real_t, RowMajor> modifiedJumpMatrix = jumpMatrix * localEmbedding;
// Register the local solver to the block preconditioner. We use
// a sparse LU solver since the local saddle point problem is not
// positive definite.
bdPrec->addOperator(k,k,localSolver);
// Add the patch to the Ieti system
modifiedJumpMatrix.moveToPtr(),
makeMatrixOp(modifiedLocalMatrix.moveToPtr()),
give(modifiedLocalRhs)
);
}
// Add the primal problem if there are primal constraints
if (ietiMapper.nPrimalDofs()>0)
{
// Register the local solver to the block preconditioner
bdPrec->addOperator(nPatches, nPatches, makeSparseCholeskySolver(primal.localMatrix()));
// Add to IETI system
primal.jumpMatrix().moveToPtr(),
makeMatrixOp(primal.localMatrix().moveToPtr()),
give(primal.localRhs())
);
}
gsInfo << "done.\n";
/**************** Setup solver and solve ****************/
gsInfo << "Setup solver and solve... \n"
" Setup multiplicity scaling... " << std::flush;
// Tell the preconditioner to set up the scaling
// The scaled Dirichlet preconditioner is in the last block
bdPrec->addOperator(bdPrecSz-1,bdPrecSz-1,sdPrec);
gsInfo << "done.\n Setup minres solver and solve... " << std::flush;
// Initial guess
x.setRandom( bdPrec->rows(), 1 );
// This is the main cg iteration
gsMatrix<> errorHistory;
.setOptions( cmd.getGroup("Solver") )
.solveDetailed( ieti.rhsForSaddlePoint(), x, errorHistory );
gsInfo << "done.\n Reconstruct solution from Lagrange multipliers... " << std::flush;
// Now, we want to have the global solution for u
std::vector<gsMatrix<>> uLocal = primal.distributePrimalSolution(
);
gsInfo << "done.\n\n";
/******************** Print end Exit ********************/
const index_t iter = errorHistory.rows()-1;
const bool success = errorHistory(iter,0) < tolerance;
if (success)
gsInfo << "Reached desired tolerance after " << iter << " iterations:\n";
else
gsInfo << "Did not reach desired tolerance after " << iter << " iterations:\n";
if (errorHistory.rows() < 20)
gsInfo << errorHistory.transpose() << "\n\n";
else
gsInfo << errorHistory.topRows(5).transpose() << " ... " << errorHistory.bottomRows(5).transpose() << "\n\n";
if (!out.empty())
{
std::time_t time = std::time(NULL);
fd.add(cmd);
fd.add(uGlobal);
fd.addComment(std::string("ieti2_example Timestamp:")+std::ctime(&time));
fd.save(out);
gsInfo << "Write solution to file " << out << "\n";
}
if (plot)
{
gsInfo << "Write Paraview data to file ieti_result.pvd\n";
for (index_t k=0; k<nPatches; ++k)
mpsol.addPatch( mb[k].makeGeometry( ietiMapper.incorporateFixedPart(k, uLocal[k]) ) );
gsWriteParaview<>( gsField<>( mp, mpsol ), "ieti_result", 1000);
//gsFileManager::open("ieti_result.pvd");
}
if (!plot&&out.empty())
{
gsInfo << "Done. No output created, re-run with --plot to get a ParaView "
"file containing the solution or --out to write solution to xml file.\n";
}
return success ? EXIT_SUCCESS : EXIT_FAILURE;
}
static uPtr make(index_t nRows, index_t nCols)
Make function returning a smart pointer.
Definition gsBlockOp.h:60
memory::shared_ptr< gsBlockOp< T > > Ptr
Shared pointer for gsBlockOp.
Definition gsBlockOp.h:48
Class containing a set of boundary conditions.
Definition gsBoundaryConditions.h:342
void getConditionsForPatch(const index_t np, gsBoundaryConditions &result) const
returns the set of all boundary conditions which refer to patch np
Definition gsBoundaryConditions.h:848
void addCondition(int p, boxSide s, condition_type::type t, gsFunctionSet< T > *f, short_t unknown=0, bool parametric=false, int comp=-1)
Adds another boundary condition.
Definition gsBoundaryConditions.h:650
Class for command-line argument parsing.
Definition gsCmdLine.h:57
Class defining a globally constant function.
Definition gsConstantFunction.h:34
Maintains a mapping from patch-local dofs to global dof indices and allows the elimination of individ...
Definition gsDofMapper.h:69
A scalar of vector field defined on a m_parametric geometry.
Definition gsField.h:55
This class represents an XML data tree which can be read from or written to a (file) stream.
Definition gsFileData.h:34
static std::string getSearchPaths()
Get the defined search paths.
Definition gsFileManager.cpp:271
static bool fileExists(const std::string &name)
Checks if the file exists.
Definition gsFileManager.cpp:62
Class defining a multivariate (real or vector) function given by a string mathematical expression.
Definition gsFunctionExpr.h:52
Abstract base class representing a geometry map.
Definition gsGeometry.h:93
void scale(T s, int coord=-1)
Apply Scaling by factor s.
Definition gsGeometry.h:413
Ieti Mapper.
Definition gsIetiMapper.h:50
Matrix incorporateFixedPart(index_t k, const gsMatrix< T > &localSolution) const
Incorporates fixedPart (eg. from eliminated Dirichlet dofs) to given patch-local solution.
Definition gsIetiMapper.hpp:400
void computeJumpMatrices(bool fullyRedundant, bool excludeCorners)
This function computes the jump matrices.
Definition gsIetiMapper.hpp:297
const Matrix & fixedPart(index_t k) const
The function values for the eliminated dofs on the given patch Only available after computeJumpMatric...
Definition gsIetiMapper.h:179
void cornersAsPrimals()
Set up the corners as primal dofs.
Definition gsIetiMapper.hpp:126
const gsDofMapper & dofMapperLocal(index_t k) const
The dof mapper for the given patch Only available after computeJumpMatrices has been called.
Definition gsIetiMapper.h:175
void init(const gsMultiBasis< T > &multiBasis, gsDofMapper dofMapperGlobal, const Matrix &fixedPart)
Init the ieti mapper after default construction.
Definition gsIetiMapper.hpp:30
Matrix constructGlobalSolutionFromLocalSolutions(const std::vector< Matrix > &localContribs)
Construct the global solution from a vector of patch-local ones.
Definition gsIetiMapper.hpp:91
const std::vector< index_t > & primalDofIndices(index_t k) const
Returns the indices of the primal dofs that are associated to the primal constraints for the given pa...
Definition gsIetiMapper.h:164
index_t nPrimalDofs() const
Returns the size of the primal problem (number of primal dofs)
Definition gsIetiMapper.h:154
std::vector< index_t > skeletonDofs(index_t patch) const
Returns a list of dofs that are (on the coarse level) coupled.
Definition gsIetiMapper.hpp:282
const JumpMatrix & jumpMatrix(index_t k) const
Returns the jump matrix for the given patch Only available after computeJumpMatrices has been called...
Definition gsIetiMapper.h:168
const std::vector< SparseVector > & primalConstraints(index_t k) const
Returns the primalConstraints (as vectors) for the given patch.
Definition gsIetiMapper.h:160
This class represents a IETI system.
Definition gsIetiSystem.h:70
OpPtr saddlePointProblem() const
Returns gsLinearOperator that represents the IETI problem as saddle point problem.
Definition gsIetiSystem.hpp:68
void addSubdomain(JumpMatrixPtr jumpMatrix, OpPtr localMatrixOp, Matrix localRhs, OpPtr localSolverOp=OpPtr())
Definition gsIetiSystem.hpp:32
std::vector< Matrix > constructSolutionFromSaddlePoint(const Matrix &x) const
Returns the local solutions for the individual subdomains.
Definition gsIetiSystem.hpp:141
void reserve(index_t n)
Reserves the memory required to store the number of subdomains.
Definition gsIetiSystem.hpp:23
Matrix rhsForSaddlePoint() const
Returns the right-hand-side that is required for the saddle point formulation of the IETI problem.
Definition gsIetiSystem.hpp:122
void solveDetailed(const VectorType &rhs, VectorType &x, VectorType &error_history)
Solves the linear system and stores the solution in x and records the error histroy.
Definition gsIterativeSolver.h:134
memory::shared_ptr< gsLinearOperator > Ptr
Shared pointer for gsLinearOperator.
Definition gsLinearOperator.h:33
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
The minimal residual (MinRes) method.
Definition gsMinimalResidual.h:26
gsMinimalResidual & setOptions(const gsOptionList &opt)
Set the options based on a gsOptionList.
Definition gsMinimalResidual.h:71
Holds a set of patch-wise bases and their topology information.
Definition gsMultiBasis.h:37
Container class for a set of geometry patches and their topology, that is, the interface connections ...
Definition gsMultiPatch.h:100
index_t addPatch(typename gsGeometry< T >::uPtr g)
Add a patch from a gsGeometry<T>::uPtr.
Definition gsMultiPatch.hpp:211
memory::unique_ptr< gsMultiPatch > uPtr
Unique pointer for gsMultiPatch.
Definition gsMultiPatch.h:109
Implementation of an (multiple right-hand side) Poisson assembler.
Definition gsPoissonAssembler.h:37
This class represents the primal system for a IETI-DP algorithm.
Definition gsPrimalSystem.h:87
static void incorporateConstraints(const std::vector< SparseVector > &primalConstraints, bool eliminatePointwiseConstraints, const SparseMatrix &localMatrix, SparseMatrix &modifiedLocalMatrix, SparseMatrix &localEmbedding, SparseMatrix &embeddingForBasis, Matrix &rhsForBasis)
Incorporates the given constraints in the local system.
Definition gsPrimalSystem.hpp:27
Reads an object from a data file, if such the requested object exists in the file.
Definition gsReadFile.h:43
This class represents the scaled Dirichlet preconditioner for a IETI problem.
Definition gsScaledDirichletPrec.h:79
OpPtr preconditioner() const
This returns the preconditioner as gsLinearOperator.
Definition gsScaledDirichletPrec.hpp:176
void addSubdomain(JumpMatrixPtr jumpMatrix, OpPtr localSchurOp)
Definition gsScaledDirichletPrec.h:107
void reserve(index_t n)
Reserves the memory required to store the given number of subdomain.
Definition gsScaledDirichletPrec.h:90
static JumpMatrix restrictJumpMatrix(const JumpMatrix &jumpMatrix, const std::vector< index_t > &dofs)
Restricts the jump matrix to the given dofs.
Definition gsScaledDirichletPrec.hpp:36
void setupMultiplicityScaling()
This sets up the member vector localScaling based on multiplicity scaling.
Definition gsScaledDirichletPrec.hpp:149
static Blocks matrixBlocks(const SparseMatrix &localMatrix, const std::vector< index_t > &dofs)
Computes the matrix blocks with respect to the given dofs.
Definition gsScaledDirichletPrec.hpp:64
Sparse matrix class, based on gsEigen::SparseMatrix.
Definition gsSparseMatrix.h:139
uPtr moveToPtr()
This function returns a smart pointer to the matrix. After calling it, the matrix object becomes empt...
Definition gsSparseMatrix.h:247
A sparse linear system indexed by sets of degrees of freedom.
Definition gsSparseSystem.h:30
Main header to be included by clients using the G+Smo library.
#define index_t
Definition gsConfig.h:32
#define gsInfo
Definition gsDebug.h:43
The G+Smo namespace, containing all definitions for the library.
S give(S &x)
Definition gsMemory.h:266
@ dirichlet
Dirichlet type.
Definition gsBoundaryConditions.h:31
@ neumann
Neumann type.
Definition gsBoundaryConditions.h:33
Definition gsScaledDirichletPrec.h:148