G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
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
26namespace gismo
27{
28
29template<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
44template<class T>
46{
47 gsWarn <<" gsAssembler<T>::Refresh is an empty call\n";
48}
49
50template<class T>
53
54template<class T>
57
58template<class T>
61
62template<class T>
65
66template<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
101template <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
124template<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
175template<class T>
176void 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
218template<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
231template<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.
314template<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
392template<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
536template<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 }
580 // AM: result topology ?
581}
582
583template<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
637template<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
648template<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
The assembler class provides generic routines for volume and boundary integrals that are used for for...
Definition gsAssembler.h:266
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
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
void penalizeDirichletDofs(short_t unk=0)
Definition gsAssembler.hpp:125
virtual void refresh()
Creates the mappers and setups the sparse system. to be implemented in derived classes,...
Definition gsAssembler.hpp:45
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
void scalarProblemGalerkinRefresh()
A prototype of the refresh function for a "standard" scalar problem. Creats one mapper based on the s...
Definition gsAssembler.hpp:102
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
virtual void assemble()
Main assemble routine, to be implemented in derived classes.
Definition gsAssembler.hpp:51
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
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
void computeDirichletDofs(short_t unk=0)
Triggers computation of the Dirichlet dofs.
Definition gsAssembler.hpp:232
static gsOptionList defaultOptions()
Returns the list of default options for assembly.
Definition gsAssembler.hpp:30
bool check()
checks for consistency and legal values of the stored members.
Definition gsAssembler.hpp:67
virtual gsAssembler * clone() const
Clone this Assembler, making a deep copy.
Definition gsAssembler.hpp:63
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
A basis represents a family of scalar basis functions defined over a common parameter domain.
Definition gsBasis.h:79
memory::unique_ptr< gsBasis > uPtr
Unique pointer for gsBasis.
Definition gsBasis.h:89
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:267
Class containing a set of boundary conditions.
Definition gsBoundaryConditions.h:342
const_iterator neumannEnd() const
Definition gsBoundaryConditions.h:536
const_iterator dirichletBegin() const
Definition gsBoundaryConditions.h:490
const_iterator neumannBegin() const
Definition gsBoundaryConditions.h:531
const_iterator dirichletEnd() const
Definition gsBoundaryConditions.h:495
Maintains a mapping from patch-local dofs to global dof indices and allows the elimination of individ...
Definition gsDofMapper.h:69
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
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
index_t boundarySize() const
Returns the number of eliminated dofs.
Definition gsDofMapper.h:457
index_t freeSize() const
Returns the number of free (not eliminated) dofs.
Definition gsDofMapper.h:436
index_t global_to_bindex(index_t gl) const
Returns the boundary index of global dof gl.
Definition gsDofMapper.h:364
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
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
bool is_boundary_index(index_t gl) const
Returns true if global dof gl is eliminated.
Definition gsDofMapper.h:386
A scalar of vector field defined on a m_parametric geometry.
Definition gsField.h:55
Class that represents the (tensor) Gauss-Legendre quadrature rule.
Definition gsGaussRule.h:28
Abstract base class representing a geometry map.
Definition gsGeometry.h:93
gsMatrix< T > & coefs()
Definition gsGeometry.h:340
memory::unique_ptr< gsGeometry > uPtr
Unique pointer for gsGeometry.
Definition gsGeometry.h:100
the gsMapData is a cache of pre-computed function (map) values.
Definition gsFuncData.h:349
gsMatrix< T > points
input (parametric) points
Definition gsFuncData.h:372
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
memory::shared_ptr< gsMultiPatch > Ptr
Shared pointer for gsMultiPatch.
Definition gsMultiPatch.h:107
gsGeometry< T > & patch(size_t i) const
Return the i-th patch.
Definition gsMultiPatch.h:292
index_t addPatch(typename gsGeometry< T >::uPtr g)
Add a patch from a gsGeometry<T>::uPtr.
Definition gsMultiPatch.hpp:211
void clear()
Clear (delete) all patches.
Definition gsMultiPatch.h:388
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
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
Class that provides a container for triplets (i,j,value) to be filled in a sparse matrix.
Definition gsSparseMatrix.h:34
A sparse linear system indexed by sets of degrees of freedom.
Definition gsSparseSystem.h:30
A vector with arbitrary coefficient type and fixed or dynamic size.
Definition gsVector.h:37
Provides generic assembler routines.
#define short_t
Definition gsConfig.h:35
#define index_t
Definition gsConfig.h:32
#define GISMO_NO_IMPLEMENTATION
Definition gsDebug.h:129
#define GISMO_ERROR(message)
Definition gsDebug.h:118
#define gsWarn
Definition gsDebug.h:50
#define GISMO_ENSURE(cond, message)
Definition gsDebug.h:102
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
Provides declaration of DomainIterator abstract interface.
Provides declaration of the Field class.
This object is a cache for computed values from an evaluator.
Provides the Gauss-Legendre quadrature rule.
Provides declaration of MultiBasis class.
Provides functions to generate structured point data.
Poisson equation element visitor.
The G+Smo namespace, containing all definitions for the library.
@ NEED_MEASURE
The density of the measure pull back.
Definition gsForwardDeclarations.h:76
S give(S &x)
Definition gsMemory.h:266
Struct that defines the boundary sides and corners and types of a geometric object.
Definition gsBoundary.h:56