We consider the Poisson boundary value problem (for simplicity here only with Dirichlet conditions):
\begin{eqnarray*}
-\Delta u &=& f \quad \text{in} \quad \Omega, \\
u &=& g \quad \text{on} \quad \partial\Omega.
\end{eqnarray*}
Its variational form is: Find \( u\in V_g \) such that
\[
\int_\Omega \nabla u \nabla v d x = \int_\Omega f v dx
\]
for all \( v\in V_0 \), which corresponds to the linear system
\[
A \underline u = \underline f.
\]
The computational domain is a non-overlapping multi-patch domain:
\[
\overline{ \Omega } = \bigcup_{k=1}^K \overline{ \Omega_k }
\]
\[
\Omega_k \cap \Omega_l = \emptyset
\quad \text{ for all } k\not=l.
\]
On each patch, we have a isogeometric function space \( V_k \). We assume that the function spaces are fully matching. The global function space is
\[
V_h = \{ v\in V \;:\; v|_{\Omega_k} \in V_k \}
\]
where \( V \) is the proper continuous space.
After reading the command line arguments, we read in the geometry file and modify the geometry as desired:
memory::unique_ptr< gsMultiPatch > uPtr
Unique pointer for gsMultiPatch.
Definition gsMultiPatch.h:109
gsMultiPatch<>& mp = *mpPtr;
for (
index_t i=0; i<splitPatches; ++i)
{
gsInfo <<
"split patches uniformly... " << std::flush;
mp = mp.uniformSplit();
}
#define index_t
Definition gsConfig.h:32
#define gsInfo
Definition gsDebug.h:43
Then, we set up the right-hand-side f and a gsBoundaryConditions object based on the command line arguments.
gsFunctionExpr<> f( "2*sin(x)*cos(y)", mp.geoDim() );
gsFunctionExpr<> gD( "sin(x)*cos(y)", mp.geoDim() );
gsConstantFunction<> gN( 1.0, mp.geoDim() );
gsBoundaryConditions<> bc;
Then, we extract the basis from the multi patch object to obtain a multi basis.
We set the spline degree and the grid size as desired.
for ( size_t i = 0; i < mb.nBases(); ++ i )
mb[i].setDegreePreservingMultiplicity(degree);
for (
index_t i = 0; i < refinements; ++i )
mb.uniformRefine();
Now, we can discuss the IETI system.
We are considering patch-wise formulations of the variational formulation:
\[
\int_{\Omega_k} \nabla u \nabla v d x = \int_{\Omega_k} f v dx
\]
Each of these bilinear forms and linear forms lead to matrices and vectors
\[
A_k \qquad\text{and}\qquad \underline f_k.
\]
Using the jump matrices \( B_k \), which are provided by the class gsIetiMapper, we obtain the following problem:
\[
\begin{pmatrix}
A_1 & & & & B_1^\top \\
& A_2 & & & B_2^\top \\
& &\ddots& & \vdots \\
& & & A_K & B_K^\top \\
B_1 & B_2 &\cdots& B_K & 0 \\
\end{pmatrix}
\begin{pmatrix}
\underline u_1 \\
\underline u_2 \\
\vdots \\
\underline u_K \\
\underline \lambda
\end{pmatrix}
=
\begin{pmatrix}
\underline f_1 \\
\underline f_2 \\
\vdots \\
\underline f_K \\
0
\end{pmatrix}
\]
This is the kind of systems, the class gsIetiSystem is working with. The problem is that – in general – the matrices \( A_k \) are singular. To circumvent this problem, in FETI-dp / IETI-dp methods, we use primal degrees of freedom, like vertex values or edge averages.
These primal dofs are handled by the classes gsPrimalSystem and again gsIetiMapper. The IETI mapper provides vectors \( c_k^{(i)} \) that realize the constraint that the primal dof is set to zero. For each patch, these primal constraints build a matrix \( C_k \). The IETI mapper also provides a vector of indices that associates each of these primal constraints to a (global) index referring to the primal dof.
Finally, we obtain one subspace (the K+1st) that refers to the primal degrees of freedom.
We have the following IETI system:
\[
\begin{pmatrix}
\tilde A_1 & & & & \tilde B_1^\top \\
& \tilde A_2 & & & \tilde B_2^\top \\
& & \ddots & & \vdots \\
& & & \tilde A_{K+1} & \tilde B_{K+1}^\top \\
\tilde B_1 & \tilde B_2 & \cdots & \tilde B_{K+1} & 0 \\
\end{pmatrix}
\begin{pmatrix}
\underline{ \tilde u}_1 \\
\underline{ \tilde u}_2 \\
\vdots \\
\underline{ \tilde u}_{K+1} \\
\underline \lambda
\end{pmatrix}
=
\begin{pmatrix}
\underline{ \tilde f}_1 \\
\underline{ \tilde f}_2 \\
\vdots \\
\underline{ \tilde f}_{K+1} \\
0
\end{pmatrix},
\qquad (*)
\]
which is passed to the class gsIetiSystem. For \( k=1,\ldots,K \), we have the local saddle point system
\[
\tilde{A}_k
=
\begin{pmatrix}
A_k & C_k^\top \\
C_k & 0
\end{pmatrix},
\]
the extended jump matrix
\[
\tilde{B}_k
=
B_k (P_0^{(k)})^\top
=
\begin{pmatrix}
B_k & 0_k
\end{pmatrix}
\]
and the extended right-hand side
\[
\underline{\tilde f}_k
=
P_0^{(k)} \underline f_k
=
\begin{pmatrix}
\underline f_k \\ 0
\end{pmatrix}.
\]
These modifications are provided by gsPrimalSystem. The class gsPrimalSystem moreover computes the energy minimizing basis functions and represents them as matrices \( \Psi_k = (P_c^{(k)})^\top \tilde{A}_k^{-1} R_c \), where \( R_c=(0,I)^\top \) and \( P_c=(I,0) \). It then computes
\[
\tilde A_{K+1} = \sum_{k=1}^K \Psi_k A_k \Psi_k^\top
\quad\text{and}\quad
\tilde B_{K+1} = \sum_{k=1}^K B_k \Psi_k^\top
\quad\text{and}\quad
\underline{\tilde f}_{K+1} = \sum_{k=1}^K \Psi_k \underline f_k.
\]
By setting a corresponding flag, it is possible to eliminate the pointwise constraints. A constraint is pointwise the correspoding row of \( C_k \) has only one non-zero entries. Typically, the corner values are pointwise constraints.
Instead of directly solving the IETI-saddle point system (*), we solve the corresponding Schur complement system
\[
F \underline \lambda = \underline g,
\]
where
\[
F = \sum_{k=1}^{K+1} \tilde B_k \tilde A_k^{-1} \tilde B_k^\top
\quad\text{and}\quad
\underline g = \sum_{k=1}^{K+1} \tilde B_k \tilde A_k^{-1} \underline{\tilde f}_k.
\]
The Schur complement system is preconditioned with the scaled Dirichlet preconditioner
\[
M_{sD}
= \sum_{k=1}^{K} \hat B_k D_k^{-1} S_k D_k^{-1} \hat B_k^\top,
\]
where \( S_k \) is the Schur complement of \( A_k \) (not: \(\tilde A_k\)) with respect to the dofs on the interfaces. \( \hat B_k \) is the restriction of \( B_k \) to the dofs on the interfaces. \( D_k \) is a scaling matrix, e.g., based on multiplicity scaling. The class gsScaledDirichletPrec not only collects the contributions of the preconditioner; it also helps with restricting to the skeleton and computing the Schur complement.
In the example file ieti2_example.cpp, we solve the saddle point system (*) with a MINRES solver, preconditioned with a block-diagonal preconditioner, where the last block is \( M_{sD} \).
First, we set up the gsIetiMapper object, which helps us with assembling and keeping track of the dof indices.
gsIetiMapper<> ietiMapper;
For initializing the IETI mapper, it is necessary to provide a gsDofMapper for the global problem and the function values for the eliminated dofs (typically the Dirichlet conditions). If systems are considered, the method it is expected to have one IETI mapper per variable.
For obtaining a gsDofMapper, we use the assembler:
{
gsExprAssembler<> assembler;
space u = assembler.getSpace(mb);
bc.setGeoMap(mp);
u.setup(bc, dirichlet::interpolation, 0);
ietiMapper.init( mb, u.mapper(), u.fixedPart() );
}
gsExprHelper< T >::space space
Space type.
Definition gsExprAssembler.h:67
Now we set the primal degrees of freedom. The following commands compute the (vectors that make up the) constraint matrices \( C_k \) and store them in the gsIetiMapper object.
if (cornersAsPrimals)
ietiMapper.cornersAsPrimals();
if (edgesAsPrimals)
ietiMapper.interfaceAveragesAsPrimals(mp,1);
if (facesAsPrimals)
ietiMapper.interfaceAveragesAsPrimals(mp,2);
The following command computes the jump matrices \( B_k \) and stores them in the gsIetiMapper object.
ietiMapper.computeJumpMatrices(fullyRedundant, noLagrangeMultipliersForCorners);
Now, we set up the classes for the IETI system, the primal system, and the scaled Dirichlet preconditioner.
gsIetiSystem<> ieti;
ieti.reserve(nPatches+1);
gsScaledDirichletPrec<> prec;
prec.reserve(nPatches);
gsPrimalSystem<> primal(ietiMapper.nPrimalDofs());
if (eliminateCorners)
primal.setEliminatePointwiseConstraints(true);
Now, we assemble the linear system and the right-hand side on each patch using a for loop. We use local versions of the geometry (gsMultiPatch), the basis (gsMultiBasis) and the boundary conditions (gsBoundaryConditions).
The function initFeSpace 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
The example file ieti2_example.cpp shows how to assemble with a classical assembler.
{
gsBoundaryConditions<> bc_local;
bc.getConditionsForPatch(k,bc_local);
gsMultiPatch<> mp_local = mp[k];
gsMultiBasis<> mb_local = mb[k];
gsExprAssembler<> assembler(1,1);
assembler.setIntegrationElements(mb_local);
gsExprEvaluator<> ev(assembler);
geometryMap G = assembler.getMap(mp_local);
space u = assembler.getSpace(mb_local);
bc_local.setGeoMap(mp_local);
u.setup(bc_local, dirichlet::interpolation, 0);
ietiMapper.initFeSpace(u,k);
auto ff = assembler.getCoeff(f, G);
assembler.initSystem();
assembler.assemble( igrad(u, G) * igrad(u, G).tr() * meas(G), u * ff * meas(G) );
variable g_N = assembler.getBdrFunction();
assembler.assembleBdr(bc_local.get("Neumann"), u * g_N.val() * nv(G).norm() );
gsSparseMatrix<real_t, RowMajor> jumpMatrix = ietiMapper.jumpMatrix(k);
gsSparseMatrix<> localMatrix = assembler.matrix();
gsMatrix<> localRhs = assembler.rhs();
gsExprHelper< T >::geometryMap geometryMap
Geometry map type.
Definition gsExprAssembler.h:65
gsExprHelper< T >::variable variable
Variable type.
Definition gsExprAssembler.h:66
expr::gsFeSolution< T > solution
Solution type.
Definition gsExprAssembler.h:68
Now, we tell the preconditioner about the local matrix \( A_k \), the local vector \( \underline f_k \) and the matrix \( B_k \). This is done before the class gsPrimalSystem modifies these objects. The following command does all necessary steps:
prec.addSubdomain(
jumpMatrix,
localMatrix,
ietiMapper.skeletonDofs(k)
)
);
static std::pair< JumpMatrix, OpPtr > restrictToSkeleton(const JumpMatrix &jumpMatrix, const SparseMatrix &localMatrix, const std::vector< index_t > &dofs)
Definition gsScaledDirichletPrec.h:195
This can also be done in a step-by-step way, for example if one does not want to use a sparse Cholesky solver (which requires symmetric positive definite problems and would be done by default). This is shown in ieti2_example.cpp.
As next step, we treat the primal dofs. We first compute energy minimizing primal basis functions. Then the following commands amends the variables jumpMatrix, localMatrix, and localRhs, which hold \( B_k \), \( A_k \) and \( \underline f_k \) before calling the function and \( \tilde B_k \), \( \tilde A_k \), and \( \underline{\tilde f}_k \) thereafter. Finally, this function collects the contributions for \( \tilde B_{K+1} \), \( \tilde A_{K+1} \), and \( \underline{\tilde f}_{K+1} \) in the object.
primal.handleConstraints(
ietiMapper.primalConstraints(k),
ietiMapper.primalDofIndices(k),
jumpMatrix,
localMatrix,
localRhs
);
This can also be done in a step-by-step way, for example if one does not want to use a sparse LU solver (which would be done by default). This is shown in the file ieti2_example.cpp.
Now, we add \( \tilde B_k \), \( \tilde A_k \), and \( \underline{\tilde f}_k \) to the IETI-system:
ieti.addSubdomain(
jumpMatrix.moveToPtr(),
makeMatrixOp(localMatrix.moveToPtr()),
);
S give(S &x)
Definition gsMemory.h:266
Additionally, one can also provide a solver object that realizes \( \tilde A_k^{-1} \), possibly the one which has already been used for the setup of the bases for the primal doefs. By default, again, a LU solver would be used.
Finally, we add \( \tilde B_{K+1} \), \( \tilde A_{K+1} \), and \( \underline{\tilde f}_{K+1} \) to the IETI-system:
if (ietiMapper.nPrimalDofs()>0)
{
= makeSparseCholeskySolver(primal.localMatrix());
ieti.addSubdomain(
primal.jumpMatrix().moveToPtr(),
makeMatrixOp(primal.localMatrix().moveToPtr()),
localSolver
);
}
memory::shared_ptr< gsLinearOperator > Ptr
Shared pointer for gsLinearOperator.
Definition gsLinearOperator.h:33
The gsScaledDirichletPrec can automatically compute the multiplicity scaling. Other scaling matrices can be manually defined.
prec.setupMultiplicityScaling();
Now, we compute the right-hand-side
\[
\underline g = \sum_{k=1}^{K+1} \tilde B_k \tilde A_k^{-1} \underline{\tilde f}_k.
\]
gsMatrix<> rhsForSchur = ieti.rhsForSchurComplement();
We choose a random initial guess.
gsMatrix<> lambda;
lambda.setRandom( ieti.nLagrangeMultipliers(), 1 );
As a next step, we solve the problem
\[
F \underline \lambda = \underline g
\]
using the scaled Dirichlet preconditioner with a conjugate gradient solver.
gsConjugateGradient<> PCG( ieti.schurComplement(), prec.preconditioner() );
PCG.setOptions( cmd.getGroup("Solver") ).solveDetailed( rhsForSchur, lambda, errorHistory );
So far, we have only computed the Lagrange multipliers \( \underline \lambda \), from which we want to recover the solution.
Here, we first compute the solutions \( \underline{\tilde u}_k \) for \( k=1,\ldots,K+1 \). Here, the first K solutions refer to the patches and have homogenous values for the primal dofs. So, we distribute the primal dof values from the primal problem (= last subdomain) to the patches (=first K subdomains) and obtain the solutions \( \underline u_k \) for \( k=1,\ldots,K \). Then, finally, the IETI mapper is able to combine everything into one solution vector \( \underline u \).
std::vector<gsMatrix<>> uLocal = primal.distributePrimalSolution(
ieti.constructSolutionFromLagrangeMultipliers(lambda)
);
gsMatrix<> uGlobal = ietiMapper.constructGlobalSolutionFromLocalSolutions(uLocal);
Annotated source file
Here is the full file examples/ieti_example.cpp
. Clicking on a function or class name will lead you to its reference documentation.
#include <ctime>
int main(int argc, char *argv[])
{
std::string geometry("domain2d/yeti_mp2.xml");
real_t stretchGeometry = 1;
std::string boundaryConditions("d");
std::string primals("c");
bool eliminateCorners = false;
real_t tolerance = 1.e-8;
bool calcEigenvalues = false;
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.addString("c", "Primals", "Primal constraints (c=corners, e=edges, f=faces)", primals);
cmd.addSwitch("e", "EliminateCorners", "Eliminate corners (if they are primals)", eliminateCorners);
cmd.addReal ("t", "Solver.Tolerance", "Stopping criterion for linear solver", tolerance);
cmd.addInt ("", "Solver.MaxIterations", "Maximum iterations for linear solver", maxIterations);
cmd.addSwitch("", "Solver.CalcEigenvalues","Estimate eigenvalues based on Lanczos", calcEigenvalues);
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; }
{
gsInfo <<
"Geometry file could not be found.\n";
return EXIT_FAILURE;
}
gsInfo <<
"Run ieti_example with options:\n" << cmd << std::endl;
gsInfo <<
"Define geometry... " << std::flush;
if (!mpPtr)
{
gsInfo <<
"No geometry found in file " << geometry <<
".\n";
return EXIT_FAILURE;
}
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)
}
gsInfo <<
"Define right-hand-side and boundary conditions... " << std::flush;
{
const index_t len = boundaryConditions.length();
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";
}
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 <<
"Setup assembler and assemble matrix... " << std::flush;
const index_t nPatches = mp.nPatches();
{
space u = assembler.getSpace(mb);
u.setup(bc, dirichlet::interpolation, 0);
ietiMapper.
init( mb, u.mapper(), u.fixedPart() );
}
bool cornersAsPrimals = false, edgesAsPrimals = false, facesAsPrimals = false;
for (size_t i=0; i<primals.length(); ++i)
switch (primals[i])
{
case 'c': cornersAsPrimals = true; break;
case 'e': edgesAsPrimals = true; break;
case 'f': facesAsPrimals = true; break;
default:
gsInfo <<
"\nUnkown type of primal constraint: \"" << primals[i] <<
"\"\n";
return EXIT_FAILURE;
}
if (cornersAsPrimals)
if (edgesAsPrimals)
if (facesAsPrimals)
bool fullyRedundant = true,
noLagrangeMultipliersForCorners = cornersAsPrimals;
if (eliminateCorners)
primal.setEliminatePointwiseConstraints(true);
{
assembler.setIntegrationElements(mb_local);
geometryMap G = assembler.getMap(mp_local);
space u = assembler.getSpace(mb_local);
u.setup(bc_local, dirichlet::interpolation, 0);
auto ff = assembler.getCoeff(f, G);
assembler.initSystem();
assembler.assemble( igrad(u, G) * igrad(u, G).tr() *
meas(G), u * ff *
meas(G) );
variable g_N = assembler.getBdrFunction();
assembler.assembleBdr(bc_local.
get(
"Neumann"), u * g_N.val() *
nv(G).norm() );
jumpMatrix,
localMatrix,
)
);
primal.handleConstraints(
jumpMatrix,
localMatrix,
localRhs
);
);
}
{
= makeSparseCholeskySolver(primal.localMatrix());
primal.jumpMatrix().moveToPtr(),
makeMatrixOp(primal.localMatrix().moveToPtr()),
localSolver
);
}
gsInfo <<
"Setup solver and solve... \n"
" Setup multiplicity scaling... " << std::flush;
gsInfo <<
"done.\n Setup rhs... " << std::flush;
gsInfo <<
"done.\n Setup cg solver for Lagrange multipliers and solve... " << std::flush;
PCG.setOptions( cmd.getGroup("Solver") ).solveDetailed( rhsForSchur, lambda, errorHistory );
gsInfo <<
"done.\n Reconstruct solution from Lagrange multipliers... " << std::flush;
std::vector<gsMatrix<>> uLocal = primal.distributePrimalSolution(
);
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 (calcEigenvalues)
gsInfo <<
"Estimated condition number: " << PCG.getConditionNumber() <<
"\n";
if (!out.empty())
{
std::time_t time = std::time(NULL);
fd.add(cmd);
fd.add(uGlobal);
fd.addComment(std::string("ieti_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";
gsWriteParaview<>(
gsField<>( mp, mpsol ),
"ieti_result", 1000);
}
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;
}
Definition gsExpressions.h:973
Definition gsExpressions.h:928
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
bcRefList get(const std::string &label, const short_t unk=0, int comp=-1) const
Definition gsBoundaryConditions.h:420
void setGeoMap(const gsFunctionSet< T > &gm)
Set the geometry map to evaluate boundary conditions.
Definition gsBoundaryConditions.h:916
Class for command-line argument parsing.
Definition gsCmdLine.h:57
The conjugate gradient method.
Definition gsConjugateGradient.h:30
Class defining a globally constant function.
Definition gsConstantFunction.h:34
Definition gsExprAssembler.h:33
Generic evaluator of isogeometric expressions.
Definition gsExprEvaluator.h:39
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
void interfaceAveragesAsPrimals(const gsMultiPatch< T > &geo, short_t d)
Set up interface averages as primal dofs.
Definition gsIetiMapper.hpp:218
void cornersAsPrimals()
Set up the corners as primal dofs.
Definition gsIetiMapper.hpp:126
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
void initFeSpace(typename gsExprAssembler< T >::space u, index_t k)
Apply the required changes to a space object of the expression assembler.
Definition gsIetiMapper.h:130
This class represents a IETI system.
Definition gsIetiSystem.h:70
OpPtr schurComplement() const
Returns gsLinearOperator that represents the Schur complement for the IETI problem.
Definition gsIetiSystem.hpp:83
void addSubdomain(JumpMatrixPtr jumpMatrix, OpPtr localMatrixOp, Matrix localRhs, OpPtr localSolverOp=OpPtr())
Definition gsIetiSystem.hpp:32
void reserve(index_t n)
Reserves the memory required to store the number of subdomains.
Definition gsIetiSystem.hpp:23
Matrix rhsForSchurComplement() const
Returns the right-hand-side that is required for the Schur complement formulation of the IETI problem...
Definition gsIetiSystem.hpp:91
std::vector< Matrix > constructSolutionFromLagrangeMultipliers(const Matrix &multipliers) const
Returns the local solutions for the individual subdomains.
Definition gsIetiSystem.hpp:107
index_t nLagrangeMultipliers() const
Returns the number of Lagrange multipliers.
Definition gsIetiSystem.h:116
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
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
This class represents the primal system for a IETI-DP algorithm.
Definition gsPrimalSystem.h:87
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
void setupMultiplicityScaling()
This sets up the member vector localScaling based on multiplicity scaling.
Definition gsScaledDirichletPrec.hpp:149
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
Main header to be included by clients using the G+Smo library.
EIGEN_STRONG_INLINE meas_expr< T > meas(const gsGeometryMap< T > &G)
The measure of a geometry map.
Definition gsExpressions.h:4555
EIGEN_STRONG_INLINE onormal_expr< T > nv(const gsGeometryMap< T > &u)
The (outer pointing) boundary normal of a geometry map.
Definition gsExpressions.h:4506
The G+Smo namespace, containing all definitions for the library.
@ dirichlet
Dirichlet type.
Definition gsBoundaryConditions.h:31
@ neumann
Neumann type.
Definition gsBoundaryConditions.h:33