28 gsBoundaryConditions<T> boundaryConditionsForDirection(
const gsBoundaryConditions<T>& bc,
index_t direction )
30 gsBoundaryConditions<T> result;
32 for (
index_t i = 1; i <= 2; ++i)
34 patchSide global(0,i+2*direction), local(0,i);
35 const boundary_condition<T>* cond = bc.getConditionFromSide(global);
37 result.addCondition(local,cond->type(),cond->function());
43 void eliminateDirichlet1D(
const gsBoundaryConditions<T>& bc,
44 const gsOptionList& opt, gsSparseMatrix<T> & result)
46 dirichlet::strategy ds = (dirichlet::strategy)opt.askInt(
"DirichletStrategy",dirichlet::elimination);
47 if (ds == dirichlet::elimination)
49 patchSide west(0,boundary::west), east(0,boundary::east);
53 if (i%2 + i/2 >= result.rows() || i%2 + i/2 >= result.cols())
58 case 1: result = result.block( 1, 1, result.rows()-1, result.cols()-1 );
break;
59 case 2: result = result.block( 0, 0, result.rows()-1, result.cols()-1 );
break;
60 case 3: result = result.block( 1, 1, result.rows()-2, result.cols()-2 );
break;
68 gsSparseMatrix<T> assembleMass(
const gsBasis<T>& basis)
70 gsExprAssembler<T> mass(1,1);
71 gsMultiBasis<T> mb(basis);
72 mass.setIntegrationElements(mb);
73 typename gsExprAssembler<T>::space u = mass.getSpace(mb);
75 mass.assemble( u * u.tr() );
76 gsSparseMatrix<T> result;
77 mass.matrix_into(result);
82 gsSparseMatrix<T> assembleStiffness(
const gsBasis<T>& basis)
84 gsExprAssembler<T> stiff(1,1);
85 gsMultiBasis<T> mb(basis);
86 stiff.setIntegrationElements(mb);
87 typename gsExprAssembler<T>::space u = stiff.getSpace(mb);
89 stiff.assemble(
grad(u) *
grad(u).tr() );
90 gsSparseMatrix<T> result;
91 stiff.matrix_into(result);
97 std::vector< gsSparseMatrix<T> > assembleTensorMass(
98 const gsBasis<T>& basis,
99 const gsBoundaryConditions<T>& bc,
100 const gsOptionList& opt
104 std::vector< gsSparseMatrix<T> > result(d);
107 result[i] = assembleMass(basis.component(d-1-i));
108 eliminateDirichlet1D(boundaryConditionsForDirection(bc,d-1-i), opt, result[i]);
114 std::vector< gsSparseMatrix<T> > assembleTensorStiffness(
115 const gsBasis<T>& basis,
116 const gsBoundaryConditions<T>& bc,
117 const gsOptionList& opt
121 std::vector< gsSparseMatrix<T> > result(d);
124 result[i] = assembleStiffness(basis.component(d-1-i));
125 eliminateDirichlet1D(boundaryConditionsForDirection(bc,d-1-i), opt, result[i]);
139 std::vector< gsSparseMatrix<T> > local_mass = assembleTensorMass(basis, bc, opt);
140 const index_t d = local_mass.size();
143 result = local_mass[i].kron(result);
156 std::vector< gsSparseMatrix<T> > local_mass = assembleTensorMass(basis, bc, opt);
158 std::vector<OpPtr> local_mass_op(d);
160 local_mass_op[i] = makeMatrixOp(local_mass[i].moveToPtr());
174 std::vector< gsSparseMatrix<T> > local_mass = assembleTensorMass(basis, bc, opt);
176 std::vector<OpPtr> local_mass_op(d);
178 local_mass_op[i] = makeSparseCholeskySolver(local_mass[i]);
194 std::vector< gsSparseMatrix<T> > local_stiff = assembleTensorStiffness(basis, bc, opt);
195 std::vector< gsSparseMatrix<T> > local_mass = assembleTensorMass(basis, bc, opt);
200 local_stiff[i] *= beta;
208 K = local_mass[i].
kron(K);
209 K += local_stiff[i].
kron(M);
210 if ( i != 0 || alpha != 0 )
211 M = local_mass[i].
kron(M);
231 std::vector< gsSparseMatrix<T> > local_stiff = assembleTensorStiffness(basis, bc, opt);
232 std::vector< gsSparseMatrix<T> > local_mass = assembleTensorMass(basis, bc, opt);
234 std::vector<OpUPtr> local_stiff_op(d);
235 std::vector<OpPtr > local_mass_op (d);
239 local_stiff[i] *= beta;
240 local_stiff_op[i] = makeMatrixOp(local_stiff[i].moveToPtr());
241 local_mass_op [i] = makeMatrixOp(local_mass [i].moveToPtr());
243 OpUPtr K =
give(local_stiff_op[0]);
244 OpPtr M =
give(local_mass_op [0]);
252 if ( i < d-1 || alpha != 0 )
273 GISMO_ASSERT ( beta != 0,
"gsPatchPreconditionersCreator<T>::fastDiagonalizationOp() does not work for beta==0." );
278 std::vector< gsSparseMatrix<T> > local_stiff = assembleTensorStiffness(basis, bc, opt);
279 std::vector< gsSparseMatrix<T> > local_mass = assembleTensorMass(basis, bc, opt);
284 local_stiff[i] *= beta;
290 sz *= local_stiff[i].rows();
294 diag.setConstant(sz,1,alpha);
299 typedef typename EVSolver::EigenvectorsType evMatrix;
300 typedef typename EVSolver::RealVectorType evVector;
303 std::vector<OpPtr> Qop(d);
304 std::vector<OpPtr> QTop(d);
313 ges.compute(local_stiff[i], local_mass[i], gsEigen::ComputeEigenvectors);
320 GISMO_ASSERT((etrans.block(1, 0, etrans.rows()-1, 1).array() < (T)(1)/100000000).all(),
321 "gsPatchPreconditionerCreator::fastDiagonalizationOp: gamma!=0 only allowed for pure Neumann.");
322 avg_term *= etrans(0,0) * etrans(0,0);
326 const evVector & D = ges.eigenvalues();
330 const index_t glob2 = sz / loc / glob;
332 for (
index_t l=0; l<loc; ++l )
333 for (
index_t m=0; m<glob; ++m )
334 for (
index_t n=0; n<glob2; ++n )
335 diag( m + l*glob + n*loc*glob, 0 ) += D(l,0);
338 ev.swap(const_cast<evMatrix&>(ges.eigenvectors()));
344 QTop[i] = makeMatrixOp( matrOp->
matrix().transpose() );
348 "gsPatchPreconditionerCreator::fastDiagonalizationOp: Internal error." );
350 diag(0,0) += avg_term;
353 diag( l, 0 ) = (T)(1)/diag( l, 0 );
355 memory::unique_ptr< gsEigen::DiagonalMatrix<T,Dynamic> > diag_mat(
new gsEigen::DiagonalMatrix<T,Dynamic>(
give(diag) ) );
359 makeMatrixOp(
give(diag_mat)),
374 const T h = basis.
knots().maxIntervalLength();
378 tildeBasis.resize(0,0); complBasis.resize(0,0);
382 const T u = (isLeftHandSide ? basis.
knots().first() : basis.
knots().last());
386 std::vector< gsMatrix<T> > allDerivs;
397 derivs.setZero(p-b, p-b);
399 const index_t offset = (isLeftHandSide ? b : 1);
402 if (odd) i_start = 1;
405 for (
index_t i = i_start; i < p; i += 2)
406 for (
index_t j = 0; j < p-b; ++j)
407 derivs(i-b, j) = math::pow(h, i) * allDerivs[i](j+offset);
409 typename gsMatrix<T>::JacobiSVD svd = derivs.jacobiSvd(gsEigen::ComputeFullV);
412 if (odd) n_tilde = (p + 1) / 2 - b;
413 else n_tilde = p / 2 - b;
415 tildeBasis = svd.matrixV().rightCols(n_tilde);
416 complBasis = svd.matrixV().leftCols(p - b - n_tilde);
421 void tildeSpaceBasis(
const gsBasis<T>& basis, gsSparseMatrix<T>& B_tilde, gsSparseMatrix<T>& B_compl,
const gsBoundaryConditions<T>& bc,
const bool odd =
true)
423 GISMO_ASSERT(
nullptr != (
dynamic_cast<const gsTensorBSplineBasis<1,T>*
>(&basis)),
424 "gsPatchPreconditionersCreator<T>::getTildeSpaceBasisTransformation and "
425 "gsPatchPreconditionersCreator<T>::subspaceCorrectedMassSmootherOp only work with tensor-B-spline bases." );
426 const gsTensorBSplineBasis<1,T>& bbasis =
static_cast<const gsTensorBSplineBasis<1,T>&
>(basis);
428 patchSide west(0,boundary::west), east(0,boundary::east);
429 bool bwest = ( bc.getConditionFromSide( west ) && bc.getConditionFromSide( west )->type() ==
condition_type::dirichlet );
430 bool beast = ( bc.getConditionFromSide( east ) && bc.getConditionFromSide( east )->type() ==
condition_type::dirichlet );
432 gsMatrix<T> b_L, b_compl_L;
433 gsMatrix<T> b_R, b_compl_R;
436 tildeSpaceBasis_oneside(bbasis,
true, b_L, b_compl_L, bwest, odd);
437 tildeSpaceBasis_oneside(bbasis,
false, b_R, b_compl_R, beast, odd);
440 const index_t n_L = b_L.cols();
441 const index_t m_L = b_L.rows();
442 const index_t n_R = b_R.cols();
443 const index_t m_R = b_R.rows();
444 const index_t n_c_L = b_compl_L.cols();
445 const index_t m_c_L = b_compl_L.rows();
446 const index_t n_c_R = b_compl_R.cols();
447 const index_t m_c_R = b_compl_R.rows();
448 const index_t n_I = n - n_L - n_R - n_c_L - n_c_R;
453 static bool warned =
false;
456 gsWarn <<
"tildeSpaceBasis was called with too few knots for that spline degree.\n"
457 <<
"So, we assume that S_tilde is empty.\n";
463 gsSparseEntries<T> E_compl;
465 for (
index_t i = 0; i < n; ++i)
466 E_compl.add(i,i,1.0);
468 B_compl.setFrom(E_compl);
472 gsSparseEntries<T> E_tilde, E_compl;
475 for (
index_t j = 0; j < n_L; ++j)
477 for (
index_t i = 0; i < m_L; ++i)
478 E_tilde.add(i, j, b_L(i, j));
481 for (
index_t j = 0; j < n_I; ++j)
483 E_tilde.add(m_L + j, n_L + j, 1.0);
486 for (
index_t j = 0; j < n_R; ++j)
488 for (
index_t i = 0; i < m_R; ++i)
489 E_tilde.add(m_L + n_I + i, n_L + n_I + j, b_R(i, j));
491 B_tilde.resize(n, n_L + n_I + n_R);
492 B_tilde.setFrom(E_tilde);
495 for (
index_t j = 0; j < n_c_L; ++j)
497 for (
index_t i = 0; i < m_c_L; ++i)
498 E_compl.add(i, j, b_compl_L(i, j));
501 for (
index_t j = 0; j < n_c_R; ++j)
503 for (
index_t i = 0; i < m_c_R; ++i)
504 E_compl.add(m_c_L + n_I + i, n_c_L + j, b_compl_R(i, j));
506 B_compl.resize(n, n_c_L + n_c_R);
507 B_compl.setFrom(E_compl);
512 void constructTildeSpaceBasis(
513 const gsBasis<T>& basis,
514 const gsBoundaryConditions<T>& bc,
515 const gsOptionList& opt,
516 std::vector< gsSparseMatrix<T> >& B_tilde,
517 std::vector< gsSparseMatrix<T> >& B_l2compl,
518 const bool odd =
true
524 dirichlet::strategy ds = (dirichlet::strategy)opt.askInt(
"DirichletStrategy",dirichlet::elimination);
525 if (ds == dirichlet::elimination)
528 tildeSpaceBasis(basis.component(d-1-i), B_tilde[i], B_l2compl[i], boundaryConditionsForDirection(bc,d-1-i), odd);
545 gsSparseMatrix<T> result(sz,sz);
546 gsSparseEntries<T> entries;
553 entries.add( i+a*(j+b*(k+c*(l+d*m))), i+a*(l+d*(k+c*(j+b*m))), 1. );
555 result.setFrom(entries);
556 result.makeCompressed();
570 std::vector< gsSparseMatrix<T> > B_tilde, B_l2compl;
571 constructTildeSpaceBasis( basis, bc, opt, B_tilde, B_l2compl, !opt.
askSwitch(
"UseVanishingEvenDerivatives",
false ) );
572 return std::pair< std::vector< gsSparseMatrix<T> >, std::vector< gsSparseMatrix<T> > >( B_tilde, B_l2compl );
585 GISMO_ASSERT ( beta != 0,
"gsPatchPreconditionersCreator<T>::subspaceCorrectedMassSmootherOp() does not work for beta==0." );
592 std::vector< gsSparseMatrix<T> > local_stiff = assembleTensorStiffness(basis, bc, opt);
593 std::vector< gsSparseMatrix<T> > local_mass = assembleTensorMass(basis, bc, opt);
598 local_stiff[i] *= beta;
602 std::vector< gsSparseMatrix<T> > B_tilde(d), B_l2compl(d);
603 constructTildeSpaceBasis(basis, bc, opt, B_tilde, B_l2compl);
605 std::vector< gsSparseMatrix<T> > M_compl(d), K_compl(d), B_compl(d);
606 std::vector< typename gsLinearOperator<T>::Ptr > M_tilde_inv(d);
612 M_inv->
apply( B_l2compl[i], B_compl_dense );
613 B_compl[i] = B_compl_dense.sparseView();
617 M_tilde_inv[i] = makeSparseCholeskySolver( M_tilde );
618 M_compl[i] = B_compl[i].transpose() * local_mass[i] * B_compl[i];
619 K_compl[i] = B_compl[i].transpose() * local_stiff[i] * B_compl[i];
625 for (
index_t type = 0; type < (1<<d); ++ type )
627 std::vector< typename gsLinearOperator<T>::Ptr > correction(0);
630 std::vector< gsSparseMatrix<T>* > transfers(d);
635 for (
index_t j = 0; j<d; ++ j )
637 if ( type & ( 1 << j ) )
638 transfers[j] = &(B_compl[d-1-j]);
641 transfers[j] = &(B_tilde[d-1-j]);
646 transfer = *(transfers[j]);
648 transfer = transfers[j]->
kron(transfer);
653 if ( transfer.cols() == 0 )
658 index_t left = 1, current = transfers[d-1]->cols(), right = 1;
659 for (
index_t j = 0; j < d-1; ++j )
660 left *= transfers[j]->cols();
662 for (
index_t j = d-1; j >= 0; --j )
664 if ( type & ( 1 << j ) )
666 transfer = transfer * kroneckerSwap<T>( right, current, left, 1, 1 );
670 current = transfers[j-1]->cols();
679 current = transfers[j-1]->cols();
687 for (
index_t j = d-1; j>=0; --j )
689 if ( ! ( type & ( 1 << j ) ) )
690 correction.push_back( M_tilde_inv[d-1-j] );
694 if ( numberInteriors == d )
695 correction[0] =
gsScaledOp<T>::make( correction[0], (T)(1)/( alpha + beta*(T)(numberInteriors)/(sigma*h*h) ) );
698 if ( numberInteriors < d )
704 for (
index_t k = d-1; k>=0; --k )
706 if ( type & ( 1 << k ) )
711 s = M_compl[d-1-k].
kron(s);
714 bc_matrix = ( alpha + beta*(T)(numberInteriors)/(sigma*h*h) ) * s;
717 for (
index_t j = d-1; j>=0; --j )
719 if ( type & ( 1 << j ) )
722 for (
index_t k = d-1; k>=0; --k )
724 if ( type & ( 1 << k ) )
728 chosenMatrix = &(K_compl[d-1-k]);
730 chosenMatrix = &(M_compl[d-1-k]);
735 s = s.
kron(*chosenMatrix);
742 correction.push_back(makeSparseCholeskySolver(bc_matrix));
750 makeMatrixOp( transOp->
matrix().transpose() ),
static uPtr make(std::vector< BasePtr > ops)
Make command returning a smart pointer.
Definition: gsKroneckerOp.h:55
static uPtr make()
Make command returning a smart pointer.
Definition: gsProductOp.h:77
static uPtr make()
Make command returning a smart pointer.
Definition: gsSumOp.h:70
static OpUPtr fastDiagonalizationOp(const gsBasis< T > &basis, const gsBoundaryConditions< T > &bc=gsBoundaryConditions< T >(), const gsOptionList &opt=gsAssembler< T >::defaultOptions(), T alpha=0, T beta=1, T gamma=0)
Definition: gsPatchPreconditionersCreator.hpp:264
static OpUPtr massMatrixOp(const gsBasis< T > &basis, const gsBoundaryConditions< T > &bc=gsBoundaryConditions< T >(), const gsOptionList &opt=gsAssembler< T >::defaultOptions())
Definition: gsPatchPreconditionersCreator.hpp:148
Dirichlet type.
Definition: gsBoundaryConditions.h:31
static OpUPtr subspaceCorrectedMassSmootherOp(const gsBasis< T > &basis, const gsBoundaryConditions< T > &bc=gsBoundaryConditions< T >(), const gsOptionList &opt=gsAssembler< T >::defaultOptions(), T sigma=(T)(12)/(T)(100), T alpha=0, T beta=1)
Definition: gsPatchPreconditionersCreator.hpp:576
uPtr moveToPtr()
This function returns a smart pointer to the matrix. After calling it, the matrix object becomes empt...
Definition: gsSparseMatrix.h:249
Provides a linear operator representing the Kronecker product of linear operators.
Simple adapter class to use a matrix (or matrix-like object) as a linear operator. Needed for the iterative method classes.
Definition: gsMatrixOp.h:33
short_t degree(short_t i) const
Degree with respect to the i-th variable. If the basis is a tensor product of (piecewise) polynomial ...
Definition: gsBSplineBasis.h:322
NestedMatrix matrix() const
Returns the matrix.
Definition: gsMatrixOp.h:84
Class for representing a Kronecker product of operators of type gsLinearOperator. ...
Definition: gsKroneckerOp.h:28
S give(S &x)
Definition: gsMemory.h:266
#define index_t
Definition: gsConfig.h:32
static uPtr make(BasePtr op, T scalar=1)
Make function returning a smart pointer.
Definition: gsLinearOperator.h:93
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
static gsSparseMatrix< T > stiffnessMatrix(const gsBasis< T > &basis, const gsBoundaryConditions< T > &bc=gsBoundaryConditions< T >(), const gsOptionList &opt=gsAssembler< T >::defaultOptions(), T alpha=0, T beta=1)
Definition: gsPatchPreconditionersCreator.hpp:184
virtual T getMinCellLength() const
Get the minimum mesh size, as expected for inverse inequalities.
Definition: gsBasis.hpp:663
virtual void evalAllDers_into(const gsMatrix< T > &u, int n, std::vector< gsMatrix< T > > &result, bool sameElement=false) const
Evaluate the nonzero functions and their derivatives up to order n at points u into result...
Definition: gsBSplineBasis.hpp:864
#define gsWarn
Definition: gsDebug.h:50
const KnotVectorType & knots(int i=0) const
Returns the knot vector of the basis.
Definition: gsBSplineBasis.h:369
static OpUPtr stiffnessMatrixOp(const gsBasis< T > &basis, const gsBoundaryConditions< T > &bc=gsBoundaryConditions< T >(), const gsOptionList &opt=gsAssembler< T >::defaultOptions(), T alpha=0, T beta=1)
Definition: gsPatchPreconditionersCreator.hpp:221
static OpUPtr massMatrixInvOp(const gsBasis< T > &basis, const gsBoundaryConditions< T > &bc=gsBoundaryConditions< T >(), const gsOptionList &opt=gsAssembler< T >::defaultOptions())
Definition: gsPatchPreconditionersCreator.hpp:166
memory::shared_ptr< gsLinearOperator > Ptr
Shared pointer for gsLinearOperator.
Definition: gsLinearOperator.h:33
memory::unique_ptr< gsSumOp > uPtr
Unique pointer for gsSumOp.
Definition: gsSumOp.h:33
GISMO_DEPRECATED index_t direction(index_t s)
Returns the parametric direction that corresponds to side s.
Definition: gsBoundary.h:1048
Class for representing the product of objects of type gsLinearOperator as gsLinearOperator.
Definition: gsProductOp.h:33
void addOperator(BasePtr op)
Add another operator.
Definition: gsSumOp.h:86
static std::pair< std::vector< gsSparseMatrix< T > >, std::vector< gsSparseMatrix< T > > > getTildeSpaceBasisTransformation(const gsBasis< T > &basis, const gsBoundaryConditions< T > &bc=gsBoundaryConditions< T >(), const gsOptionList &opt=gsAssembler< T >::defaultOptions())
Definition: gsPatchPreconditionersCreator.hpp:564
A univariate B-spline basis.
Definition: gsBSplineBasis.h:69
Class containing a set of boundary conditions.
Definition: gsBoundaryConditions.h:341
EIGEN_STRONG_INLINE grad_expr< E > grad(const E &u)
The gradient of a variable.
Definition: gsExpressions.h:4492
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
uPtr moveToPtr()
This function returns a smart pointer to the matrix. After calling it, the matrix object becomes empt...
Definition: gsMatrix.h:170
gsSparseMatrix kron(const gsSparseMatrix &other) const
Returns the Kronecker product of this with other.
Definition: gsSparseMatrix.h:414
virtual void apply(const gsMatrix< T > &input, gsMatrix< T > &x) const =0
apply the operator on the input vector and store the result in x
bool askSwitch(const std::string &label, const bool &value=false) const
Reads value for option label from options.
Definition: gsOptionList.cpp:128
Class which holds a list of parameters/options, and provides easy access to them. ...
Definition: gsOptionList.h:32
A class representing the product of gsLinearOperator s.
static gsSparseMatrix< T > massMatrix(const gsBasis< T > &basis, const gsBoundaryConditions< T > &bc=gsBoundaryConditions< T >(), const gsOptionList &opt=gsAssembler< T >::defaultOptions())
Definition: gsPatchPreconditionersCreator.hpp:133
Allows an operator to be multiplied with a scalar.
Definition: gsLinearOperator.h:77
Simple adapter classes to use matrices or linear solvers as gsLinearOperators.
Provides the sum of gsLinearOperator s as a gsLinearOperator.
Generic expressions matrix assembly.
A basis represents a family of scalar basis functions defined over a common parameter domain...
Definition: gsBasis.h:78
Provides declaration of TensorBSplineBasis abstract interface.