G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsExprAssembler.h
Go to the documentation of this file.
1 
14 #pragma once
15 
16 #include <gsUtils/gsPointGrid.h>
19 
21 
22 namespace gismo
23 {
24 
29 template<class T>
31 {
32 private:
33  typename gsExprHelper<T>::Ptr m_exprdata;
34  const gsMultiPatch<T>* m_gmap;
35 
36  gsOptionList m_options;
37 
38  gsSparseMatrix<T> m_matrix;
39  gsMatrix<T> m_rhs;
40 
41  std::list<gsFeSpaceData<T> > m_sdata;
42  std::vector<gsFeSpaceData<T>*> m_vrow;
43  std::vector<gsFeSpaceData<T>*> m_vcol;
44 
45  typedef typename gsExprHelper<T>::nullExpr nullExpr;
46 
47 public:
48 
49  typedef typename gsSparseMatrix<T>::BlockView matBlockView;
50 
51  typedef typename gsSparseMatrix<T>::constBlockView matConstBlockView;
52 
53  typedef typename gsBoundaryConditions<T>::bcRefList bcRefList;
54  typedef gsBoxTopology::bContainer bContainer;
55  typedef gsBoxTopology::ifContainer ifContainer;
56 
57  typedef typename gsExprHelper<T>::element element;
58  typedef typename gsExprHelper<T>::geometryMap geometryMap;
60  typedef typename gsExprHelper<T>::space space;
61  typedef typename expr::gsFeSolution<T> solution;
62 
63 public:
64 
65  void cleanUp()
66  {
67  m_exprdata->cleanUp();
68  }
69 
73  gsExprAssembler(index_t _rBlocks = 1, index_t _cBlocks = 1)
74  : m_exprdata(gsExprHelper<T>::make()), m_gmap(nullptr), m_options(defaultOptions()),
75  m_vrow(_rBlocks,nullptr), m_vcol(_cBlocks,nullptr)
76  { }
77 
78  // The copy constructor replicates the same environent but does
79  // not copy the expression helper
80 
83 
85  index_t numDofs() const
86  {
87  GISMO_ASSERT( m_vcol.back()->mapper.isFinalized(),
88  "gsExprAssembler::numDofs() says: initSystem() has not been called.");
89  return m_vcol.back()->mapper.firstIndex() +
90  m_vcol.back()->mapper.freeSize();
91  }
92 
95  {
96  GISMO_ASSERT( m_vrow.back()->mapper.isFinalized(),
97  "initSystem() has not been called.");
98  return m_vrow.back()->mapper.firstIndex() +
99  m_vrow.back()->mapper.freeSize();
100  }
101 
105  {
106  index_t nb = 0;
107  for (size_t i = 0; i!=m_vrow.size(); ++i)
108  nb += m_vrow[i]->dim;
109  return nb;
110  }
111 
113  gsOptionList & options() {return m_options;}
114 
116  const gsSparseMatrix<T> & matrix() const { return m_matrix; }
117 
119  void matrix_into(gsSparseMatrix<T> & out) { out = give(m_matrix); }
120 
121  EIGEN_STRONG_INLINE gsSparseMatrix<T> giveMatrix()
122  {
123  gsSparseMatrix<T> rvo;
124  rvo.swap(m_matrix);
125  return rvo;
126  }
127 
129  const gsMatrix<T> & rhs() const { return m_rhs; }
130 
132  void rhs_into(gsMatrix<T> & out) { out = give(m_rhs); }
133 
137  { m_exprdata->setMultiBasis(mesh); }
138 
141  void setGeometryMap(const gsMultiPatch<T> & gMap)
142  { m_gmap = &gMap;}
143 
144  const gsMultiPatch<T>& getGeometryMap() const
145  {
146  return (nullptr == m_gmap ? m_exprdata->multiPatch() : *m_gmap);
147  }
148 
149 #if EIGEN_HAS_RVALUE_REFERENCES
150  void setIntegrationElements(const gsMultiBasis<T> &&) = delete;
151  //const gsMultiBasis<T> * c++98
152 #endif
153 
156  { return m_exprdata->multiBasis(); }
157 
158  const typename gsExprHelper<T>::Ptr exprData() const { return m_exprdata; }
159 
162  { return m_exprdata->getMap(g); }
163 
166  space getSpace(const gsFunctionSet<T> & mp, index_t dim = 1, index_t id = 0)
167  {
168  //if multiBasisSet() then check domainDom
169  GISMO_ASSERT(1==mp.targetDim(), "Expecting scalar source space");
170  GISMO_ASSERT(static_cast<size_t>(id)<m_vcol.size(),
171  "Given ID "<<id<<" exceeds "<<m_vcol.size()-1 );
172 
173  if (m_vcol[id]==nullptr)
174  {
175  m_sdata.emplace_back(mp,dim,id);
176  m_vcol[id] = &m_sdata.back();
177  if ((size_t)id<m_vrow.size() && nullptr==m_vrow[id]) m_vrow[id]=m_vcol[id];
178  }
179  else
180  {
181  m_vcol[id]->fs = &mp;
182  m_vcol[id]->dim = dim;
183  }
184 
185  expr::gsFeSpace<T> u = m_exprdata->getSpace(mp,dim);
186  u.setSpaceData(*m_vcol[id]);
187  return u;
188  }
189 
192  space getTestSpace(const gsFunctionSet<T> & mp, index_t dim = 1, index_t id = 0)
193  {
194  GISMO_ASSERT(1==mp.targetDim(), "Expecting scalar source space");
195  GISMO_ASSERT(static_cast<size_t>(id)<m_vrow.size(),
196  "Given ID "<<id<<" exceeds "<<m_vrow.size()-1 );
197 
198  if ( (m_vrow[id]==nullptr) ||
199  ((size_t)id<m_vcol.size() && m_vrow[id]==m_vcol[id]) )
200  {
201  m_sdata.emplace_back(mp,dim,id);
202  m_vrow[id] = &m_sdata.back();
203  }
204  else
205  {
206  m_vrow[id]->fs = &mp;
207  m_vrow[id]->dim = dim;
208  }
209 
210  expr::gsFeSpace<T> s = m_exprdata->getSpace(mp,dim);
211  s.setSpaceData(m_sdata.back());
212  return s;
213  }
214 
228  { return getTestSpace( mp,(-1 == dim ? u.dim() : dim), u.id() ); }
229 
232  space trialSpace(const index_t id) const
233  {
234  GISMO_ASSERT(NULL!=m_vcol[id], "Not set.");
235  expr::gsFeSpace<T> s = m_exprdata->
236  getSpace(*m_vcol[id]->fs,m_vcol[id]->dim);
237  s.setSpaceData(*m_vcol[id]);
238  return s;
239  }
240 
242  space trialSpace(space & v) const { return trialSpace(v.id()); }
243 
247  {
248  GISMO_ASSERT(NULL!=m_vrow[id], "Not set.");
249  expr::gsFeSpace<T> s = m_exprdata->
250  getSpace(*m_vrow[id]->fs,m_vrow[id]->dim);
251  s.setSpaceData(*m_vrow[id]);
252  return s;
253  }
254 
256  space testSpace(space u) const { return testSpace(u.id()); }
257 
261  { return m_exprdata->getVar(func, 1); }
262 
265  expr::gsComposition<T> getCoeff(const gsFunctionSet<T> & func, geometryMap & G)
266  { return m_exprdata->getVar(func,G); }
267 
275  { return solution(s, cf); }
276 
277  variable getBdrFunction() const { return m_exprdata->getMutVar(); }
278 
279  expr::gsComposition<T> getBdrFunction(geometryMap & G) const
280  { return m_exprdata->getMutVar(G); }
281 
282  element getElement() const { return m_exprdata->getElement(); }
283 
284  // note: not used
285  void setFixedDofVector(gsMatrix<T> & dof, short_t unk = 0);
286  // note: not used
287  void setFixedDofs(const gsMatrix<T> & coefMatrix, short_t unk = 0, size_t patch = 0);
288 
290  void initSystem(const index_t numRhs = 1)
291  {
292  // Check spaces.nPatches==mesh.patches
293  initMatrix();
294  m_rhs.setZero(numTestDofs(), numRhs);
295  }
296 
298  void initMatrix()
299  {
300  resetDimensions();
301  clearMatrix(false);
302  }
303 
304  void clearRhs() { m_rhs.setZero(); }
305 
312  void clearMatrix(const bool& save_sparsety_pattern = true)
313  {
314  if (m_matrix.nonZeros() && save_sparsety_pattern)
315  {
316  std::fill(m_matrix.valuePtr(),
317  m_matrix.valuePtr() + m_matrix.nonZeros(), 0.);
318  }
319  else
320  {
321  m_matrix = gsSparseMatrix<T>(numTestDofs(), numDofs());
322 
323  if (0 == m_matrix.rows() || 0 == m_matrix.cols())
324  gsWarn << " No internal DOFs, zero sized system.\n";
325  else {
326  // Pick up values from options
327  const T bdA = m_options.getReal("bdA");
328  const index_t bdB = m_options.getInt("bdB");
329  const T bdO = m_options.getReal("bdO");
330  T nz = 1;
331  const short_t dim = m_exprdata->multiBasis().domainDim();
332  for (short_t i = 0; i != dim; ++i)
333  nz *= bdA * static_cast<T>(
334  m_exprdata->multiBasis().maxDegree(i)) +
335  static_cast<T>(bdB);
336 
337  m_matrix.reservePerColumn(numBlocks() *
338  cast<T, index_t>(nz * (1.0 + bdO)));
339  }
340  }
341  }
342 
344  void initVector(const index_t numRhs = 1)
345  {
346  resetDimensions();
347  m_rhs.setZero(numTestDofs(), numRhs);
348  }
349 
353  matBlockView matrixBlockView()
354  {
355  GISMO_ASSERT( m_vcol.back()->mapper.isFinalized(),
356  "initSystem() has not been called.");
357  gsVector<index_t> rowSizes, colSizes;
358  _blockDims(rowSizes, colSizes);
359  return m_matrix.blockView(rowSizes,colSizes);
360  }
361 
365  matConstBlockView matrixBlockView() const
366  {
367  GISMO_ASSERT( m_vcol.back()->mapper.isFinalized(),
368  "initSystem() has not been called.");
369  gsVector<index_t> rowSizes, colSizes;
370  _blockDims(rowSizes, colSizes);
371  return m_matrix.blockView(rowSizes,colSizes);
372  }
373 
375  void setOptions(gsOptionList opt) { m_options = opt; } // gsOptionList opt
376  // .swap(opt) todo
377 
381  template<class... expr> void assemble(const expr &... args);
382 
386  template<class... expr> void assembleBdr(const bcRefList & BCs, expr&... args);
387 
388  template<class... expr> void assembleBdr(const bContainer & bnd, expr&... args);
389 
390  template<class... expr> void assembleIfc(const ifContainer & iFaces, expr... args);
391  /*
392  template<class... expr> void collocate(expr... args);// eg. collocate(-ilapl(u), f)
393  */
394 
395  void quPointsWeights(std::vector<gsMatrix<T> >& cPoints, std::vector<gsVector<T> > & cWeights);
396 
398  // respect to the solution \a u
399  template<class expr> void assembleJacobian(const expr residual, solution & u);
400 
401  template<class expr> void assembleJacobianIfc(const ifContainer & iFaces,
402  const expr residual, solution u);
403 
404 private:
405 
406  void _blockDims(gsVector<index_t> & rowSizes,
407  gsVector<index_t> & colSizes)
408  {
409  if (1==m_vcol.size() && 1==m_vrow.size())
410  {
411  const gsDofMapper & dm = m_vcol.back()->mapper;
412  rowSizes.resize(3);
413  colSizes.resize(3);
414  rowSizes[0]=colSizes[0] = dm.freeSize()-dm.coupledSize();
415  rowSizes[1]=colSizes[1] = dm.coupledSize();
416  rowSizes[2]=colSizes[2] = dm.boundarySize();
417  }
418  else
419  {
420  rowSizes.resize(m_vrow.size());
421  for (index_t r = 0; r != rowSizes.size(); ++r) // for all row-blocks
422  rowSizes[r] = m_vrow[r]->dim() * m_vrow[r]->mapper.freeSize();
423  colSizes.resize(m_vcol.size());
424  for (index_t c = 0; c != colSizes.size(); ++c) // for all col-blocks
425  colSizes[c] = m_vcol[c]->dim() * m_vcol[c]->mapper.freeSize();
426  }
427  }
428 
431  void resetDimensions();
432 
433  // Prints the expression to a text stream
434  struct __printExpr
435  {
436  template <typename E> void operator() (const gismo::expr::_expr<E> & v)
437  { v.print(gsInfo);gsInfo<<"\n"; }
438  } _printExpr;
439 
440  // Checks validity of an expression
441  struct __checkExpr
442  {
443  template <typename E> void operator() (const gsExprAssembler & ea,
444  const gismo::expr::_expr<E> & ee)
445  {
446  auto u = ee.rowVar();
447  auto v = ee.colVar();
448 #ifndef NDEBUG
449  const bool m = E::isMatrix();
450 #endif
451  GISMO_ASSERT(v.isValid(), "The row space is not valid");
452  GISMO_ASSERT(!m || u.isValid(), "The column space is not valid");
453  GISMO_ASSERT(m || (ea.numDofs()==ee.rhs().size()), "The right-hand side vector is not initialized");
454  }
455  } _checkExpr;
456 
457  // Evaluates expression and and assembles global matrix/rhs
458  struct _eval
459  {
460  gsSparseMatrix<T> & m_matrix;
461  gsMatrix<T> & m_rhs;
462  const gsVector<T> & m_quWeights;
463  bool m_elim;
464  gsMatrix<T> localMat;
465  gsMatrix<T> aux;
466 
467  _eval(gsSparseMatrix<T> & _matrix,
468  gsMatrix<T> & _rhs,
469  const gsVector<> & _quWeights)
470  : m_matrix(_matrix), m_rhs(_rhs),
471  m_quWeights(_quWeights), m_elim(true)
472  { }
473 
474  void setElim(bool elim) {m_elim = elim;}
475 
476  template <typename E> void operator() (const gismo::expr::_expr<E> & ee)
477  {
478  // ------- Compute -------
479  quadrature(ee,localMat);
480 
481  // ------- Accumulate -------
482  if (E::isMatrix())
483  if (m_elim) push<true,true>(ee.rowVar(), ee.colVar());
484  else push<true,false>(ee.rowVar(), ee.colVar());
485  else if (E::isVector())
486  if (m_elim) push<false,true>(ee.rowVar(), ee.colVar());
487  else push<false,false>(ee.rowVar(), ee.colVar());
488  else
489  {
490  GISMO_ERROR("Something went terribly wrong at this point");
491  //GISMO_ASSERTrowSpan() && (!colSpan())
492  }
493 
494  }// operator()
495 
496  template <typename E>
497  inline void quadrature(const gismo::expr::_expr<E> & ee,
498  gsMatrix<T> & lm)
499  {
500  // ------- Compute -------
501  const T * w = m_quWeights.data();
502  lm.noalias() = (*w) * ee.eval(0);
503  for (index_t k = 1; k != m_quWeights.rows(); ++k)
504  lm.noalias() += (*(++w)) * ee.eval(k);
505  }
506 
507  template <typename E> void diff(const gismo::expr::_expr<E> & ee,
508  solution & u)
509  {
510  GISMO_ASSERT(E::isVector(), "Expecting a vector expression.");
511  static const T delta = 0.00001;
512 
513  const index_t sz = u.space().cardinality();
514  localMat.setZero(sz, sz);
515 
516  for ( index_t c=0; c!= u.dim(); c++)
517  {
518  const index_t rls = c * u.data().actives.rows(); //local stride
519  for ( index_t j = 0; j != sz/u.dim(); j++ ) // for all basis functions (col(j))
520  {
521  const index_t jj = u.mapper().index(u.data().actives.at(j),
522  u.space().data().patchId, c);
523  if (u.mapper().is_free_index(jj) )
524  {
525  //todo: take local copy of local solution u
526 
527  //Perturb \a u
528  u.perturbLocal( delta , jj, u.space().data().patchId);
529  quadrature(ee, aux);
530  localMat.col(rls+j) += 8 * aux;
531  u.perturbLocal( delta , jj, u.space().data().patchId);
532  quadrature(ee, aux);
533  localMat.col(rls+j) -= aux;
534  u.perturbLocal(-3*delta, jj, u.space().data().patchId);
535  quadrature(ee, aux);
536  localMat.col(rls+j) -= 8 * aux;
537  u.perturbLocal( -delta , jj, u.space().data().patchId);
538  quadrature(ee, aux);
539  localMat.col(rls+j) += aux;
540  localMat.col(rls+j) /= 12*delta;
541  //Unperturb \a u
542  u.perturbLocal(2*delta, jj, u.space().data().patchId);
543  }
544  }
545  }
546 
547  // ------- Accumulate -------
548  push<true,false>(ee.rowVar(), ee.rowVar());
549  }
550 
551  void operator() (const expr::_expr<expr::gsNullExpr<T> > &) {}
552 
553  template<bool isMatrix, bool elim = true>
554  void push(const expr::gsFeSpace<T> & v,
555  const expr::gsFeSpace<T> & u)
556  {
557  GISMO_ASSERT(v.isValid(), "The row space is not valid");
558  GISMO_ASSERT(!isMatrix || u.isValid(), "The column space is not valid");
559  //GISMO_ASSERT(isMatrix || (numDofs()==m_rhs.size()), "The right-hand side vector is not initialized");
560 
561  const index_t rd = v.dim();//row
562  const index_t cd = u.dim();//col
563  //const index_t rp = v.data().patchId;
564  //const index_t cp = (isMatrix ? u.data().patchId : 0);
565  const gsDofMapper & rowMap = v.mapper();
566  const gsDofMapper & colMap = (isMatrix ? u.mapper() : rowMap);
567  gsMatrix<index_t> & rowInd0 = const_cast<gsMatrix<index_t>&>(v.data().actives);
568  gsMatrix<index_t> & colInd0 = (isMatrix ? const_cast<gsMatrix<index_t>&>(u.data().actives) : rowInd0);
569  const gsMatrix<T> & fixedDofs = (isMatrix ? u.fixedPart() : gsMatrix<T>());
570 
571  if (isMatrix)
572  {
573  GISMO_ASSERT( rowInd0.rows()*rd==localMat.rows() && colInd0.rows()*cd==localMat.cols(),
574  "Invalid local matrix (expected "<<rowInd0.rows()*rd <<"x"<< colInd0.rows()*cd <<"), got\n" << localMat );
575 
576  GISMO_ASSERT( colMap.boundarySize()==fixedDofs.size(),
577  "Invalid values for fixed part");
578 
579  //GISMO_ASSERT( colMap.boundarySize()==0 || m_rhs.cols()==1,
580  // "Invalid values for fixed part");
581  }
582 
583  for (index_t r = 0; r != rd; ++r)
584  {
585  const index_t rls = r * rowInd0.rows(); //local stride
586  for (index_t i = 0; i != rowInd0.rows(); ++i)
587  {
588  const index_t ii = rowMap.index(rowInd0.at(i),v.data().patchId,r); //N_i
589  if ( rowMap.is_free_index(ii) )
590  {
591  if (isMatrix)
592  {
593  for (index_t c = 0; c != cd; ++c)
594  {
595  const index_t cls = c * colInd0.rows(); //local stride
596 
597  for (index_t j = 0; j != colInd0.rows(); ++j)
598  {
599  if ( 0 == localMat(rls+i,cls+j) ) continue;
600 
601  const index_t jj = colMap.index(colInd0.at(j),u.data().patchId,c); // N_j
602  if ( colMap.is_free_index(jj) )
603  {
604  // If matrix is symmetric, we could
605  // store only lower triangular part
606  //if ( (!symm) || jj <= ii )
607 # pragma omp critical (acc_m_matrix)
608  m_matrix.coeffRef(ii, jj) += localMat(rls+i,cls+j);
609  }
610  else if (elim) // colMap.is_boundary_index(jj) )
611  {
612  // Symmetric treatment of eliminated BCs
613  // GISMO_ASSERT(1==m_rhs.cols(), "-");
614 # pragma omp critical (acc_m_rhs)
615  m_rhs.at(ii) -= localMat(rls+i,cls+j) *
616  fixedDofs.at(colMap.global_to_bindex(jj));
617  }
618  }
619  }
620  }
621  else
622  {
623  //The right-hand side can have more than one columns
624 # pragma omp critical (acc_m_rhs)
625  m_rhs.row(ii) += localMat.row(rls+i);
626  }
627  }
628  }
629  }
630  }//push
631 
632  };
633 
634 }; // gsExprAssembler
635 
636 template<class T>
638 {
639  gsOptionList opt;
640  opt.addInt("DirichletValues" , "Method for computation of Dirichlet DoF values [100..103]", 101);
641  opt.addInt("DirichletStrategy", "Method for enforcement of Dirichlet BCs [11..14]", 11);
642  opt.addReal("quA", "Number of quadrature points: quA*deg + quB; For patchRule: Regularity of the target space", 1.0 );
643  opt.addInt ("quB", "Number of quadrature points: quA*deg + quB; For patchRule: Degree of the target space", 1 );
644  opt.addReal("bdA", "Estimated nonzeros per column of the matrix: bdA*deg + bdB", 2.0 );
645  opt.addInt ("bdB", "Estimated nonzeros per column of the matrix: bdA*deg + bdB", 1 );
646  opt.addReal("bdO", "Overhead of sparse mem. allocation: (1+bdO)(bdA*deg + bdB) [0..1]", 0.333);
647  opt.addInt ("quRule", "Quadrature rule used (1) Gauss-Legendre; (2) Gauss-Lobatto; (3) Patch-Rule",1);
648  opt.addSwitch("overInt", "Apply over-integration on boundary elements or not?", false);
649  opt.addSwitch("flipSide", "Flip side of interface where integration is performed.", false);
650  opt.addSwitch("movingInterface", "Used in interface assembly when interface is not stationary.", false);
651  return opt;
652 
654 
655  //storage of quadrature points, TP, ... non-linear assembly.
656 
657  //gsExpressions.h -> split ?
658 
659  //parallel interface assembly..
660 
661  // mpi assemly. ???
662 }
663 
664 template<class T>
666 {
667  gsMatrix<T> & fixedDofs = m_vcol[unk]->fixedDofs;
668  fixedDofs.swap(vals);
669  vals.resize(0, 0);
670  // Assuming that the DoFs are already set by the user
671  GISMO_ENSURE( fixedDofs.size() == m_vcol[unk]->mapper.boundarySize(),
672  "The Dirichlet DoFs were not provided correctly.");
673 }
674 
675 template<class T>
676 void gsExprAssembler<T>::setFixedDofs(const gsMatrix<T> & coefMatrix, short_t unk, size_t patch)
677 {
678  GISMO_ASSERT( m_options.getInt("DirichletValues") == dirichlet::user, "Incorrect options");
679 
680  expr::gsFeSpace<T> & u = *m_vcol[unk];
681  //const index_t dirStr = m_options.getInt("DirichletStrategy");
682  const gsMultiBasis<T> & mbasis = *dynamic_cast<const gsMultiBasis<T>* >(m_vcol[unk]->fs);
683 
684  const gsDofMapper & mapper = m_vcol[unk]->mapper;
685 // const gsDofMapper & mapper =
686 // dirichlet::elimination == dirStr ? u.mapper
687 // : mbasis.getMapper(dirichlet::elimination,
688 // static_cast<iFace::strategy>(m_options.getInt("InterfaceStrategy")),
689 // bbc, u.id()) ;
690 
691  gsMatrix<T> & fixedDofs = m_vcol[unk]->fixedDofs;
692  GISMO_ASSERT(fixedDofs.size() == m_vcol[unk]->mapper.boundarySize(),
693  "Fixed DoFs were not initialized.");
694 
695  // for every side with a Dirichlet BC
696  typedef typename gsBoundaryConditions<T>::bcRefList bcRefList;
697  for ( typename bcRefList::const_iterator it = u.bc().dirichletBegin();
698  it != u.bc().dirichletEnd() ; ++it )
699  {
700  const index_t com = it->unkComponent();
701  const index_t k = it->patch();
702  if ( k == patch )
703  {
704  // Get indices in the patch on this boundary
705  const gsMatrix<index_t> boundary =
706  mbasis[k].boundary(it->side());
707 
708  //gsInfo <<"Setting the value for: "<< boundary.transpose() <<"\n";
709 
710  for (index_t i=0; i!= boundary.size(); ++i)
711  {
712  // Note: boundary.at(i) is the patch-local index of a
713  // control point on the patch
714  const index_t ii = mapper.bindex( boundary.at(i) , k, com );
715 
716  fixedDofs.at(ii) = coefMatrix(boundary.at(i), com);
717  }
718  }
719  }
720 } // setFixedDofs
721 
722 
723 template<class T> void gsExprAssembler<T>::resetDimensions()
724 {
725  if (!m_vcol.front()->valid()) m_vcol.front()->init();
726  if (!m_vrow.front()->valid()) m_vrow.front()->init();
727  for (size_t i = 1; i!=m_vcol.size(); ++i)
728  {
729  if (!m_vcol.front()->valid()) m_vcol.front()->init();
730  m_vcol[i]->mapper.setShift(m_vcol[i-1]->mapper.firstIndex() +
731  m_vcol[i-1]->dim*m_vcol[i-1]->mapper.freeSize() );
732 
733  if ( m_vcol[i] != m_vrow[i] )
734  {
735  if (!m_vrow.front()->valid()) m_vrow.front()->init();
736  m_vrow[i]->mapper.setShift(m_vrow[i-1]->mapper.firstIndex() +
737  m_vrow[i-1]->dim*m_vrow[i-1]->mapper.freeSize() );
738  }
739  }
740 }
741 
742 template<size_t I, class op, typename... Ts>
743 void op_tuple_impl (op & _op, const std::tuple<Ts...> &tuple)
744 {
745  _op(std::get<I>(tuple));
746  if (I + 1 < sizeof... (Ts))
747  op_tuple_impl<(I+1 < sizeof... (Ts) ? I+1 : I)> (_op, tuple);
748 }
749 
750 template<class op, typename... Ts>
751 void op_tuple (op & _op, const std::tuple<Ts...> &tuple)
752 { op_tuple_impl<0>(_op,tuple); }
753 
754 template<class T>
755 template<class... expr>
756 void gsExprAssembler<T>::assemble(const expr &... args)
757 {
758  GISMO_ASSERT(matrix().cols()==numDofs(), "System not initialized, matrix().cols() = "<<matrix().cols()<<"!="<<numDofs()<<" = numDofs()");
759 
760  bool failed = false;
761 #pragma omp parallel shared(failed)
762 {
763 # ifdef _OPENMP
764  const int tid = omp_get_thread_num();
765  const int nt = omp_get_num_threads();
766 # endif
767  auto arg_tpl = std::make_tuple(args...);
768 
769  m_exprdata->parse(arg_tpl);
770  m_exprdata->activateFlags(SAME_ELEMENT);
771  //op_tuple(__printExpr(), arg_tpl);
772 
773  typename gsQuadRule<T>::uPtr QuRule; // Quadrature rule
774 
775  gsVector<T> quWeights; // quadrature weights
776  _eval ee(m_matrix, m_rhs, quWeights);
777  const index_t elim = m_options.getInt("DirichletStrategy");
778  ee.setElim(dirichlet::elimination==elim);
779 
780  // Note: omp thread will loop over all patches and will work on Ep/nt
781  // elements, where Ep is the elements on the patch.
782  for (unsigned patchInd = 0; patchInd < m_exprdata->multiBasis().nBases() && (!failed); ++patchInd) //todo: distribute in parallel somehow?
783  {
784  QuRule = gsQuadrature::getPtr(m_exprdata->multiBasis().basis(patchInd), m_options);
785 
786  // Initialize domain element iterator for current patch
787  typename gsBasis<T>::domainIter domIt = // add patchInd to domainiter ?
788  m_exprdata->multiBasis().basis(patchInd).makeDomainIterator();
789  m_exprdata->getElement().set(*domIt,quWeights);
790 
791  // Start iteration over elements of patchInd
792 # ifdef _OPENMP
793  for ( domIt->next(tid); domIt->good() && (!failed); domIt->next(nt) )
794 # else
795  for (; domIt->good(); domIt->next() )
796 # endif
797  {
798  // Map the Quadrature rule to the element
799  QuRule->mapTo( domIt->lowerCorner(), domIt->upperCorner(),
800  m_exprdata->points(), quWeights);
801 
802  if (m_exprdata->points().cols()==0)
803  continue;
804 
805 // Activate the try-catch only if G+Smo is not in DEBUG
806 #ifdef NDEBUG
807  // Perform required pre-computations on the quadrature nodes
808  try
809  {
810  m_exprdata->precompute(patchInd);
811  //m_exprdata->precompute(patchInd, QuRule, *domIt); // todo
812  }
813  catch (...)
814  {
815  // #pragma omp single copyprivate(failed) // broadcasting "failed". Does not work
816  #pragma omp atomic write
817  failed = true;
818  break;
819  }
820 #else
821  m_exprdata->precompute(patchInd);
822 #endif
823 
824 
825  // Assemble contributions of the element
826  op_tuple(ee, arg_tpl);
827  }
828  }
829 }//omp parallel
830  // Throw something else?? (floating point exception?)
831  GISMO_ENSURE(!failed,"Assembly failed due to an error");
832  m_matrix.makeCompressed();
833 }
834 
835 template<class T>
836 template<class... expr>
837 void gsExprAssembler<T>::assembleBdr(const bcRefList & BCs, expr&... args)
838 {
839  GISMO_ASSERT(matrix().cols()==numDofs(), "System not initialized");
840 
841  if ( BCs.empty() || 0==numDofs() ) return;
842  m_exprdata->setMutSource(*BCs.front().get().function()); //initialize once
843 
844 // #pragma omp parallel
845 // {
846 // # ifdef _OPENMP
847 // const int tid = omp_get_thread_num();
848 // const int nt = omp_get_num_threads();
849 // # endif
850  auto arg_tpl = std::make_tuple(args...);
851  m_exprdata->parse(arg_tpl);
852  m_exprdata->activateFlags(SAME_ELEMENT);
853 
854  typename gsQuadRule<T>::uPtr QuRule; // Quadrature rule
855  gsVector<T> quWeights; // quadrature weights
856 
857  _eval ee(m_matrix, m_rhs, quWeights);
858 
859 //# pragma omp parallel for
860  for (typename bcRefList::const_iterator iit = BCs.begin(); iit!= BCs.end(); ++iit)
861  {
862  const boundary_condition<T> * it = &iit->get();
863 
864  QuRule = gsQuadrature::getPtr(m_exprdata->multiBasis().basis(it->patch()), m_options, it->side().direction());
865 
866  // Update boundary function source
867  m_exprdata->setMutSource(*it->function());
868 
869  typename gsBasis<T>::domainIter domIt =
870  m_exprdata->multiBasis().basis(it->patch()).
871  makeDomainIterator(it->side());
872  m_exprdata->getElement().set(*domIt,quWeights);
873 
874  // Start iteration over elements
875  for (; domIt->good(); domIt->next() )
876  {
877  // Map the Quadrature rule to the element
878  QuRule->mapTo( domIt->lowerCorner(), domIt->upperCorner(),
879  m_exprdata->points(), quWeights);
880 
881  if (m_exprdata->points().cols()==0)
882  continue;
883 
884  // Perform required pre-computations on the quadrature nodes
885  m_exprdata->precompute(it->patch(), it->side());
886 
887  // Assemble contributions of the element
888  op_tuple(ee, arg_tpl);
889  }
890  }
891 
892 //}//omp parallel
893 
894  m_matrix.makeCompressed();
895 }
896 
897 
898 template<class T>
899 template<class... expr>
900 void gsExprAssembler<T>::assembleBdr(const bContainer & bnd, expr&... args)
901 {
902  GISMO_ASSERT(matrix().cols()==numDofs(), "System not initialized");
903 
904  if ( bnd.size()==0 || 0==numDofs() ) return;
905 
906  auto arg_tpl = std::make_tuple(args...);
907  m_exprdata->parse(arg_tpl);
908 
909  typename gsQuadRule<T>::uPtr QuRule; // Quadrature rule ---->OUT
910  gsVector<T> quWeights; // quadrature weights
911 
912  _eval ee(m_matrix, m_rhs, quWeights);
913 
914 //# pragma omp parallel for
915 
916  for (gsBoxTopology::const_biterator it = bnd.begin();
917  it != bnd.end(); ++it )
918  {
919  QuRule = gsQuadrature::getPtr(m_exprdata->multiBasis().basis(it->patch),
920  m_options, it->side().direction());
921 
922  typename gsBasis<T>::domainIter domIt =
923  m_exprdata->multiBasis().basis(it->patch).
924  makeDomainIterator(it->side());
925  m_exprdata->getElement().set(*domIt,quWeights);
926 
927  // Start iteration over elements
928  for (; domIt->good(); domIt->next() )
929  {
930  // Map the Quadrature rule to the element
931  QuRule->mapTo( domIt->lowerCorner(), domIt->upperCorner(),
932  m_exprdata->points(), quWeights);
933 
934  if (m_exprdata->points().cols()==0)
935  continue;
936 
937  // Perform required pre-computations on the quadrature nodes
938  m_exprdata->precompute(it->patch, it->side());
939 
940  // Assemble contributions of the element
941  op_tuple(ee, arg_tpl);
942  }
943  }
944 
945 //}//omp parallel
946 
947  m_matrix.makeCompressed();
948 }
949 
950 template<class T> template<class... expr>
951 void gsExprAssembler<T>::assembleIfc(const ifContainer & iFaces, expr... args)
952 {
953  GISMO_ASSERT(matrix().cols()==numDofs(), "System not initialized");
954 
955 // #pragma omp parallel
956 // {
957  typedef typename gsFunction<T>::uPtr ifacemap;
958 
959  auto arg_tpl = std::make_tuple(args...);
960 
961  m_exprdata->parse(arg_tpl);
962  m_exprdata->activateFlags(SAME_ELEMENT); //note: SAME_ELEMENT is 0 at the opposite/mirrored patch
963 
964  typename gsQuadRule<T>::uPtr QuRule;
965  gsVector<T> quWeights;// quadrature weights
966  _eval ee(m_matrix, m_rhs, quWeights);
967 
968  const bool flipSide = m_options.askSwitch("flipSide", false);
969 
970  ifacemap interfaceMap;
971 // # pragma omp for
972  for (gsBoxTopology::const_iiterator it = iFaces.begin();
973  it != iFaces.end(); ++it )
974  {
975  // If flipSide switch is enabled, then the integration will be
976  // performed on the opposite side of the interface
977  const boundaryInterface & iFace = flipSide ? it->getInverse() : *it;
978  const index_t patch1 = iFace.first() .patch;
979  const index_t patch2 = iFace.second().patch;
980 
981  if (iFace.type() == interaction::conforming)
982  interfaceMap = gsAffineFunction<T>::make( iFace.dirMap(), iFace.dirOrientation(),
983  m_exprdata->multiBasis().basis(patch1).support(),
984  m_exprdata->multiBasis().basis(patch2).support() );
985  else
986  interfaceMap = gsCPPInterface<T>::make(getGeometryMap(), m_exprdata->multiBasis(), iFace);
987 
988  QuRule = gsQuadrature::getPtr(m_exprdata->multiBasis().basis(patch1),
989  m_options, iFace.first().side().direction());
990 
991  typename gsBasis<T>::domainIter domIt =
992  m_exprdata->multiBasis().basis(patch1)
993  .makeDomainIterator(iFace.first().side());
994  m_exprdata->getElement().set(*domIt, quWeights);
995 
996  // Start iteration over elements
997  for (; domIt->good(); domIt->next() )
998  {
999  // Map the Quadrature rule to the element
1000  QuRule->mapTo( domIt->lowerCorner(), domIt->upperCorner(),
1001  m_exprdata->points(), quWeights);
1002  interfaceMap->eval_into(m_exprdata->points(), m_exprdata->pointsIfc());
1003 
1004  if (m_exprdata->points().cols()==0)
1005  continue;
1006 
1007  // Perform required pre-computations on the quadrature nodes
1008  m_exprdata->precompute(iFace);
1009 
1010  //eg.
1011  // uL*vL/2 + uR*vL/2 - uL*vR/2 - uR*vR/2
1012  //[ B11 B21 ]
1013  //[ B12 B22 ]
1014 
1015  op_tuple(ee, arg_tpl);
1016  }
1017  }
1018 
1019 // }//omp parallel
1020  m_matrix.makeCompressed();
1021 }
1022 
1023 template<class T> template<class expr>
1024 void gsExprAssembler<T>::assembleJacobian(const expr residual, solution & u)
1025 {
1026  GISMO_ASSERT(matrix().cols()==numDofs(), "System not initialized");
1027  GISMO_ASSERT(expr::isVector(), "Expecting a vector expression.");
1028 
1029  clearMatrix();
1030  clearRhs();
1031 
1032 #pragma omp parallel
1033 {
1034 # ifdef _OPENMP
1035  const int tid = omp_get_thread_num();
1036  const int nt = omp_get_num_threads();
1037 # endif
1038 
1039  m_exprdata->parse(residual, u);
1040  m_exprdata->activateFlags(SAME_ELEMENT);
1041  //op_tuple(__printExpr(), arg_tpl);
1042 
1043  typename gsQuadRule<T>::uPtr QuRule; // Quadrature rule ---->OUT
1044 
1045  gsVector<T> quWeights; // quadrature weights
1046 
1047  _eval ee(m_matrix, m_rhs, quWeights);
1048 
1049  // Note: omp thread will loop over all patches and will work on Ep/nt
1050  // elements, where Ep is the elements on the patch.
1051  for (unsigned patchInd = 0; patchInd < m_exprdata->multiBasis().nBases(); ++patchInd)
1052  {
1053  QuRule = gsQuadrature::getPtr(m_exprdata->multiBasis().basis(patchInd), m_options);
1054 
1055  // Initialize domain element iterator for current patch
1056  typename gsBasis<T>::domainIter domIt = // add patchInd to domainiter ?
1057  m_exprdata->multiBasis().basis(patchInd).makeDomainIterator();
1058  m_exprdata->getElement().set(*domIt,quWeights);
1059 
1060  // Start iteration over elements of patchInd
1061 # ifdef _OPENMP
1062  for ( domIt->next(tid); domIt->good(); domIt->next(nt) )
1063 # else
1064  for (; domIt->good(); domIt->next() )
1065 # endif
1066  {
1067  // Map the Quadrature rule to the element
1068  QuRule->mapTo( domIt->lowerCorner(), domIt->upperCorner(),
1069  m_exprdata->points(), quWeights);
1070 
1071  if (m_exprdata->points().cols()==0)
1072  continue;
1073 
1074  // Evaluate at quadrature points
1075  m_exprdata->precompute(patchInd);
1076 
1077 # pragma omp critical (assemble_fdiffs)
1078  {
1079  // ee(residual); //Computes residual to m_rhs
1080  ee.diff(residual, u); //Computes Jacobian
1081  }
1082  }
1083  }
1084 
1085 }//omp parallel
1086  m_matrix.makeCompressed();
1087 }
1088 
1089 
1090 template<class T> template<class expr>
1091 void gsExprAssembler<T>::assembleJacobianIfc(const ifContainer & iFaces,
1092  const expr residual, solution u)
1093 {
1094  GISMO_ASSERT(matrix().cols()==numDofs(), "System not initialized");
1095  GISMO_ASSERT(expr::isVector(), "Expecting a vector expression.");
1096 
1097  // clearMatrix();
1098 
1099  m_exprdata->parse(residual, u);
1100  m_exprdata->activateFlags(SAME_ELEMENT);
1101  //op_tuple(__printExpr(), arg_tpl);
1102 
1103  typename gsQuadRule<T>::uPtr QuRule; // Quadrature rule
1104  gsVector<T> quWeights; // quadrature weights
1105 
1106  _eval ee(m_matrix, m_rhs, quWeights);
1107  const bool flipSide = m_options.askSwitch("flipSide", false);
1108  const bool movingInterface = m_options.askSwitch("movingInterface", false);
1109 
1110  for (gsBoxTopology::const_iiterator it = iFaces.begin();
1111  it != iFaces.end(); ++it )
1112  {
1113  // If flipSide switch is enabled, then the integration will be
1114  // performed on the opposite side of the interface
1115  const boundaryInterface & iFace = flipSide ? it->getInverse() : *it;
1116  const index_t patch1 = iFace.first() .patch;
1117  //const index_t patch2 = iFace.second().patch;
1118 
1119  gsCPPInterface<T> interfaceMap(getGeometryMap(), // ! make current geometry
1120  m_exprdata->multiBasis(), iFace);
1121 
1122  QuRule = gsQuadrature::getPtr(m_exprdata->multiBasis().basis(patch1),
1123  m_options, iFace.first().side().direction());
1124 
1125  typename gsBasis<T>::domainIter domIt =
1126  m_exprdata->multiBasis().basis(patch1)
1127  .makeDomainIterator(iFace.first().side());
1128  m_exprdata->getElement().set(*domIt, quWeights);
1129 
1130  // Start iteration over elements
1131  for (; domIt->good(); domIt->next() )
1132  {
1133  // Map the Quadrature rule to the element
1134  QuRule->mapTo( domIt->lowerCorner(), domIt->upperCorner(),
1135  m_exprdata->points(), quWeights);
1136  interfaceMap.eval_into(m_exprdata->points(), m_exprdata->pointsIfc());
1137 
1138  if (m_exprdata->points().cols()==0)
1139  continue;
1140 
1141  // Perform required pre-computations on the quadrature nodes
1142  m_exprdata->precompute(iFace);
1143 
1144  // ee(residual);
1145  if (!movingInterface)
1146  {
1147  ee.diff(residual, u);
1148  }
1149  else // For Moving Geometry Maps
1150  {
1151  GISMO_ASSERT(expr::isVector(), "Expecting a vector expression.");
1152  static const T delta = 0.00001;
1153 
1154  const index_t sz = residual.eval(0).rows(); // Caution this must be the correct size , depending if .right() or .left() are used
1155  ee.localMat.setZero(sz, sz);
1156 
1157  auto & rowVar = residual.rowVar();
1158 
1159  for ( index_t c=0; c!= u.dim(); c++)
1160  {
1161  const index_t rls = c * rowVar.data().actives.rows(); //local stride
1162  for ( index_t j = 0; j != sz/u.dim(); j++ ) // for all basis functions (col(j))
1163  {
1164  const index_t jj = u.mapper().index(rowVar.data().actives(j),
1165  rowVar.data().patchId, c);
1166  if (rowVar.mapper().is_free_index(jj) )
1167  {
1168  //Perturb \a u
1169  u.perturbLocal( delta , jj, rowVar.data().patchId);
1170  interfaceMap.updateBdr();
1171  interfaceMap.eval_into(m_exprdata->points(), m_exprdata->pointsIfc());
1172  m_exprdata->precompute(iFace);
1173  ee.quadrature(residual, ee.aux);
1174  ee.localMat.col(rls+j) += 8 * ee.aux;
1175 
1176 
1177  u.perturbLocal( delta , jj, rowVar.data().patchId);
1178  interfaceMap.updateBdr();
1179  interfaceMap.eval_into(m_exprdata->points(), m_exprdata->pointsIfc());
1180  m_exprdata->precompute(iFace);
1181  ee.quadrature(residual, ee.aux);
1182  ee.localMat.col(rls+j) -= ee.aux;
1183 
1184  u.perturbLocal(-3*delta, jj, rowVar.data().patchId);
1185  interfaceMap.updateBdr();
1186  interfaceMap.eval_into(m_exprdata->points(), m_exprdata->pointsIfc());
1187  m_exprdata->precompute(iFace);
1188  ee.quadrature(residual, ee.aux);
1189  ee.localMat.col(rls+j) -= 8 * ee.aux;
1190 
1191  u.perturbLocal( -delta , jj, rowVar.data().patchId);
1192  interfaceMap.updateBdr();
1193  interfaceMap.eval_into(m_exprdata->points(), m_exprdata->pointsIfc());
1194  m_exprdata->precompute(iFace);
1195  ee.quadrature(residual, ee.aux);
1196  ee.localMat.col(rls+j) += ee.aux;
1197 
1198  ee.localMat.col(rls+j) /= 12*delta;
1199  //Unperturb \a u
1200  u.perturbLocal(2*delta, jj, rowVar.data().patchId);
1201  interfaceMap.updateBdr();
1202  }
1203  }
1204  }
1205 
1206  // ------- Accumulate -------
1207  ee.template push<true,false>(residual.rowVar(), residual.rowVar());
1208  }
1209  }
1210  }
1211 
1212  m_matrix.makeCompressed();
1213 }
1214 
1215 template<class T>
1216 void gsExprAssembler<T>::quPointsWeights(std::vector<gsMatrix<T> >& cPoints, std::vector<gsVector<T> > & cWeights)
1217 {
1218  GISMO_ASSERT(matrix().cols()==numDofs(), "System not initialized, matrix().cols() = "<<matrix().cols()<<"!="<<numDofs()<<" = numDofs()");
1219 
1220 #pragma omp parallel
1221 {
1222 # ifdef _OPENMP
1223  const int tid = omp_get_thread_num();
1224  const int nt = omp_get_num_threads();
1225 # endif
1226 
1227  typename gsQuadRule<T>::uPtr QuRule; // Quadrature rule
1228 
1229  gsVector<T> quWeights; // quadrature weights
1230  _eval ee(m_matrix, m_rhs, quWeights);
1231  const index_t elim = m_options.getInt("DirichletStrategy");
1232  ee.setElim(dirichlet::elimination==elim);
1233 
1234  cPoints.resize( m_exprdata->multiBasis().nBases() );
1235  cWeights.resize( m_exprdata->multiBasis().nBases() );
1236 
1237  // Note: omp thread will loop over all patches and will work on Ep/nt
1238  // elements, where Ep is the elements on the patch.
1239  index_t count = 0;
1240  for (unsigned patchInd = 0; patchInd < m_exprdata->multiBasis().nBases(); ++patchInd)
1241  {
1242  auto & bb = m_exprdata->multiBasis().basis(patchInd);
1243 
1244  QuRule = gsQuadrature::getPtr(bb, m_options);
1245  const index_t numNodes = QuRule->numNodes();
1246 
1247  const index_t sz = bb.numElements() * numNodes;
1248  cPoints[patchInd].resize(bb.domainDim(), sz );
1249  cWeights[patchInd].resize( sz );
1250 
1251  // Initialize domain element iterator for current patch
1252  typename gsBasis<T>::domainIter domIt = bb.makeDomainIterator();
1253  m_exprdata->getElement().set(*domIt,quWeights);
1254 
1255  // Start iteration over elements of patchInd
1256 # ifdef _OPENMP
1257  for ( domIt->next(tid); domIt->good(); domIt->next(nt) )
1258 # else
1259  for (; domIt->good(); domIt->next() )
1260 # endif
1261  {
1262  // Map the Quadrature rule to the element
1263  QuRule->mapTo( domIt->lowerCorner(), domIt->upperCorner(),
1264  m_exprdata->points(), quWeights);
1265 
1266  cWeights[patchInd].segment(count, numNodes) = quWeights;
1267  cPoints[patchInd].middleCols(count, numNodes) = m_exprdata->points();
1268  count += numNodes;
1269  }
1270  }
1271 }//omp parallel
1272 
1273  m_matrix.makeCompressed();
1274 }
1275 
1276 
1277 
1278 } //namespace gismo
function_ptr function() const
Returns the function data pointer of the boundary condition.
Definition: gsBoundaryConditions.h:254
void initVector(const index_t numRhs=1)
Initializes the right-hand side vector only.
Definition: gsExprAssembler.h:344
void assembleJacobian(const expr residual, solution &u)
Assembles the Jacobian matrix of the expression args with.
Definition: gsExprAssembler.h:1024
Definition: gsExprAssembler.h:30
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:298
void resetDimensions()
Reset the dimensions of all involved spaces. Called internally by the init* functions.
Definition: gsExprAssembler.h:723
index_t boundarySize() const
Returns the number of eliminated dofs.
Definition: gsDofMapper.h:457
gsExprHelper< T >::variable variable
Variable type.
Definition: gsExprAssembler.h:59
Definition: gsExpressions.h:96
void initMatrix()
Initializes the sparse matrix only.
Definition: gsExprAssembler.h:298
gsExprHelper< T >::geometryMap geometryMap
Geometry map type.
Definition: gsExprAssembler.h:58
void clearMatrix(const bool &save_sparsety_pattern=true)
Re-Init Matrix (set zero by default)
Definition: gsExprAssembler.h:312
Provides a mapping between the corresponding sides of two patches sharing an interface, by means of a Closest Point Projection.
#define short_t
Definition: gsConfig.h:35
space getTestSpace(const gsFunctionSet< T > &mp, index_t dim=1, index_t id=0)
Definition: gsExprAssembler.h:192
Provides a mapping between the corresponding sides of two patches sharing an interface, by means of a closest point projection.
Definition: gsCPPInterface.h:32
boxSide side() const
Returns the side to which this boundary condition refers to.
Definition: gsBoundaryConditions.h:269
void matrix_into(gsSparseMatrix< T > &out)
Writes the resulting matrix in out. The internal matrix is moved.
Definition: gsExprAssembler.h:119
space testSpace(const index_t id)
Definition: gsExprAssembler.h:246
S give(S &x)
Definition: gsMemory.h:266
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:756
#define index_t
Definition: gsConfig.h:32
Generic expressions helper.
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
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:61
space trialSpace(space &v) const
Return the trial space of a pre-existing test space v.
Definition: gsExprAssembler.h:242
index_t numDofs() const
Returns the number of degrees of freedom (after initialization)
Definition: gsExprAssembler.h:85
const index_t & getInt(const std::string &label) const
Reads value for option label from options.
Definition: gsOptionList.cpp:37
space trialSpace(const index_t id) const
Definition: gsExprAssembler.h:232
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
Maintains a mapping from patch-local dofs to global dof indices and allows the elimination of individ...
Definition: gsDofMapper.h:68
index_t numBlocks() const
Definition: gsExprAssembler.h:104
index_t coupledSize() const
Returns the number of coupled (not eliminated) dofs.
Definition: gsDofMapper.cpp:601
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:227
index_t patch() const
Returns the patch to which this boundary condition refers to.
Definition: gsBoundaryConditions.h:266
virtual short_t targetDim() const
Dimension of the target space.
Definition: gsFunctionSet.h:560
const gsMatrix< T > & rhs() const
Returns the right-hand side vector(s)
Definition: gsExprAssembler.h:129
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
const gsSparseMatrix< T > & matrix() const
Returns the left-hand global matrix.
Definition: gsExprAssembler.h:116
index_t numTestDofs() const
Returns the number of test functions (after initialization)
Definition: gsExprAssembler.h:94
#define gsWarn
Definition: gsDebug.h:50
Holds a set of patch-wise bases and their topology information.
Definition: gsMultiBasis.h:36
expr::gsComposition< T > getCoeff(const gsFunctionSet< T > &func, geometryMap &G)
Definition: gsExprAssembler.h:265
#define gsInfo
Definition: gsDebug.h:43
Definition: gsDirichletValues.h:23
Interface for the set of functions defined on a domain (the total number of functions in the set equa...
Definition: gsFuncData.h:23
matConstBlockView matrixBlockView() const
Definition: gsExprAssembler.h:365
geometryMap getMap(const gsFunctionSet< T > &g)
Registers g as an isogeometric geometry map and return a handle to it.
Definition: gsExprAssembler.h:161
Container class for a set of geometry patches and their topology, that is, the interface connections ...
Definition: gsMultiPatch.h:33
space getSpace(const gsFunctionSet< T > &mp, index_t dim=1, index_t id=0)
Definition: gsExprAssembler.h:166
Creates a variety of quadrature rules.
void setOptions(gsOptionList opt)
Set the assembler options.
Definition: gsExprAssembler.h:375
void setGeometryMap(const gsMultiPatch< T > &gMap)
Set the geometrymap ( used for interface assembly)
Definition: gsExprAssembler.h:141
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
Enable optimizations based on the assumption that all evaluation points are in the same bezier domain...
Definition: gsForwardDeclarations.h:89
Class that defines a boundary condition for a side of a patch for some unknown variable of a PDE...
Definition: gsBoundaryConditions.h:106
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
Provides functions to generate structured point data.
EIGEN_STRONG_INLINE idMat_expr id(const index_t dim)
The identity matrix of dimension dim.
Definition: gsExpressions.h:4472
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
matBlockView matrixBlockView()
Definition: gsExprAssembler.h:353
static gsOptionList defaultOptions()
Returns the list of default options for assembly.
Definition: gsExprAssembler.h:637
gsExprHelper< T >::element element
Current element.
Definition: gsExprAssembler.h:57
gsOptionList & options()
Returns a reference to the options structure.
Definition: gsExprAssembler.h:113
Struct which represents an interface between two patches.
Definition: gsBoundary.h:649
gsExprHelper< T >::space space
Space type.
Definition: gsExprAssembler.h:60
Class which holds a list of parameters/options, and provides easy access to them. ...
Definition: gsOptionList.h:32
index_t freeSize() const
Returns the number of free (not eliminated) dofs.
Definition: gsDofMapper.h:436
const gsMultiBasis< T > & integrationElements() const
Returns the domain of integration.
Definition: gsExprAssembler.h:155
void setIntegrationElements(const gsMultiBasis< T > &mesh)
Sets the domain of integration.
Definition: gsExprAssembler.h:136
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
gsExprAssembler(index_t _rBlocks=1, index_t _cBlocks=1)
Definition: gsExprAssembler.h:73
expr::gsFeSolution< T > solution
Solution type.
Definition: gsExprAssembler.h:61
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:274
void initSystem(const index_t numRhs=1)
Initializes the sparse system (sparse matrix and rhs)
Definition: gsExprAssembler.h:290
index_t patch
The index of the patch.
Definition: gsBoundary.h:234
variable getCoeff(const gsFunctionSet< T > &func)
Definition: gsExprAssembler.h:260
virtual void eval_into(const gsMatrix< T > &u, gsMatrix< T > &result) const
Evaluates the interface map.
Definition: gsCPPInterface.hpp:62
short_t direction() const
Returns the parametric direction orthogonal to this side.
Definition: gsBoundary.h:113
Definition: gsExpressions.h:114
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:837
Real getReal(const std::string &label) const
Reads value for option label from options.
Definition: gsOptionList.cpp:44
space testSpace(space u) const
Return the test space of a pre-existing trial space u.
Definition: gsExprAssembler.h:256
void rhs_into(gsMatrix< T > &out)
Writes the resulting vector in out. The internal data is moved.
Definition: gsExprAssembler.h:132
patchSide & first()
first, returns the first patchSide of this interface
Definition: gsBoundary.h:776