FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
burgers_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#include <kernel/global/vector.hpp>
13
14namespace FEAT
15{
16 namespace Assembly
17 {
61 template<typename DataType_, typename IndexType_, int dim_>
63 {
64 public:
66 typedef DataType_ DataType;
67
70
72 DataType_ nu;
73
75 DataType_ theta;
76
78 DataType_ beta;
79
81 DataType_ frechet_beta;
82
84 DataType_ sd_delta;
85
87 DataType_ sd_nu;
88
90 DataType_ sd_v_norm;
91
94 deformation(false),
95 nu(DataType_(1)),
96 theta(DataType_(0)),
97 beta(DataType_(0)),
98 frechet_beta(DataType_(0)),
99 sd_delta(DataType_(0)),
100 sd_nu(DataType_(0)),
101 sd_v_norm(DataType_(0))
102 {
103 }
104
123 template<typename Space_, typename CubatureFactory_>
127 const Space_& space,
128 const CubatureFactory_& cubature_factory,
129 const DataType_ scale = DataType_(1)
130 ) const
131 {
132 // validate matrix and vector dimensions
133 XASSERTM(matrix.rows() == space.get_num_dofs(), "invalid matrix dimensions");
134 XASSERTM(matrix.columns() == space.get_num_dofs(), "invalid matrix dimensions");
135 XASSERTM(convect.size() == space.get_num_dofs(), "invalid vector size");
136
139
140 // tolerance: sqrt(eps)
141 const DataType tol_eps = Math::sqrt(Math::eps<DataType>());
142
143 // first of all, let's see what we have to assemble
144 const bool need_diff = (Math::abs(nu) > DataType(0));
145 const bool need_conv = (Math::abs(beta) > DataType(0));
146 const bool need_conv_frechet = (Math::abs(frechet_beta) > DataType(0));
147 const bool need_reac = (Math::abs(theta) > DataType(0));
148 const bool need_streamdiff = (Math::abs(sd_delta) > DataType(0)) && (sd_v_norm > tol_eps);
149
150 // define our assembly traits
152
153 // fetch our trafo
154 const typename AsmTraits::TrafoType& trafo = space.get_trafo();
155
156 // create a trafo evaluator
157 typename AsmTraits::TrafoEvaluator trafo_eval(trafo);
158
159 // create a space evaluator and evaluation data
160 typename AsmTraits::SpaceEvaluator space_eval(space);
161
162 // create a dof-mapping
163 typename AsmTraits::DofMapping dof_mapping(space);
164
165 // create trafo evaluation data
166 typename AsmTraits::TrafoEvalData trafo_data;
167
168 // create space evaluation data
169 typename AsmTraits::SpaceEvalData space_data;
170
171 // create cubature rule
172 typename AsmTraits::CubatureRuleType cubature_rule(Cubature::ctor_factory, cubature_factory);
173
174 // create matrix scatter-axpy
175 typename MatrixType::ScatterAxpy scatter_matrix(matrix);
176
177 // create convection gather-axpy
178 typename VectorType::GatherAxpy gather_conv(convect);
179
180 // get maximum number of local dofs
181 static constexpr int max_local_dofs = AsmTraits::max_local_test_dofs;
182
183 // create local matrix data
184 typedef Tiny::Matrix<DataType, dim_, dim_> MatrixValue;
186 LocalMatrixType local_matrix;
187
188 // create local vector data
189 typedef Tiny::Vector<DataType, dim_> VectorValue;
190 typedef Tiny::Vector<VectorValue, max_local_dofs> LocalVectorType;
191
192 // local convection field dofs
193 LocalVectorType local_conv_dofs;
194
195 // our local velocity value
196 Tiny::Vector<DataType, dim_> loc_v, mean_v;
197
198 // our local velocity gradient
200
201 loc_v.format();
202 mean_v.format();
203 loc_grad_v.format();
204
205 // compute reference element barycentre
207 for(int i(0); i < dim_; ++i)
208 barycentre[i] = Shape::ReferenceCell<typename Space_::ShapeType>::template centre<DataType>(i);
209
210 // our local streamline diffusion coefficients
212 streamdiff_coeffs.format();
213
214 // our local delta for streamline diffusion
215 DataType local_delta = DataType(0);
216
217 // loop over all cells of the mesh
218 for(typename AsmTraits::CellIterator cell(trafo_eval.begin()); cell != trafo_eval.end(); ++cell)
219 {
220 // prepare trafo evaluator
221 trafo_eval.prepare(cell);
222
223 // prepare space evaluator
224 space_eval.prepare(trafo_eval);
225
226 // initialize dof-mapping
227 dof_mapping.prepare(cell);
228
229 // fetch number of local dofs
230 const int num_loc_dofs = space_eval.get_num_local_dofs();
231
232 // gather our local convection dofs
233 local_conv_dofs.format();
234 gather_conv(local_conv_dofs, dof_mapping);
235
236 // compute mesh width if necessary
237 if(need_streamdiff)
238 {
239 // reset local delta
240 local_delta = DataType(0);
241
242 // evaluate trafo and space at barycentre
243 trafo_eval(trafo_data, barycentre);
244 space_eval(space_data, trafo_data);
245
246 // compute velocity at barycentre
247 mean_v.format();
248 for(int i(0); i < num_loc_dofs; ++i)
249 mean_v.axpy(space_data.phi[i].value, local_conv_dofs[i]);
250
251 // compute norm of mean velocity
252 const DataType local_norm_v = mean_v.norm_euclid();
253
254 // do we have a non-zero velocity?
255 if(local_norm_v > tol_eps)
256 {
257 // compute local mesh width w.r.t. mean velocity
258 const DataType local_h = trafo_eval.width_directed(mean_v) * local_norm_v;
259
260 // compute local Re_T
261 const DataType local_re = (local_norm_v * local_h) / this->sd_nu;
262
263 // compute local delta
264 local_delta = this->sd_delta * (local_h / this->sd_v_norm) * (DataType(2)*local_re) / (DataType(1) + local_re);
265 }
266 }
267
268 // format our local matrix and vector
269 local_matrix.format();
270
271 // loop over all quadrature points and integrate
272 for(int point(0); point < cubature_rule.get_num_points(); ++point)
273 {
274 // compute trafo data
275 trafo_eval(trafo_data, cubature_rule.get_point(point));
276
277 // compute basis function data
278 space_eval(space_data, trafo_data);
279
280 // pre-compute cubature weight
281 const DataType weight = trafo_data.jac_det * cubature_rule.get_weight(point);
282
283 // evaluate convection function and its gradient (if required)
284 if(need_conv || need_streamdiff)
285 {
286 loc_v.format();
287 for(int i(0); i < num_loc_dofs; ++i)
288 {
289 // update velocity value
290 loc_v.axpy(space_data.phi[i].value, local_conv_dofs[i]);
291 }
292 }
293 if(need_conv_frechet)
294 {
295 loc_grad_v.format();
296 for(int i(0); i < num_loc_dofs; ++i)
297 {
298 // update velocity gradient
299 loc_grad_v.add_outer_product(local_conv_dofs[i], space_data.phi[i].grad);
300 }
301 }
302
303 // evaluate streamline diffusion coefficients
304 if(need_streamdiff)
305 {
306 for(int i(0); i < num_loc_dofs; ++i)
307 {
308 streamdiff_coeffs[i] = Tiny::dot(loc_v, space_data.phi[i].grad);
309 }
310 }
311
312 // assemble diffusion matrix?
313 if(need_diff && !deformation)
314 {
315 // assemble gradient-tensor diffusion
316
317 // test function loop
318 for(int i(0); i < num_loc_dofs; ++i)
319 {
320 // trial function loop
321 for(int j(0); j < num_loc_dofs; ++j)
322 {
323 // compute scalar value
324 const DataType value = nu * weight * Tiny::dot(space_data.phi[i].grad, space_data.phi[j].grad);
325
326 // update local matrix
327 local_matrix[i][j].add_scalar_main_diag(value);
328 }
329 }
330 }
331 else if(need_diff && deformation)
332 {
333 // assemble deformation-tensor diffusion
334 // test function loop
335 for(int i(0); i < num_loc_dofs; ++i)
336 {
337 // trial function loop
338 for(int j(0); j < num_loc_dofs; ++j)
339 {
340 // compute inner product of grad(phi) and grad(psi)
341 const DataType value = nu * weight * Tiny::dot(space_data.phi[j].grad, space_data.phi[i].grad);
342
343 // if(point == 1)
344 // printf("i %i j %i val %f\n", i, j, float(value));
345 // update local matrix
346 local_matrix[i][j].add_scalar_main_diag(value);
347
348 // add outer product of grad(phi) and grad(psi)
349 local_matrix[i][j].add_outer_product(space_data.phi[j].grad, space_data.phi[i].grad, nu * weight);
350 }
351 }
352 }
353
354 // assemble convection?
355 if(need_conv)
356 {
357 // test function loop
358 for(int i(0); i < num_loc_dofs; ++i)
359 {
360 // trial function loop
361 for(int j(0); j < num_loc_dofs; ++j)
362 {
363 // compute scalar value
364 const DataType value = beta * weight * space_data.phi[i].value * Tiny::dot(loc_v, space_data.phi[j].grad);
365
366 // update local matrix
367 local_matrix[i][j].add_scalar_main_diag(value);
368 }
369 }
370 }
371
372 // assemble convection Frechet?
373 if(need_conv_frechet)
374 {
375 // test function loop
376 for(int i(0); i < num_loc_dofs; ++i)
377 {
378 // trial function loop
379 for(int j(0); j < num_loc_dofs; ++j)
380 {
381 // compute scalar value
382 const DataType value = frechet_beta * weight * space_data.phi[i].value * space_data.phi[j].value;
383
384 // printf("i %i, j %i, val %f\n", i, j, float(value));
385 // update local matrix
386 local_matrix[i][j].axpy(value, loc_grad_v);
387 }
388 }
389 }
390
391 // assemble reaction?
392 if(need_reac)
393 {
394 // test function loop
395 for(int i(0); i < num_loc_dofs; ++i)
396 {
397 // trial function loop
398 for(int j(0); j < num_loc_dofs; ++j)
399 {
400 // compute scalar value
401 const DataType value = theta * weight * space_data.phi[i].value * space_data.phi[j].value;
402
403 // update local matrix
404 local_matrix[i][j].add_scalar_main_diag(value);
405 }
406 }
407 }
408
409 // assemble streamline diffusion?
410 if(need_streamdiff && (local_delta > tol_eps))
411 {
412 // test function loop
413 for(int i(0); i < num_loc_dofs; ++i)
414 {
415 // trial function loop
416 for(int j(0); j < num_loc_dofs; ++j)
417 {
418 // compute scalar value
419 const DataType value = local_delta * weight * streamdiff_coeffs[i] * streamdiff_coeffs[j];
420
421 // update local matrix
422 local_matrix[i][j].add_scalar_main_diag(value);
423 }
424 }
425 }
426 // continue with next cubature point
427 }
428
429 // scatter into matrix
430 scatter_matrix(local_matrix, dof_mapping, dof_mapping, scale);
431
432 // finish dof mapping
433 dof_mapping.finish();
434
435 // finish evaluators
436 space_eval.finish();
437 trafo_eval.finish();
438 }
439 }
440
459 template<typename Matrix_, typename Space_, typename CubatureFactory_>
461 Matrix_& matrix,
463 const Space_& space,
464 const CubatureFactory_& cubature_factory,
465 const DataType_ scale = DataType_(1)
466 ) const
467 {
468 // validate matrix and vector dimensions
469 XASSERTM(matrix.rows() == space.get_num_dofs(), "invalid matrix dimensions");
470 XASSERTM(matrix.columns() == space.get_num_dofs(), "invalid matrix dimensions");
471 XASSERTM(convect.size() == space.get_num_dofs(), "invalid vector size");
472
474 typedef Matrix_ MatrixType;
475
476 // tolerance: sqrt(eps)
477 const DataType tol_eps = Math::sqrt(Math::eps<DataType>());
478
479 // first of all, let's see what we have to assemble
480 const bool need_diff = (Math::abs(nu) > DataType(0));
481 const bool need_conv = (Math::abs(beta) > DataType(0));
482 const bool need_reac = (Math::abs(theta) > DataType(0));
483 const bool need_streamdiff = (Math::abs(sd_delta) > DataType(0)) && (sd_v_norm > tol_eps);
484
485 // deformation tensor is not available for scalar matrices
486 XASSERTM(!deformation, "deformation tensor is not available for scalar matrices");
487 XASSERTM(frechet_beta == DataType(0), "convection Frechet derivative is not available for scalar matrices");
488
489 // define our assembly traits
491
492 // fetch our trafo
493 const typename AsmTraits::TrafoType& trafo = space.get_trafo();
494
495 // create a trafo evaluator
496 typename AsmTraits::TrafoEvaluator trafo_eval(trafo);
497
498 // create a space evaluator and evaluation data
499 typename AsmTraits::SpaceEvaluator space_eval(space);
500
501 // create a dof-mapping
502 typename AsmTraits::DofMapping dof_mapping(space);
503
504 // create trafo evaluation data
505 typename AsmTraits::TrafoEvalData trafo_data;
506
507 // create space evaluation data
508 typename AsmTraits::SpaceEvalData space_data;
509
510 // create cubature rule
511 typename AsmTraits::CubatureRuleType cubature_rule(Cubature::ctor_factory, cubature_factory);
512
513 // create matrix scatter-axpy
514 typename MatrixType::ScatterAxpy scatter_matrix(matrix);
515
516 // create convection gather-axpy
517 typename VectorType::GatherAxpy gather_conv(convect);
518
519 // get maximum number of local dofs
520 static constexpr int max_local_dofs = AsmTraits::max_local_test_dofs;
521
522 // create local matrix data
523 typedef typename AsmTraits::template TLocalMatrix<DataType> LocalMatrixType;
524 LocalMatrixType local_matrix;
525
526 // create local vector data
527 typedef Tiny::Vector<DataType, dim_> VectorValue;
528 typedef Tiny::Vector<VectorValue, max_local_dofs> LocalVectorType;
529
530 // local convection field dofs
531 LocalVectorType local_conv_dofs;
532
533 // our local velocity value
534 Tiny::Vector<DataType, dim_> loc_v, mean_v;
535 loc_v.format();
536 mean_v.format();
537
538 // compute reference element barycentre
540 for(int i(0); i < dim_; ++i)
541 barycentre[i] = Shape::ReferenceCell<typename Space_::ShapeType>::template centre<DataType>(i);
542
543 // our local streamline diffusion coefficients
545 streamdiff_coeffs.format();
546
547 // our local delta for streamline diffusion
548 DataType local_delta = DataType(0);
549
550 // loop over all cells of the mesh
551 for(typename AsmTraits::CellIterator cell(trafo_eval.begin()); cell != trafo_eval.end(); ++cell)
552 {
553 // prepare trafo evaluator
554 trafo_eval.prepare(cell);
555
556 // prepare space evaluator
557 space_eval.prepare(trafo_eval);
558
559 // initialize dof-mapping
560 dof_mapping.prepare(cell);
561
562 // fetch number of local dofs
563 const int num_loc_dofs = space_eval.get_num_local_dofs();
564
565 // gather our local convection dofs
566 local_conv_dofs.format();
567 gather_conv(local_conv_dofs, dof_mapping);
568
569 // compute mesh width if necessary
570 if(need_streamdiff)
571 {
572 // reset local delta
573 local_delta = DataType(0);
574
575 // evaluate trafo and space at barycentre
576 trafo_eval(trafo_data, barycentre);
577 space_eval(space_data, trafo_data);
578
579 // compute velocity at barycentre
580 mean_v.format();
581 for(int i(0); i < num_loc_dofs; ++i)
582 mean_v.axpy(space_data.phi[i].value, local_conv_dofs[i]);
583
584 // compute norm of mean velocity
585 const DataType local_norm_v = mean_v.norm_euclid();
586
587 // do we have a non-zero velocity?
588 if(local_norm_v > tol_eps)
589 {
590 // compute local mesh width w.r.t. mean velocity
591 const DataType local_h = trafo_eval.width_directed(mean_v) * local_norm_v;
592
593 // compute local Re_T
594 const DataType local_re = (local_norm_v * local_h) / this->sd_nu;
595
596 // compute local delta
597 local_delta = this->sd_delta * (local_h / this->sd_v_norm) * (DataType(2)*local_re) / (DataType(1) + local_re);
598 }
599 }
600
601 // format our local matrix and vector
602 local_matrix.format();
603
604 // loop over all quadrature points and integrate
605 for(int point(0); point < cubature_rule.get_num_points(); ++point)
606 {
607 // compute trafo data
608 trafo_eval(trafo_data, cubature_rule.get_point(point));
609
610 // compute basis function data
611 space_eval(space_data, trafo_data);
612
613 // pre-compute cubature weight
614 const DataType weight = trafo_data.jac_det * cubature_rule.get_weight(point);
615
616 // evaluate convection function and its gradient (if required)
617 if(need_conv || need_streamdiff)
618 {
619 loc_v.format();
620 for(int i(0); i < num_loc_dofs; ++i)
621 {
622 // update velocity value
623 loc_v.axpy(space_data.phi[i].value, local_conv_dofs[i]);
624 }
625 }
626
627 // evaluate streamline diffusion coefficients
628 if(need_streamdiff)
629 {
630 for(int i(0); i < num_loc_dofs; ++i)
631 {
632 streamdiff_coeffs[i] = Tiny::dot(loc_v, space_data.phi[i].grad);
633 }
634 }
635
636 // assemble diffusion?
637 if(need_diff)
638 {
639 // test function loop
640 for(int i(0); i < num_loc_dofs; ++i)
641 {
642 // trial function loop
643 for(int j(0); j < num_loc_dofs; ++j)
644 {
645 local_matrix[i][j] += nu * weight * Tiny::dot(space_data.phi[i].grad, space_data.phi[j].grad);
646 }
647 }
648 }
649
650 // assemble convection?
651 if(need_conv)
652 {
653 // test function loop
654 for(int i(0); i < num_loc_dofs; ++i)
655 {
656 // trial function loop
657 for(int j(0); j < num_loc_dofs; ++j)
658 {
659 local_matrix[i][j] += beta * weight * space_data.phi[i].value * Tiny::dot(loc_v, space_data.phi[j].grad);
660 }
661 }
662 }
663
664 // assemble reaction?
665 if(need_reac)
666 {
667 // test function loop
668 for(int i(0); i < num_loc_dofs; ++i)
669 {
670 // trial function loop
671 for(int j(0); j < num_loc_dofs; ++j)
672 {
673 local_matrix[i][j] += theta * weight * space_data.phi[i].value * space_data.phi[j].value;
674 }
675 }
676 }
677
678 // assemble streamline diffusion?
679 if(need_streamdiff && (local_delta > tol_eps))
680 {
681 // test function loop
682 for(int i(0); i < num_loc_dofs; ++i)
683 {
684 // trial function loop
685 for(int j(0); j < num_loc_dofs; ++j)
686 {
687 local_matrix[i][j] += local_delta * weight * streamdiff_coeffs[i] * streamdiff_coeffs[j];
688 }
689 }
690 }
691
692 // continue with next cubature point
693 }
694
695 // scatter into matrix
696 scatter_matrix(local_matrix, dof_mapping, dof_mapping, scale);
697
698 // finish dof mapping
699 dof_mapping.finish();
700
701 // finish evaluators
702 space_eval.finish();
703 trafo_eval.finish();
704 }
705 }
706
728 template<typename Space_, typename CubatureFactory_>
733 const Space_& space,
734 const CubatureFactory_& cubature_factory,
735 const DataType_ scale = DataType_(1)
736 ) const
737 {
738 // validate matrix and vector dimensions
739 XASSERTM(vector.size() == space.get_num_dofs(), "invalid vector size");
740 XASSERTM(convect.size() == space.get_num_dofs(), "invalid vector size");
741
743
744 // first of all, let's see what we have to assemble
745 const bool need_diff = (Math::abs(nu) > DataType(0));
746 const bool need_conv = (Math::abs(beta) > DataType(0));
747 //const bool need_conv_frechet = (frechet_beta > DataType(0));
748 const bool need_reac = (Math::abs(theta) > DataType(0));
749
750 // define our assembly traits
752
753 // fetch our trafo
754 const typename AsmTraits::TrafoType& trafo = space.get_trafo();
755
756 // create a trafo evaluator
757 typename AsmTraits::TrafoEvaluator trafo_eval(trafo);
758
759 // create a space evaluator and evaluation data
760 typename AsmTraits::SpaceEvaluator space_eval(space);
761
762 // create a dof-mapping
763 typename AsmTraits::DofMapping dof_mapping(space);
764
765 // create trafo evaluation data
766 typename AsmTraits::TrafoEvalData trafo_data;
767
768 // create space evaluation data
769 typename AsmTraits::SpaceEvalData space_data;
770
771 // create cubature rule
772 typename AsmTraits::CubatureRuleType cubature_rule(Cubature::ctor_factory, cubature_factory);
773
774 // create vector-scatter-axpy (if needed)
775 typename VectorType::ScatterAxpy scatter_vector(vector);
776
777 // create convection gather-axpy
778 typename VectorType::GatherAxpy gather_conv(convect);
779
780 // create primal gather-axpy
781 typename VectorType::GatherAxpy gather_prim(primal);
782
783 // get maximum number of local dofs
784 static constexpr int max_local_dofs = AsmTraits::max_local_test_dofs;
785
786 // create local vector data
787 typedef Tiny::Vector<DataType, dim_> VectorValue;
788 typedef Tiny::Vector<VectorValue, max_local_dofs> LocalVectorType;
789 LocalVectorType local_vector;
790
791 // local convection field dofs
792 LocalVectorType local_conv_dofs;
793
794 // local primal vector dofs
795 LocalVectorType local_prim_dofs;
796
797 // our local velocity value
799
800 // our local velocity gradient
801 //Tiny::Matrix<DataType, dim_, dim_> loc_grad_v;
802
803 loc_v.format();
804 //loc_grad_v.format();
805
806 // loop over all cells of the mesh
807 for(typename AsmTraits::CellIterator cell(trafo_eval.begin()); cell != trafo_eval.end(); ++cell)
808 {
809 // prepare trafo evaluator
810 trafo_eval.prepare(cell);
811
812 // prepare space evaluator
813 space_eval.prepare(trafo_eval);
814
815 // initialize dof-mapping
816 dof_mapping.prepare(cell);
817
818 // fetch number of local dofs
819 const int num_loc_dofs = space_eval.get_num_local_dofs();
820
821 // gather our local convection dofs
822 local_conv_dofs.format();
823 gather_conv(local_conv_dofs, dof_mapping);
824
825 // gather our local primal dofs
826 local_prim_dofs.format();
827 gather_prim(local_prim_dofs, dof_mapping);
828
829 // format our local vector
830 local_vector.format();
831
832 // loop over all quadrature points and integrate
833 for(int point(0); point < cubature_rule.get_num_points(); ++point)
834 {
835 // compute trafo data
836 trafo_eval(trafo_data, cubature_rule.get_point(point));
837
838 // compute basis function data
839 space_eval(space_data, trafo_data);
840
841 // pre-compute cubature weight
842 const DataType weight = trafo_data.jac_det * cubature_rule.get_weight(point);
843
844 // evaluate convection function and its gradient (if required)
845 if(need_conv)
846 {
847 loc_v.format();
848 for(int i(0); i < num_loc_dofs; ++i)
849 {
850 // update velocity value
851 loc_v.axpy(space_data.phi[i].value, local_conv_dofs[i]);
852 }
853 }
854 /*if(need_conv_frechet)
855 {
856 loc_grad_v.format();
857 for(int i(0); i < num_loc_dofs; ++i)
858 {
859 // update velocity gradient
860 loc_grad_v.add_outer_product(local_conv_dofs[i], space_data.phi[i].grad);
861 }
862 }*/
863
864 // assemble diffusion matrix?
865 if(need_diff && !deformation)
866 {
867 // assemble gradient-tensor diffusion
868
869 // test function loop
870 for(int i(0); i < num_loc_dofs; ++i)
871 {
872 // trial function loop
873 for(int j(0); j < num_loc_dofs; ++j)
874 {
875 // compute scalar value
876 const DataType value = nu * weight * Tiny::dot(space_data.phi[i].grad, space_data.phi[j].grad);
877
878 // update local vector
879 local_vector[i].axpy(value, local_prim_dofs[j]);
880 }
881 }
882 }
883 else if(need_diff && deformation)
884 {
885 // assemble deformation-tensor diffusion
886
887 // test function loop
888 for(int i(0); i < num_loc_dofs; ++i)
889 {
890 // trial function loop
891 for(int j(0); j < num_loc_dofs; ++j)
892 {
893 // compute inner product of grad(phi) and grad(psi)
894 const DataType value1 = nu * weight * Tiny::dot(space_data.phi[i].grad, space_data.phi[j].grad);
895
896 // compute outer product of grad(phi) and grad(psi)
897 const DataType value2 = nu * weight * Tiny::dot(local_prim_dofs[j], space_data.phi[i].grad);
898
899 // update local vector
900 local_vector[i].axpy(value1, local_prim_dofs[j]);
901 local_vector[i].axpy(value2, space_data.phi[j].grad);
902 }
903 }
904 }
905
906 // assemble convection?
907 if(need_conv)
908 {
909 // test function loop
910 for(int i(0); i < num_loc_dofs; ++i)
911 {
912 // trial function loop
913 for(int j(0); j < num_loc_dofs; ++j)
914 {
915 // compute scalar value
916 const DataType value = beta * weight * space_data.phi[i].value * Tiny::dot(loc_v, space_data.phi[j].grad);
917
918 // update local vector
919 local_vector[i].axpy(value, local_prim_dofs[j]);
920 }
921 }
922 }
923
924 // assemble reaction?
925 if(need_reac)
926 {
927 // test function loop
928 for(int i(0); i < num_loc_dofs; ++i)
929 {
930 // trial function loop
931 for(int j(0); j < num_loc_dofs; ++j)
932 {
933 // compute scalar value
934 const DataType value = theta * weight * space_data.phi[i].value * space_data.phi[j].value;
935
936 // update local vector
937 local_vector[i].axpy(value, local_prim_dofs[j]);
938 }
939 }
940 }
941
942 // continue with next cubature point
943 }
944
945 // scatter into vector
946 scatter_vector(local_vector, dof_mapping, scale);
947
948 // finish dof mapping
949 dof_mapping.finish();
950
951 // finish evaluators
952 space_eval.finish();
953 trafo_eval.finish();
954 }
955 }
956
964 {
965 const auto* vals = convect.elements();
966 DataType_ r = DataType(0);
967 for(Index i(0); i < convect.size(); ++i)
968 r = Math::max(r, vals[i].norm_euclid());
969 this->sd_v_norm = r;
970 }
971
981 template<typename LocalVector_, typename Mirror_>
983 {
984 this->set_sd_v_norm(convect.local());
985 const auto* gate = convect.get_gate();
986 if(gate != nullptr)
987 this->sd_v_norm = gate->max(this->sd_v_norm);
988 }
989 }; // class BurgersAssembler<...>
990 } // namespace Assembly
991} // namespace FEAT
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
Common single-space assembly traits class template.
Definition: asm_traits.hpp:83
Burgers operator assembly class.
void assemble_scalar_matrix(Matrix_ &matrix, const LAFEM::DenseVectorBlocked< DataType_, IndexType_, dim_ > &convect, const Space_ &space, const CubatureFactory_ &cubature_factory, const DataType_ scale=DataType_(1)) const
Assembles the Burgers operator into a scalar matrix.
DataType_ sd_delta
scaling parameter for streamline diffusion stabilization operator S
DataType_ DataType
the datatype we use here
DataType_ frechet_beta
scaling parameter for Frechet derivative of convective operator K'
DataType_ beta
scaling parameter for convective operator K
DataType_ nu
scaling parameter for diffusive operator L (aka viscosity)
void set_sd_v_norm(const LAFEM::DenseVectorBlocked< DataType_, IndexType_, dim_ > &convect)
Sets the convection field norm for the local streamline diffusion parameter delta_T.
void assemble_vector(LAFEM::DenseVectorBlocked< DataType_, IndexType_, dim_ > &vector, const LAFEM::DenseVectorBlocked< DataType_, IndexType_, dim_ > &convect, const LAFEM::DenseVectorBlocked< DataType_, IndexType_, dim_ > &primal, const Space_ &space, const CubatureFactory_ &cubature_factory, const DataType_ scale=DataType_(1)) const
Assembles the Burgers operator into a vector.
DataType_ sd_v_norm
velocity norm for streamline diffusion
void assemble_matrix(LAFEM::SparseMatrixBCSR< DataType_, IndexType_, dim_, dim_ > &matrix, const LAFEM::DenseVectorBlocked< DataType_, IndexType_, dim_ > &convect, const Space_ &space, const CubatureFactory_ &cubature_factory, const DataType_ scale=DataType_(1)) const
Assembles the Burgers operator into a matrix.
DataType_ theta
scaling parameter for reactive operator M
DataType_ sd_nu
viscosity parameter nu_S for streamline diffusion (usually equal to nu)
void set_sd_v_norm(const Global::Vector< LocalVector_, Mirror_ > &convect)
Sets the convection field norm for the streamline diffusion parameter delta_T.
bool deformation
specifies whether to use the deformation tensor
DataType max(DataType x) const
Computes the maximum of a scalar variable over all processes.
Definition: gate.hpp:619
Global vector wrapper class template.
Definition: vector.hpp:68
const GateType * get_gate() const
Returns a const pointer to the internal gate of the vector.
Definition: vector.hpp:148
LocalVector_ & local()
Returns a reference to the internal local LAFEM vector object.
Definition: vector.hpp:121
Blocked Dense data vector class template.
auto elements() const -> const typename Intern::DenseVectorBlockedPerspectiveHelper< DT_, BlockSize_, perspective_ >::Type *
Retrieve a pointer to the data array.
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_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 DataType norm_euclid() const
Computes the euclid norm of this vector.
T_ sqrt(T_ x)
Returns the square-root of a value.
Definition: math.hpp:300
T_ abs(T_ x)
Returns the absolute value.
Definition: math.hpp:275
T_ max(T_ a, T_ b)
Returns the maximum of two values.
Definition: math.hpp:137
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
std::uint64_t Index
Index data type.
Reference cell traits structure.
Definition: shape.hpp:230