35 typename gsExprHelper<T>::Ptr m_exprdata;
45 std::list<gsFeSpaceData<T> > m_sdata;
46 std::vector<gsFeSpaceData<T>*> m_vrow;
47 std::vector<gsFeSpaceData<T>*> m_vcol;
50 mutable bool m_modified;
52 typedef typename gsExprHelper<T>::nullExpr nullExpr;
60 typedef typename gsBoundaryConditions<T>::bcRefList bcRefList;
61 typedef gsBoxTopology::bContainer bContainer;
62 typedef gsBoxTopology::ifContainer ifContainer;
64 typedef typename gsExprHelper<T>::element
element;
68 typedef typename expr::gsFeSolution<T>
solution;
74 m_exprdata->cleanUp();
82 m_vrow(_rBlocks,nullptr), m_vcol(_cBlocks,nullptr), m_sparsity(0), m_modified(false)
95 "gsExprAssembler::numDofs() says: initSystem() has not been called.");
96 return m_vcol.back()->mapper.firstIndex() +
97 m_vcol.back()->mapper.freeSize();
104 "initSystem() has not been called.");
105 return m_vrow.back()->mapper.firstIndex() +
106 m_vrow.back()->mapper.freeSize();
114 for (
size_t i = 0; i!=m_vrow.size(); ++i)
115 nb += m_vrow[i]->dim;
124 {
return m_fmatrix; }
128 {
return m_modified ?
makeMatrix() : m_matrix; }
134 m_fmatrix.toSparseMatrix(m_matrix);
143 out =
give(m_matrix);
150 return give(m_matrix);
162 { m_exprdata->setMultiBasis(mesh); }
171 return (
nullptr == m_gmap ? m_exprdata->multiPatch() : *m_gmap);
174#if EIGEN_HAS_RVALUE_REFERENCES
181 {
return m_exprdata->multiBasis(); }
183 const typename gsExprHelper<T>::Ptr exprData()
const {
return m_exprdata; }
187 {
return m_exprdata->getMap(g); }
194 GISMO_ASSERT(1==mp.targetDim(),
"Expecting scalar source space");
196 "Given ID "<<
id<<
" exceeds "<<m_vcol.size()-1 );
198 if (m_vcol[
id]==
nullptr)
200 m_sdata.emplace_back(mp,dim,
id);
201 m_vcol[id] = &m_sdata.back();
202 if ((
size_t)
id<m_vrow.size() &&
nullptr==m_vrow[
id]) m_vrow[id]=m_vcol[id];
206 m_vcol[id]->fs = ∓
207 m_vcol[id]->dim = dim;
211 u.setSpaceData(*m_vcol[
id]);
219 GISMO_ASSERT(1==mp.targetDim(),
"Expecting scalar source space");
221 "Given ID "<<
id<<
" exceeds "<<m_vrow.size()-1 );
223 if ( (m_vrow[
id]==
nullptr) ||
224 ((
size_t)
id<m_vcol.size() && m_vrow[
id]==m_vcol[
id]) )
226 m_sdata.emplace_back(mp,dim,
id);
227 m_vrow[id] = &m_sdata.back();
231 m_vrow[id]->fs = ∓
232 m_vrow[id]->dim = dim;
236 s.setSpaceData(m_sdata.back());
253 {
return getTestSpace( mp,(-1 == dim ? u.dim() : dim), u.id() ); }
261 getSpace(*m_vcol[
id]->fs,m_vcol[
id]->dim);
262 s.setSpaceData(*m_vcol[
id]);
275 getSpace(*m_vrow[
id]->fs,m_vrow[
id]->dim);
276 s.setSpaceData(*m_vrow[
id]);
286 {
return m_exprdata->getVar(func, 1); }
291 {
return m_exprdata->getVar(func,G); }
302 variable getBdrFunction()
const {
return m_exprdata->getMutVar(); }
304 expr::gsComposition<T> getBdrFunction(
geometryMap & G)
const
305 {
return m_exprdata->getMutVar(G); }
307 element getElement()
const {
return m_exprdata->getElement(); }
310 void setFixedDofVector(gsMatrix<T> & dof,
short_t unk = 0);
312 void setFixedDofs(
const gsMatrix<T> & coefMatrix,
short_t unk = 0,
size_t patch = 0);
329 void clearRhs() { m_rhs.setZero(); }
339 if (m_fmatrix.nonZeros() && save_sparsety_pattern)
341 m_fmatrix.assignZero();
348 if (0 == m_fmatrix.
rows() || 0 == m_fmatrix.
cols())
349 gsWarn <<
" No internal DOFs, zero sized system.\n";
352 const T bdA = m_options.
getReal(
"bdA");
354 const T bdO = m_options.
getReal(
"bdO");
356 const short_t dim = m_exprdata->multiBasis().domainDim();
357 for (
short_t i = 0; i != dim; ++i)
358 nz *= bdA *
static_cast<T
>(
359 m_exprdata->multiBasis().maxDegree(i)) +
363 cast<T, index_t>(nz * (1.0 + bdO)));
371 _computePattern(args...);
378 _computePatternBdr(BCs, args...);
385 _computePatternIfc(iFaces, args...);
402 "initSystem() has not been called.");
404 _blockDims(rowSizes, colSizes);
406 return m_matrix.
blockView(rowSizes,colSizes);
415 "initSystem() has not been called.");
417 _blockDims(rowSizes, colSizes);
419 return m_matrix.
blockView(rowSizes,colSizes);
429 template<
class... expr>
void assemble(
const expr &... args);
434 template<
class... expr>
void assembleBdr(
const bcRefList & BCs, expr&... args);
436 template<
class... expr>
void assembleBdr(
const bContainer & bnd, expr&... args);
438 template<
class... expr>
void assembleIfc(
const ifContainer & iFaces, expr... args);
449 template<
class expr>
void assembleJacobianIfc(
const ifContainer & iFaces,
454 template<
class... expr>
void _computePattern(
const expr &... args);
455 template<
class... expr>
void _computePatternBdr(
const bcRefList & BCs,
const expr &... args);
456 template<
class... expr>
void _computePatternIfc(
const ifContainer & iFaces, expr... args);
461 if (1==m_vcol.size() && 1==m_vrow.size())
472 rowSizes.resize(m_vrow.size());
473 for (
index_t r = 0; r != rowSizes.size(); ++r)
474 rowSizes[r] = m_vrow[r]->dim() * m_vrow[r]->mapper.freeSize();
475 colSizes.resize(m_vcol.size());
476 for (
index_t c = 0; c != colSizes.size(); ++c)
477 colSizes[c] = m_vcol[c]->dim() * m_vcol[c]->mapper.freeSize();
488 template <
typename E>
void operator() (
const gismo::expr::_expr<E> & v)
495 template <
typename E>
void operator() (
const gsExprAssembler & ea,
496 const gismo::expr::_expr<E> & ee)
498 auto u = ee.rowVar();
499 auto v = ee.colVar();
501 const bool m = E::isMatrix();
503 GISMO_ASSERT(v.isValid(),
"The row space is not valid");
504 GISMO_ASSERT(!m || u.isValid(),
"The column space is not valid");
505 GISMO_ASSERT(m || (ea.numDofs()==ee.rhs().size()),
"The right-hand side vector is not initialized");
513 _checkMatrix(
bool & _result) : m_result(_result) { }
514 template <
typename E>
void operator() (
const gismo::expr::_expr<E> &)
515 { m_result |= E::isMatrix(); }
522 FiberMatrix & m_fmatrix;
524 const gsVector<T> & m_quWeights;
526 gsMatrix<T> localMat;
529 _eval(FiberMatrix & _fmatrix,
531 const gsVector<> & _quWeights)
532 : m_fmatrix(_fmatrix), m_rhs(_rhs),
533 m_quWeights(_quWeights), m_elim(true)
536 void setElim(
bool elim) {m_elim = elim;}
538 template <
typename E>
void operator() (
const gismo::expr::_expr<E> & ee)
540 GISMO_ASSERT(E::isMatrix() || E::isVector(),
"Expecting a matrix or vector expression.");
542 ( E::isVector() || (ee.colVar().data().flags &
SAME_ELEMENT) ) )
545 quadrature(ee, localMat);
547 if (m_elim) push<E::isMatrix(),true>(ee.rowVar(), ee.colVar(), 0, 0);
548 else push<E::isMatrix(),false>(ee.rowVar(), ee.colVar(), 0, 0);
556 const T * w = m_quWeights.data();
557 for (k = 0; k != m_quWeights.rows(); ++k)
560 localMat.noalias() = (*(w++)) * ee.eval(k);
562 if (m_elim) push<E::isMatrix(),true>(ee.rowVar(), ee.colVar(), ra, ca);
563 else push<E::isMatrix(),false>(ee.rowVar(), ee.colVar(), ra, ca);
568 template <
typename E>
569 inline void quadrature(
const gismo::expr::_expr<E> & ee,
573 const T * w = m_quWeights.data();
574 lm.noalias() = (*w) * ee.eval(0);
575 for (
index_t k = 1; k != m_quWeights.rows(); ++k)
576 lm.noalias() += (*(++w)) * ee.eval(k);
579 template <
typename E>
void diff(
const gismo::expr::_expr<E> & ee,
582 GISMO_ASSERT(E::isVector(),
"Expecting a vector expression.");
583 static const T delta = 0.00001;
585 const index_t sz = u.space().cardinality();
586 localMat.setZero(sz, sz);
588 for (
index_t c=0; c!= u.dim(); c++)
590 const index_t rls = c * u.data().actives.rows();
591 for (
index_t j = 0; j != sz/u.dim(); j++ )
593 const index_t jj = u.mapper().index(u.data().actives.at(j),
594 u.space().data().patchId, c);
595 if (u.mapper().is_free_index(jj) )
600 u.perturbLocal( delta , jj, u.space().data().patchId);
602 localMat.col(rls+j) += 8 * aux;
603 u.perturbLocal( delta , jj, u.space().data().patchId);
605 localMat.col(rls+j) -= aux;
606 u.perturbLocal(-3*delta, jj, u.space().data().patchId);
608 localMat.col(rls+j) -= 8 * aux;
609 u.perturbLocal( -delta , jj, u.space().data().patchId);
611 localMat.col(rls+j) += aux;
612 localMat.col(rls+j) /= 12*delta;
614 u.perturbLocal(2*delta, jj, u.space().data().patchId);
620 push<true,false>(ee.rowVar(), ee.rowVar());
623 void operator() (
const expr::_expr<expr::gsNullExpr<T> > &) {}
625 template<
bool isMatrix,
bool elim = true>
626 void push(
const expr::gsFeSpace<T> & v,
629 GISMO_ASSERT(v.isValid(),
"The row space is not valid");
630 GISMO_ASSERT(!isMatrix || u.isValid(),
"The column space is not valid");
637 const gsDofMapper & rowMap = v.mapper();
638 const gsDofMapper & colMap = (isMatrix ? u.mapper() : rowMap);
639 gsMatrix<index_t> & rowInd0 =
const_cast<gsMatrix<index_t>&
>(v.data().actives);
640 gsMatrix<index_t> & colInd0 = (isMatrix ?
const_cast<gsMatrix<index_t>&
>(u.data().actives) : rowInd0);
641 const gsMatrix<T> & fixedDofs = (isMatrix ? u.fixedPart() : gsMatrix<T>());
645 GISMO_ASSERT( rowInd0.rows()*rd==localMat.rows() && colInd0.rows()*cd==localMat.cols(),
646 "Invalid local matrix (expected "<<rowInd0.rows()*rd <<
"x"<< colInd0.rows()*cd <<
"), got\n" << localMat );
649 "Invalid values for fixed part");
655 for (
index_t r = 0; r != rd; ++r)
657 const index_t rls = r * rowInd0.rows();
658 for (
index_t i = 0; i != rowInd0.rows(); ++i)
660 const index_t ii = rowMap.index(rowInd0(i,ra),v.data().patchId,r);
661 if ( rowMap.is_free_index(ii) )
665 for (
index_t c = 0; c != cd; ++c)
667 const index_t cls = c * colInd0.rows();
669 for (
index_t j = 0; j != colInd0.rows(); ++j)
671 if ( 0 == localMat(rls+i,cls+j) )
continue;
673 const index_t jj = colMap.index(colInd0(j,ca),u.data().patchId,c);
674 if ( colMap.is_free_index(jj) )
680 m_fmatrix.coeffRef(ii, jj) += localMat(rls+i,cls+j);
687 m_rhs.at(ii) -= localMat(rls+i,cls+j) *
688 fixedDofs.at(colMap.global_to_bindex(jj));
697 for(
index_t a = 0; a!= m_rhs.cols();++a)
700 m_rhs(ii,a) += localMat(rls+i,a);
703 m_rhs.row(ii) += localMat.row(rls+i);
715 FiberMatrix & m_fmatrix;
716 const gsMatrix<T> & m_point;
718 gsMatrix<index_t> rowInd0, colInd0;
720 std::vector<omp_lock_t> & m_lock;
722 _pattern(FiberMatrix & _fmatrix,
723 const gsMatrix<T> & _point,
unsigned & _patchid
725 , std::vector<omp_lock_t> & _lock
728 : m_fmatrix(_fmatrix), m_point(_point), patchid(_patchid)
734 template <
typename E>
void operator() (
const gismo::expr::_expr<E> & ee)
738 push(ee.rowVar(), ee.colVar());
741 void operator() (
const expr::_expr<expr::gsNullExpr<T> > &) {}
743 void push(
const expr::gsFeSpace<T> & v,
744 const expr::gsFeSpace<T> & u)
746 GISMO_ASSERT(v.isValid(),
"The row space is not valid");
747 GISMO_ASSERT(u.isValid(),
"The column space is not valid");
750 const gsDofMapper & rowMap = v.mapper();
751 const gsDofMapper & colMap = u.mapper();
752 rowInd0 = v.source().piece(patchid).active(m_point);
753 colInd0 = u.source().piece(patchid).active(m_point);
754 for (
index_t c = 0; c != cd; ++c)
755 for (
index_t j = 0; j != colInd0.rows(); ++j)
757 const index_t jj = colMap.index(colInd0.at(j),patchid,c);
758 if ( colMap.is_free_index(jj) )
761 omp_set_lock(&m_lock[jj]);
763 for (
index_t r = 0; r != rd; ++r)
764 for (
index_t i = 0; i != rowInd0.rows(); ++i)
766 const index_t ii = rowMap.index(rowInd0.at(i),patchid,r);
767 if ( rowMap.is_free_index(ii) )
768 m_fmatrix.insertExplicitZero(ii, jj);
771 omp_unset_lock(&m_lock[jj]);
784 opt.
addInt(
"DirichletValues" ,
"Method for computation of Dirichlet DoF values [100..103]", 101);
785 opt.
addInt(
"DirichletStrategy",
"Method for enforcement of Dirichlet BCs [11..14]", 11);
786 opt.
addReal(
"quA",
"Number of quadrature points: quA*deg + quB; For patchRule: Regularity of the target space", 1.0 );
787 opt.
addInt (
"quB",
"Number of quadrature points: quA*deg + quB; For patchRule: Degree of the target space", 1 );
788 opt.
addReal(
"bdA",
"Estimated nonzeros per column of the matrix: bdA*deg + bdB", 2.0 );
789 opt.
addInt (
"bdB",
"Estimated nonzeros per column of the matrix: bdA*deg + bdB", 1 );
790 opt.
addReal(
"bdO",
"Overhead of sparse mem. allocation: (1+bdO)(bdA*deg + bdB) [0..1]", 0.333);
791 opt.
addInt (
"quRule",
"Quadrature rule used (1) Gauss-Legendre; (2) Gauss-Lobatto; (3) Patch-Rule",1);
792 opt.
addSwitch(
"overInt",
"Apply over-integration on boundary elements or not?",
false);
793 opt.
addSwitch(
"flipSide",
"Flip side of interface where integration is performed.",
false);
794 opt.
addSwitch(
"movingInterface",
"Used in interface assembly when interface is not stationary.",
false);
812 fixedDofs.swap(vals);
815 GISMO_ENSURE( fixedDofs.size() == m_vcol[unk]->mapper.boundarySize(),
816 "The Dirichlet DoFs were not provided correctly.");
820void gsExprAssembler<T>::setFixedDofs(
const gsMatrix<T> & coefMatrix,
short_t unk,
size_t patch)
822 GISMO_ASSERT( m_options.
getInt(
"DirichletValues") == dirichlet::user,
"Incorrect options");
824 expr::gsFeSpace<T> & u = *m_vcol[unk];
826 const gsMultiBasis<T> & mbasis = *
dynamic_cast<const gsMultiBasis<T>*
>(m_vcol[unk]->fs);
828 const gsDofMapper & mapper = m_vcol[unk]->mapper;
835 gsMatrix<T> & fixedDofs = m_vcol[unk]->fixedDofs;
836 GISMO_ASSERT(fixedDofs.size() == m_vcol[unk]->mapper.boundarySize(),
837 "Fixed DoFs were not initialized.");
840 typedef typename gsBoundaryConditions<T>::bcRefList bcRefList;
841 for (
typename bcRefList::const_iterator it = u.bc().dirichletBegin();
842 it != u.bc().dirichletEnd() ; ++it )
844 const index_t com = it->unkComponent();
849 const gsMatrix<index_t> boundary =
850 mbasis[k].boundary(it->side());
854 for (
index_t i=0; i!= boundary.size(); ++i)
858 const index_t ii = mapper.bindex( boundary.at(i) , k, com );
860 fixedDofs.at(ii) = coefMatrix(boundary.at(i), com);
869 if (!m_vcol.front()->valid()) m_vcol.front()->init();
870 if (!m_vrow.front()->valid()) m_vrow.front()->init();
871 for (
size_t i = 1; i!=m_vcol.size(); ++i)
873 if (!m_vcol.front()->valid()) m_vcol.front()->init();
874 m_vcol[i]->mapper.setShift(m_vcol[i-1]->mapper.firstIndex() +
875 m_vcol[i-1]->dim*m_vcol[i-1]->mapper.freeSize() );
877 if ( m_vcol[i] != m_vrow[i] )
879 if (!m_vrow.front()->valid()) m_vrow.front()->init();
880 m_vrow[i]->mapper.setShift(m_vrow[i-1]->mapper.firstIndex() +
881 m_vrow[i-1]->dim*m_vrow[i-1]->mapper.freeSize() );
886template<
size_t I,
class op,
typename... Ts>
887void op_tuple_impl (op & _op,
const std::tuple<Ts...> &tuple)
889 _op(std::get<I>(tuple));
890 if (I + 1 <
sizeof... (Ts))
891 op_tuple_impl<(I+1 <
sizeof... (Ts) ? I+1 : I)> (_op, tuple);
894template<
class op,
typename... Ts>
895void op_tuple (op & _op,
const std::tuple<Ts...> &tuple)
896{ op_tuple_impl<0>(_op,tuple); }
899template<
class... expr>
900void gsExprAssembler<T>::_computePattern(
const expr &... args)
902 GISMO_ASSERT(m_fmatrix.cols()==numDofs(),
"System not initialized, matrix.cols() = "<<m_fmatrix.cols()<<
"!="<<numDofs()<<
" = numDofs()");
905 std::vector<omp_lock_t> lock(numDofs());
906 for (
auto & l : lock)
913 const int tid = omp_get_thread_num();
914 const int nt = omp_get_num_threads();
916 auto arg_tpl = std::make_tuple(args...);
917 m_exprdata->parsePattern(arg_tpl);
919 typename gsBasis<T>::domainIter domIt;
921 _pattern pp(m_fmatrix, m_exprdata->points(), patchInd
926 const unsigned nP = m_exprdata->multiBasis().nBases();
928 const unsigned offset = (nP<(unsigned)(nt) ? 1 : nP/nt);
929 for (
unsigned Ind = 0; Ind != nP; ++Ind)
931 patchInd = (Ind + offset * tid) % nP;
932 domIt = m_exprdata->multiBasis().basis(patchInd).makeDomainIterator();
933 for ( domIt->next(tid); domIt->good(); domIt->next(nt) )
935 for (patchInd = 0; patchInd != nP; ++patchInd)
937 domIt = m_exprdata->multiBasis().basis(patchInd).makeDomainIterator();
938 for (; domIt->good(); domIt->next() )
941 m_exprdata->points() = domIt->centerPoint();
942 op_tuple(pp, arg_tpl);
947 for (
auto & l : lock)
948 omp_destroy_lock(&l);
953template<
class... expr>
954void gsExprAssembler<T>::_computePatternBdr(
const bcRefList & BCs,
const expr &... args)
956 GISMO_ASSERT(m_fmatrix.cols()==numDofs(),
"System not initialized, matrix.cols() = "<<m_fmatrix.cols()<<
"!="<<numDofs()<<
" = numDofs()");
958 if ( BCs.empty() || 0==numDofs() )
return;
961 std::vector<omp_lock_t> lock(numDofs());
962 for (
auto & l : lock)
974 auto arg_tpl = std::make_tuple(args...);
975 m_exprdata->parsePattern(arg_tpl);
976 typename gsBasis<T>::domainIter domIt;
978 _pattern pp(m_fmatrix, m_exprdata->points(), patchInd
984 for (
typename bcRefList::const_iterator iit = BCs.begin(); iit!= BCs.end(); ++iit)
986 const boundary_condition<T> * it = &iit->get();
988 patchInd = it->patch();
989 domIt = m_exprdata->multiBasis().basis(it->patch()).
990 makeDomainIterator(it->side());
994 for (; domIt->good(); domIt->next() )
996# pragma omp single nowait
998 m_exprdata->points() = domIt->centerPoint();
999 op_tuple(pp, arg_tpl);
1007 for (
auto & l : lock)
1008 omp_destroy_lock(&l);
1014template<
class... expr>
1015void gsExprAssembler<T>::_computePatternIfc(
const ifContainer & iFaces, expr... args)
1017 GISMO_ASSERT(m_fmatrix.cols()==numDofs(),
"System not initialized");
1018 if ( iFaces.empty() || 0==numDofs() )
return;
1021 std::vector<omp_lock_t> lock(numDofs());
1022 for (
auto & l : lock)
1026 typename gsBasis<T>::domainIter domIt;
1027 const bool flipSide = m_options.
askSwitch(
"flipSide",
false);
1030 auto arg_tpl = std::make_tuple(args...);
1031 m_exprdata->parsePattern(arg_tpl);
1032 unsigned patchInd(0);
1033 _pattern pp(m_fmatrix, m_exprdata->points(), patchInd
1039 ifacemap interfaceMap;
1040 for (gsBoxTopology::const_iiterator it = iFaces.begin();
1041 it != iFaces.end(); ++it )
1045 const boundaryInterface & iFace = flipSide ? it->getInverse() : *it;
1046 const index_t patch1 = iFace.first() .patch;
1047 const index_t patch2 = iFace.second().patch;
1049 if (iFace.type() == interaction::conforming)
1051 m_exprdata->multiBasis().basis(patch1).support(),
1052 m_exprdata->multiBasis().basis(patch2).support() );
1054 interfaceMap = gsCPPInterface<T>::make(getGeometryMap(), m_exprdata->multiBasis(), iFace);
1056 domIt = m_exprdata->multiBasis().basis(patch1)
1057 .makeDomainIterator(iFace.first().side());
1061 for (; domIt->good(); domIt->next() )
1063# pragma omp single nowait
1065 m_exprdata->points() = domIt->centerPoint();
1066 interfaceMap->eval_into(m_exprdata->points(), m_exprdata->pointsIfc());
1067 op_tuple(pp, arg_tpl);
1076template<
class... expr>
1079 GISMO_ASSERT(m_fmatrix.cols()==numDofs(),
"System not initialized, matrix.cols() = "<<m_fmatrix.cols()<<
"!="<<numDofs()<<
" = numDofs()");
1081 if ((m_sparsity & 1) == 0)
1082 this->_computePattern(args...);
1084 bool failed =
false;
1086#pragma omp parallel shared(failed)
1089 const int tid = omp_get_thread_num();
1090 const int nt = omp_get_num_threads();
1092 auto arg_tpl = std::make_tuple(args...);
1093 m_exprdata->parse(arg_tpl);
1098 _checkMatrix CM(m_modified);
1099 op_tuple(CM, arg_tpl);
1101 _eval ee(m_fmatrix, m_rhs, m_exprdata->weights());
1102 ee.setElim(dirichlet::elimination==elim);
1103 typename gsQuadRule<T>::uPtr QuRule;
1104 typename gsBasis<T>::domainIter domIt;
1108 const unsigned nP = m_exprdata->multiBasis().nBases();
1110 const unsigned offset = (nP<(unsigned)(nt) ? 1 : nP/nt);
1111 for (
unsigned Ind = 0; Ind < nP && (!failed); ++Ind)
1114 const unsigned patchInd = (Ind + offset * tid) % nP;
1116 for (
unsigned patchInd = 0; patchInd < nP && (!failed); ++patchInd)
1123 m_exprdata->multiBasis().basis(patchInd).makeDomainIterator();
1127 for ( domIt->next(tid); domIt->good() && (!failed); domIt->next(nt) )
1129 for (; domIt->good(); domIt->next() )
1133 QuRule->
mapTo( domIt->lowerCorner(), domIt->upperCorner(),
1134 m_exprdata->points(), m_exprdata->weights());
1136 if (m_exprdata->points().cols()==0)
1144 m_exprdata->precompute(patchInd);
1149 #pragma omp atomic write
1154 m_exprdata->precompute(patchInd);
1157 op_tuple(ee, arg_tpl);
1162 GISMO_ENSURE(!failed,
"Assembly failed due to an error");
1166template<
class... expr>
1169 GISMO_ASSERT(m_fmatrix.cols()==numDofs(),
"System not initialized");
1171 if ( BCs.empty() || 0==numDofs() )
return;
1173 if ((m_sparsity & 2) == 0)
1174 this->_computePatternBdr(BCs, args...);
1176 m_exprdata->setMutSource(*BCs.front().get().function());
1184 auto arg_tpl = std::make_tuple(args...);
1185 m_exprdata->parse(arg_tpl);
1188 typename gsQuadRule<T>::uPtr QuRule;
1191 _checkMatrix CM(m_modified);
1192 op_tuple(CM, arg_tpl);
1193 _eval ee(m_fmatrix, m_rhs, m_exprdata->weights());
1196 for (
typename bcRefList::const_iterator iit = BCs.begin(); iit!= BCs.end(); ++iit)
1200 QuRule =
gsQuadrature::getPtr(m_exprdata->multiBasis().basis(it->patch()), m_options, it->side().direction());
1203 m_exprdata->setMutSource(*it->function());
1205 typename gsBasis<T>::domainIter domIt =
1206 m_exprdata->multiBasis().basis(it->patch()).
1207 makeDomainIterator(it->side());
1210 for (; domIt->good(); domIt->next() )
1213 QuRule->
mapTo( domIt->lowerCorner(), domIt->upperCorner(),
1214 m_exprdata->points(), m_exprdata->weights());
1216 if (m_exprdata->points().cols()==0)
1220 m_exprdata->precompute(it->patch(), it->side());
1223 op_tuple(ee, arg_tpl);
1232template<
class... expr>
1235 GISMO_ASSERT(m_fmatrix.cols()==numDofs(),
"System not initialized");
1237 if ( bnd.size()==0 || 0==numDofs() )
return;
1239 auto arg_tpl = std::make_tuple(args...);
1240 m_exprdata->parse(arg_tpl);
1242 typename gsQuadRule<T>::uPtr QuRule;
1245 _checkMatrix CM(m_modified);
1246 op_tuple(CM, arg_tpl);
1247 _eval ee(m_fmatrix, m_rhs, m_exprdata->weights());
1251 for (gsBoxTopology::const_biterator it = bnd.begin();
1252 it != bnd.end(); ++it )
1255 m_options, it->side().direction());
1257 typename gsBasis<T>::domainIter domIt =
1258 m_exprdata->multiBasis().basis(it->patch).
1259 makeDomainIterator(it->side());
1262 for (; domIt->good(); domIt->next() )
1265 QuRule->
mapTo( domIt->lowerCorner(), domIt->upperCorner(),
1266 m_exprdata->points(), m_exprdata->weights());
1268 if (m_exprdata->points().cols()==0)
1272 m_exprdata->precompute(it->patch, it->side());
1275 op_tuple(ee, arg_tpl);
1283template<
class T>
template<
class... expr>
1284void gsExprAssembler<T>::assembleIfc(
const ifContainer & iFaces, expr... args)
1286 GISMO_ASSERT(m_fmatrix.cols()==numDofs(),
"System not initialized");
1288 if ((m_sparsity & 4) == 0)
1289 this->_computePatternIfc(iFaces, args...);
1295 auto arg_tpl = std::make_tuple(args...);
1297 m_exprdata->parse(arg_tpl);
1300 typename gsQuadRule<T>::uPtr QuRule;
1303 _checkMatrix CM(m_modified);
1304 op_tuple(CM, arg_tpl);
1305 _eval ee(m_fmatrix, m_rhs, m_exprdata->weights());
1307 const bool flipSide = m_options.
askSwitch(
"flipSide",
false);
1309 ifacemap interfaceMap;
1311 for (gsBoxTopology::const_iiterator it = iFaces.begin();
1312 it != iFaces.end(); ++it )
1316 const boundaryInterface & iFace = flipSide ? it->getInverse() : *it;
1317 const index_t patch1 = iFace.first() .patch;
1318 const index_t patch2 = iFace.second().patch;
1320 if (iFace.type() == interaction::conforming)
1322 m_exprdata->multiBasis().basis(patch1).support(),
1323 m_exprdata->multiBasis().basis(patch2).support() );
1325 interfaceMap = gsCPPInterface<T>::make(getGeometryMap(), m_exprdata->multiBasis(), iFace);
1328 m_options, iFace.first().side().direction());
1330 typename gsBasis<T>::domainIter domIt =
1331 m_exprdata->multiBasis().basis(patch1)
1332 .makeDomainIterator(iFace.first().side());
1335 for (; domIt->good(); domIt->next() )
1338 QuRule->mapTo( domIt->lowerCorner(), domIt->upperCorner(),
1339 m_exprdata->points(), m_exprdata->weights());
1340 interfaceMap->eval_into(m_exprdata->points(), m_exprdata->pointsIfc());
1342 if (m_exprdata->points().cols()==0)
1346 m_exprdata->precompute(iFace);
1353 op_tuple(ee, arg_tpl);
1360template<
class T>
template<
class expr>
1363 GISMO_ASSERT(m_fmatrix.cols()==numDofs(),
"System not initialized");
1364 GISMO_ASSERT(expr::isVector(),
"Expecting a vector expression.");
1372 const int tid = omp_get_thread_num();
1373 const int nt = omp_get_num_threads();
1376 m_exprdata->parse(residual, u);
1380 typename gsQuadRule<T>::uPtr QuRule;
1383 _eval ee(m_fmatrix, m_rhs, m_exprdata->weights());
1387 for (
unsigned patchInd = 0; patchInd < m_exprdata->multiBasis().nBases(); ++patchInd)
1392 typename gsBasis<T>::domainIter domIt =
1393 m_exprdata->multiBasis().basis(patchInd).makeDomainIterator();
1397 for ( domIt->next(tid); domIt->good(); domIt->next(nt) )
1399 for (; domIt->good(); domIt->next() )
1403 QuRule->
mapTo( domIt->lowerCorner(), domIt->upperCorner(),
1404 m_exprdata->points(), m_exprdata->weights());
1406 if (m_exprdata->points().cols()==0)
1410 m_exprdata->precompute(patchInd);
1412# pragma omp critical (assemble_fdiffs)
1415 ee.diff(residual, u);
1424template<
class T>
template<
class expr>
1426 const expr residual, solution u)
1428 GISMO_ASSERT(m_fmatrix.cols()==numDofs(),
"System not initialized");
1429 GISMO_ASSERT(expr::isVector(),
"Expecting a vector expression.");
1433 m_exprdata->parse(residual, u);
1437 typename gsQuadRule<T>::uPtr QuRule;
1441 _eval ee(m_fmatrix, m_rhs, m_exprdata->weights());
1442 const bool flipSide = m_options.
askSwitch(
"flipSide",
false);
1443 const bool movingInterface = m_options.
askSwitch(
"movingInterface",
false);
1445 for (gsBoxTopology::const_iiterator it = iFaces.begin();
1446 it != iFaces.end(); ++it )
1455 m_exprdata->multiBasis(), iFace);
1460 typename gsBasis<T>::domainIter domIt =
1461 m_exprdata->multiBasis().basis(patch1)
1462 .makeDomainIterator(iFace.
first().side());
1465 for (; domIt->good(); domIt->next() )
1468 QuRule->
mapTo( domIt->lowerCorner(), domIt->upperCorner(),
1469 m_exprdata->points(), m_exprdata->weights());
1470 interfaceMap.eval_into(m_exprdata->points(), m_exprdata->pointsIfc());
1472 if (m_exprdata->points().cols()==0)
1476 m_exprdata->precompute(iFace);
1479 if (!movingInterface)
1481 ee.diff(residual, u);
1485 GISMO_ASSERT(expr::isVector(),
"Expecting a vector expression.");
1486 static const T delta = 0.00001;
1488 const index_t sz = residual.eval(0).rows();
1489 ee.localMat.setZero(sz, sz);
1491 auto & rowVar = residual.rowVar();
1493 for (
index_t c=0; c!= u.dim(); c++)
1495 const index_t rls = c * rowVar.data().actives.rows();
1496 for (
index_t j = 0; j != sz/u.dim(); j++ )
1498 const index_t jj = u.mapper().index(rowVar.data().actives(j),
1499 rowVar.data().patchId, c);
1500 if (rowVar.mapper().is_free_index(jj) )
1503 u.perturbLocal( delta , jj, rowVar.data().patchId);
1504 interfaceMap.updateBdr();
1505 interfaceMap.eval_into(m_exprdata->points(), m_exprdata->pointsIfc());
1506 m_exprdata->precompute(iFace);
1507 ee.quadrature(residual, ee.aux);
1508 ee.localMat.col(rls+j) += 8 * ee.aux;
1511 u.perturbLocal( delta , jj, rowVar.data().patchId);
1512 interfaceMap.updateBdr();
1513 interfaceMap.eval_into(m_exprdata->points(), m_exprdata->pointsIfc());
1514 m_exprdata->precompute(iFace);
1515 ee.quadrature(residual, ee.aux);
1516 ee.localMat.col(rls+j) -= ee.aux;
1518 u.perturbLocal(-3*delta, jj, rowVar.data().patchId);
1519 interfaceMap.updateBdr();
1520 interfaceMap.eval_into(m_exprdata->points(), m_exprdata->pointsIfc());
1521 m_exprdata->precompute(iFace);
1522 ee.quadrature(residual, ee.aux);
1523 ee.localMat.col(rls+j) -= 8 * ee.aux;
1525 u.perturbLocal( -delta , jj, rowVar.data().patchId);
1526 interfaceMap.updateBdr();
1527 interfaceMap.eval_into(m_exprdata->points(), m_exprdata->pointsIfc());
1528 m_exprdata->precompute(iFace);
1529 ee.quadrature(residual, ee.aux);
1530 ee.localMat.col(rls+j) += ee.aux;
1532 ee.localMat.col(rls+j) /= 12*delta;
1534 u.perturbLocal(2*delta, jj, rowVar.data().patchId);
1535 interfaceMap.updateBdr();
1541 ee.template push<true,false>(residual.rowVar(), residual.rowVar());
1548void gsExprAssembler<T>::quPointsWeights(std::vector<gsMatrix<T> >& cPoints, std::vector<gsVector<T> > & cWeights)
1550 GISMO_ASSERT(m_fmatrix.cols()==numDofs(),
"System not initialized, matrix.cols() = "<<m_fmatrix.cols()<<
"!="<<numDofs()<<
" = numDofs()");
1555 const int tid = omp_get_thread_num();
1556 const int nt = omp_get_num_threads();
1559 typename gsQuadRule<T>::uPtr QuRule;
1560 cPoints.resize( m_exprdata->multiBasis().nBases() );
1561 cWeights.resize( m_exprdata->multiBasis().nBases() );
1566 for (
unsigned patchInd = 0; patchInd < m_exprdata->multiBasis().nBases(); ++patchInd)
1568 auto & bb = m_exprdata->multiBasis().basis(patchInd);
1571 const index_t numNodes = QuRule->numNodes();
1573 const index_t sz = bb.numElements() * numNodes;
1574 cPoints[patchInd].resize(bb.domainDim(), sz );
1575 cWeights[patchInd].resize( sz );
1582 for ( domIt->next(tid); domIt->good(); domIt->next(nt) )
1584 for (; domIt->good(); domIt->next() )
1588 QuRule->mapTo( domIt->lowerCorner(), domIt->upperCorner(),
1589 m_exprdata->points(), m_exprdata->weights());
1591 cWeights[patchInd].segment(count, numNodes) = m_exprdata->weights();
1592 cPoints[patchInd].middleCols(count, numNodes) = m_exprdata->points();
short_t direction() const
Returns the parametric direction orthogonal to this side.
Definition gsBoundary.h:113
Definition gsExpressions.h:973
Definition gsExpressions.h:928
static uPtr make(const gsMatrix< T > mat, const gsVector< T > trans)
Affine maps are the composition of a linear map with a translation this constructor takes the two com...
Definition gsAffineFunction.h:75
virtual domainIter makeDomainIterator() const
Create a domain iterator for the computational mesh of this basis, that points to the first element o...
Definition gsBasis.hpp:542
Provides a mapping between the corresponding sides of two patches sharing an interface,...
Definition gsCPPInterface.h:33
Maintains a mapping from patch-local dofs to global dof indices and allows the elimination of individ...
Definition gsDofMapper.h:69
index_t boundarySize() const
Returns the number of eliminated dofs.
Definition gsDofMapper.h:457
index_t coupledSize() const
Returns the number of coupled (not eliminated) dofs.
Definition gsDofMapper.cpp:601
index_t freeSize() const
Returns the number of free (not eliminated) dofs.
Definition gsDofMapper.h:436
Definition gsExprAssembler.h:33
void computePatternBdr(const bcRefList &BCs, const expr &... args)
Initializes the pattern of the sparse matrix at boundary integrals.
Definition gsExprAssembler.h:376
void computePattern(const expr &... args)
Initializes the pattern of the sparse matrix.
Definition gsExprAssembler.h:369
void setIntegrationElements(const gsMultiBasis< T > &mesh)
Sets the domain of integration.
Definition gsExprAssembler.h:161
void assembleBdr(const bcRefList &BCs, expr &... args)
Adds the expressions args to the system matrix/rhs The arguments are considered as integrals over the...
Definition gsExprAssembler.h:1167
void rhs_into(gsMatrix< T > &out)
Writes the resulting vector in out. The internal data is moved.
Definition gsExprAssembler.h:157
space trialSpace(const index_t id) const
Definition gsExprAssembler.h:257
gsExprHelper< T >::geometryMap geometryMap
Geometry map type.
Definition gsExprAssembler.h:65
space getTestSpace(const gsFunctionSet< T > &mp, index_t dim=1, index_t id=0)
Definition gsExprAssembler.h:217
space getSpace(const gsFunctionSet< T > &mp, index_t dim=1, index_t id=0)
Definition gsExprAssembler.h:191
index_t numDofs() const
Returns the number of degrees of freedom (after initialization)
Definition gsExprAssembler.h:92
void initMatrix()
Initializes the sparse matrix only.
Definition gsExprAssembler.h:323
const gsSparseMatrix< T > & makeMatrix() const
Definition gsExprAssembler.h:132
const gsMatrix< T > & rhs() const
Returns the right-hand side vector(s)
Definition gsExprAssembler.h:154
gsExprHelper< T >::element element
Current element.
Definition gsExprAssembler.h:64
void resetDimensions()
Reset the dimensions of all involved spaces. Called internally by the init* functions.
Definition gsExprAssembler.h:867
void computePatternIfc(const ifContainer &iFaces, expr... args)
Initializes the pattern of the sparse matrix at boundary integrals.
Definition gsExprAssembler.h:383
solution getSolution(const expr::gsFeSpace< T > &s, gsMatrix< T > &cf) const
Registers a representation of a solution variable from space s, based on the vector cf.
Definition gsExprAssembler.h:299
geometryMap getMap(const gsFunctionSet< T > &g)
Registers g as an isogeometric geometry map and return a handle to it.
Definition gsExprAssembler.h:186
space testSpace(space u) const
Return the test space of a pre-existing trial space u.
Definition gsExprAssembler.h:281
space trialSpace(space &v) const
Return the trial space of a pre-existing test space v.
Definition gsExprAssembler.h:267
gsExprAssembler(index_t _rBlocks=1, index_t _cBlocks=1)
Definition gsExprAssembler.h:80
gsExprHelper< T >::variable variable
Variable type.
Definition gsExprAssembler.h:66
void initSystem(const index_t numRhs=1)
Initializes the sparse system (sparse matrix and rhs)
Definition gsExprAssembler.h:315
void matrix_into(gsSparseMatrix< T > &out)
Writes the resulting matrix in out. The internal matrix is moved.
Definition gsExprAssembler.h:140
void setOptions(gsOptionList opt)
Set the assembler options.
Definition gsExprAssembler.h:423
variable getCoeff(const gsFunctionSet< T > &func)
Definition gsExprAssembler.h:285
void setGeometryMap(const gsMultiPatch< T > &gMap)
Set the geometrymap ( used for interface assembly)
Definition gsExprAssembler.h:166
void assembleJacobian(const expr residual, solution &u)
Assembles the Jacobian matrix of the expression args with.
Definition gsExprAssembler.h:1361
void assemble(const expr &... args)
Adds the expressions args to the system matrix/rhs The arguments are considered as integrals over the...
Definition gsExprAssembler.h:1077
expr::gsFeSolution< T > solution
Solution type.
Definition gsExprAssembler.h:68
matBlockView matrixBlockView()
Definition gsExprAssembler.h:399
space testSpace(const index_t id)
Definition gsExprAssembler.h:271
const gsMultiBasis< T > & integrationElements() const
Returns the domain of integration.
Definition gsExprAssembler.h:180
gsOptionList & options()
Returns a reference to the options structure.
Definition gsExprAssembler.h:120
matConstBlockView matrixBlockView() const
Definition gsExprAssembler.h:412
void clearMatrix(const bool &save_sparsety_pattern=true)
Re-Init Matrix (set zero by default)
Definition gsExprAssembler.h:337
space getTestSpace(space u, const gsFunctionSet< T > &mp, index_t dim=-1)
Registers mp as an isogeometric test space corresponding to trial space u and return a handle to it.
Definition gsExprAssembler.h:252
index_t numBlocks() const
Definition gsExprAssembler.h:111
expr::gsComposition< T > getCoeff(const gsFunctionSet< T > &func, geometryMap &G)
Definition gsExprAssembler.h:290
void initVector(const index_t numRhs=1)
Initializes the right-hand side vector only.
Definition gsExprAssembler.h:390
static gsOptionList defaultOptions()
Returns the list of default options for assembly.
Definition gsExprAssembler.h:781
gsExprHelper< T >::space space
Space type.
Definition gsExprAssembler.h:67
const FiberMatrix & fiberMatrix() const
Returns the internally stored sparse fiber matrix.
Definition gsExprAssembler.h:123
const gsSparseMatrix< T > & matrix() const
Returns the left-hand global matrix.
Definition gsExprAssembler.h:127
index_t numTestDofs() const
Returns the number of test functions (after initialization)
Definition gsExprAssembler.h:101
Definition gsExprHelper.h:27
A specialized sparse matrix class which stores each row as a separate sparse vector.
Definition gsFiberMatrix.h:31
index_t rows() const
Definition gsFiberMatrix.h:93
index_t cols() const
Definition gsFiberMatrix.h:96
Interface for the set of functions defined on a domain (the total number of functions in the set equa...
Definition gsFunctionSet.h:219
memory::unique_ptr< gsFunction > uPtr
Unique pointer for gsFunction.
Definition gsFunction.h:68
Represents a block-view of the given matrix.
Definition gsMatrixBlockView.h:32
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
Class which holds a list of parameters/options, and provides easy access to them.
Definition gsOptionList.h:33
void addInt(const std::string &label, const std::string &desc, const index_t &value)
Adds a option named label, with description desc and value value.
Definition gsOptionList.cpp:201
bool askSwitch(const std::string &label, const bool &value=false) const
Reads value for option label from options.
Definition gsOptionList.cpp:128
const index_t & getInt(const std::string &label) const
Reads value for option label from options.
Definition gsOptionList.cpp:37
Real getReal(const std::string &label) const
Reads value for option label from options.
Definition gsOptionList.cpp:44
void addReal(const std::string &label, const std::string &desc, const Real &value)
Adds a option named label, with description desc and value value.
Definition gsOptionList.cpp:211
void addSwitch(const std::string &label, const std::string &desc, const bool &value)
Adds a option named label, with description desc and value value.
Definition gsOptionList.cpp:235
virtual void mapTo(const gsVector< T > &lower, const gsVector< T > &upper, gsMatrix< T > &nodes, gsVector< T > &weights) const
Maps quadrature rule (i.e., points and weights) from the reference domain to an element.
Definition gsQuadRule.h:177
Sparse matrix class, based on gsEigen::SparseMatrix.
Definition gsSparseMatrix.h:139
BlockView blockView(const gsVector< index_t > &rowSizes, const gsVector< index_t > &colSizes)
Return a block view of the matrix with rowSizes and colSizes.
Definition gsSparseMatrix.h:336
A vector with arbitrary coefficient type and fixed or dynamic size.
Definition gsVector.h:37
Provides a mapping between the corresponding sides of two patches sharing an interface,...
#define short_t
Definition gsConfig.h:35
#define index_t
Definition gsConfig.h:32
#define gsWarn
Definition gsDebug.h:50
#define GISMO_ENSURE(cond, message)
Definition gsDebug.h:102
#define gsInfo
Definition gsDebug.h:43
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
Generic expressions helper.
A specialized sparse matrix class which stores separately each fiber.
Provides functions to generate structured point data.
Creates a variety of quadrature rules.
The G+Smo namespace, containing all definitions for the library.
@ SAME_ELEMENT
Enable optimizations based on the assumption that all evaluation points are in the same bezier domain...
Definition gsForwardDeclarations.h:89
S give(S &x)
Definition gsMemory.h:266
Struct which represents an interface between two patches.
Definition gsBoundary.h:650
patchSide & first()
first, returns the first patchSide of this interface
Definition gsBoundary.h:776
Class that defines a boundary condition for a side of a patch for some unknown variable of a PDE.
Definition gsBoundaryConditions.h:107
static gsQuadRule< T >::uPtr getPtr(const gsBasis< T > &basis, const gsOptionList &options, short_t fixDir=-1)
Constructs a quadrature rule based on input options.
Definition gsQuadrature.h:64
index_t patch
The index of the patch.
Definition gsBoundary.h:234