FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
oldroyd_assembler.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8#include <kernel/assembly/asm_traits.hpp>
9#include <kernel/lafem/dense_vector.hpp>
10#include <kernel/lafem/sparse_matrix_bcsr.hpp>
11#include <kernel/lafem/dense_vector_blocked.hpp>
12
13namespace FEAT
14{
15 namespace Assembly
16 {
37 {
38 public:
66 template<typename DT_, typename IT_, typename SpaceV_, typename SpaceS_, int dim_, int nsc_>
67 static void assemble_matrix(
70 const SpaceV_& space_v,
71 const SpaceS_& space_s,
72 const Cubature::DynamicFactory& cubature_factory,
73 const DT_ lambda,
74 const DT_ gamma = DT_(1),
75 const DT_ zeta = DT_(1)
76 )
77 {
78 // validate matrix and vector dimensions
79 XASSERTM(matrix.rows() == space_s.get_num_dofs(), "invalid matrix dimensions");
80 XASSERTM(matrix.columns() == space_s.get_num_dofs(), "invalid matrix dimensions");
81 XASSERTM(convect.size() == space_v.get_num_dofs(), "invalid vector size");
82
85
86 // define our assembly traits
87 // we will "abuse" the 'trial space' of this assembly space for the velocity space,
88 // the stress space is both the test and the 'real' trial space here
89 typedef AsmTraits2<DT_, SpaceS_, SpaceV_, TrafoTags::jac_det,
91
92 // out datatype
93 typedef typename AsmTraits::DataType DataType;
94
95 // fetch our trafo
96 const typename AsmTraits::TrafoType& trafo = space_s.get_trafo();
97
98 // create a trafo evaluator
99 typename AsmTraits::TrafoEvaluator trafo_eval(trafo);
100
101 // create the space evaluators
102 typename AsmTraits::TestEvaluator space_eval_s(space_s);
103 typename AsmTraits::TrialEvaluator space_eval_v(space_v);
104
105 // create the dof-mappings
106 typename AsmTraits::TestDofMapping dof_mapping_s(space_s);
107 typename AsmTraits::TrialDofMapping dof_mapping_v(space_v);
108
109 // create trafo evaluation data
110 typename AsmTraits::TrafoEvalData trafo_data;
111
112 // create space evaluation data
113 typename AsmTraits::TestEvalData space_data_s;
114 typename AsmTraits::TrialEvalData space_data_v;
115
116 // create cubature rule
117 typename AsmTraits::CubatureRuleType cubature_rule(Cubature::ctor_factory, cubature_factory);
118
119 // create matrix scatter-axpy
120 typename MatrixType::ScatterAxpy scatter_matrix(matrix);
121
122 // create convection gather-axpy
123 typename VectorType::GatherAxpy gather_conv(convect);
124
125 // get maximum number of local dofs
126 static constexpr int max_local_dofs_s = AsmTraits::max_local_test_dofs;
127 static constexpr int max_local_dofs_v = AsmTraits::max_local_trial_dofs;
128
129 // create local matrix data
130 typedef Tiny::Matrix<DataType, nsc_, nsc_> MatrixValue;
132 LocalMatrixType local_matrix;
133
134 // create local vector data
135 typedef Tiny::Vector<DataType, dim_> VectorValue;
136 typedef Tiny::Vector<VectorValue, max_local_dofs_v> LocalVectorType;
137
138 // local convection field dofs
139 LocalVectorType local_conv_dofs;
140
141 // our local velocity value
143
144 // our local velocity gradient
146
147 loc_v.format();
148 loc_grad_v.format();
149
150 // loop over all cells of the mesh
151 for(typename AsmTraits::CellIterator cell(trafo_eval.begin()); cell != trafo_eval.end(); ++cell)
152 {
153 // prepare trafo evaluator
154 trafo_eval.prepare(cell);
155
156 // prepare space evaluator
157 space_eval_s.prepare(trafo_eval);
158 space_eval_v.prepare(trafo_eval);
159
160 // initialize dof-mapping
161 dof_mapping_s.prepare(cell);
162 dof_mapping_v.prepare(cell);
163
164 // fetch number of local dofs
165 const int num_loc_dofs_s = space_eval_s.get_num_local_dofs();
166 const int num_loc_dofs_v = space_eval_v.get_num_local_dofs();
167
168 // gather our local convection dofs
169 local_conv_dofs.format();
170 gather_conv(local_conv_dofs, dof_mapping_v);
171
172 // format our local matrix and vector
173 local_matrix.format();
174
175 // loop over all quadrature points and integrate
176 for(int point(0); point < cubature_rule.get_num_points(); ++point)
177 {
178 // compute trafo data
179 trafo_eval(trafo_data, cubature_rule.get_point(point));
180
181 // compute basis function data
182 space_eval_s(space_data_s, trafo_data);
183 space_eval_v(space_data_v, trafo_data);
184
185 // pre-compute cubature weight
186 const DataType weight = trafo_data.jac_det * cubature_rule.get_weight(point);
187
188 // evaluate convection function and its gradient (if required)
189 loc_v.format();
190 loc_grad_v.format();
191 for(int i(0); i < num_loc_dofs_v; ++i)
192 {
193 loc_v.axpy(space_data_v.phi[i].value, local_conv_dofs[i]);
194 loc_grad_v.add_outer_product(local_conv_dofs[i], space_data_v.phi[i].grad);
195 }
196
197 // test function loop
198 for(int i(0); i < num_loc_dofs_s; ++i)
199 {
200 // trial function loop
201 for(int j(0); j < num_loc_dofs_s; ++j)
202 {
203 // add reactive term 'lambda*sigma'
204 local_matrix[i][j].add_scalar_main_diag(lambda * weight * space_data_s.phi[i].value * space_data_s.phi[j].value);
205
206 // add scalar term 'gamma*v*grad(sigma)' for all components of sigma
207 local_matrix[i][j].add_scalar_main_diag(gamma * weight * space_data_s.phi[i].value * Tiny::dot(loc_v, space_data_s.phi[j].grad));
208
209 // evaluate actual Oldroyd operator
210 core_eval(local_matrix[i][j], loc_grad_v, -zeta * weight * space_data_s.phi[i].value * space_data_s.phi[j].value);
211 }
212 }
213
214 // continue with next cubature point
215 }
216
217 // scatter into matrix
218 scatter_matrix(local_matrix, dof_mapping_s, dof_mapping_s, DataType(1));
219
220 // finish dof mapping
221 dof_mapping_v.finish();
222 dof_mapping_s.finish();
223
224 // finish evaluators
225 space_eval_v.finish();
226 space_eval_s.finish();
227 trafo_eval.finish();
228 }
229 }
230
231 protected:
240 template<typename DT_>
242 {
243 // we have
244 //
245 // X := grad(v) * sigma + sigma * grad(v)^T
246 //
247 // = [ dx(v1) dy(v1) ] * [ sigma_11 sigma_12 ] + [ sigma_11 sigma_12 ] * [ dx(v1) dx(v2) ]
248 // [ dx(v2) dy(v2) ] [ sigma_21 sigma_22 ] [ sigma_21 sigma_22 ] [ dy(v1) dy(v2) ]
249 // \_________________/ \_____________________/ \_____________________/ \_________________/
250 // =: G =: S = S = G^T
251 //
252 // = [ G_11 G_12 ] * [ S_1 S_2 ] + [ S_1 S_2 ] * [ G_11 G_21 ]
253 // [ G_21 G_22 ] [ S_3 S_4 ] [ S_3 S_4 ] [ G_12 G_22 ]
254 //
255 // = [ G_11*S_1 + G_12*S_3 G_11*S_2 + G_12*S_4 ] + [ S_1*G_11 + S_2*G_12 S_1*G_21 + S_2*G_22 ]
256 // [ G_21*S_1 + G_22*S_3 G_21*S_2 + G_22*S_4 ] + [ S_3*G_11 + S_4*G_12 S_3*G_21 + S_4*G_22 ]
257 //
258 // = [ 2*G_11*S_1 + G_12*S_2 + G_12*S_3 G_21*S_1 + (G_11+G_22)*S_2 + G_12*S_4 ]
259 // [ G_21*S_1 + (G_11+G_22)*S_3 + G_12*S_4 G_21*S_2 + G_21*S_3 + 2*G_22*S_4 ]
260 //
261 // = [ X_1 X_2 ]
262 // [ X_3 X_4 ]
263 //
264 // Now re-write definition of X as 4x4 matrix-vector-product of M and S
265 //
266 // [ X_1 ] = [ M_11 M_12 M_13 M_14 ] * [ S_1 ]
267 // [ X_2 ] [ M_21 M_22 M_23 M_24 ] [ S_2 ]
268 // [ X_3 ] [ M_31 M_32 M_33 M_34 ] [ S_3 ]
269 // [ X_4 ] [ M_41 M_42 M_43 M_44 ] [ S_4 ]
270
271 // X_1 = M_1. * S
272 M(0,0) += omega * DT_(2) * G(0,0); // 2 * G_11 * S_1
273 M(0,1) += omega * G(0,1); // G_12 * S_2
274 M(0,2) += omega * G(0,1); // G_12 * S_3
275 //M(0,3) += DT_(0); // 0 * S_4
276
277 // X_2 = M_2. * S
278 M(1,0) += omega * G(1,0); // G_21 * S_1
279 M(1,1) += omega * (G(0,0) + G(1,1)); // (G_11+G_22) * S_2
280 //M(1,2) += DT_(0); // 0 * S_3
281 M(1,3) += omega * G(0,1); // G_12 * S_4
282
283 // X_3 = M_3. * S
284 M(2,0) += omega * G(1,0); // G_21 * S_1
285 //M(2,1) += DT_(0); // 0 * S_2
286 M(2,2) += omega * (G(0,0) + G(1,1)); // (G_11+G_22) * S_3
287 M(2,3) += omega * (G(0,1)); // G_12 * S_4
288
289 // X_4 = M_4. * S
290 //M(3,0) += DT_(0); // 0 * S_1
291 M(3,1) += omega * G(1,0); // G_21 * S_2
292 M(3,2) += omega * G(1,0); // G_21 * S_3
293 M(3,3) += omega * DT_(2) * G(1,1); // 2 * G_22 * S_4
294 }
295
304 template<typename DT_>
306 {
307 // we have
308 //
309 // X := grad(v) * sigma + sigma * grad(v)^T
310 //
311 // = [ dx(v1) dy(v1) ] * [ sigma_11 sigma_12 ] + [ sigma_11 sigma_12 ] * [ dx(v1) dx(v2) ]
312 // [ dx(v2) dy(v2) ] [ sigma_21 sigma_22 ] [ sigma_21 sigma_22 ] [ dy(v1) dy(v2) ]
313 // \_________________/ \_____________________/ \_____________________/ \_________________/
314 // =: G =: S = S = G^T
315 //
316 // = [ G_11 G_12 ] * [ S_1 S_3 ] + [ S_1 S_3 ] * [ G_11 G_21 ]
317 // [ G_21 G_22 ] [ S_3 S_2 ] [ S_3 S_2 ] [ G_12 G_22 ]
318 //
319 // At this point we exploit the symmetry of sigma, i.e. we have S_3 := sigma_12 = sigma_21, then:
320 //
321 // = [ G_11*S_1 + G_12*S_3 G_11*S_3 + G_12*S_2 ] + [ S_1*G_11 + S_3*G_12 S_1*G_21 + S_3*G_22 ]
322 // [ G_21*S_1 + G_22*S_3 G_21*S_3 + G_22*S_2 ] + [ S_3*G_11 + S_2*G_12 S_3*G_21 + S_2*G_22 ]
323 //
324 // = [ 2*G_11*S_1 + 2*G_12*S_3 G_21*S_1 + G_12*S_2 + (G_11+G_22)*S_3 ]
325 // [ G_21*S_1 + G_12*S_2 + (G_11+G_22)*S_3 2*G_22*S_2 + 2*G_21*S_3 ]
326 //
327 // = [ X_1 X_3 ]
328 // [ X_3 X_2 ]
329 //
330 // At this point, we exploit the symmetry of X and it as 3x3 matrix-vector-product of M and S
331 //
332 // [ X_1 ] = [ M_11 M_12 M_13 ] * [ S_1 ]
333 // [ X_2 ] [ M_21 M_22 M_23 ] [ S_3 ]
334 // [ X_3 ] [ M_31 M_32 M_33 ] [ S_3 ]
335
336 // X_1 = M_1. * S
337 M(0,0) += omega * DT_(2) * G(0,0); // 2 * G_11 * S_1
338 //M(0,1) += DT_(0); // 0 * S_2
339 M(0,2) += omega * DT_(2) * G(0,1); // 2 * G_12 * S_3
340
341 // X_2 = M_2. * S
342 //M(1,0) += DT_(0); // 0 * S_1
343 M(1,1) += omega * DT_(2) * G(1,1); // 2 * G_22 * S_2
344 M(1,2) += omega * DT_(2) * G(1,0); // 2 * G_21 * S_3
345
346 // X_2 = M_2. * S
347 M(2,0) += omega * G(1,0); // G_21 * S_1
348 M(2,1) += omega * G(0,1); // G_12 * S_2
349 M(2,2) += omega * (G(0,0) + G(1,1)); // (G_11+G_22) * S_3
350 }
351 }; // class OldroydAssembler
352 } // namespace Assembly
353} // namespace FEAT
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
Common test-/trial-space assembly traits class template.
Definition: asm_traits.hpp:227
Oldroyd-B operator assembly class.
static void core_eval(Tiny::Matrix< DT_, 3, 3, 3, 3 > &M, const Tiny::Matrix< DT_, 2, 2, 2, 2 > &G, const DT_ omega)
Auxiliary evaluation function: symmetric 2D version.
static void assemble_matrix(LAFEM::SparseMatrixBCSR< DT_, IT_, nsc_, nsc_ > &matrix, const LAFEM::DenseVectorBlocked< DT_, IT_, dim_ > &convect, const SpaceV_ &space_v, const SpaceS_ &space_s, const Cubature::DynamicFactory &cubature_factory, const DT_ lambda, const DT_ gamma=DT_(1), const DT_ zeta=DT_(1))
Assembles the Oldroyd operator onto a stress matrix.
static void core_eval(Tiny::Matrix< DT_, 4, 4, 4, 4 > &M, const Tiny::Matrix< DT_, 2, 2, 2, 2 > &G, const DT_ omega)
Auxiliary evaluation function: unsymmetric 2D version.
Blocked Dense data vector class template.
Index size() const
The number of elements.
CSR based blocked sparse matrix.
Index rows() const
Retrieve matrix row count.
Index columns() const
Retrieve matrix column count.
Tiny Matrix class template.
CUDA_HOST_DEVICE Matrix & add_scalar_main_diag(DataType alpha)
Adds a value onto the matrix's main diagonal.
CUDA_HOST_DEVICE Matrix & add_outer_product(const Vector< T_, m_, snx_ > &x, const Vector< T_, n_, sny_ > &y, const DataType alpha=DataType(1))
Adds the outer product of two vectors onto the matrix.
CUDA_HOST_DEVICE void format(DataType alpha=DataType(0))
Formats the matrix.
Tiny Vector class template.
CUDA_HOST_DEVICE void format(DataType alpha=DataType(0))
Formats the vector.
CUDA_HOST_DEVICE Vector & axpy(DataType alpha, const Vector< T_, n_, snx_ > &x)
Adds another scaled vector onto this vector.
CUDA_HOST_DEVICE T_ dot(const T_ &a, const T_ &b)
Computes the dot-product of two scalars.
FEAT namespace.
Definition: adjactor.hpp:12
@ value
specifies whether the space should supply basis function values
@ grad
specifies whether the space should supply basis function gradients
@ jac_det
specifies whether the trafo should supply jacobian determinants