G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsVisitorCDR.h
Go to the documentation of this file.
1 
14 #pragma once
15 
16 namespace gismo
17 {
18 
37 template <class T>
39 {
40 public:
41 
45  gsVisitorCDR(const gsPde<T> & pde)
46  {
47  const gsConvDiffRePde<T>* cdr =
48  static_cast<const gsConvDiffRePde<T>*>(&pde);
49 
50  coeff_A_ptr = cdr->diffusion ();
51  coeff_b_ptr = cdr->convection();
52  coeff_c_ptr = cdr->reaction ();
53  rhs_ptr = cdr->rhs ();
54 
55  flagStabType = stabilizerCDR::none;
56 
57  GISMO_ASSERT( rhs_ptr->targetDim() == 1 ,
58  "Not yet tested for multiple right-hand-sides");
59  }
60 
79  const gsFunction<T> & coeff_A,
80  const gsFunction<T> & coeff_b,
81  const gsFunction<T> & coeff_c,
82  stabilizerCDR::method flagStabilization = stabilizerCDR::SUPG) :
83  rhs_ptr(&rhs),
84  coeff_A_ptr( & coeff_A),coeff_b_ptr( & coeff_b),coeff_c_ptr( & coeff_c),
85  flagStabType( flagStabilization )
86  {
87  GISMO_ASSERT( rhs.targetDim() == 1 ,"Not yet tested for multiple right-hand-sides");
88  GISMO_ASSERT( flagStabilization == stabilizerCDR::none || flagStabilization == stabilizerCDR::SUPG, "flagStabilization not known");
89  }
90 
92  void initialize(const gsBasis<T> & basis,
93  const index_t ,
94  const gsOptionList & options,
95  gsQuadRule<T> & rule)
96  {
97  // Setup Quadrature
98  rule = gsQuadrature::get(basis, options); // harmless slicing occurs here
99 
100  //flagStabType = static_cast<unsigned>(options.askSwitch("SUPG", false));
101  flagStabType = static_cast<stabilizerCDR::method>(options.askInt("Stabilization", stabilizerCDR::none));
102 
103  // Set Geometry evaluation flags
104  md.flags = NEED_VALUE | NEED_MEASURE | NEED_GRAD_TRANSFORM | NEED_2ND_DER;
105  }
106 
108  inline void evaluate(const gsBasis<T> & basis, // to do: more unknowns
109  const gsGeometry<T> & geo,
110  const gsMatrix<T> & quNodes)
111  {
112  base = &geo;
113  md.points = quNodes;
114 
115  // Compute the active basis functions
116  // Assumes actives are the same for all quadrature points on the elements
117  basis.active_into(md.points.col(0), actives);
118  numActive = actives.rows();
119 
120  // Evaluate basis functions on element
121  basis.evalAllDers_into(md.points, 2, basisData, true);
122 
123  // Compute image of Gauss nodes under geometry mapping as well as Jacobians
124  geo.computeMap(md);
125 
126  // Evaluate the coefficients
127  coeff_A_ptr->eval_into(md.values[0], coeff_A_vals);
128  coeff_b_ptr->eval_into(md.values[0], coeff_b_vals);
129  coeff_c_ptr->eval_into(md.values[0], coeff_c_vals);
130 
131  // Evaluate right-hand side at the geometry points
132  rhs_ptr->eval_into(md.values[0], rhsVals); // to do: parametric rhs ?
133 
134  // Initialize local matrix/rhs
135  localMat.setZero(numActive, numActive);
136  localRhs.setZero(numActive, rhsVals.rows());//multiple right-hand sides
137  }
138 
140  inline void assemble(gsDomainIterator<T> & element,
141  const gsVector<T> & quWeights)
142  {
143 
144  const index_t N = numActive;
145 
146  gsMatrix<T> & basisVals = basisData[0];
147  gsMatrix<T> & basisGrads = basisData[1];
148  gsMatrix<T> & basis2ndDerivs = basisData[2];
149 
150  const unsigned d = element.dim();
151 
152  // supgMat will contain the contributions to the assembled matrix
153  // that come from the SUPG stabilization. It is initialized whether
154  // SUPG-stabilization is used or not, because the SUPG-parameter
155  // has to be computed AFTER the loop over the quadrature points
156  // (see below).
157  gsMatrix<T> supgMat( localMat.rows(), localMat.cols() );
158  supgMat.setZero();
159 
160  for (index_t k = 0; k < quWeights.rows(); ++k) // loop over quadrature nodes
161  {
162  // Multiply weight by the geometry measure
163  const T weight = quWeights[k] * md.measure(k);
164 
165  // Compute physical gradients at k as a Dim x numActive matrix
166  transformGradients (md, k, basisGrads, physBasisGrad);
167  transformDeriv2Hgrad (md, k, basisGrads, basis2ndDerivs, physBasisd2);
168 
169  // d ... dim
170  // N ... numActive
171 
172  // physBasisGrad : d x N
173  // A.col(k) : d^2 x 1
174  // tmp_A : d x d
175  gsMatrix<T> tmp_A = coeff_A_vals.col(k);
176  tmp_A.resize(d,d);
177 
178  // b.col(k) : d x 1
179  // physBasisGrad : d x N
180  // tmp_b : 1 x N
181  gsMatrix<T> b_basisGrads = coeff_b_vals.col(k).transpose() * physBasisGrad;
182 
183  // basisVals.col(k): N x 1
184  // rhsVals.col(k) : 1 x 1
185  // result: : N x 1
186  localRhs.noalias() += weight * ( basisVals.col(k) * rhsVals.col(k).transpose() ) ;
187 
188  // ( N x d ) * ( d x d ) * ( d x N ) = N x N
189  localMat.noalias() += weight * (physBasisGrad.transpose() * ( tmp_A * physBasisGrad) );
190  // ( N x 1 ) * ( 1 x N) = N x N
191  localMat.noalias() += weight * (basisVals.col(k) * b_basisGrads);
192  // ( scalar ) * ( N x 1 ) * ( 1 x N ) = N x N
193  localMat.noalias() += weight * coeff_c_vals(0,k) * (basisVals.col(k) * basisVals.col(k).transpose());
194 
195 
196  if( flagStabType == stabilizerCDR::SUPG ) // 1: SUPG
197  {
198  //const typename gsMatrix<T>::constColumns J = geoEval.jacobian(k); //todo: correct?
199  const typename gsFuncData<T>::matrixTransposeView J = md.jacobian(k);
200  gsMatrix<T> Jinv = J.inverse();
201 
202  gsMatrix<T> grad_b_basisGradsT(N,d);
203  grad_b_basisGradsT.setZero();
204 
205  // loop over all basis functions
206  for( index_t fct_i = 0; fct_i < N; ++fct_i )
207  {
208  gsMatrix<T> tmp_basis2ndDerivs(d,d);
209  tmp_basis2ndDerivs.setZero();
210  if( d == 2 )
211  {
212  tmp_basis2ndDerivs(0,0) = physBasisd2(fct_i, 0);
213  tmp_basis2ndDerivs(1,1) = physBasisd2(fct_i, 1);
214  tmp_basis2ndDerivs(0,1) =
215  tmp_basis2ndDerivs(1,0) = physBasisd2(fct_i, 2);
216  }
217  else if (d == 3 )
218  {
219  tmp_basis2ndDerivs(0,0) = physBasisd2(fct_i, 0);
220  tmp_basis2ndDerivs(1,1) = physBasisd2(fct_i, 1);
221  tmp_basis2ndDerivs(2,2) = physBasisd2(fct_i, 2);
222  tmp_basis2ndDerivs(0,1) =
223  tmp_basis2ndDerivs(1,0) = physBasisd2(fct_i, 3);
224  tmp_basis2ndDerivs(0,2) =
225  tmp_basis2ndDerivs(2,0) = physBasisd2(fct_i, 4);
226  tmp_basis2ndDerivs(1,2) =
227  tmp_basis2ndDerivs(2,1) = physBasisd2(fct_i, 5);
228  }
229  else
230  {
231  GISMO_ERROR("What kind of dimension are you using? Should be 2 or 3.");
232  }
233 
234  //grad_b_basisGradsT.row(fct_i) = (tmp_basis2ndDerivs * coeff_b_vals.col(k) ).transpose();
235  for( unsigned i = 0; i < d; ++i )
236  for( unsigned j = 0; j < d; ++j )
237  grad_b_basisGradsT(fct_i, i) += coeff_b_vals(j,k) * tmp_basis2ndDerivs(j,i);
238  }
239 
240  supgMat.noalias() += weight * grad_b_basisGradsT * ( tmp_A * physBasisGrad );
241  supgMat.noalias() += weight * (b_basisGrads.transpose() * b_basisGrads);
242  supgMat.noalias() += weight * coeff_c_vals(0,k) * ( b_basisGrads.transpose() * basisVals.col(k).transpose());
243 
244  }
245  }
246 
247  if( flagStabType == stabilizerCDR::SUPG ) // 1: SUPG
248  {
249  // Calling getSUPGParameter re-evaluates the (*base) geometry. // todo: is that correct so?
250  // Thus, it has to be called AFTER geo (*base) has been used.
251  T supgParam = getSUPGParameter( element.lowerCorner(),
252  element.upperCorner());
253  // Add the contributions from the SUPG-stabilization.
254  localMat.noalias() += supgParam * supgMat;
255  }
256  }
257 
258  inline void localToGlobal(const index_t patchIndex,
259  const std::vector<gsMatrix<T> > & eliminatedDofs,
260  gsSparseSystem<T> & system)
261  {
262  // Map patch-local DoFs to global DoFs
263  system.mapColIndices(actives, patchIndex, actives);
264 
265  // Add contributions to the system matrix and right-hand side
266  system.push(localMat, localRhs, actives, eliminatedDofs.front(), 0, 0);
267  }
268 
271  const gsVector<T> & up)
272  {
273  const index_t N = 2;
274 
275  const index_t d = lo.size();
276 
277  gsMatrix<T> b_at_phys_pts;
278 
279  // compute the center point of the cell...
280 
281  // ...get the points map it to the physical space...
282  gsMatrix<T> phys_pts = md.values[0];
283  // ...evaluate the convection coefficient there, ...
284  coeff_b_ptr->eval_into( phys_pts, b_at_phys_pts );
285  // ...and get it's norm.
286  T b_norm = 0;
287  for( index_t i=0; i < d; i++)
288  b_norm += b_at_phys_pts(i,0) * b_at_phys_pts(i,0);
289  b_norm = math::sqrt( b_norm );
290 
291  T SUPG_param = (T)(0.0);
292  if( b_norm > 0 )
293  {
294  gsMatrix<T> aMat;
295 
296  if( d == 2 )
297  {
298  index_t N1 = N+1;
299  md.points.resize( 2, 4*N1 );
300  aMat.resize( 2, 4*N1 );
301 
302  for( index_t i = 0; i <= N; ++i )
303  {
304  T a = (T)(i)/(T)(N);
305  aMat(0,i) = a;
306  aMat(1,i) = (T)(0.0);
307  aMat(0,i+N1) = a;
308  aMat(1,i+N1) = (T)(1.0);
309 
310  aMat(0,i+2*N1) = (T)(0.0);
311  aMat(1,i+2*N1) = a;
312  aMat(0,i+3*N1) = (T)(1.0);
313  aMat(1,i+3*N1) = a;
314  }
315  }
316  else if( d == 3 )
317  {
318 
319  GISMO_ASSERT(false,"NOT IMLEMENTED YET, Mark m271");
320 
321  /*
322  md.points.resize( 3, 6*(N+1)*(N+1) );
323  aMat.resize( 3, 6*(N+1)*(N+1) );
324 
325  index_t N1 = N+1;
326  md.points.resize( 2, 4*N1 );
327  aMat.resize( 2, 4*N1 );
328 
329  index_t ij = 0;
330  for( index_t i = 0; i <= N; ++i )
331  for( index_t j = 0; j <= N; ++j )
332  {
333  T ai = (T)(i)/(T)(N);
334  T aj = (T)(j)/(T)(N);
335  aMat(0,ij) = (T)(0.0);
336  aMat(1,ij) = (T)(0.0);
337  aMat(2,ij) = (T)(0.0);
338  aMat(0,ij+N1) = (T)(1.0);
339  aMat(1,ij+N1) = (T)(1.0);
340  aMat(1,ij+N1) = (T)(1.0);
341 
342  }
343  */
344 
345  }
346  else
347  {
348  GISMO_ASSERT(false,"WRONG DIMENSION. Mark m243");
349  }
350 
351 
352  for( index_t di = 0; di < d; ++di )
353  for( index_t i = 0; i < aMat.cols(); ++i)
354  {
355  md.points(di,i) = ( (T)(1) - aMat(di,i) )*lo[di] + aMat(di,i) * up[di];
356  }
357 
358  base->computeMap(md);
359  gsMatrix<T> b_proj = md.values[0].transpose() * b_at_phys_pts;
360 
361  T b_proj_min = b_proj(0,0);
362  T b_proj_max = b_proj(0,0);
363  for( index_t i = 0; i < b_proj.size(); i++)
364  {
365  if( b_proj_min > b_proj(i) )
366  b_proj_min = b_proj(i);
367  if( b_proj_max < b_proj(i) )
368  b_proj_max = b_proj(i);
369  }
370  SUPG_param = ( b_proj_max - b_proj_min ) / ( (T)(2) * b_norm );
371  }
372 
373  return SUPG_param;
374  }
375 
376 
377 
378 protected:
379  // Right hand side
380  const gsFunction<T> * rhs_ptr;
381  // PDE Coefficient
382  const gsFunction<T> * coeff_A_ptr;
383  const gsFunction<T> * coeff_b_ptr;
384  const gsFunction<T> * coeff_c_ptr;
385  // flag for stabilization method
386  stabilizerCDR::method flagStabType;
387 
388 protected:
389  // Basis values
390  std::vector<gsMatrix<T> > basisData;
391  gsMatrix<T> physBasisGrad, physBasisd2;
392  gsMatrix<index_t> actives;
393  index_t numActive;
394 
395  gsMatrix<T> coeff_A_vals;
396  gsMatrix<T> coeff_b_vals;
397  gsMatrix<T> coeff_c_vals;
398 
399 protected:
400  // Local values of the right hand side
401  gsMatrix<T> rhsVals;
402 
403 protected:
404  // Local matrices
405  gsMatrix<T> localMat;
406  gsMatrix<T> localRhs;
407 
408  const gsGeometry<T> * base;
409  gsMapData<T> md;
410 };
411 
412 
413 } // namespace gismo
Use SUPG.
Definition: gsCDRAssembler.h:30
Abstract base class representing a geometry map.
Definition: gsGeometry.h:92
Do not use a stabilizer.
Definition: gsCDRAssembler.h:31
Class representing a reference quadrature rule.
Definition: gsQuadRule.h:28
void mapColIndices(const gsMatrix< index_t > &actives, const index_t patchIndex, gsMatrix< index_t > &result, const index_t c=0) const
mapColIndices Maps a set of basis indices by the corresponding dofMapper.
Definition: gsSparseSystem.h:584
virtual void computeMap(gsMapData< T > &InOut) const
Computes map function data.
Definition: gsFunction.hpp:822
virtual void evalAllDers_into(const gsMatrix< T > &u, int n, std::vector< gsMatrix< T > > &result, bool sameElement=false) const
Evaluate the nonzero functions and their derivatives up to order n at points u into result...
Definition: gsFunctionSet.hpp:81
short_t dim() const
Return dimension of the elements.
Definition: gsDomainIterator.h:115
void evaluate(const gsBasis< T > &basis, const gsGeometry< T > &geo, const gsMatrix< T > &quNodes)
Evaluate on element.
Definition: gsVisitorCDR.h:108
virtual const gsVector< T > & upperCorner() const
Returns the upper corner of the current element.
Definition: gsDomainIterator.h:151
the gsMapData is a cache of pre-computed function (map) values.
Definition: gsFuncData.h:324
Abstract class representing a PDE (partial differential equation).
Definition: gsPde.h:43
#define index_t
Definition: gsConfig.h:32
A function from a n-dimensional domain to an m-dimensional image.
Definition: gsFunction.h:59
void push(const gsMatrix< T > &localMat, const gsMatrix< T > &localRhs, const gsMatrix< index_t > &actives, const gsMatrix< T > &eliminatedDofs, const size_t r=0, const size_t c=0)
push pushes the local system matrix and rhs for an element to the global system,
Definition: gsSparseSystem.h:972
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
gsVisitorCDR(const gsFunction< T > &rhs, const gsFunction< T > &coeff_A, const gsFunction< T > &coeff_b, const gsFunction< T > &coeff_c, stabilizerCDR::method flagStabilization=stabilizerCDR::SUPG)
Constructor for gsVisitorCDR, convection-diffusion-reaction.
Definition: gsVisitorCDR.h:78
virtual short_t targetDim() const
Dimension of the target space.
Definition: gsFunctionSet.h:560
static gsQuadRule< T > get(const gsBasis< T > &basis, const gsOptionList &options, short_t fixDir=-1)
Constructs a quadrature rule based on input options.
Definition: gsQuadrature.h:48
T getSUPGParameter(const gsVector< T > &lo, const gsVector< T > &up)
Returns the parameter required for SUPG.
Definition: gsVisitorCDR.h:270
Class which enables iteration over all elements of a parameter domain.
Definition: gsDomainIterator.h:67
gsVisitorCDR(const gsPde< T > &pde)
Constructor.
Definition: gsVisitorCDR.h:45
virtual const gsVector< T > & lowerCorner() const
Returns the lower corner of the current element.
Definition: gsDomainIterator.h:140
A convection-diffusion-reaction PDE, including source term on the right-hand side.
Definition: gsConvDiffRePde.h:35
The density of the measure pull back.
Definition: gsForwardDeclarations.h:76
Visitor for the convection-diffusion-reaction equation.
Definition: gsVisitorCDR.h:38
method
Definition: gsCDRAssembler.h:28
Value of the object.
Definition: gsForwardDeclarations.h:72
index_t askInt(const std::string &label, const index_t &value=0) const
Reads value for option label from options.
Definition: gsOptionList.cpp:117
void initialize(const gsBasis< T > &basis, const index_t, const gsOptionList &options, gsQuadRule< T > &rule)
Initialize.
Definition: gsVisitorCDR.h:92
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
void assemble(gsDomainIterator< T > &element, const gsVector< T > &quWeights)
Assemble.
Definition: gsVisitorCDR.h:140
Gradient transformation matrix.
Definition: gsForwardDeclarations.h:77
Class which holds a list of parameters/options, and provides easy access to them. ...
Definition: gsOptionList.h:32
A basis represents a family of scalar basis functions defined over a common parameter domain...
Definition: gsBasis.h:78
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