G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsVisitorNavierStokes.h
Go to the documentation of this file.
1
15#pragma once
16
18#include <gsCore/gsFuncData.h>
19#include <algorithm>
20
22
23namespace gismo
24{
25
26template <class T>
27class gsVisitorNavierStokes
28{
29public:
30
31 gsVisitorNavierStokes(const gsPde<T> & pde_, const gsMultiPatch<T> & velocity_,
32 const gsMultiPatch<T> & pressure_)
33 : dim(), pde_ptr(static_cast<const gsBasePde<T>*>(&pde_)), assemblyType(), patch(),
34 viscosity(), forceScaling(), density(),
35 N_V(), N_P(), velocity(velocity_), pressure(pressure_)
36 {}
37
38 void initialize(const gsBasisRefs<T> & basisRefs,
39 const index_t patchIndex,
40 const gsOptionList & options,
41 gsQuadRule<T> & rule)
42 {
43 GISMO_UNUSED(patchIndex);
44 // parametric dimension of the first displacement component
45 dim = basisRefs.front().dim();
46 // a quadrature rule is defined by the basis for the first velocity component.
47 // the same rule is used for the presure
48 rule = gsQuadrature::get(basisRefs.front(), options);
49 // saving necessary info
50 assemblyType = options.getInt("Assembly");
51 viscosity = options.getReal("Viscosity");
52 density = options.getReal("Density");
53 patch = patchIndex;
54 forceScaling = options.getReal("ForceScaling");
55 // resize containers for global indices
56 globalIndices.resize(dim+1);
57 blockNumbers.resize(dim+1);
58 }
59
60 inline void evaluate(const gsBasisRefs<T> & basisRefs,
61 const gsGeometry<T> & geo,
62 const gsMatrix<T> & quNodes)
63 {
64 // store quadrature points of the element for geometry evaluation
65 md.points = quNodes;
66 // NEED_VALUE to get points in the physical domain for evaluation of the RHS
67 // NEED_MEASURE to get the Jacobian determinant values for integration
68 // NEED_GRAD_TRANSFORM to get the Jacobian matrix to transform gradient from the parametric to physical domain
69 // NEED_2ND_DER to transform hessians to physical domain
71 // Compute image of the quadrature points plus gradient, jacobian and other necessary data
72 geo.computeMap(md);
73 // find local indices of the velocity and pressure basis functions active on the element
74 basisRefs.front().active_into(quNodes.col(0),localIndicesVel);
75 N_V = localIndicesVel.rows();
76 basisRefs.back().active_into(quNodes.col(0), localIndicesPres);
77 N_P = localIndicesPres.rows();
78 // Evaluate velocity basis functions and their derivatives on the element (and hessians, if SUPG is used)
79 basisRefs.front().evalAllDers_into(quNodes,1,basisValuesVel);
80 // Evaluate pressure basis functions on the element
81 basisRefs.back().eval_into(quNodes,basisValuesPres);
82 // Evaluate gradients of pressure basis functions if SUPG is used
83 basisRefs.back().deriv_into(quNodes,basisGradsPres);
84 // Evaluate right-hand side at the image of the quadrature points
85 pde_ptr->rhs()->eval_into(md.values[0],forceValues);
86 // store quadrature points of the element for velocity evaluation
87 mdVelocity.points = quNodes;
88 // NEED_VALUE to compute velocity values
89 // NEED_DERIV to compute velocity gradient
90 // NEED_2ND_DER to compute velocity hessian
91 mdVelocity.flags = NEED_VALUE | NEED_DERIV;
92 // evaluate velocity
93 velocity.patch(patch).computeMap(mdVelocity);
94 // evaluate pressure values; for some reason, pressure evaluation via gsMapData doesn't work
95 pressure.patch(patch).eval_into(quNodes,pressureValues);
96 }
97
98 inline void assemble(gsDomainIterator<T> & element,
99 const gsVector<T> & quWeights)
100 {
101 GISMO_UNUSED(element);
102 if (assemblyType == 0)
103 assembleOseen(element,quWeights);
104 else if (assemblyType == 1)
105 assembleNewtonUpdate(element,quWeights);
106 else if (assemblyType == 2)
107 assembleNewtonFull(element,quWeights);
108 }
109
110 inline void localToGlobal(const int patchIndex,
111 const std::vector<gsMatrix<T> > & eliminatedDofs,
112 gsSparseSystem<T> & system)
113 {
114 // computes global indices for velocity components
115 for (short_t d = 0; d < dim; ++d)
116 {
117 system.mapColIndices(localIndicesVel, patchIndex, globalIndices[d], d);
118 blockNumbers.at(d) = d;
119 }
120 // computes global indices for pressure
121 system.mapColIndices(localIndicesPres, patchIndex, globalIndices[dim], dim);
122 blockNumbers.at(dim) = dim;
123 // push to global system
124 system.pushToRhs(localRhs,globalIndices,blockNumbers);
125 system.pushToMatrix(localMat,globalIndices,eliminatedDofs,blockNumbers,blockNumbers);
126 }
127
128protected:
129
130 void assembleNewtonUpdate(gsDomainIterator<T> & element,
131 const gsVector<T> & quWeights)
132 {
133 GISMO_UNUSED(element);
134 // Initialize local matrix/rhs // A | D
135 localMat.setZero(dim*N_V + N_P, dim*N_V + N_P); // --|-- matrix structure
136 localRhs.setZero(dim*N_V + N_P,1); // B | 0// roughly estimate h - diameter of the element ( for SUPG)
137 // T h = cellSize(element);
138 // Loop over the quadrature nodes
139 for (index_t q = 0; q < quWeights.rows(); ++q)
140 {
141 // Multiply quadrature weight by the geometry measure
142 const T weight = quWeights[q] * md.measure(q);
143 // Compute physical gradients of the velocity basis functions at q as a dim x numActiveFunction matrix
144 transformGradients(md, q, basisValuesVel[1], physGradVel);
145 // Compute physical Jacobian of the current velocity field
146 physJacCurVel = mdVelocity.jacobian(q)*(md.jacobian(q).cramerInverse());
147 // matrix A: diffusion
148 block = weight*density*viscosity * physGradVel.transpose()*physGradVel;
149 for (short_t d = 0; d < dim; ++d)
150 localMat.block(d*N_V,d*N_V,N_V,N_V) += block.block(0,0,N_V,N_V);
151 // matrix A: advection
152 block = weight*basisValuesVel[0].col(q) * (mdVelocity.values[0].col(q).transpose()*physGradVel);
153 for (short_t d = 0; d < dim; ++d)
154 localMat.block(d*N_V,d*N_V,N_V,N_V) += density*block.block(0,0,N_V,N_V);
155 // matrix A: reaction
156 block = weight*density*basisValuesVel[0].col(q) * basisValuesVel[0].col(q).transpose();
157 for (short_t di = 0; di < dim; ++di)
158 for (short_t dj = 0; dj < dim; ++dj)
159 localMat.block(di*N_V,dj*N_V,N_V,N_V) += physJacCurVel(di,dj)*block.block(0,0,N_V,N_V);
160 // matrices B and D
161 for (short_t d = 0; d < dim; ++d)
162 {
163 block = weight*basisValuesPres.col(q)*physGradVel.row(d);
164 localMat.block(dim*N_V,d*N_V,N_P,N_V) -= block.block(0,0,N_P,N_V); // B
165 localMat.block(d*N_V,dim*N_V,N_V,N_P) -= block.transpose().block(0,0,N_V,N_P); // D
166 }
167 // rhs: force
168 for (short_t d = 0; d < dim; ++d)
169 localRhs.middleRows(d*N_V,N_V).noalias() += weight *density* forceScaling *
170 forceValues(d,q) * basisValuesVel[0].col(q);
171 // rhs: residual diffusion
172 for (short_t d = 0; d < dim; ++d)
173 localRhs.middleRows(d*N_V,N_V).noalias() -= weight * viscosity * density*
174 (physJacCurVel.row(d)*physGradVel).transpose();
175 // rhs: residual nonlinear
176 for (short_t d = 0; d < dim; ++d)
177 localRhs.middleRows(d*N_V,N_V).noalias() -= weight * density*
178 (physJacCurVel.row(d) * mdVelocity.values[0].col(q))(0,0) * basisValuesVel[0].col(q);
179 // rhs: residual pressure
180 for (short_t d = 0; d < dim; ++d)
181 localRhs.middleRows(d*N_V,N_V).noalias() += weight *
182 pressureValues.at(q) * physGradVel.row(d).transpose();
183 // rhs: constraint residual
184 localRhs.middleRows(dim*N_V,N_P).noalias() += weight *
185 basisValuesPres.col(q) * physJacCurVel.trace();
186 }
187 }
188
189 void assembleNewtonFull(gsDomainIterator<T> & element,
190 const gsVector<T> & quWeights)
191 {
192 GISMO_UNUSED(element);
193 // Initialize local matrix/rhs // A | D
194 localMat.setZero(dim*N_V + N_P, dim*N_V + N_P); // --|-- matrix structure
195 localRhs.setZero(dim*N_V + N_P,1); // B | 0// roughly estimate h - diameter of the element ( for SUPG)
196 // T h = cellSize(element);
197 // Loop over the quadrature nodes
198 for (index_t q = 0; q < quWeights.rows(); ++q)
199 {
200 // Multiply quadrature weight by the geometry measure
201 const T weight = quWeights[q] * md.measure(q);
202 // Compute physical gradients of the velocity basis functions at q as a dim x numActiveFunction matrix
203 transformGradients(md, q, basisValuesVel[1], physGradVel);
204 // Compute physical Jacobian of the current velocity field
205 physJacCurVel = mdVelocity.jacobian(q)*(md.jacobian(q).cramerInverse());
206 // matrix A: diffusion
207 block = weight*density*viscosity * physGradVel.transpose()*physGradVel;
208 for (short_t d = 0; d < dim; ++d)
209 localMat.block(d*N_V,d*N_V,N_V,N_V) += block.block(0,0,N_V,N_V);
210 // matrix A: advection
211 block = weight*basisValuesVel[0].col(q) * (mdVelocity.values[0].col(q).transpose()*physGradVel);
212 for (short_t d = 0; d < dim; ++d)
213 localMat.block(d*N_V,d*N_V,N_V,N_V) += density*block.block(0,0,N_V,N_V);
214 // matrix A: reaction
215 block = weight*density*basisValuesVel[0].col(q) * basisValuesVel[0].col(q).transpose();
216 for (short_t di = 0; di < dim; ++di)
217 for (short_t dj = 0; dj < dim; ++dj)
218 localMat.block(di*N_V,dj*N_V,N_V,N_V) += physJacCurVel(di,dj)*block.block(0,0,N_V,N_V);
219 // matrices B and D
220 for (short_t d = 0; d < dim; ++d)
221 {
222 block = weight*basisValuesPres.col(q)*physGradVel.row(d);
223 localMat.block(dim*N_V,d*N_V,N_P,N_V) -= block.block(0,0,N_P,N_V); // B
224 localMat.block(d*N_V,dim*N_V,N_V,N_P) -= block.transpose().block(0,0,N_V,N_P); // D
225 }
226 // rhs: force
227 for (short_t d = 0; d < dim; ++d)
228 localRhs.middleRows(d*N_V,N_V).noalias() += weight *density* forceScaling *
229 forceValues(d,q) * basisValuesVel[0].col(q);
230 // rhs: residual nonlinear
231 for (short_t d = 0; d < dim; ++d)
232 localRhs.middleRows(d*N_V,N_V).noalias() += weight * density*
233 (physJacCurVel.row(d) * mdVelocity.values[0].col(q))(0,0) * basisValuesVel[0].col(q);
234 }
235 }
236
237 void assembleOseen(gsDomainIterator<T> & element,
238 const gsVector<T> & quWeights)
239 {
240 GISMO_UNUSED(element);
241 // Initialize local matrix/rhs // A | D
242 localMat.setZero(dim*N_V + N_P, dim*N_V + N_P); // --|-- matrix structure
243 localRhs.setZero(dim*N_V + N_P,1); // B | 0
244
245 // Loop over the quadrature nodes
246 for (index_t q = 0; q < quWeights.rows(); ++q)
247 {
248 // Multiply quadrature weight by the geometry measure
249 const T weight = quWeights[q] * md.measure(q);
250 // Compute physical gradients of the velocity basis functions at q as a dim x numActiveFunction matrix
251 transformGradients(md, q, basisValuesVel[1], physGradVel);
252 // Compute physical Jacobian of the current velocity field
253 physJacCurVel = mdVelocity.jacobian(q)*(md.jacobian(q).cramerInverse());
254 // matrix A: diffusion
255 block = weight*viscosity *density* physGradVel.transpose()*physGradVel;
256 for (short_t d = 0; d < dim; ++d)
257 localMat.block(d*N_V,d*N_V,N_V,N_V) += block.block(0,0,N_V,N_V);
258 // matrix A: advection
259 block = weight*basisValuesVel[0].col(q) *
260 (mdVelocity.values[0].col(q).transpose()*physGradVel);
261 for (short_t d = 0; d < dim; ++d)
262 localMat.block(d*N_V,d*N_V,N_V,N_V) += density*block.block(0,0,N_V,N_V);
263 // matrices B and D
264 for (short_t d = 0; d < dim; ++d)
265 {
266 block = weight*basisValuesPres.col(q)*physGradVel.row(d);
267 localMat.block(dim*N_V,d*N_V,N_P,N_V) -= block.block(0,0,N_P,N_V); // B
268 localMat.block(d*N_V,dim*N_V,N_V,N_P) -= block.transpose().block(0,0,N_V,N_P); // D
269 }
270 // rhs: force
271 for (short_t d = 0; d < dim; ++d)
272 localRhs.middleRows(d*N_V,N_V).noalias() += weight *density* forceScaling *
273 forceValues(d,q) * basisValuesVel[0].col(q);
274 }
275 }
276
277protected:
278 // problem info
279 short_t dim;
280 const gsBasePde<T> * pde_ptr;
281 // switch between assembling different linear systems (Newton or Oseen iterations)
282 index_t assemblyType;
283 index_t patch; // current patch
284 // constants: viscosity and the force scaling factor
285 T viscosity, forceScaling, density;
286 // geometry mapping
287 gsMapData<T> md;
288 // local components of the global linear system
289 gsMatrix<T> localMat;
290 gsMatrix<T> localRhs;
291 // local indices (at the current patch) of basis functions active at the current element
292 gsMatrix<index_t> localIndicesVel;
293 gsMatrix<index_t> localIndicesPres;
294 // number of velocity and pressure basis functions active at the current element
295 index_t N_V, N_P;
296 // values and derivatives of velocity basis functions at quadrature points at the current element
297 // values are stored as a N_V x numQuadPoints matrix; not sure about derivatives, must be smth like N_V*dim x numQuadPoints
298 // if supg is true, also stores the hessian
299 std::vector<gsMatrix<T> > basisValuesVel;
300 // values of pressure basis functions active at the current element;
301 // stores as a N_P x numQuadPoints matrix
302 gsMatrix<T> basisValuesPres;
303 // if supg is true, stores the derivatives
304 gsMatrix<T> basisGradsPres;
305 // RHS values at quadrature points at the current element; stored as a dim x numQuadPoints matrix
306 gsMatrix<T> forceValues;
307 // current displacement field
308 const gsMultiPatch<T> & velocity;
309 // evaluation data of the current velocity field
310 gsMapData<T> mdVelocity;
311 // current pressure field
312 const gsMultiPatch<T> & pressure;
313 // pressure values at the current element; stored as a 1 x numQuadPoints matrix
314 gsMatrix<T> pressureValues;
315 // pressure gradients at the current element (only for supg); stored as a dim x numQuadPoints matrix
316 gsMatrix<T> pressureGrads;
317
318 // all temporary matrices defined here for efficiency
319 gsMatrix<T> block, physGradVel, physJacCurVel;
320 // containers for global indices
321 std::vector< gsMatrix<index_t> > globalIndices;
322 gsVector<index_t> blockNumbers;
323};
324
325} // namespace gismo
IMHO, a useless class, but it is necessary to use the gsAssembler class. Contains proper information ...
#define short_t
Definition gsConfig.h:35
#define index_t
Definition gsConfig.h:32
#define GISMO_UNUSED(x)
Definition gsDebug.h:112
This object is a cache for computed values from an evaluator.
Creates a variety of quadrature rules.
The G+Smo namespace, containing all definitions for the library.
@ NEED_VALUE
Value of the object.
Definition gsForwardDeclarations.h:72
@ NEED_DERIV
Gradient of the object.
Definition gsForwardDeclarations.h:73
@ 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