G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsVisitorCDR.h
Go to the documentation of this file.
1
14#pragma once
15
16namespace gismo
17{
18
37template <class T>
39{
40public:
41
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
378protected:
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
388protected:
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
399protected:
400 // Local values of the right hand side
401 gsMatrix<T> rhsVals;
402
403protected:
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
A basis represents a family of scalar basis functions defined over a common parameter domain.
Definition gsBasis.h:79
A convection-diffusion-reaction PDE, including source term on the right-hand side.
Definition gsConvDiffRePde.h:36
Class which enables iteration over all elements of a parameter domain.
Definition gsDomainIterator.h:68
virtual const gsVector< T > & lowerCorner() const
Returns the lower corner of the current element.
Definition gsDomainIterator.h:140
short_t dim() const
Return dimension of the elements.
Definition gsDomainIterator.h:115
virtual const gsVector< T > & upperCorner() const
Returns the upper corner of the current element.
Definition gsDomainIterator.h:151
A function from a n-dimensional domain to an m-dimensional image.
Definition gsFunction.h:60
virtual short_t targetDim() const
Dimension of the target space.
Definition gsFunctionSet.h:595
virtual void computeMap(gsMapData< T > &InOut) const
Computes map function data.
Definition gsFunction.hpp:817
Abstract base class representing a geometry map.
Definition gsGeometry.h:93
the gsMapData is a cache of pre-computed function (map) values.
Definition gsFuncData.h:349
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
Class which holds a list of parameters/options, and provides easy access to them.
Definition gsOptionList.h:33
index_t askInt(const std::string &label, const index_t &value=0) const
Reads value for option label from options.
Definition gsOptionList.cpp:117
Abstract class representing a PDE (partial differential equation).
Definition gsPde.h:44
Class representing a reference quadrature rule.
Definition gsQuadRule.h:29
A sparse linear system indexed by sets of degrees of freedom.
Definition gsSparseSystem.h:30
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
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
A vector with arbitrary coefficient type and fixed or dynamic size.
Definition gsVector.h:37
Visitor for the convection-diffusion-reaction equation.
Definition gsVisitorCDR.h:39
gsVisitorCDR(const gsPde< T > &pde)
Constructor.
Definition gsVisitorCDR.h:45
void initialize(const gsBasis< T > &basis, const index_t, const gsOptionList &options, gsQuadRule< T > &rule)
Initialize.
Definition gsVisitorCDR.h:92
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
T getSUPGParameter(const gsVector< T > &lo, const gsVector< T > &up)
Returns the parameter required for SUPG.
Definition gsVisitorCDR.h:270
void assemble(gsDomainIterator< T > &element, const gsVector< T > &quWeights)
Assemble.
Definition gsVisitorCDR.h:140
void evaluate(const gsBasis< T > &basis, const gsGeometry< T > &geo, const gsMatrix< T > &quNodes)
Evaluate on element.
Definition gsVisitorCDR.h:108
#define index_t
Definition gsConfig.h:32
#define GISMO_ERROR(message)
Definition gsDebug.h:118
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
The G+Smo namespace, containing all definitions for the library.
@ NEED_VALUE
Value of the object.
Definition gsForwardDeclarations.h:72
@ NEED_GRAD_TRANSFORM
Gradient transformation matrix.
Definition gsForwardDeclarations.h:77
@ NEED_MEASURE
The density of the measure pull back.
Definition gsForwardDeclarations.h:76
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:51
method
Definition gsCDRAssembler.h:29
@ SUPG
Use SUPG.
Definition gsCDRAssembler.h:30
@ none
Do not use a stabilizer.
Definition gsCDRAssembler.h:31