G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsAssembler.hpp
Go to the documentation of this file.
1 
16 #include <gsCore/gsMultiBasis.h>
18 #include <gsCore/gsField.h>
19 #include <gsUtils/gsPointGrid.h>
20 
21 #include <gsAssembler/gsVisitorPoisson.h> // Stiffness volume integrals and load vector
22 
23 #include <gsCore/gsFuncData.h>
24 
25 
26 namespace gismo
27 {
28 
29 template<class T>
31 {
32  gsOptionList opt;
33  opt.addInt("DirichletStrategy", "Method for enforcement of Dirichlet BCs [11..14]", 11 );
34  opt.addInt("DirichletValues" , "Method for computation of Dirichlet DoF values [100..103]", 101);
35  opt.addInt("InterfaceStrategy", "Method of treatment of patch interfaces [0..3]", 1 );
36  opt.addReal("quA", "Number of quadrature points: quA*deg + quB", 1.0 );
37  opt.addInt ("quB", "Number of quadrature points: quA*deg + quB", 1 );
38  opt.addReal("bdA", "Estimated nonzeros per column of the matrix: bdA*deg + bdB", 2.0 );
39  opt.addInt ("bdB", "Estimated nonzeros per column of the matrix: bdA*deg + bdB", 1 );
40  opt.addReal("bdO", "Overhead of sparse mem. allocation: (1+bdO)(bdA*deg + bdB) [0..1]", 0.333);
41  return opt;
42 }
43 
44 template<class T>
46 {
47  gsWarn <<" gsAssembler<T>::Refresh is an empty call\n";
48 }
49 
50 template<class T>
53 
54 template<class T>
57 
58 template<class T>
61 
62 template<class T>
65 
66 template<class T>
68 {
69  const gsBoundaryConditions<T> & m_bConditions = m_pde_ptr->bc();
70 
71  // Check if boundary conditions are OK
72  const index_t np = m_bases.front().nBases();
73  for (typename gsBoundaryConditions<T>::const_iterator it =
74  m_bConditions.dirichletBegin() ; it != m_bConditions.dirichletEnd(); ++it )
75  {
76  GISMO_ENSURE( it->ps.patch < np && it->ps.patch >= 0,
77  "Problem: a Dirichlet boundary condition is set "
78  "on a patch id which does not exist.");
79  }
80 
81  for (typename gsBoundaryConditions<T>::const_iterator it =
82  m_bConditions.neumannBegin() ; it != m_bConditions.neumannEnd(); ++it )
83  {
84  GISMO_ENSURE( it->ps.patch < np && it->ps.patch >= 0,
85  "Problem: a Neumann boundary condition is set "
86  "on a patch id which does not exist.");
87  }
88 
89  //TODO: add check m_bases[i].nBases() == pde.domain().nPatches().
90 
91  if ( m_pde_ptr->domain().nPatches() == 0)
92  gsWarn<< "No domain given ! \n";
93 
94  const dirichlet::strategy dirStr = static_cast<dirichlet::strategy>(m_options.getInt("DirichletStrategy"));
95  if ( 0 == m_pde_ptr->bc().size() && dirStr!=dirichlet::none && static_cast<dirichlet::values>(dirStr)==dirichlet::homogeneous )
96  gsWarn<< "No boundary conditions given ! \n";
97 
98  return true;
99 }
100 
101 template <class T>
103 {
104  // Check for coherency
105  GISMO_ASSERT(this->check(), "Incoherent data in Assembler");
106 
107  GISMO_ASSERT(1==m_bases.size(), "Expecting a single discrete space "
108  "for standard scalar Galerkin");
109 
110  // 1. Obtain a map from basis functions to matrix columns and rows
111  gsDofMapper mapper;
112  m_bases.front().getMapper(
113  static_cast<dirichlet::strategy>(m_options.getInt("DirichletStrategy")),
114  static_cast<iFace::strategy>(m_options.getInt("InterfaceStrategy")),
115  this->pde().bc(), mapper, 0);
116 
117  if ( 0 == mapper.freeSize() ) // Are there any interior dofs ?
118  gsWarn << " No internal DOFs, zero sized system.\n";
119 
120  // 2. Create the sparse system
121  m_system = gsSparseSystem<T>(mapper);//1,1
122 }
123 
124 template<class T>
126 {
127  GISMO_ASSERT( m_options.getInt("DirichletStrategy")
128  == dirichlet::penalize, "Incorrect options");
129 
130  static const T PP = 1e9; // magic number
131 
132  const gsMultiBasis<T> & mbasis = m_bases[m_system.colBasis(unk)];
133  const gsDofMapper & mapper = m_system.colMapper(unk);
134  // Note: dofs in the system, however dof values need to be computed
135  const gsDofMapper & bmap = mbasis.getMapper(dirichlet::elimination,
136  static_cast<iFace::strategy>(m_options.getInt("InterfaceStrategy")),
137  m_pde_ptr->bc(), unk) ;
138 
139  GISMO_ENSURE( m_ddof[unk].rows() == mapper.boundarySize() &&
140  m_ddof[unk].cols() == m_pde_ptr->numRhs(),
141  "The Dirichlet DoFs were not computed.");
142 
143  // BCs
144  for ( typename gsBoundaryConditions<T>::const_iterator
145  it = m_pde_ptr->bc().dirichletBegin();
146  it != m_pde_ptr->bc().dirichletEnd(); ++it )
147  {
148  const gsBasis<T> & basis = mbasis[it->patch()];
149 
150  gsMatrix<index_t> bnd = basis.boundary(it->side() );
151  for (index_t k=0; k!= bnd.size(); ++k)
152  {
153  // free dof position
154  const index_t ii = mapper.index ( bnd(k) , it->patch() );
155  // boundary dof position
156  const index_t bb = bmap .bindex( bnd(k) , it->patch() );
157 
158  m_system.matrix()(ii,ii) = PP;
159  m_system.rhs().row(ii) = PP * m_ddof[unk].row(bb);
160  }
161  }
162 
163  // Corner values
164  for ( typename gsBoundaryConditions<T>::const_citerator
165  it = m_pde_ptr->bc().cornerBegin();
166  it != m_pde_ptr->bc().cornerEnd(); ++it )
167  {
168  const index_t i = mbasis[it->patch].functionAtCorner(it->corner);
169  const index_t ii = mapper.bindex( i , it->patch );
170  m_system.matrix()(ii,ii) = PP;
171  m_system.rhs().row(ii).setConstant(PP * it->value);
172  }
173 }
174 
175 template<class T>
176 void gsAssembler<T>::setFixedDofs(const gsMatrix<T> & coefMatrix, short_t unk, size_t patch)
177 {
178  GISMO_ASSERT( m_options.getInt("DirichletValues") == dirichlet::user, "Incorrect options");
179 
180  const dirichlet::strategy dirStr = static_cast<dirichlet::strategy>(m_options.getInt("DirichletStrategy"));
181  const gsMultiBasis<T> & mbasis = m_bases[m_system.colBasis(unk)];
182  const gsDofMapper & mapper =
183  dirichlet::elimination == dirStr ? m_system.colMapper(unk)
184  : mbasis.getMapper(dirichlet::elimination,
185  static_cast<iFace::strategy>(m_options.getInt("InterfaceStrategy")),
186  m_pde_ptr->bc(), unk) ;
187 
188  GISMO_ASSERT(m_ddof[unk].rows()==mapper.boundarySize() &&
189  m_ddof[unk].cols() == m_pde_ptr->numRhs(),
190  "Fixed DoFs were not initialized");
191 
192  // for every side with a Dirichlet BC
193  for ( typename gsBoundaryConditions<T>::const_iterator
194  it = m_pde_ptr->bc().dirichletBegin();
195  it != m_pde_ptr->bc().dirichletEnd() ; ++it )
196  {
197  const index_t k = it->patch();
198  if ( k == static_cast<index_t>(patch) )
199  {
200  // Get indices in the patch on this boundary
202  mbasis[k].boundary(it->side());
203 
204  //gsInfo <<"Setting the value for: "<< boundary.transpose() <<"\n";
205 
206  for (index_t i=0; i!= boundary.size(); ++i)
207  {
208  // Note: boundary.at(i) is the patch-local index of a
209  // control point on the patch
210  const index_t ii = mapper.bindex( boundary.at(i) , k );
211 
212  m_ddof[unk].row(ii) = coefMatrix.row(boundary.at(i));
213  }
214  }
215  }
216 }
217 
218 template<class T>
220 {
221  if(m_ddof.size()==0)
222  m_ddof.resize(m_system.numColBlocks());
223  m_ddof[unk].swap(vals);
224  // Assuming that the DoFs are already set by the user
225  GISMO_ENSURE( m_ddof[unk].rows() == m_system.colMapper(unk).boundarySize()
226  , //&& m_ddof[unk].cols() == m_pde_ptr->numRhs(),
227  "The Dirichlet DoFs were not provided correctly.");
228 }
229 
230 
231 template<class T>
233 {
234  //if ddof-size is not set
235  //fixme: discuss if this is really the right place for this.
236 
237  // correction: m_ddof should have an array of ddofs for every unknown,
238  // not for every block in the sparse system;
239  // number of columns in each array is a number of components in the corresponding unknown;
240  // sparse system gets this info during construction;
241  // m_system.numUnknown() provides the number of unknown;
242  // m_system.unkSize(i) provides the number of components in the unknown i
243  if(m_ddof.size()==0)
244  m_ddof.resize(m_system.numUnknowns());
245 
246  if ( m_options.getInt("DirichletStrategy") == dirichlet::nitsche)
247  return; // Nothing to compute
248 
249  const gsMultiBasis<T> & mbasis = m_bases[m_system.colBasis(unk)];
250  const gsDofMapper & mapper =
251  dirichlet::elimination == m_options.getInt("DirichletStrategy") ?
252  m_system.colMapper(unk) :
253  mbasis.getMapper(dirichlet::elimination,
254  static_cast<iFace::strategy>(m_options.getInt("InterfaceStrategy")),
255  m_pde_ptr->bc(), unk);
256 
257  //gsDebugVar(m_options.getInt("DirichletAAAStrategy"));
258  //gsDebugVar(m_options.getInt("DirichletValues"));
259 
260  switch ( m_options.getInt("DirichletValues") )
261  {
262  case dirichlet::homogeneous:
263  // If we have a homogeneous Dirichlet problem fill boundary
264  // DoFs with zeros
265  m_ddof[unk].setZero(mapper.boundarySize(), m_system.unkSize(unk) * m_pde_ptr->numRhs() );
266  break;
267  case dirichlet::interpolation:
268  computeDirichletDofsIntpl(mapper, mbasis,unk);
269  break;
270  case dirichlet::l2Projection:
271  computeDirichletDofsL2Proj(mapper, mbasis,unk);
272  break;
273  case dirichlet::user :
274  // Assuming that the DoFs are already set by the user
275  GISMO_ENSURE( m_ddof[unk].size() == mapper.boundarySize()*m_system.unkSize(unk)* m_pde_ptr->numRhs(), "The Dirichlet DoFs are not set.");
276  m_ddof[unk].resize(mapper.boundarySize(), m_system.unkSize(unk)* m_pde_ptr->numRhs());
277  break;
278  default:
279  GISMO_ERROR("Something went wrong with Dirichlet values.");
280  }
281 
282  // Corner values
283  for ( typename gsBoundaryConditions<T>::const_citerator
284  it = m_pde_ptr->bc().cornerBegin();
285  it != m_pde_ptr->bc().cornerEnd(); ++it )
286  {
287  if(it->unknown == unk)
288  {
289  const index_t i = mbasis[it->patch].functionAtCorner(it->corner);
290  const index_t ii = mapper.bindex( i , it->patch );
291  m_ddof[unk].row(ii).setConstant(it->value);
292  }
293  else
294  continue;
295 
296  }
297 }
298 
299 
300 // SKleiss: Note that this implementation is not useable for (T)HB-Splines!
301 //
302 // 1. Computation of the Dirichlet values explicitly uses gsPointGrid(rr)
303 // Computing a grid of evaluation points does not make sense for any locally
304 // refined basis.
305 // Also, "component(i)" is used.
306 // I'm afraid this makes sense ONLY FOR TENSOR-PRODUCT bases.
307 //
308 // 2. As of now (16.May 2014), the boundaryBasis of (T)HB-spline basis is not
309 // implemented, as far as I know.
310 //
311 // 3. gsInterpolate uses the anchors of the boundary basis.
312 // With truncated hierarchical B-splines, the use of classical anchors does
313 // not work, because functions might be truncated to zero at these points.
314 template<class T> //
316  const gsMultiBasis<T> & mbasis,
317  const short_t unk_)
318 {
319  m_ddof[unk_].resize(mapper.boundarySize(), m_system.unkSize(unk_) * m_pde_ptr->numRhs() );
320  // Iterate over all patch-sides with Dirichlet-boundary conditions
321  for ( typename gsBoundaryConditions<T>::const_iterator
322  it = m_pde_ptr->bc().dirichletBegin();
323  it != m_pde_ptr->bc().dirichletEnd(); ++it )
324  {
325  //const int unk = it->unknown();
326  const index_t k = it->patch();
327  if(it->unknown()!=unk_)
328  continue;
329  const gsBasis<T> & basis = mbasis[k];
330 
331  // Get dofs on this boundary
332  const gsMatrix<index_t> boundary = basis.boundary(it->side());
333 
334  // If the condition is homogeneous then fill with zeros
335  if ( it->isHomogeneous() )
336  {
337  for (index_t i=0; i!= boundary.size(); ++i)
338  {
339  const index_t ii= mapper.bindex( boundary.at(i) , k );
340  m_ddof[unk_].row(ii).setZero();
341  }
342  continue;
343  }
344 
345  // Get the side information
346  short_t dir = it->side().direction( );
347  index_t param = (it->side().parameter() ? 1 : 0);
348 
349  // Compute grid of points on the face ("face anchors")
350  std::vector< gsVector<T> > rr;
351  rr.reserve( this->patches().parDim() );
352 
353  for ( short_t i=0; i < this->patches().parDim(); ++i)
354  {
355  if ( i==dir )
356  {
357  gsVector<T> b(1);
358  b[0] = ( basis.component(i).support() ) (0, param);
359  rr.push_back(b);
360  }
361  else
362  {
363  rr.push_back( basis.component(i).anchors().transpose() );
364  }
365  }
366 
367  GISMO_ASSERT(it->function()->targetDim() == m_system.unkSize(unk_) * m_pde_ptr->numRhs(),
368  "Given Dirichlet boundary function does not match problem dimension."
369  <<it->function()->targetDim()<<" != "<<m_system.unkSize(unk_) << " * " << m_system.rhs().cols()<<"\n");
370 
371  // Compute dirichlet values
372  gsMatrix<T> fpts;
373  if ( it->parametric() )
374  fpts = it->function()->eval( gsPointGrid<T>( rr ) );
375  else
376  fpts = it->function()->eval( m_pde_ptr->domain()[it->patch()].eval( gsPointGrid<T>( rr ) ) );
377 
378  // Interpolate dirichlet boundary
379  typename gsBasis<T>::uPtr h = basis.boundaryBasis(it->side());
380  typename gsGeometry<T>::uPtr geo = h->interpolateAtAnchors(fpts);
381  const gsMatrix<T> & dVals = geo->coefs();
382 
383  // Save corresponding boundary dofs
384  for (index_t l=0; l!= boundary.size(); ++l)
385  {
386  const index_t ii = mapper.bindex( boundary.at(l) , it->patch() );
387  m_ddof[unk_].row(ii) = dVals.row(l);
388  }
389  }
390 }
391 
392 template<class T>
394  const gsMultiBasis<T> & ,
395  const short_t unk_)
396 {
397  m_ddof[unk_].resize( mapper.boundarySize(), m_system.unkSize(unk_)* m_pde_ptr->numRhs());
398 
399  // Set up matrix, right-hand-side and solution vector/matrix for
400  // the L2-projection
401  gsSparseEntries<T> projMatEntries;
402  gsMatrix<T> globProjRhs;
403  globProjRhs.setZero( mapper.boundarySize(), m_system.unkSize(unk_)* m_pde_ptr->numRhs() );
404 
405  // Temporaries
406  gsVector<T> quWeights;
407 
408  gsMatrix<T> rhsVals;
409  gsMatrix<index_t> globIdxAct;
410  gsMatrix<T> basisVals;
411 
413 
414  // Iterate over all patch-sides with Dirichlet-boundary conditions
415  for ( typename gsBoundaryConditions<T>::const_iterator
416  iter = m_pde_ptr->bc().dirichletBegin();
417  iter != m_pde_ptr->bc().dirichletEnd(); ++iter )
418  {
419  if (iter->isHomogeneous() )
420  continue;
421 
422  GISMO_ASSERT(iter->function()->targetDim() == m_system.unkSize(unk_)* m_pde_ptr->numRhs(),
423  "Given Dirichlet boundary function does not match problem dimension."
424  <<iter->function()->targetDim()<<" != "<<m_system.unkSize(unk_)<<"x"<<m_system.rhs().cols()<<"\n");
425 
426  const short_t unk = iter->unknown();
427  if(unk!=unk_)
428  continue;
429  const index_t patchIdx = iter->patch();
430  const gsBasis<T> & basis = (m_bases[unk])[patchIdx];
431 
432  const gsGeometry<T> & patch = m_pde_ptr->patches()[patchIdx];
433 
434  // Set up quadrature to degree+1 Gauss points per direction,
435  // all lying on iter->side() except from the direction which
436  // is NOT along the element
437 
438  gsGaussRule<T> bdQuRule(basis, 1.0, 1, iter->side().direction());
439 
440  // Create the iterator along the given part boundary.
441  typename gsBasis<T>::domainIter bdryIter = basis.makeDomainIterator(iter->side());
442 
443  for(; bdryIter->good(); bdryIter->next() )
444  {
445  bdQuRule.mapTo( bdryIter->lowerCorner(), bdryIter->upperCorner(),
446  md.points, quWeights);
447 
448  //geoEval->evaluateAt( md.points );
449  patch.computeMap(md);
450 
451  // the values of the boundary condition are stored
452  // to rhsVals. Here, "rhs" refers to the right-hand-side
453  // of the L2-projection, not of the PDE.
454  rhsVals = iter->function()->eval( m_pde_ptr->domain()[patchIdx].eval( md.points ) );
455 
456  basis.eval_into( md.points, basisVals);
457 
458  // Indices involved here:
459  // --- Local index:
460  // Index of the basis function/DOF on the patch.
461  // Does not take into account any boundary or interface conditions.
462  // --- Global Index:
463  // Each DOF has a unique global index that runs over all patches.
464  // This global index includes a re-ordering such that all eliminated
465  // DOFs come at the end.
466  // The global index also takes care of glued interface, i.e., corresponding
467  // DOFs on different patches will have the same global index, if they are
468  // glued together.
469  // --- Boundary Index (actually, it's a "Dirichlet Boundary Index"):
470  // The eliminated DOFs, which come last in the global indexing,
471  // have their own numbering starting from zero.
472 
473  // Get the global indices (second line) of the local
474  // active basis (first line) functions/DOFs:
475  basis.active_into(md.points.col(0), globIdxAct );
476  mapper.localToGlobal( globIdxAct, patchIdx, globIdxAct);
477 
478  // Out of the active functions/DOFs on this element, collect all those
479  // which correspond to a boundary DOF.
480  // This is checked by calling mapper.is_boundary_index( global Index )
481 
482  // eltBdryFcts stores the row in basisVals/globIdxAct, i.e.,
483  // something like a "element-wise index"
484  std::vector<index_t> eltBdryFcts;
485  eltBdryFcts.reserve(mapper.boundarySize());
486  for( index_t i=0; i < globIdxAct.rows(); i++)
487  if( mapper.is_boundary_index( globIdxAct(i,0)) )
488  eltBdryFcts.push_back( i );
489 
490  // Do the actual assembly:
491  for( index_t k=0; k < md.points.cols(); k++ )
492  {
493  const T weight_k = quWeights[k] * md.measure(k);
494 
495  // Only run through the active boundary functions on the element:
496  for( size_t i0=0; i0 < eltBdryFcts.size(); i0++ )
497  {
498  // Each active boundary function/DOF in eltBdryFcts has...
499  // ...the above-mentioned "element-wise index"
500  const unsigned i = eltBdryFcts[i0];
501  // ...the boundary index.
502  const unsigned ii = mapper.global_to_bindex( globIdxAct( i ));
503 
504  for( size_t j0=0; j0 < eltBdryFcts.size(); j0++ )
505  {
506  const unsigned j = eltBdryFcts[j0];
507  const unsigned jj = mapper.global_to_bindex( globIdxAct( j ));
508 
509  // Use the "element-wise index" to get the needed
510  // function value.
511  // Use the boundary index to put the value in the proper
512  // place in the global projection matrix.
513  projMatEntries.add(ii, jj, weight_k * basisVals(i,k) * basisVals(j,k));
514  } // for j
515 
516  globProjRhs.row(ii) += weight_k * basisVals(i,k) * rhsVals.col(k).transpose();
517 
518  } // for i
519  } // for k
520  } // bdryIter
521  } // boundaryConditions-Iterator
522 
523  gsSparseMatrix<T> globProjMat( mapper.boundarySize(), mapper.boundarySize() );
524  globProjMat.setFrom( projMatEntries );
525  globProjMat.makeCompressed();
526 
527  // Solve the linear system:
528  // The position in the solution vector already corresponds to the
529  // numbering by the boundary index. Hence, we can simply take them
530  // for the values of the eliminated Dirichlet DOFs.
531  typename gsSparseSolver<T>::CGDiagonal solver;
532  m_ddof[unk_] = solver.compute( globProjMat ).solve ( globProjRhs );
533 
534 } // computeDirichletDofsL2Proj
535 
536 template<class T>
538  gsMultiPatch<T>& result, short_t unk) const
539 {
540  // we might need to get a result even without having the system ..
541  //GISMO_ASSERT(m_dofs == m_rhs.rows(), "Something went wrong, assemble() not called?");
542 
543  // fixme: based on \a m_options and \a unk choose the right dof mapper
544  const gsDofMapper & mapper = m_system.colMapper(unk);
545 
546  result.clear(); // result is cleared first
547 
548  /*
549  GISMO_ASSERT(solVector.rows() == m_dofs,
550  "The provided solution vector does not match the system."
551  " Expected: "<<mapper.freeSize()<<", Got:"<<solVector.rows() );
552  */
553  // is the situation whtn solVector has more than one columns important?
554  const index_t dim = ( 0!=solVector.cols() ? solVector.cols() : m_ddof[unk].cols() );
555 
556  // to do: test unknown_dim == dim
557 
558  gsMatrix<T> coeffs;
559  for (size_t p = 0; p < m_pde_ptr->domain().nPatches(); ++p)
560  {
561  // Reconstruct solution coefficients on patch p
562  const size_t sz = m_bases[m_system.colBasis(unk)][p].size();
563  coeffs.resize(sz, dim);
564 
565  for (size_t i = 0; i < sz; ++i)
566  {
567  if ( mapper.is_free(i, p) ) // DoF value is in the solVector
568  {
569  coeffs.row(i) = solVector.row( mapper.index(i, p) );
570  }
571  else // eliminated DoF: fill with Dirichlet data
572  {
573  coeffs.row(i) = m_ddof[unk].row( mapper.bindex(i, p) ).head(dim);
574  }
575  }
576 
577  result.addPatch( m_bases[m_system.colBasis(unk)][p].makeGeometry( give(coeffs) ) );
578  }
579 
580  // AM: result topology ?
581 }
582 
583 template<class T>
585  gsMultiPatch<T>& result,
586  const gsVector<index_t> & unknowns) const
587 {
588  // we might need to get a result even without having the system ..
589  //GISMO_ASSERT(m_dofs == m_rhs.rows(), "Something went wrong, assemble() not called?");
590 
591  GISMO_ASSERT(solVector.cols()==1, "Vector valued output only works for single rhs");
592  index_t idx;
593 
594  const short_t dim = unknowns.rows();
595 
596  // fixme: based on \a m_options and \a unk choose the right dof mapper
597  std::vector<gsDofMapper> mappers(dim);
598  for(short_t unk = 0; unk<dim;++unk)
599  mappers[unk] = m_system.colMapper(unknowns[unk]);
600 
601  result.clear(); // result is cleared first
602 
603  gsMatrix<T> coeffs;
604  gsVector<index_t> basisIndices(dim);
605  for(short_t unk = 0; unk<dim;++unk)
606  basisIndices[unk] = m_system.colBasis(unknowns[unk]);
607 
608  for (size_t p = 0; p < m_pde_ptr->domain().nPatches(); ++p)
609  {
610  const size_t sz = m_bases[basisIndices[0]][p].size(); //must be equal for all unk
611  coeffs.resize(sz, dim);
612 
613  for(short_t unk = 0; unk<dim;++unk)
614  {
615  // Reconstruct solution coefficients on patch p
616  for (size_t i = 0; i < sz; ++i)
617  {
618  if ( mappers[unk].is_free(i, p) ) // DoF value is in the solVector
619  {
620  m_system.mapToGlobalColIndex(i,p,idx,unknowns[unk]);
621  coeffs(i,unk) = solVector(idx,0);
622  // coeffs(i,unk) = solVector(mappers[unk].index(i, p),0);
623  }
624  else // eliminated DoF: fill with Dirichlet data
625  {
626  coeffs(i,unk) = m_ddof[unknowns[unk]](mappers[unk].bindex(i, p),0);
627  }
628  }
629  }
630  result.addPatch( m_bases[basisIndices[0]][p].makeGeometry( give(coeffs) ) );
631  }
632 
633  // AM: result topology ?
634 }
635 
636 
637 template<class T>
639  short_t unk) const
640 {
641  typename gsMultiPatch<T>::Ptr result(new gsMultiPatch<T>);
642  constructSolution(solVector,*result, unk);
643  return gsField<T>(m_pde_ptr->domain(), result, true);
644 }
645 
646 
647 //This silently assumes the same basis for all components
648 template<class T>
650  gsMultiPatch<T>& result, T theta) const
651 {
652  // GISMO_ASSERT(m_dofs == m_rhs.rows(), "Something went wrong, assemble() not called?");
653  index_t idx;
654 
655  for (size_t p = 0; p < m_pde_ptr->domain().nPatches(); ++p)
656  {
657  // Update solution coefficients on patch p
658  const size_t sz = m_bases[0][p].size();
659 
660  gsMatrix<T> & coeffs = result.patch(p).coefs();
661 
662  for (index_t j = 0; j < m_system.numColBlocks(); ++j)
663  {
664  const gsDofMapper & mapper = m_system.colMapper(j);
665  for (size_t i = 0; i < sz; ++i)
666  {
667  if ( mapper.is_free(i, p) ) // DoF value is in the solVector
668  {
669  m_system.mapToGlobalColIndex(i,p,idx,j);
670  coeffs(i,j) += theta * solVector(idx,0);
671  }
672  }
673  }
674  }
675 }
676 
677 }// namespace gismo
memory::shared_ptr< gsMultiPatch > Ptr
Shared pointer for gsMultiPatch.
Definition: gsMultiPatch.h:41
index_t addPatch(typename gsGeometry< T >::uPtr g)
Add a patch from a gsGeometry&lt;T&gt;::uPtr.
Definition: gsMultiPatch.hpp:210
virtual gsAssembler * create() const
Create an empty Assembler of the derived type and return a pointer to it. Call the initialize functio...
Definition: gsAssembler.hpp:59
Abstract base class representing a geometry map.
Definition: gsGeometry.h:92
Class that provides a container for triplets (i,j,value) to be filled in a sparse matrix...
Definition: gsSparseMatrix.h:33
Provides the Gauss-Legendre quadrature rule.
gsBasis< T >::uPtr boundaryBasis(boxSide const &s)
Returns the boundary basis for side s.
void computeDirichletDofsIntpl(const gsDofMapper &mapper, const gsMultiBasis< T > &mbasis, const short_t unk_=0)
calculates the values of the eliminated dofs based on Interpolation.
Definition: gsAssembler.hpp:315
const_iterator dirichletBegin() const
Definition: gsBoundaryConditions.h:490
void clear()
Clear (delete) all patches.
Definition: gsMultiPatch.h:319
Provides generic assembler routines.
index_t boundarySize() const
Returns the number of eliminated dofs.
Definition: gsDofMapper.h:457
void computeDirichletDofsL2Proj(const gsDofMapper &mapper, const gsMultiBasis< T > &mbasis, const short_t unk_=0)
calculates the values of the eliminated dofs based on L2 Projection.
Definition: gsAssembler.hpp:393
#define GISMO_NO_IMPLEMENTATION
Definition: gsDebug.h:129
virtual void computeMap(gsMapData< T > &InOut) const
Computes map function data.
Definition: gsFunction.hpp:822
A scalar of vector field defined on a m_parametric geometry.
Definition: gsField.h:54
virtual gsAssembler * clone() const
Clone this Assembler, making a deep copy.
Definition: gsAssembler.hpp:63
#define short_t
Definition: gsConfig.h:35
virtual void updateSolution(const gsMatrix< T > &solVector, gsMultiPatch< T > &result, T theta=(T)(1)) const
Update solution by adding the computed solution vector to the current solution specified by...
Definition: gsAssembler.hpp:649
Provides declaration of MultiBasis class.
Struct that defines the boundary sides and corners and types of a geometric object.
Definition: gsBoundary.h:55
the gsMapData is a cache of pre-computed function (map) values.
Definition: gsFuncData.h:324
bool is_free(index_t i, index_t k=0, index_t c=0) const
Returns true if local dof i of patch k is not eliminated.
Definition: gsDofMapper.h:382
void penalizeDirichletDofs(short_t unk=0)
Definition: gsAssembler.hpp:125
S give(S &x)
Definition: gsMemory.h:266
const_iterator neumannBegin() const
Definition: gsBoundaryConditions.h:531
virtual void refresh()
Creates the mappers and setups the sparse system. to be implemented in derived classes, see scalarProblemGalerkinRefresh() for a possible implementation.
Definition: gsAssembler.hpp:45
#define index_t
Definition: gsConfig.h:32
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
virtual const gsBasis< T > & component(short_t i) const
For a tensor product basis, return the (const) 1-d basis for the i-th parameter component.
Definition: gsBasis.hpp:514
void localToGlobal(const gsMatrix< index_t > &locals, index_t patchIndex, gsMatrix< index_t > &globals, index_t comp=0) const
Computes the global indices of the input local indices.
Definition: gsDofMapper.cpp:25
#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
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_iterator neumannEnd() const
Definition: gsBoundaryConditions.h:536
index_t index(index_t i, index_t k=0, index_t c=0) const
Returns the global dof index associated to local dof i of patch k.
Definition: gsDofMapper.h:325
T at(index_t i) const
Returns the i-th element of the vectorization of the matrix.
Definition: gsMatrix.h:211
index_t global_to_bindex(index_t gl) const
Returns the boundary index of global dof gl.
Definition: gsDofMapper.h:364
bool is_boundary_index(index_t gl) const
Returns true if global dof gl is eliminated.
Definition: gsDofMapper.h:386
#define gsWarn
Definition: gsDebug.h:50
Holds a set of patch-wise bases and their topology information.
Definition: gsMultiBasis.h:36
void setFixedDofs(const gsMatrix< T > &coefMatrix, short_t unk=0, size_t patch=0)
the user can manually set the dirichlet Dofs for a given patch and unknown, based on the Basis coeffi...
Definition: gsAssembler.hpp:176
gsGeometry< T > & patch(size_t i) const
Return the i-th patch.
Definition: gsMultiPatch.h:226
Provides declaration of DomainIterator abstract interface.
void scalarProblemGalerkinRefresh()
A prototype of the refresh function for a &quot;standard&quot; scalar problem. Creats one mapper based on the s...
Definition: gsAssembler.hpp:102
Container class for a set of geometry patches and their topology, that is, the interface connections ...
Definition: gsMultiPatch.h:33
Poisson equation element visitor.
The density of the measure pull back.
Definition: gsForwardDeclarations.h:76
index_t bindex(index_t i, index_t k=0, index_t c=0) const
Returns the boundary index of local dof i of patch k.
Definition: gsDofMapper.h:334
memory::unique_ptr< gsGeometry > uPtr
Unique pointer for gsGeometry.
Definition: gsGeometry.h:100
virtual void eval_into(const gsMatrix< T > &u, gsMatrix< T > &result) const
Evaluates nonzero basis functions at point u into result.
Definition: gsBasis.hpp:443
virtual memory::unique_ptr< gsGeometry< T > > interpolateAtAnchors(gsMatrix< T > const &vals) const
Applies interpolation of values pts using the anchors as parameter points. May be reimplemented in de...
Definition: gsBasis.hpp:244
memory::unique_ptr< gsBasis > uPtr
Unique pointer for gsBasis.
Definition: gsBasis.h:89
bool check()
checks for consistency and legal values of the stored members.
Definition: gsAssembler.hpp:67
Class containing a set of boundary conditions.
Definition: gsBoundaryConditions.h:341
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.
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
gsMatrix< T > points
input (parametric) points
Definition: gsFuncData.h:348
virtual void constructSolution(const gsMatrix< T > &solVector, gsMultiPatch< T > &result, short_t unk=0) const
Construct solution from computed solution vector for a single unknows.
Definition: gsAssembler.hpp:537
Class which holds a list of parameters/options, and provides easy access to them. ...
Definition: gsOptionList.h:32
The assembler class provides generic routines for volume and boundary integrals that are used for for...
Definition: gsAssembler.h:265
virtual void assemble()
Main assemble routine, to be implemented in derived classes.
Definition: gsAssembler.hpp:51
Class that represents the (tensor) Gauss-Legendre quadrature rule.
Definition: gsGaussRule.h:27
This object is a cache for computed values from an evaluator.
void computeDirichletDofs(short_t unk=0)
Triggers computation of the Dirichlet dofs.
Definition: gsAssembler.hpp:232
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:493
static gsOptionList defaultOptions()
Returns the list of default options for assembly.
Definition: gsAssembler.hpp:30
const_iterator dirichletEnd() const
Definition: gsBoundaryConditions.h:495
void setFixedDofVector(gsMatrix< T > vals, short_t unk=0)
the user can manually set the dirichlet Dofs for a given patch and unknown.
Definition: gsAssembler.hpp:219
gsMatrix< index_t > boundary(boxSide const &s) const
Returns the indices of the basis functions that are nonzero at the domain boundary as single-column-m...
Definition: gsBasis.h:520
A basis represents a family of scalar basis functions defined over a common parameter domain...
Definition: gsBasis.h:78
Provides declaration of the Field class.
gsMatrix< T > & coefs()
Definition: gsGeometry.h:340
virtual void active_into(const gsMatrix< T > &u, gsMatrix< index_t > &result) const
Returns the indices of active basis functions at points u, as a list of indices, in result...
Definition: gsBasis.hpp:293