ug4
Loading...
Searching...
No Matches
conv_shape.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011-2015: G-CSC, Goethe University Frankfurt
3 * Author: Andreas Vogel
4 *
5 * This file is part of UG4.
6 *
7 * UG4 is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License version 3 (as published by the
9 * Free Software Foundation) with the following additional attribution
10 * requirements (according to LGPL/GPL v3 §7):
11 *
12 * (1) The following notice must be displayed in the Appropriate Legal Notices
13 * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 *
15 * (2) The following notice must be displayed at a prominent place in the
16 * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 *
18 * (3) The following bibliography is recommended for citation and must be
19 * preserved in all covered files:
20 * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 * parallel geometric multigrid solver on hierarchically distributed grids.
22 * Computing and visualization in science 16, 4 (2013), 151-164"
23 * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 * flexible software system for simulating pde based models on high performance
25 * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU Lesser General Public License for more details.
31 */
32
33#ifndef __H__UG__LIB_DISC__SPATIAL_DISC__ELEM_DISC__DENSITY_DRIVEN_FLOW__FV1__CONV_SHAPE__
34#define __H__UG__LIB_DISC__SPATIAL_DISC__ELEM_DISC__DENSITY_DRIVEN_FLOW__FV1__CONV_SHAPE__
35
36#include <boost/mpl/range_c.hpp>
37#include <boost/mpl/for_each.hpp>
38
39// ug4 headers
43
44namespace ug{
45
47// No Upwind
49
50template <int TDim>
52 : public IConvectionShapes<TDim>
53{
54 public:
57
60
62 static const int dim = TDim;
63
64 protected:
65 // explicitly forward some function
68 using base_type::D_vel;
72
73 public:
76 {
77 // the shapes do not depend on the DiffDisp. Thus, we can set the
78 // derivative to be always zero w.r.t. the DiffDisp for all shapes
80
81 // register evaluation function
82 boost::mpl::for_each<typename domain_traits<dim>::AllElemList>(RegisterElemFunc(this));
83 boost::mpl::for_each< boost::mpl::range_c<int, 1, dim+1> >(RegisterRefDimFunc(this));
84 }
85
87 template <typename TFVGeom>
88 bool update(const TFVGeom* geo,
89 const MathVector<dim>* Velocity,
90 const MathMatrix<dim, dim>* DiffDisp,
91 bool computeDeriv);
92
93 private:
94
97 {
99 RegisterElemFunc(this_type * pThis) : m_pThis(pThis) {}
100 template<typename TElem> void operator() (TElem &)
101 {
102 m_pThis->template register_func_for_elem_fvgeom< TElem, FV1Geometry<TElem, dim> >();
103 m_pThis->template register_func_for_elem_fvgeom< TElem, FV1CondensedGeometry<TElem, dim> >();
104 m_pThis->template register_func_for_elem_fvgeom< TElem, HFV1Geometry<TElem, dim> >();
105 }
106 };
107
109 template <typename TElem, typename TFVGeom>
111 {
112 typedef bool (this_type::*TFunc) (const TFVGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
113 base_type::template register_update_func<TFVGeom, TFunc>(&this_type::template update<TFVGeom>);
114 }
115
118 {
121 template<typename TRefDim> void operator() (TRefDim &) {m_pThis->register_func_for_refDim<TRefDim::value> ();}
122 };
123
125 template <int refDim>
127 {
128 typedef DimFV1Geometry<refDim, dim> TGeom;
129 typedef bool (this_type::*TFunc) (const TGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
130 base_type::template register_update_func<TGeom, TFunc>(&this_type::template update<TGeom>);
131 }
132};
133
134template <int TDim>
135template <typename TFVGeom>
136bool
138update(const TFVGeom* geo,
139 const MathVector<dim>* Velocity,
140 const MathMatrix<dim, dim>* DiffDisp,
141 bool computeDeriv)
142{
143 UG_ASSERT(geo != nullptr, "Null pointer");
144 UG_ASSERT(Velocity != nullptr, "Null pointer");
145
146// \todo: think about: this should be something like scvf.num_sh()
147 const size_t numSH = geo->num_sh();
148
149// loop subcontrol volume faces
150 for(size_t ip = 0; ip < geo->num_scvf(); ++ip)
151 {
152 // get subcontrol volume face
153 const typename TFVGeom::SCVF& scvf = geo->scvf(ip);
154
155 // Compute flux
156 const number flux = VecDot(scvf.normal(), Velocity[ip]);
157
158 // Write Shapes
159 for(size_t sh = 0; sh < scvf.num_sh(); sh++)
160 conv_shape(ip, sh) = flux * scvf.shape(sh);
161
162 // this is introduced here, hopefully temporarily: The problem is, that
163 // for hanging nodes the number of shape function is not the number of
164 // corners, but scvf.num_sh() currently returns the number of corners.
165 // this is actually enough to interpolate the function, but still we
166 // should reset the interpolation adding for hanging dofs to zero
167 for(size_t sh = scvf.num_sh(); sh < numSH; sh++)
168 conv_shape(ip, sh) = 0.0;
169
170 // Write Derivatives if wanted
171 if(computeDeriv){
172 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
173 VecScale(D_vel(ip, sh), scvf.normal(), scvf.shape(sh));
174
175 // temporary, see above
176 for(size_t sh = scvf.num_sh(); sh < numSH; sh++)
177 VecSet(D_vel(ip, sh), 0.0);
178 }
179
180 // The shapes do not depend of the diffusion tensor
181 }
182
183// we're done
184 return true;
185}
186
188// Full Upwind
190
191template <int TDim>
193 : public IConvectionShapes<TDim>
194{
195 public:
198
201
203 static const int dim = TDim;
204
205 protected:
206 // explicitly forward some function
209 using base_type::D_vel;
213
214 public:
217 {
218 // the shapes do not depend on the DiffDisp. Thus, we can set the
219 // derivative to be always zero w.r.t. the DiffDisp for all shapes
221
222 // register evaluation function
223 boost::mpl::for_each<typename domain_traits<dim>::AllElemList>(RegisterElemFunc(this));
224 boost::mpl::for_each< boost::mpl::range_c<int, 1, dim+1> >(RegisterRefDimFunc(this));
225 }
226
228 template <typename TFVGeom>
229 bool update(const TFVGeom* geo,
230 const MathVector<dim>* Velocity,
231 const MathMatrix<dim, dim>* DiffDisp,
232 bool computeDeriv);
233
234 private:
235
238 {
240 RegisterElemFunc(this_type * pThis) : m_pThis(pThis) {}
241 template<typename TElem> void operator() (TElem &)
242 {
243 m_pThis->template register_func_for_elem_fvgeom< TElem, FV1Geometry<TElem, dim> >();
244 m_pThis->template register_func_for_elem_fvgeom< TElem, FV1CondensedGeometry<TElem, dim> >();
245 m_pThis->template register_func_for_elem_fvgeom< TElem, HFV1Geometry<TElem, dim> >();
246 }
247 };
248
250 template <typename TElem, typename TFVGeom>
252 {
253 typedef bool (this_type::*TFunc) (const TFVGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
254 base_type::template register_update_func<TFVGeom, TFunc>(&this_type::template update<TFVGeom>);
255 }
256
259 {
262 template<typename TRefDim> void operator() (TRefDim &) {m_pThis->register_func_for_refDim<TRefDim::value> ();}
263 };
264
266 template <int refDim>
268 {
269 typedef DimFV1Geometry<refDim, dim> TGeom;
270 typedef bool (this_type::*TFunc) (const TGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
271 base_type::template register_update_func<TGeom, TFunc>(&this_type::template update<TGeom>);
272 }
273};
274
275template <int TDim>
276template <typename TFVGeom>
278update(const TFVGeom* geo,
279 const MathVector<dim>* Velocity,
280 const MathMatrix<dim, dim>* DiffDisp,
281 bool computeDeriv)
282{
283 UG_ASSERT(geo != nullptr, "Null pointer");
284 UG_ASSERT(Velocity != nullptr, "Null pointer");
285
286// \todo: think about: this should be something like scvf.num_sh()
287 const size_t numSH = geo->num_sh();
288
289// loop subcontrol volume faces
290 for(size_t ip = 0; ip < geo->num_scvf(); ++ip)
291 {
292 // get subcontrol volume face
293 const typename TFVGeom::SCVF& scvf = geo->scvf(ip);
294
295 // Compute flux
296 const number flux = VecDot(scvf.normal(), Velocity[ip]);
297
298 size_t from = scvf.from();
299 size_t to = scvf.to();
300
301 // if e.g. hanging nodes are involved, no upwind can be performed...
302 if((from >= scvf.num_sh()) || (to >= scvf.num_sh())){
303 // No upwind...
304 // Write Shapes
305 for(size_t sh = 0; sh < scvf.num_sh(); sh++)
306 conv_shape(ip, sh) = flux * scvf.shape(sh);
307
308 UG_ASSERT(scvf.num_sh() == numSH, "sh's have to match!");
309
310 // Write Derivatives if wanted
311 if(computeDeriv){
312 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
313 VecScale(D_vel(ip, sh), scvf.normal(), scvf.shape(sh));
314 }
315
316 continue;
317 }
318
319 // Full upwind below...
320 // Choose Upwind corner
321 size_t up = (flux >= 0) ? from : to;
322
323 // Write Shapes
324 for(size_t sh = 0; sh < scvf.num_sh(); ++sh) conv_shape(ip, sh) = 0.0;
325
326 conv_shape(ip, up) = flux;
327
328 // Write Derivatives if wanted
329 if(computeDeriv)
330 {
331 for(size_t sh = 0; sh < numSH; ++sh) VecSet(D_vel(ip, sh), 0.0);
332 D_vel(ip, up) = scvf.normal();
333 }
334
335 // The shapes do not depend of the diffusion tensor
336 }
337
338// we're done
339 return true;
340}
341
343// Weighted Upwind
345
346template <int TDim>
348 : public IConvectionShapes<TDim>
349{
350 public:
353
356
358 static const int dim = TDim;
359
360 protected:
361 // explicitly forward some function
364 using base_type::D_vel;
368
369 public:
372 {
373 // the shapes do not depend on the DiffDisp. Thus, we can set the
374 // derivative to be always zero w.r.t. the DiffDisp for all shapes
376
377 // register evaluation function
378 boost::mpl::for_each<typename domain_traits<dim>::AllElemList>(RegisterElemFunc(this));
379 boost::mpl::for_each< boost::mpl::range_c<int, 1, dim+1> >(RegisterRefDimFunc(this));
380 }
381
384 {
385 set_weight(weight);
386
387 // the shapes do not depend on the DiffDisp. Thus, we can set the
388 // derivative to be always zero w.r.t. the DiffDisp for all shapes
390
391 // register evaluation function
392 boost::mpl::for_each<typename domain_traits<dim>::AllElemList>(RegisterElemFunc(this));
393 boost::mpl::for_each< boost::mpl::range_c<int, 1, dim+1> >(RegisterRefDimFunc(this));
394 }
395
397 void set_weight(number weight) {m_weight = weight;}
398
400 template <typename TFVGeom>
401 bool update(const TFVGeom* geo,
402 const MathVector<dim>* Velocity,
403 const MathMatrix<dim, dim>* DiffDisp,
404 bool computeDeriv);
405
406 private:
407 // weight between no and full upwind (1.0 -> full upwind, 0.0 -> no upwind)
409
410 private:
411
414 {
416 RegisterElemFunc(this_type * pThis) : m_pThis(pThis) {}
417 template<typename TElem> void operator() (TElem &)
418 {
419 m_pThis->template register_func_for_elem_fvgeom< TElem, FV1Geometry<TElem, dim> >();
420 m_pThis->template register_func_for_elem_fvgeom< TElem, FV1CondensedGeometry<TElem, dim> >();
421 m_pThis->template register_func_for_elem_fvgeom< TElem, HFV1Geometry<TElem, dim> >();
422 }
423 };
424
426 template <typename TElem, typename TFVGeom>
428 {
429 typedef bool (this_type::*TFunc) (const TFVGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
430 base_type::template register_update_func<TFVGeom, TFunc>(&this_type::template update<TFVGeom>);
431 }
432
435 {
438 template<typename TRefDim> void operator() (TRefDim &) {m_pThis->register_func_for_refDim<TRefDim::value> ();}
439 };
440
442 template <int refDim>
444 {
445 typedef DimFV1Geometry<refDim, dim> TGeom;
446 typedef bool (this_type::*TFunc) (const TGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
447 base_type::template register_update_func<TGeom, TFunc>(&this_type::template update<TGeom>);
448 }
449};
450
451template <int TDim>
452template <typename TFVGeom>
454update(const TFVGeom* geo,
455 const MathVector<dim>* Velocity,
456 const MathMatrix<dim, dim>* DiffDisp,
457 bool computeDeriv)
458{
459 UG_ASSERT(geo != nullptr, "Null pointer");
460 UG_ASSERT(Velocity != nullptr, "Null pointer");
461
462// \todo: think about: this should be something like scvf.num_sh()
463 const size_t numSH = geo->num_sh();
464
465// loop subcontrol volume faces
466 for(size_t ip = 0; ip < geo->num_scvf(); ++ip)
467 {
468 // get subcontrol volume face
469 const typename TFVGeom::SCVF& scvf = geo->scvf(ip);
470
471 // Compute flux
472 const number flux = VecDot(scvf.normal(), Velocity[ip]);
473
474 size_t from = scvf.from();
475 size_t to = scvf.to();
476
477 // if e.g. hanging nodes are involved, no upwind can be performed...
478 if((from >= scvf.num_sh()) || (to >= scvf.num_sh())){
479 // No upwind...
480 // Write Shapes
481 for(size_t sh = 0; sh < scvf.num_sh(); sh++)
482 conv_shape(ip, sh) = flux * scvf.shape(sh);
483
484 UG_ASSERT(scvf.num_sh() == numSH, "sh's have to match!");
485
486 // Write Derivatives if wanted
487 if(computeDeriv){
488 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
489 VecScale(D_vel(ip, sh), scvf.normal(), scvf.shape(sh));
490 }
491
492 continue;
493 }
494
495 // Choose Upwind corner
496 size_t up = (flux >= 0) ? from : to;
497
498 // write no upwind part of shapes
499 const number noUpFlux = (1.-m_weight)*flux;
500 for(size_t sh = 0; sh < scvf.num_sh(); ++sh)
501 conv_shape(ip, sh) = noUpFlux * scvf.shape(sh);
502
503 // add full upwind part of shapes
504 conv_shape(ip, up) += m_weight * flux;
505
506 // Write Derivatives if wanted
507 if(computeDeriv)
508 {
509 // write no upwind part of derivatives
510 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
511 VecScale(D_vel(ip, sh), scvf.normal(),
512 (1.-m_weight)*scvf.shape(sh));
513 // see comment above
514 for(size_t sh = scvf.num_sh(); sh < numSH; sh++)
515 VecSet(D_vel(ip, sh), 0.0);
516
517 // add full upwind part of derivatives
518 VecScaleAppend(D_vel(ip, up), m_weight, scvf.normal());
519 }
520
521 // The shapes do not depend of the diffusion tensor
522 }
523
524// we're done
525 return true;
526}
527
528
530// Partial Upwind
532
533template <int TDim>
535 : public IConvectionShapes<TDim>
536{
537 public:
540
543
545 static const int dim = TDim;
546
547 protected:
548 // explicitly forward some function
551 using base_type::D_vel;
555
556 public:
559 {
560 // register evaluation function
561 boost::mpl::for_each<typename domain_traits<dim>::AllElemList>(RegisterElemFunc(this));
562 boost::mpl::for_each< boost::mpl::range_c<int, 1, dim+1> >(RegisterRefDimFunc(this));
563 }
564
566 template <typename TFVGeom>
567 bool update(const TFVGeom* geo,
568 const MathVector<dim>* Velocity,
569 const MathMatrix<dim, dim>* DiffDisp,
570 bool computeDeriv);
571
572 private:
573
576 {
578 RegisterElemFunc(this_type * pThis) : m_pThis(pThis) {}
579 template<typename TElem> void operator() (TElem &)
580 {
581 m_pThis->template register_func_for_elem_fvgeom< TElem, FV1Geometry<TElem, dim> >();
582 m_pThis->template register_func_for_elem_fvgeom< TElem, FV1CondensedGeometry<TElem, dim> >();
583 }
584 };
585
587 template <typename TElem, typename TFVGeom>
589 {
590 typedef bool (this_type::*TFunc) (const TFVGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
591 base_type::template register_update_func<TFVGeom, TFunc>(&this_type::template update<TFVGeom>);
592 }
593
596 {
599 template<typename TRefDim> void operator() (TRefDim &) {m_pThis->register_func_for_refDim<TRefDim::value> ();}
600 };
601
603 template <int refDim>
605 {
606 typedef DimFV1Geometry<refDim, dim> TGeom;
607 typedef bool (this_type::*TFunc) (const TGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
608 base_type::template register_update_func<TGeom, TFunc>(&this_type::template update<TGeom>);
609 }
610};
611
612template <int TDim>
613template <typename TFVGeom>
614bool
616update(const TFVGeom* geo,
617 const MathVector<dim>* Velocity,
618 const MathMatrix<dim, dim>* DiffDisp,
619 bool computeDeriv)
620{
621 UG_ASSERT(geo != nullptr, "Null pointer");
622 UG_ASSERT(Velocity != nullptr, "Null pointer");
623// UG_ASSERT(DiffDisp != nullptr, "Null pointer");
624
625// Compute Volume of Element
626// typedef typename TFVGeom::ref_elem_type ref_elem_type;
627 const number vol = ElementSize<dim>(geo->roid(), geo->corners());
628
629// loop subcontrol volume faces
630 for(size_t i = 0; i < geo->num_scvf(); ++i)
631 {
632 // get subcontrol volume face
633 const typename TFVGeom::SCVF& scvf = geo->scvf(i);
634
635 // get corners
636 const size_t from = scvf.from();
637 const size_t to = scvf.to();
638
639 // get gradients
640 const MathVector<dim>& gradTo = scvf.global_grad(to);
641 const MathVector<dim>& gradFrom = scvf.global_grad(from);
642
643 // set lambda negative as default
644 number lambda = -1;
645
646 // if DiffDisp-Tensor passed, compute lambda
647 if(DiffDisp != nullptr)
648 {
649 // Get Gradients
650 MathVector<dim> DiffGrad;
651
652 // Compute DiffGrad = D * Grad Phi_to
653 MatVecMult(DiffGrad, DiffDisp[i], gradTo);
654
655 // Compute GradDiffGrad = < Grad Phi_from, DiffGrad >
656 const number GradDiffGrad = VecDot(DiffGrad, gradFrom);
657
658 // Set lambda
659 lambda = - GradDiffGrad * vol;
660 }
661
662 // Compute flux
663 const number flux = VecDot(scvf.normal(), Velocity[i]);
664
665 // reset values
666 for (size_t sh = 0; sh < scvf.num_sh(); ++sh)
667 conv_shape(i, sh) = 0.0;
668 if (computeDeriv)
669 for (size_t sh = 0; sh < scvf.num_sh(); ++sh) {
670 VecSet(D_vel(i, sh), 0.0);
671 MatSet(conv_shape_diffusion(i, sh), 0.0);
672 }
673
674
675 // check: Currently hanging nodes not supported.
676 // /todo: add support for hanging nodes
677 if (from >= scvf.num_sh() || to >= scvf.num_sh())
678 UG_THROW("PartialUpwind: Currently not implemented for hanging nodes.")
679
680
681 // Case 1:
682 // full upwind is used
684 if(lambda <= 0 || DiffDisp == nullptr)
685 {
686 // Choose Upwind corner
687 const size_t up = (flux >= 0) ? scvf.from() : scvf.to();
688
689 // Write Shapes
690 conv_shape(i, up) = flux;
691
692 // Write Derivatives if wanted
693 if(computeDeriv)
694 {
695 // set derivative
696 D_vel(i, up) = scvf.normal();
697
698 // does not depend on diffusion
699 set_non_zero_deriv_diffusion_flag(false);
700 }
701
702 // everything done
703 continue;
704 }
705
707 // Case 2:
708 // The case of the diffusion dominance (central differences)
710 if (2 * lambda > fabs(flux))
711 {
712 conv_shape(i, from) = flux / 2.0;
713 conv_shape(i, to) = flux / 2.0;
714
715 if(computeDeriv)
716 {
717 set_non_zero_deriv_diffusion_flag(false);
718
719 VecScale(D_vel(i,from), scvf.normal(), 1.0/2.0);
720 VecScale(D_vel(i, to), scvf.normal(), 1.0/2.0);
721 }
722
723 // everything done
724 continue;
725 }
726
728 // Case 3:
729 // The cases of the convection dominance
731 set_non_zero_deriv_diffusion_flag(true);
732 if (flux >= 0)
733 {
734 conv_shape(i, from) = flux - lambda;
735 conv_shape(i, to) = lambda;
736
737 if(computeDeriv)
738 D_vel(i,from) = scvf.normal();
739 }
740 else
741 {
742 conv_shape(i, from) = - lambda;
743 conv_shape(i, to) = flux + lambda;
744
745 if(computeDeriv)
746 D_vel(i,to) = scvf.normal();
747 }
748
749 if (computeDeriv)
750 {
751 for (size_t k = 0; k < (size_t)dim; k++)
752 for (size_t l = 0; l < (size_t)dim; l++)
753 {
754 conv_shape_diffusion(i, from)(k,l) = gradFrom[k]*gradTo[l]*vol;
755 conv_shape_diffusion(i, to)(k,l) = - gradFrom[k]*gradTo[l]*vol;
756 }
757 }
758 }
759
760// we're done
761 return true;
762}
763
765// Skewed Upwind
767
768template <int TDim>
770 : public IConvectionShapes<TDim>
771{
772public:
775
778
780 static const int dim = TDim;
781
782protected:
783 // explicitly forward some function
786 using base_type::D_vel;
790
791public:
794 {
795 // the shapes do not depend on the DiffDisp. Thus, we can set the
796 // derivative to be always zero w.r.t. the DiffDisp for all shapes
798
799 // register evaluation function
800 boost::mpl::for_each<typename domain_traits<dim>::AllElemList>(RegisterElemFunc(this));
801 boost::mpl::for_each<boost::mpl::range_c<int, 1, dim + 1>>(RegisterRefDimFunc(this));
802 }
803
805 template <typename TFVGeom>
806 bool update(const TFVGeom *geo,
807 const MathVector<dim> *Velocity,
808 const MathMatrix<dim, dim> *DiffDisp,
809 bool computeDeriv);
810
811private:
814 {
817 template <typename TElem>
818 void operator()(TElem &)
819 {
820 m_pThis->template register_func_for_elem_fvgeom<TElem, FV1Geometry<TElem, dim>>();
821 //m_pThis->template register_func_for_elem_fvgeom< TElem, FV1CondensedGeometry<TElem, dim> >();
822 //m_pThis->template register_func_for_elem_fvgeom< TElem, HFV1Geometry<TElem, dim> >();
823 }
824 };
825
827 template <typename TElem, typename TFVGeom>
829 {
830 typedef bool (this_type::*TFunc)(const TFVGeom *, const MathVector<dim> *, const MathMatrix<dim, dim> *, bool);
831 base_type::template register_update_func<TFVGeom, TFunc>(&this_type::template update<TFVGeom>);
832 }
833
836 {
839 template <typename TRefDim>
840 void operator()(TRefDim &) { m_pThis->register_func_for_refDim<TRefDim::value>(); }
841 };
842
844 template <int refDim>
846 {
847 //typedef DimFV1Geometry<refDim, dim> TGeom;
848 //typedef bool (this_type::*TFunc) (const TGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
849 //base_type::template register_update_func<TGeom, TFunc>(&this_type::template update<TGeom>);
850 }
851};
852
854template <typename TRefElem, int TWorldDim>
855void GetNodeNextToCut(size_t &coOut,
856 const MathVector<TWorldDim> &IP,
857 const MathVector<TWorldDim> &IPVel,
858 const MathVector<TWorldDim> *vCornerCoords)
859{
860 // help variables
861 size_t side = 0;
862 MathVector<TWorldDim> globalIntersection;
863 MathVector<TRefElem::dim> localIntersection;
864
865 // compute intersection of ray in direction of ip velocity with elem side
866 // we search the ray only in upwind direction
867 if (!ElementSideRayIntersection<TRefElem, TWorldDim>(side, globalIntersection, localIntersection,
868 IP, IPVel, false /* i.e. search upwind */, vCornerCoords))
869 UG_THROW("GetNodeNextToCut: ElementSideRayIntersection failed");
870
871 // get reference element
872 static const TRefElem &rRefElem = Provider<TRefElem>::get();
873 const int dim = TRefElem::dim;
874
875 // reset minimum
876 number min = std::numeric_limits<number>::max();
877
878 // loop corners of side
879 for (size_t i = 0; i < rRefElem.num(dim - 1, side, 0); ++i)
880 {
881 // get corner
882 const size_t co = rRefElem.id(dim - 1, side, 0, i);
883
884 // Compute Distance to intersection
885 number dist = VecDistanceSq(globalIntersection, vCornerCoords[co]);
886
887 // if distance is smaller, choose this node
888 if (dist < min)
889 {
890 min = dist;
891 coOut = co;
892 }
893 }
894}
895
896template <int TDim>
897template <typename TFVGeom>
899 update(const TFVGeom *geo,
900 const MathVector<dim> *Velocity,
901 const MathMatrix<dim, dim> *DiffDisp,
902 bool computeDeriv)
903{
904 UG_ASSERT(geo != nullptr, "Null pointer");
905 UG_ASSERT(Velocity != nullptr, "Null pointer");
906
907 // \todo: think about: this should be something like scvf.num_sh()
908 const size_t numSH = geo->num_sh();
909
910 // loop subcontrol volume faces
911 for (size_t ip = 0; ip < geo->num_scvf(); ++ip)
912 {
913 // get subcontrol volume face
914 const typename TFVGeom::SCVF &scvf = geo->scvf(ip);
915
916 // Compute flux
917 const number flux = VecDot(scvf.normal(), Velocity[ip]);
918
919 // Switch to no upwind in case of small velocity
920 if (VecTwoNorm(Velocity[ip]) < 1e-14)
921 {
922 // No upwind!
923 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
924 conv_shape(ip, sh) = flux * scvf.shape(sh);
925 for (size_t sh = scvf.num_sh(); sh < numSH; sh++)
926 conv_shape(ip, sh) = 0.0;
927 if (computeDeriv)
928 {
929 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
930 VecScale(D_vel(ip, sh), scvf.normal(), scvf.shape(sh));
931 // temporary: case of hanging nodes
932 for (size_t sh = scvf.num_sh(); sh < numSH; sh++)
933 VecSet(D_vel(ip, sh), 0.0);
934 }
935 continue;
936 }
937
938 // initialize shapes with zeroes
939 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
940 conv_shape(ip, sh) = 0.0;
941
942 // Hanging nodes
943 // this is introduced here, hopefully temporarily: The problem is, that
944 // for hanging nodes the number of shape function is not the number of
945 // corners, but scvf.num_sh() currently returns the number of corners.
946 // this is actually enough to interpolate the function, but still we
947 // should reset the interpolation adding for hanging dofs to zero
948 for (size_t sh = scvf.num_sh(); sh < numSH; sh++)
949 conv_shape(ip, sh) = 0.0;
950
951 const MathVector<dim> *vCornerCoords = geo->corners();
952 size_t up = 0;
953 try
954 {
955 GetNodeNextToCut<typename TFVGeom::ref_elem_type, dim>(up, scvf.global_ip(), Velocity[ip], vCornerCoords);
956 }
957 UG_CATCH_THROW("Skewed upwind: Cannot find node next to cut");
958
959 conv_shape(ip, up) = flux;
960
961 // Write Derivatives if wanted
962 if (computeDeriv)
963 {
964 for (size_t sh = 0; sh < numSH; ++sh)
965 VecSet(D_vel(ip, sh), 0.0);
966 D_vel(ip, up) = scvf.normal();
967 }
968
969 // The shapes do not depend of the diffusion tensor
970 }
971
972 // we're done
973 return true;
974}
975
977// Linear Profile Skewed Upwind
979
980template <int TDim>
982 : public IConvectionShapes<TDim>
983{
984public:
987
990
992 static const int dim = TDim;
993
994protected:
995 // explicitly forward some function
998 using base_type::D_vel;
1002
1003public:
1006 {
1007 // the shapes do not depend on the DiffDisp. Thus, we can set the
1008 // derivative to be always zero w.r.t. the DiffDisp for all shapes
1010
1011 // register evaluation function
1012 boost::mpl::for_each<typename domain_traits<dim>::AllElemList>(RegisterElemFunc(this));
1013 boost::mpl::for_each<boost::mpl::range_c<int, 1, dim + 1>>(RegisterRefDimFunc(this));
1014 }
1015
1017 template <typename TFVGeom>
1018 bool update(const TFVGeom *geo,
1019 const MathVector<dim> *Velocity,
1020 const MathMatrix<dim, dim> *DiffDisp,
1021 bool computeDeriv);
1022
1023private:
1026 {
1029 template <typename TElem>
1030 void operator()(TElem &)
1031 {
1032 m_pThis->template register_func_for_elem_fvgeom<TElem, FV1Geometry<TElem, dim>>();
1033 //m_pThis->template register_func_for_elem_fvgeom< TElem, FV1CondensedGeometry<TElem, dim> >();
1034 //m_pThis->template register_func_for_elem_fvgeom< TElem, HFV1Geometry<TElem, dim> >();
1035 }
1036 };
1037
1039 template <typename TElem, typename TFVGeom>
1041 {
1042 typedef bool (this_type::*TFunc)(const TFVGeom *, const MathVector<dim> *, const MathMatrix<dim, dim> *, bool);
1043 base_type::template register_update_func<TFVGeom, TFunc>(&this_type::template update<TFVGeom>);
1044 }
1045
1048 {
1051 template <typename TRefDim>
1052 void operator()(TRefDim &) { m_pThis->register_func_for_refDim<TRefDim::value>(); }
1053 };
1054
1056 template <int refDim>
1058 {
1059 //typedef DimFV1Geometry<refDim, dim> TGeom;
1060 //typedef bool (this_type::*TFunc) (const TGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
1061 //base_type::template register_update_func<TGeom, TFunc>(&this_type::template update<TGeom>);
1062 }
1063};
1064
1065template <int TDim>
1066template <typename TFVGeom>
1068 update(const TFVGeom *geo,
1069 const MathVector<dim> *Velocity,
1070 const MathMatrix<dim, dim> *DiffDisp,
1071 bool computeDeriv)
1072{
1073 UG_ASSERT(geo != nullptr, "Null pointer");
1074 UG_ASSERT(Velocity != nullptr, "Null pointer");
1075
1076 // \todo: think about: this should be something like scvf.num_sh()
1077 const size_t numSH = geo->num_sh();
1078
1079 // loop subcontrol volume faces
1080 for (size_t ip = 0; ip < geo->num_scvf(); ++ip)
1081 {
1082 // get subcontrol volume face
1083 const typename TFVGeom::SCVF &scvf = geo->scvf(ip);
1084
1085 // Compute flux
1086 const number flux = VecDot(scvf.normal(), Velocity[ip]);
1087
1088 // Switch to no upwind in case of small velocity
1089 if (VecTwoNorm(Velocity[ip]) < 1e-14)
1090 {
1091 // No upwind!
1092 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
1093 conv_shape(ip, sh) = flux * scvf.shape(sh);
1094 for (size_t sh = scvf.num_sh(); sh < numSH; sh++)
1095 conv_shape(ip, sh) = 0.0;
1096 if (computeDeriv)
1097 {
1098 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
1099 VecScale(D_vel(ip, sh), scvf.normal(), scvf.shape(sh));
1100 // temporary, see above
1101 for (size_t sh = scvf.num_sh(); sh < numSH; sh++)
1102 VecSet(D_vel(ip, sh), 0.0);
1103 }
1104 continue;
1105 }
1106
1107 // initialize shapes with zeroes
1108 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
1109 conv_shape(ip, sh) = 0.0;
1110
1111 // Hanging nodes
1112 // this is introduced here, hopefully temporarily: The problem is, that
1113 // for hanging nodes the number of shape function is not the number of
1114 // corners, but scvf.num_sh() currently returns the number of corners.
1115 // this is actually enough to interpolate the function, but still we
1116 // should reset the interpolation adding for hanging dofs to zero
1117 for (size_t sh = scvf.num_sh(); sh < numSH; sh++)
1118 conv_shape(ip, sh) = 0.0;
1119
1120 const MathVector<dim> *vCornerCoords = geo->corners();
1121 // Reference element type
1122 typedef typename TFVGeom::ref_elem_type TRefElem;
1123 size_t side = 0;
1124 MathVector<dim> globalIntersection;
1125 MathVector<TRefElem::dim> localIntersection;
1126
1127 try
1128 {
1129 ElementSideRayIntersection<TRefElem, dim>(side, globalIntersection, localIntersection,
1130 scvf.global_ip(), Velocity[ip], false /* search upwind */, vCornerCoords);
1131 }
1132 UG_CATCH_THROW("GetLinearProfileSkewedUpwindShapes: Cannot find cut side.");
1133
1134 // get linear trial space
1135 static const ReferenceObjectID roid = TRefElem::REFERENCE_OBJECT_ID;
1136 const LocalShapeFunctionSet<TRefElem::dim> &TrialSpace =
1137 LocalFiniteElementProvider::get<TRefElem::dim>(roid, LFEID(LFEID::LAGRANGE, dim, 1));
1138
1139 // get Reference Element
1140 static const TRefElem &rRefElem = Provider<TRefElem>::get();
1141
1142 // Shape function values
1143 std::vector<number> vShape;
1144 // Values of shape function gradients
1145 std::vector<MathVector<TRefElem::dim>> vShapeGrad;
1146 // Get values at the intersection point
1147 TrialSpace.shapes(vShape, localIntersection);
1148 TrialSpace.grads(vShapeGrad, localIntersection);
1149
1150 size_t num_corners_inters_side = rRefElem.num(dim - 1, side, 0);
1151
1152 // loop corners of side
1153 for (size_t j = 0; j < num_corners_inters_side; ++j)
1154 {
1155 // get corner
1156 const size_t co = rRefElem.id(dim-1, side, 0, j);
1157
1158 // write shape
1159 conv_shape(ip, co) = flux * vShape[co];
1160 }
1161
1162 // Write Derivatives if wanted
1163 if (computeDeriv)
1164 {
1165 // No derivatives yet!
1166 }
1167
1168 // The shapes do not depend of the diffusion tensor
1169 }
1170
1171 // we're done
1172 return true;
1173}
1174
1175
1176} // end namespace ug
1177
1178#endif /* __H__UG__LIB_DISC__SPATIAL_DISC__ELEM_DISC__DENSITY_DRIVEN_FLOW__FV1__CONV_SHAPE__ */
Definition conv_shape.h:194
IConvectionShapes< TDim > base_type
Base class.
Definition conv_shape.h:197
void register_func_for_elem_fvgeom()
registers the update function for an element type and a FV geometry
Definition conv_shape.h:251
void register_func_for_refDim()
registers the update function for a reference dimension
Definition conv_shape.h:267
static const int dim
Dimension.
Definition conv_shape.h:203
bool update(const TFVGeom *geo, const MathVector< dim > *Velocity, const MathMatrix< dim, dim > *DiffDisp, bool computeDeriv)
update of values for FV1Geometry
Definition conv_shape.h:278
ConvectionShapesFullUpwind()
constructor
Definition conv_shape.h:216
ConvectionShapesFullUpwind< TDim > this_type
This class.
Definition conv_shape.h:200
ConvectionShapesLinearProfileSkewedUpwind< TDim > this_type
This class.
Definition conv_shape.h:989
void register_func_for_refDim()
registers the update function for a reference dimension
Definition conv_shape.h:1057
ConvectionShapesLinearProfileSkewedUpwind()
constructor
Definition conv_shape.h:1005
void register_func_for_elem_fvgeom()
registers the update function for an element type and a FV geometry
Definition conv_shape.h:1040
static const int dim
Dimension.
Definition conv_shape.h:992
IConvectionShapes< TDim > base_type
Base class.
Definition conv_shape.h:986
bool update(const TFVGeom *geo, const MathVector< dim > *Velocity, const MathMatrix< dim, dim > *DiffDisp, bool computeDeriv)
update of values for FV geometry
Definition conv_shape.h:1068
Definition conv_shape.h:53
static const int dim
Dimension.
Definition conv_shape.h:62
void register_func_for_elem_fvgeom()
registers the update function for an element type and a FV geometry
Definition conv_shape.h:110
bool update(const TFVGeom *geo, const MathVector< dim > *Velocity, const MathMatrix< dim, dim > *DiffDisp, bool computeDeriv)
update of values for FV geometry
Definition conv_shape.h:138
IConvectionShapes< TDim > base_type
Base class.
Definition conv_shape.h:56
ConvectionShapesNoUpwind()
constructor
Definition conv_shape.h:75
void register_func_for_refDim()
registers the update function for a reference dimension
Definition conv_shape.h:126
ConvectionShapesNoUpwind< TDim > this_type
This class.
Definition conv_shape.h:59
Definition conv_shape.h:536
ConvectionShapesPartialUpwind< TDim > this_type
This class.
Definition conv_shape.h:542
IConvectionShapes< TDim > base_type
Base class.
Definition conv_shape.h:539
void register_func_for_elem_fvgeom()
registers the update function for an element type and a FV geometry
Definition conv_shape.h:588
void register_func_for_refDim()
registers the update function for a reference dimension
Definition conv_shape.h:604
ConvectionShapesPartialUpwind()
constructor
Definition conv_shape.h:558
bool update(const TFVGeom *geo, const MathVector< dim > *Velocity, const MathMatrix< dim, dim > *DiffDisp, bool computeDeriv)
update of values for FV1Geometry
Definition conv_shape.h:616
static const int dim
Dimension.
Definition conv_shape.h:545
Definition conv_shape.h:771
static const int dim
Dimension.
Definition conv_shape.h:780
ConvectionShapesSkewedUpwind< TDim > this_type
This class.
Definition conv_shape.h:777
ConvectionShapesSkewedUpwind()
constructor
Definition conv_shape.h:793
void register_func_for_refDim()
registers the update function for a reference dimension
Definition conv_shape.h:845
bool update(const TFVGeom *geo, const MathVector< dim > *Velocity, const MathMatrix< dim, dim > *DiffDisp, bool computeDeriv)
update of values for FV geometry
Definition conv_shape.h:899
void register_func_for_elem_fvgeom()
registers the update function for an element type and a FV geometry
Definition conv_shape.h:828
IConvectionShapes< TDim > base_type
Base class.
Definition conv_shape.h:774
Definition conv_shape.h:349
void register_func_for_elem_fvgeom()
registers the update function for an element type and a FV geometry
Definition conv_shape.h:427
void register_func_for_refDim()
registers the update function for a reference dimension
Definition conv_shape.h:443
number m_weight
Definition conv_shape.h:408
ConvectionShapesWeightedUpwind< TDim > this_type
This class.
Definition conv_shape.h:355
ConvectionShapesWeightedUpwind(number weight)
constructor
Definition conv_shape.h:383
IConvectionShapes< TDim > base_type
Base class.
Definition conv_shape.h:352
bool update(const TFVGeom *geo, const MathVector< dim > *Velocity, const MathMatrix< dim, dim > *DiffDisp, bool computeDeriv)
update of values for FV1Geometry
Definition conv_shape.h:454
void set_weight(number weight)
set weighting between full upwind (1.0) and no upwind (0.0)
Definition conv_shape.h:397
ConvectionShapesWeightedUpwind()
constructor
Definition conv_shape.h:371
static const int dim
Dimension.
Definition conv_shape.h:358
Geometry and shape functions for 1st order Vertex-Centered Finite Volume.
Definition fv1_geom.h:665
Interface class for upwind methods.
Definition conv_shape_interface.h:100
void register_update_func(TAssFunc func)
register a update function for a Geometry
Definition conv_shape_interface.h:249
void set_non_zero_deriv_diffusion_flag(bool flag)
sets the shape ip flag
Definition conv_shape_interface.h:174
MathMatrix< dim, dim > & conv_shape_diffusion(size_t scvf, size_t sh)
non-const access to upwind shapes for ip vel
Definition conv_shape_interface.h:193
const MathVector< dim > & D_vel(size_t scvf, size_t sh) const
upwind shape for corner vel
Definition conv_shape_interface.h:141
number & conv_shape(size_t scvf, size_t sh)
non-const access to ip velocity (i.e. interpolated velocity at ip)
Definition conv_shape_interface.h:177
bool non_zero_deriv_diffusion() const
returns if upwind shape w.r.t. ip vel is non-zero
Definition conv_shape_interface.h:149
Identifier for Local Finite Elements.
Definition local_finite_element_id.h:98
@ LAGRANGE
Definition local_finite_element_id.h:104
virtual base class for local shape function sets
Definition local_shape_function_set.h:70
virtual void grads(grad_type *vGrad, const MathVector< dim > &x) const =0
returns all gradients evaluated at a point
virtual void shapes(shape_type *vShape, const MathVector< dim > &x) const =0
returns all shape functions evaluated at a point
A class for fixed size, dense matrices.
Definition math_matrix.h:63
a mathematical Vector with N entries.
Definition math_vector.h:97
static TClass & get()
returns a singleton based on the identifier
Definition provider.h:54
void MatSet(matrix_t &mInOut, typename matrix_t::value_type s)
Set each matrix entry to a scalar (componentwise)
Definition math_matrix_functions_common_impl.hpp:794
#define UG_ASSERT(expr, msg)
Definition assert.h:70
#define UG_CATCH_THROW(msg)
Definition error.h:64
#define UG_THROW(msg)
Definition error.h:57
double number
Definition types.h:124
void MatVecMult(vector_t_out &vOut, const matrix_t &m, const vector_t_in &v)
Matrix - Vector Multiplication.
Definition math_matrix_vector_functions_common_impl.hpp:49
void VecScaleAppend(vector_t &vOut, typename vector_t::value_type s1, const vector_t &v1)
Scales a Vector and adds it to a second vector.
Definition math_vector_functions_common_impl.hpp:126
void VecSet(vector_t &vInOut, typename vector_t::value_type s)
Set each vector component to scalar (componentwise)
Definition math_vector_functions_common_impl.hpp:539
vector_t::value_type VecDistanceSq(const vector_t &v1, const vector_t &v2)
returns the squared distance of two vector_ts.
Definition math_vector_functions_common_impl.hpp:351
void VecScale(vector_t &vOut, const vector_t &v, typename vector_t::value_type s)
scales a MathVector<N>
Definition math_vector_functions_common_impl.hpp:252
vector_t::value_type VecTwoNorm(const vector_t &v)
Definition math_vector_functions_common_impl.hpp:577
vector_t::value_type VecDot(const vector_t &v1, const vector_t &v2)
returns the dot-product of two vector_ts
Definition math_vector_functions_common_impl.hpp:385
the ug namespace
ReferenceObjectID
these ids are used to identify the shape of a geometric object.
Definition grid_base_objects.h:74
void GetNodeNextToCut(size_t &coOut, const MathVector< TWorldDim > &IP, const MathVector< TWorldDim > &IPVel, const MathVector< TWorldDim > *vCornerCoords)
computes the closest node to a elem side ray intersection
Definition conv_shape.h:855
functor for registering the shapes for the element-templated FV geometries
Definition conv_shape.h:238
void operator()(TElem &)
Definition conv_shape.h:241
this_type * m_pThis
Definition conv_shape.h:239
RegisterElemFunc(this_type *pThis)
Definition conv_shape.h:240
functor for registering the shapes for the reference-dimension-templated FV geometries
Definition conv_shape.h:259
RegisterRefDimFunc(this_type *pThis)
Definition conv_shape.h:261
this_type * m_pThis
Definition conv_shape.h:260
void operator()(TRefDim &)
Definition conv_shape.h:262
functor for registering the shapes for the element-templated FV geometries
Definition conv_shape.h:1026
void operator()(TElem &)
Definition conv_shape.h:1030
RegisterElemFunc(this_type *pThis)
Definition conv_shape.h:1028
functor for registering the shapes for the reference-dimension-templated FV geometries
Definition conv_shape.h:1048
RegisterRefDimFunc(this_type *pThis)
Definition conv_shape.h:1050
void operator()(TRefDim &)
Definition conv_shape.h:1052
functor for registering the shapes for the element-templated FV geometries
Definition conv_shape.h:97
this_type * m_pThis
Definition conv_shape.h:98
RegisterElemFunc(this_type *pThis)
Definition conv_shape.h:99
void operator()(TElem &)
Definition conv_shape.h:100
functor for registering the shapes for the reference-dimension-templated FV geometries
Definition conv_shape.h:118
void operator()(TRefDim &)
Definition conv_shape.h:121
RegisterRefDimFunc(this_type *pThis)
Definition conv_shape.h:120
this_type * m_pThis
Definition conv_shape.h:119
functor for registering the shapes for the element-templated FV geometries
Definition conv_shape.h:576
void operator()(TElem &)
Definition conv_shape.h:579
this_type * m_pThis
Definition conv_shape.h:577
RegisterElemFunc(this_type *pThis)
Definition conv_shape.h:578
functor for registering the shapes for the reference-dimension-templated FV geometries
Definition conv_shape.h:596
this_type * m_pThis
Definition conv_shape.h:597
void operator()(TRefDim &)
Definition conv_shape.h:599
RegisterRefDimFunc(this_type *pThis)
Definition conv_shape.h:598
functor for registering the shapes for the element-templated FV geometries
Definition conv_shape.h:814
this_type * m_pThis
Definition conv_shape.h:815
void operator()(TElem &)
Definition conv_shape.h:818
RegisterElemFunc(this_type *pThis)
Definition conv_shape.h:816
functor for registering the shapes for the reference-dimension-templated FV geometries
Definition conv_shape.h:836
this_type * m_pThis
Definition conv_shape.h:837
RegisterRefDimFunc(this_type *pThis)
Definition conv_shape.h:838
void operator()(TRefDim &)
Definition conv_shape.h:840
functor for registering the shapes for the element-templated FV geometries
Definition conv_shape.h:414
RegisterElemFunc(this_type *pThis)
Definition conv_shape.h:416
void operator()(TElem &)
Definition conv_shape.h:417
this_type * m_pThis
Definition conv_shape.h:415
functor for registering the shapes for the reference-dimension-templated FV geometries
Definition conv_shape.h:435
void operator()(TRefDim &)
Definition conv_shape.h:438
RegisterRefDimFunc(this_type *pThis)
Definition conv_shape.h:437
this_type * m_pThis
Definition conv_shape.h:436