Plugins
Loading...
Searching...
No Matches
levset_lin_extrapol_impl.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020: G-CSC, Goethe University Frankfurt
3 * Author: Dmitry Logashenko
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/*
34 * Implementation of functions from levset_lin_extrapol.h
35 */
36
37namespace ug {
38namespace LevelSet {
39
40// ug4 headers
41#include "common/common.h"
44#ifdef UG_PARALLEL
46#endif
47
53template <int WDim, typename TElem>
55{
56 typedef TElem elem_t;
57 static const int dim = WDim;
58 static const int ref_dim = TElem::dim;
59
60public:
61
68 static void compute
69 (
70 const MathVector<dim> vCornerCoords [],
71 size_t base_co,
72 const LocalVector& locLSF,
73 MathVector<dim>& ext_grad
74 )
75 {
76 // Get the reference element and the reference mapping:
78 const DimReferenceElement<ref_dim>& dre = ReferenceElementProvider::template get<ref_dim> (roid);
79
80 // Get the Jacobian of the transformation:
84 = ReferenceMappingProvider::get<ref_dim, dim> (roid, vCornerCoords);
85 map.jacobian_transposed (JT, dre.corner (base_co));
86 RightInverse (JTinv, JT);
87
88 // Compute the gradient of the LSF
89 const LocalShapeFunctionSet<ref_dim>& rTrialSpace
90 = LocalFiniteElementProvider::get<ref_dim> (roid, LFEID (LFEID::LAGRANGE, ref_dim, 1));
91 std::vector<MathVector<ref_dim> > loc_shape_grads (TElem::NUM_VERTICES);
92 MathVector<ref_dim> loc_base_grad;
93 rTrialSpace.grads (loc_shape_grads, dre.corner (base_co));
94 VecSet (loc_base_grad, 0.0);
95 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
96 {
97 const number lsf_co = locLSF.value (0, co);
98 VecScaleAppend(loc_base_grad, lsf_co, loc_shape_grads[co]);
99 }
100 MatVecMult (ext_grad, JTinv, loc_base_grad);
101
102 // Rescale the gradient of the LSF
103 ext_grad *= 1 / locLSF.value (0, base_co);
104 }
105};
106
112template <int WDim>
114{
115 static const int dim = WDim;
116
117public:
118
119 static void compute
120 (
121 const MathVector<dim> vCornerCoords [],
122 size_t base_co,
123 const LocalVector& locLSF,
124 MathVector<dim>& ext_grad
125 )
126 {
127 UG_THROW ("LevSetGFlinearExtrapolation: Illegal dimensionality.");
128 }
129};
130
136template <int WDim, int RDim>
138{
139 static const int dim = WDim;
140 static const int ref_dim = RDim;
141
142public:
143
150 static void compute
151 (
152 const GridObject* elem,
153 size_t n_co,
154 const MathVector<dim> vCornerCoords [],
155 size_t base_co,
156 const LocalVector& locLSF,
157 MathVector<dim>& ext_grad
158 )
159 {
160 // Get the reference element and the reference mapping:
161 const ReferenceObjectID roid = elem->reference_object_id ();
162 const DimReferenceElement<ref_dim>& dre = ReferenceElementProvider::template get<ref_dim> (roid);
163
164 // Get the Jacobian of the transformation:
168 = ReferenceMappingProvider::get<ref_dim, dim> (roid, vCornerCoords);
169 map.jacobian_transposed (JT, dre.corner (base_co));
170 RightInverse (JTinv, JT);
171
172 // Compute the gradient of the LSF
173 const LocalShapeFunctionSet<ref_dim>& rTrialSpace
174 = LocalFiniteElementProvider::get<ref_dim> (roid, LFEID (LFEID::LAGRANGE, ref_dim, 1));
175 std::vector<MathVector<ref_dim> > loc_shape_grads (n_co);
176 MathVector<ref_dim> loc_base_grad;
177 rTrialSpace.grads (loc_shape_grads, dre.corner (base_co));
178 VecSet (loc_base_grad, 0.0);
179 for (size_t co = 0; co < n_co; co++)
180 {
181 const number lsf_co = locLSF.value (0, co);
182 VecScaleAppend(loc_base_grad, lsf_co, loc_shape_grads[co]);
183 }
184 MatVecMult (ext_grad, JTinv, loc_base_grad);
185
186 // Rescale the gradient of the LSF
187 ext_grad *= 1 / locLSF.value (0, base_co);
188 }
189};
190
196template <int WDim>
197class DimScaledLSFGrad<WDim, 0>
198{
199 static const int dim = WDim;
200
201public:
202
209 static void compute
210 (
211 const GridObject* elem,
212 size_t n_co,
213 const MathVector<dim> vCornerCoords [],
214 size_t base_co,
215 const LocalVector& locLSF,
216 MathVector<dim>& ext_grad
217 )
218 {
219 UG_THROW ("LevSetGFlinearExtrapolation: Illegal dimensionality.");
220 }
221};
222
223/*-------- class LevSetGFlinearExtrapolation --------*/
224
232template <typename TDomain, typename TAlgebra>
234(
235 size_t n_co,
236 GridObject * pElem,
237 int si,
238 int g_level,
239 bool use_hanging,
240 const MathVector<dim> vCornerCoords [],
241 number time
242)
243{
244 if (m_spLSF.invalid ()) return 1; // "no LSF" == "completely inside"
245
246// Hanging nodes are not supported
247 if (use_hanging)
248 UG_THROW ("LevSetGFsimpleExtrapolation: Hanging nodes are not supported.");
249
250// the level-set function on the level
251 UG_ASSERT (g_level >= 0 && (size_t) g_level < m_vGLData.size (), "Grid level of the level-set function mismatch!");
252 SmartPtr<ls_grid_func_type> spLSF = m_vGLData[g_level].lsf_on_gl;
253
254// keep the current element
255 m_pElem = pElem; m_si = si; m_vCornerCoords = vCornerCoords;
256 m_time = time;
257
258// get the corner values of the LSF:
259 spLSF->indices (pElem, m_indLSF, use_hanging);
260 m_locLSF.resize (m_indLSF);
261 GetLocalVector (m_locLSF, *spLSF);
262
263// check if the element is inside, or outside, or intersected
264 int inside, outside;
265
266 inside = outside = 0;
267 for (size_t co = 0; co < m_indLSF.num_dof (); co++)
268 {
269 if (corner_inside (co))
270 inside = 1;
271 else
272 outside = 1;
273 }
274
275 inside -= outside;
276
277 if (inside != 0)
278 return inside; // not intersected
279
280// for an intersected element, compute the center
281 m_elemCenter = vCornerCoords[0];
282 for (size_t co = 1; co < n_co; co++)
283 m_elemCenter += vCornerCoords[co];
284 m_elemCenter /= (number) n_co;
285
286// get the corners
287 if (m_excl_ssg.size () != 0)
288 {
289 Grid::vertex_traits::secure_container corner_list;
290 m_excl_ssg.subset_handler()->grid()->associated_elements (corner_list, pElem);
291 if (corner_list.size () != n_co) // hanging nodes?
292 UG_THROW ("LevSetGFsimpleExtrapolation: Hanging nodes are not supported. - Illegal number of vertices in an element.");
293 for (size_t co = 0; co < n_co; co++)
294 m_co_excluded [co] = m_excl_ssg.contains (m_excl_ssg.subset_handler()->get_subset_index (corner_list [co]));
295 }
296 else
297 for (size_t co = 0; co < max_num_corners; co++)
298 m_co_excluded [co] = false;
299
300 return 0;
301}
302
306template <typename TDomain, typename TAlgebra>
308(
309 size_t fct
310) const
311{
312 const ICData & ic_data = m_vICData[fct];
313
314 if (ic_data.func.invalid ())
315 return ic_data.value;
316
317 number val;
318 (* ic_data.func) (val, m_elemCenter, m_time, m_si);
319 return val;
320}
321
328template <typename TDomain, typename TAlgebra>
329template <typename TElem>
331(
332 LocalVector& locU,
333 size_t base_co
334) const
335{
336 for (size_t fct = 0; fct < locU.num_all_fct (); fct++)
337 if (locU.num_all_dof (fct) != TElem::NUM_VERTICES)
338 UG_THROW ("LevSetGFlinearExtrapolation:"
339 " Hanging nodes are not currently supported for the ghost-fluid method");
340
341 MathVector<dim> ext_grad;
342 ScaledLSFGrad<dim, TElem>::compute (m_vCornerCoords, base_co, m_locLSF, ext_grad);
343
344 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
345 if ((! corner_inside (co)) && (! corner_excluded (co))) /* extrapolate */
346 {
347 for (size_t fct = 0; fct < locU.num_all_fct (); fct++)
348 if (m_vICData[fct].Dirichlet)
349 { // extrapolate as a linear function with the computed gradient
351 VecSubtract (r, m_vCornerCoords[co], m_vCornerCoords[base_co]);
352 const number factor = 1 + VecDot (ext_grad, r);
353 locU.value (fct, co) = factor * locU.value (fct, base_co);
354 /*TODO: Take into account the interface values. */
355 }
356 else
357 // zero gradint, use the same values
358 locU.value (fct, co) = locU.value (fct, base_co);
359 }
360 // else use the original values (at the corners 'inside')
361}
362
369template <typename TDomain, typename TAlgebra>
370template <int refDim>
372(
373 size_t num_co,
374 size_t base_co,
375 number * u,
376 size_t fct
377) const
378{
379 if (fct < 0 || fct >= m_vICData.size ())
380 UG_THROW ("LevSetGFlinearExtrapolation: Wrong function index.");
381
382 bool Dirichlet = m_vICData[fct].Dirichlet;
383 //number interface_val = m_vICData[fct].value;
384
385 if (Dirichlet)
386 {
387 MathVector<dim> ext_grad;
388 DimScaledLSFGrad<dim, refDim>::compute (m_pElem, num_co, m_vCornerCoords, base_co, m_locLSF, ext_grad);
389 for (size_t co = 0; co < num_co; co++)
390 if ((! corner_inside (co)) && (! corner_excluded (co))) /* extrapolate */
391 { // extrapolate as a linear function with the computed gradient
393 VecSubtract (r, m_vCornerCoords[co], m_vCornerCoords[base_co]);
394 const number factor = 1 + VecDot (ext_grad, r);
395 u [co] = factor * u [base_co];
396 /*TODO: Take into account the interface values. */
397 }
398 }
399 else
400 {
401 for (size_t co = 0; co < num_co; co++)
402 if ((! corner_inside (co)) && (! corner_excluded (co))) /* "extrapolate" (use the same values) */
403 u [co] = u [base_co];
404 }
405 // else use the original values (at the corners 'outside')
406}
407
414template <typename TDomain, typename TAlgebra>
416(
417 size_t num_co,
418 size_t base_co,
419 number * u,
420 size_t fct
421) const
422{
423 const ReferenceObjectID roid = m_pElem->reference_object_id ();
425 const int ref_dim = dre.dimension ();
426 switch (ref_dim)
427 {
428 case 0: extrapolate_by_lsf_in_<0> (num_co, base_co, u, fct); break;
429 case 1: extrapolate_by_lsf_in_<1> (num_co, base_co, u, fct); break;
430 case 2: extrapolate_by_lsf_in_<2> (num_co, base_co, u, fct); break;
431 case 3: extrapolate_by_lsf_in_<3> (num_co, base_co, u, fct); break;
432 default:
433 UG_THROW ("LevSetGFlinearExtrapolation: Wrong dimensionality of the element.");
434 };
435}
436
443template <typename TDomain, typename TAlgebra>
444template <int refDim>
446(
447 size_t num_co,
448 number * u,
449 size_t fct
450) const
451{
452 if (fct < 0 || fct >= m_vICData.size ())
453 UG_THROW ("LevSetGFlinearExtrapolation: Wrong function index.");
454
455 bool Dirichlet = m_vICData[fct].Dirichlet;
456 //number interface_val = m_vICData[fct].value;
457
458 for (size_t co = 0; co < num_co; co++)
459 if ((! corner_inside (co)) && (! corner_excluded (co))) /* extrapolate */
460 {
461 size_t n_base_co = 0;
462 u [co] = 0;
463 for (size_t base_co = 0; base_co < num_co; base_co++)
464 if (corner_inside (base_co)) /* use this corner to extrapolate */
465 {
466 if (Dirichlet)
467 { // extrapolate as a linear function with the computed gradient
468 MathVector<dim> ext_grad, r;
469 DimScaledLSFGrad<dim, refDim>::compute (m_pElem, num_co, m_vCornerCoords, base_co, m_locLSF, ext_grad);
470 VecSubtract (r, m_vCornerCoords[co], m_vCornerCoords[base_co]);
471 const number factor = 1 + VecDot (ext_grad, r);
472 u [co] = factor * u [base_co];
473 /*TODO: Take into account the interface values. */
474 }
475 else // use the same values (zero gradient)
476 u [co] += u [base_co];
477 n_base_co++;
478 }
479 UG_ASSERT (n_base_co != 0, "LevSetGFlinearExtrapolation:"
480 "Attempt to interpolate in an element that is not cut.");
481 u [co] /= n_base_co;
482 }
483 // else use the original values (at the corners 'outside')
484}
485
492template <typename TDomain, typename TAlgebra>
494(
495 size_t num_co,
496 number * u,
497 size_t fct
498) const
499{
500 const ReferenceObjectID roid = m_pElem->reference_object_id ();
502 const int ref_dim = dre.dimension ();
503 switch (ref_dim)
504 {
505 case 0: extrapolate_by_lsf_in_<0> (num_co, u, fct); break;
506 case 1: extrapolate_by_lsf_in_<1> (num_co, u, fct); break;
507 case 2: extrapolate_by_lsf_in_<2> (num_co, u, fct); break;
508 case 3: extrapolate_by_lsf_in_<3> (num_co, u, fct); break;
509 default:
510 UG_THROW ("LevSetGFlinearExtrapolation: Wrong dimensionality of the element.");
511 };
512}
513
517template <typename TDomain, typename TAlgebra>
518template <typename TElem>
520(
521 LocalVector& locD,
522 size_t base_co
523)
524{
525 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
526 if (co != base_co)
527 for (size_t fct = 0; fct < locD.num_all_fct (); fct++)
528 locD.value (fct, co) = 0;
529}
530
536template <typename TDomain, typename TAlgebra>
537template <typename TElem>
539(
540 LocalMatrix& locM,
541 size_t base_co
542)
543{
544 MathVector<dim> ext_grad;
545 ScaledLSFGrad<dim, TElem>::compute (m_vCornerCoords, base_co, m_locLSF, ext_grad);
546
547// eliminate
548 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
549 if ((! corner_inside (co)) && (! corner_excluded (co)))
550 {
551 for (size_t row_fct = 0; row_fct < locM.num_all_row_fct (); row_fct++)
552 for (size_t col_fct = 0; col_fct < locM.num_all_col_fct (); col_fct++)
553 {
554 number & a_ij = locM.value (row_fct, base_co, col_fct, co);
555 if (m_vICData[col_fct].Dirichlet)
556 { // extrapolate as a linear function with the computed gradient
558 VecSubtract (r, m_vCornerCoords[co], m_vCornerCoords[base_co]);
559 const number factor = 1 + VecDot (ext_grad, r);
560 locM.value (row_fct, base_co, col_fct, base_co) += a_ij * factor;
561 }
562 else
563 locM.value (row_fct, base_co, col_fct, base_co) += a_ij;
564 a_ij = 0;
565 }
566 }
567
568// clear
569 for (size_t row_co = 0; row_co < TElem::NUM_VERTICES; row_co++)
570 if (row_co != base_co)
571 for (size_t col_co = 0; col_co < TElem::NUM_VERTICES; col_co++)
572 for (size_t row_fct = 0; row_fct < locM.num_all_row_fct (); row_fct++)
573 for (size_t col_fct = 0; col_fct < locM.num_all_col_fct (); col_fct++)
574 locM.value (row_fct, row_co, col_fct, col_co) = 0;
575}
576
584template <typename TDomain, typename TAlgebra>
585template <typename TElem>
587(
588 LocalMatrix& locM,
589 LocalVector& locB,
590 size_t base_co
591)
592{
593 MathVector<dim> ext_grad;
594 ScaledLSFGrad<dim, TElem>::compute (m_vCornerCoords, base_co, m_locLSF, ext_grad);
595
596// eliminate
597 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
598 if ((! corner_inside (co)) && (! corner_excluded (co)))
599 {
600 for (size_t row_fct = 0; row_fct < locM.num_all_row_fct (); row_fct++)
601 for (size_t col_fct = 0; col_fct < locM.num_all_col_fct (); col_fct++)
602 {
603 number & a_ij = locM.value (row_fct, base_co, col_fct, co);
604 if (m_vICData[col_fct].Dirichlet)
605 { // extrapolate as a linear function with the computed gradient
607 VecSubtract (r, m_vCornerCoords[co], m_vCornerCoords[base_co]);
608 const number factor = 1 + VecDot (ext_grad, r);
609 locM.value (row_fct, base_co, col_fct, base_co) += a_ij * factor;
610 //locB.value (row_fct, base_co) -= a_ij * m_vICData[col_fct].value * (1 - t);
611 //TODO: Take into account the interface value
612 }
613 else
614 locM.value (row_fct, base_co, col_fct, base_co) += a_ij;
615 a_ij = 0;
616 }
617 }
618
619// clear
620 for (size_t row_co = 0; row_co < TElem::NUM_VERTICES; row_co++)
621 if (row_co != base_co)
622 for (size_t row_fct = 0; row_fct < locM.num_all_row_fct (); row_fct++)
623 {
624 locB.value (row_fct, row_co) = 0;
625 for (size_t col_co = 0; col_co < TElem::NUM_VERTICES; col_co++)
626 for (size_t col_fct = 0; col_fct < locM.num_all_col_fct (); col_fct++)
627 locM.value (row_fct, row_co, col_fct, col_co) = 0;
628 }
629}
630
640template <typename TDomain, typename TAlgebra>
641template <typename TElem>
643(
644 LocalMatrix& locM,
645 LocalVector& locB
646)
647{
648// eliminate
649 for (size_t base_co = 0; base_co < TElem::NUM_VERTICES; base_co++)
650 if (corner_inside (base_co))
651 {
652 MathVector<dim> ext_grad;
653 ScaledLSFGrad<dim, TElem>::compute (m_vCornerCoords, base_co, m_locLSF, ext_grad);
654
655 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
656 if ((! corner_inside (co)) && (! corner_excluded (co)))
657 {
658 for (size_t row_fct = 0; row_fct < locM.num_all_row_fct (); row_fct++)
659 for (size_t col_fct = 0; col_fct < locM.num_all_col_fct (); col_fct++)
660 {
661 number & a_ij = locM.value (row_fct, base_co, col_fct, co);
662 if (m_vICData[col_fct].Dirichlet)
663 { // extrapolate as a linear function with the computed gradient
665 VecSubtract (r, m_vCornerCoords[co], m_vCornerCoords[base_co]);
666 const number factor = 1 + VecDot (ext_grad, r);
667 locM.value (row_fct, base_co, col_fct, base_co) += a_ij * factor;
668 //locB.value (row_fct, base_co) -= a_ij * m_vICData[col_fct].value * (1 - t);
669 //TODO: Take into account the interface value
670 }
671 else
672 locM.value (row_fct, base_co, col_fct, base_co) += a_ij;
673 a_ij = 0;
674 }
675 }
676 }
677
678// clear
679 for (size_t row_co = 0; row_co < TElem::NUM_VERTICES; row_co++)
680 if (! corner_inside (row_co))
681 for (size_t row_fct = 0; row_fct < locM.num_all_row_fct (); row_fct++)
682 {
683 locB.value (row_fct, row_co) = 0;
684 for (size_t col_co = 0; col_co < TElem::NUM_VERTICES; col_co++)
685 for (size_t col_fct = 0; col_fct < locM.num_all_col_fct (); col_fct++)
686 locM.value (row_fct, row_co, col_fct, col_co) = 0;
687 }
688}
689
694template <typename TDomain, typename TAlgebra>
696{
697 m_vGLData.resize (0); // to deallocate the old data
698 if (! m_spLSF.valid ()) return; // no level-set function
699
700 int finest_lev = m_spLSF->grid_level().level ();
701 GridLevel::ViewType view_type = m_spLSF->grid_level().type (); //TODO: Is it correct, to preserve the view type?
702 SmartPtr<ApproximationSpace<domain_type> > approx_space = m_spLSF->approx_space ();
703
704 if (finest_lev == GridLevel::TOP)
705 finest_lev = approx_space->num_levels () - 1;
706 UG_ASSERT (finest_lev >= 0, "Wrong finest grid level!");
707
708// the finest grid level (as specified by the original LSF)
709 m_vGLData.resize (finest_lev + 1);
710 m_vGLData[finest_lev].lsf_on_gl = m_spLSF;
711 m_vGLData[finest_lev].inject = SPNULL;
712
713// coarser grid levels
714 for (int fine_lev = finest_lev; fine_lev > 0; fine_lev--)
715 {
716 int coarse_lev = fine_lev - 1;
717 GridLevel fine_gl (fine_lev, view_type);
718 GridLevel coarse_gl (coarse_lev, view_type);
719
720 m_vGLData[coarse_lev].lsf_on_gl = SmartPtr<ls_grid_func_type> (new ls_grid_func_type (approx_space, coarse_gl, false));
721
722 m_vGLData[coarse_lev].inject = SmartPtr<projection_type> (new projection_type (approx_space));
723 m_vGLData[coarse_lev].inject->set_levels (coarse_gl, fine_gl);
724 m_vGLData[coarse_lev].inject->init ();
725 }
726}
727
731template <typename TDomain, typename TAlgebra>
733{
734 if (m_vGLData.size () < 2) return; // nothing to project
735 for (int coarse_lev = m_vGLData.size () - 2; coarse_lev >= 0; coarse_lev--)
736 m_vGLData[coarse_lev].inject->do_restrict
737 (* m_vGLData[coarse_lev].lsf_on_gl, * m_vGLData[coarse_lev + 1].lsf_on_gl);
738}
739
743template <typename TDomain, typename TAlgebra>
745(
746 vector_type & d,
747 const DoFDistribution * dd
748) const
749{
750 typedef typename DoFDistribution::traits<Vertex>::const_iterator t_vert_iterator;
751
752// If no LSF given, do nothing
753 if (m_spLSF.invalid ()) return;
754
755// Grid level of the dof distribution, and the correct level-set function
756 int level = dd->grid_level().level ();
757 if (level == GridLevel::TOP)
758 level = dd->multi_grid()->top_level ();
759 if (level < 0 || (size_t) level >= m_vGLData.size ())
760 UG_THROW ("Attempt to assemble on a grid level where the LSF is undefined.");
761 SmartPtr<ls_grid_func_type> spLSF = m_vGLData[level].lsf_on_gl;
762
763// Arrays for the indices in the grid functions:
764 std::vector<size_t> vLSFVertInd (1);
765 std::vector<size_t> vDefVertInd;
766
767// Loop the vertices
768 t_vert_iterator iter = dd->template begin<Vertex> ();
769 t_vert_iterator iterEnd = dd->template end<Vertex> ();
770 for (; iter != iterEnd; iter++)
771 {
772 Vertex * pVertex = *iter;
773
774 // Check if the vertex is excluded:
775 if (m_excl_ssg.size () != 0 && m_excl_ssg.contains (m_excl_ssg.subset_handler()->get_subset_index (pVertex)))
776 continue;
777
778 // Get the multiindex of the LSF and check the value of the LSF
779 if (spLSF->inner_algebra_indices (pVertex, vLSFVertInd) != 1)
780 UG_THROW ("LevSetGFlinearExtrapolation: Non-scalar Level-Set Function.");
781 if (lsf_inside (BlockRef ((* spLSF) [vLSFVertInd[0]], 0)))
782 continue;
783
784 // Get the multiindices of the grid function and set the values:
785 size_t n_dofs = dd->inner_algebra_indices (pVertex, vDefVertInd);
786 for (size_t dof = 0; dof < n_dofs; dof++)
787 d [vDefVertInd[dof]] = 0;
788 }
789}
790
794template <typename TDomain, typename TAlgebra>
796(
797 vector_type & u,
798 const DoFDistribution * dd,
799 number time
800)
801{
802 typedef typename DoFDistribution::traits<Vertex>::const_iterator t_vert_iterator;
803
804// If no LSF given, do nothing
805 if (m_spLSF.invalid ()) return;
806
807// Grid level of the dof distribution, and the correct level-set function
808 int level = dd->grid_level().level ();
809 if (level == GridLevel::TOP)
810 level = dd->multi_grid()->top_level ();
811 if (level < 0 || (size_t) level >= m_vGLData.size ())
812 UG_THROW ("LevSetGFlinearExtrapolation: Attempt to assemble on a grid level where the LSF is undefined.");
813 SmartPtr<ls_grid_func_type> spLSF = m_vGLData[level].lsf_on_gl;
814
815 std::vector<size_t> vLSFVertInd (1);
816 std::vector<DoFIndex> multInd (1);
817
818 ANumber aBC;
819 AUInt aNumElem;
820 grid_type & grid = * (grid_type *) (dd->multi_grid().get ()); // we cancel the 'const' specifier here!
821 grid.attach_to_vertices (aBC);
822 grid.attach_to_vertices (aNumElem);
824 Grid::VertexAttachmentAccessor<AUInt> aaNumElem (grid, aNumElem);
825 typedef typename domain_traits<dim>::DimElemList AssembleElemList;
826
827// Initialize the outer vertices near the interface: Sum up the extrapolated values
828 for (size_t fct = 0; fct < dd->num_fct (); fct++)
829 {
830 // Prepare the attachments
831 t_vert_iterator iter = dd->template begin<Vertex> ();
832 t_vert_iterator iterEnd = dd->template end<Vertex> ();
833 for (; iter != iterEnd; iter++)
834 {
835 Vertex * pVertex = *iter;
836 aaBC [pVertex] = 0;
837 aaNumElem [pVertex] = 0;
838 }
839
840 // Sup up and count the values
841 boost::mpl::for_each<AssembleElemList> (SumUpNearIfOuterValues (this, u, fct, dd, time, aaBC, aaNumElem));
842# ifdef UG_PARALLEL
843 AttachmentAllReduce<Vertex> (grid, aBC, PCL_RO_SUM);
844 AttachmentAllReduce<Vertex> (grid, aNumElem, PCL_RO_SUM);
845# endif
846
847 // Average the extrapolated values
848 for (int si = 0; si < dd->num_subsets (); si++)
849 {
850 // Check if the function index is defined in this subset
851 if (! dd->is_def_in_subset (fct, si))
852 continue;
853
854 // Check if the subset is excluded:
855 if (m_excl_ssg.size () != 0 && m_excl_ssg.contains (si))
856 continue;
857
858 // Loop the vertices
859 t_vert_iterator iter = dd->template begin<Vertex> (si);
860 t_vert_iterator iterEnd = dd->template end<Vertex> (si);
861 for (; iter != iterEnd; iter++)
862 {
863 Vertex * pVertex = *iter;
864
865 // Get the multiindex of the LSF and check the value of the LSF
866 if (spLSF->inner_algebra_indices (pVertex, vLSFVertInd) != 1)
867 UG_THROW ("LevSetGFlinearExtrapolation: Non-scalar Level-Set Function.");
868 if (lsf_inside (BlockRef ((* spLSF) [vLSFVertInd[0]], 0)))
869 continue; // we do not reset the values that are inside
870
871 if (dd->inner_dof_indices (pVertex, fct, multInd) != 1)
872 UG_THROW ("LevSetGFlinearExtrapolation: More than one DoF per vertex for a component. Not the Lagrange element?");
873
874 const uint nElem = aaNumElem [pVertex];
875 if (nElem != 0) // if 0, the values have not been extrapolated at this vertex
876 {
877 const number bcVal = aaBC [pVertex];
878 DoFRef (u, multInd[0]) = bcVal / nElem;
879 }
880 else
881 DoFRef (u, multInd[0]) = 0;
882 }
883 }
884 }
885
886 grid.detach_from_vertices (aNumElem);
887 grid.detach_from_vertices (aBC);
888}
889
893template <typename TDomain, typename TAlgebra>
894template <typename TElem>
896(
897 vector_type & u,
898 size_t fct,
899 const DoFDistribution * dd,
900 number time,
903)
904{
905 typedef typename DoFDistribution::traits<TElem>::const_iterator t_elem_iterator;
906
907// get the position accessor (here only available in the LSF)
908 position_accessor_type & aaPos = m_spLSF->domain()->position_accessor ();
909
910// grid level of the dof distribution, and the correct level-set function
911 int level = dd->grid_level().level ();
912 if (level == GridLevel::TOP)
913 level = dd->multi_grid()->top_level ();
914 SmartPtr<ls_grid_func_type> spLSF = m_vGLData[level].lsf_on_gl;
915
916// loop the subsets and the elements in every subset
917 std::vector<DoFIndex> multInd (1);
918 for (int si = 0; si < dd->num_subsets (); si++)
919 {
920 t_elem_iterator iterEnd = dd->template end<TElem> (si);
921 for (t_elem_iterator iter = dd->template begin<TElem> (si); iter != iterEnd; iter++)
922 {
923 TElem * pElem = *iter;
924
925 // get the corners of the element
926 Vertex * vVertex [TElem::NUM_VERTICES];
927 MathVector<dim> vCornerCoords [TElem::NUM_VERTICES];
928 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
929 vCornerCoords[co] = aaPos[vVertex[co] = pElem->vertex (co)];
930
931 // check whether we are inside
932 if (check_elem_lsf
933 (TElem::NUM_VERTICES, pElem, si, level, false, vCornerCoords, time) != 0)
934 continue; // this element is not cut, do not consider it
935
936 // get/extrapolate the values of the grid function there
937 number vValue [TElem::NUM_VERTICES];
938
939 // get the original values at the corners that are inside
940 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
941 {
942 if (dd->inner_dof_indices (vVertex[co], fct, multInd) != 1)
943 UG_THROW ("LevSetGFlinearExtrapolation: More than one DoF per vertex for a component. Not the Lagrange element?");
944 if (corner_inside (co))
945 vValue[co] = DoFRef (u, multInd[0]);
946 }
947 // extrapolate values to the corners that are outside and add the contribution
948 extrapolate_by_lsf (TElem::NUM_VERTICES, vValue, fct);
949 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
950 if (! corner_inside (co))
951 {
952 aaBC[vVertex[co]] += vValue[co]; // add the value
953 (aaNumElem[vVertex[co]])++; // increase the counter
954 }
955 }
956 }
957}
958
962template <typename TDomain, typename TAlgebra>
964(
965 matrix_type & A,
966 const DoFDistribution * dd
967) const
968{
969 typedef typename DoFDistribution::traits<Vertex>::const_iterator t_vert_iterator;
970
971// If no LSF given, do nothing
972 if (m_spLSF.invalid ()) return;
973
974// Grid level of the dof distribution, and the correct level-set function
975 int level = dd->grid_level().level ();
976 if (level == GridLevel::TOP)
977 level = dd->multi_grid()->top_level ();
978 if (level < 0 || (size_t) level >= m_vGLData.size ())
979 UG_THROW ("Attempt to assemble on a grid level where the LSF is undefined.");
980 SmartPtr<ls_grid_func_type> spLSF = m_vGLData[level].lsf_on_gl;
981
982// Arrays for the indices in the grid functions:
983 std::vector<size_t> vLSFVertInd (1);
984 std::vector<size_t> vMatVertInd;
985
986// Loop the vertices
987 t_vert_iterator iter = dd->template begin<Vertex> ();
988 t_vert_iterator iterEnd = dd->template end<Vertex> ();
989 for (; iter != iterEnd; iter++)
990 {
991 Vertex * pVertex = *iter;
992
993 // Check if the vertex is excluded:
994 if (m_excl_ssg.size () != 0 && m_excl_ssg.contains (m_excl_ssg.subset_handler()->get_subset_index (pVertex)))
995 continue;
996
997 // Get the multiindex of the LSF and check the value of the LSF
998 if (spLSF->inner_algebra_indices (pVertex, vLSFVertInd) != 1)
999 UG_THROW ("LevSetGFlinearExtrapolation: Non-scalar Level-Set Function.");
1000 if (lsf_inside (BlockRef ((* spLSF) [vLSFVertInd[0]], 0)))
1001 continue;
1002
1003 // Get the multiindices of the grid function and set the values:
1004 size_t n_dofs = dd->inner_algebra_indices (pVertex, vMatVertInd);
1005 for (size_t dof = 0; dof < n_dofs; dof++)
1006 SetDirichletRow (A, vMatVertInd[dof]);
1007 }
1008}
1009
1010} // namespace LevelSet
1011} // end namespace ug
1012
1013/* End of File */
bool invalid() const
const MathVector< dim, int > * corner() const
virtual void jacobian_transposed(MathMatrix< dim, worldDim > &JT, const MathVector< dim > &locPos) const=0
const GridLevel & grid_level() const
SmartPtr< MultiGrid > multi_grid()
size_t inner_algebra_indices(GridObject *elem, std::vector< size_t > &ind, bool bClear=true) const
size_t inner_dof_indices(GridObject *elem, size_t fct, std::vector< DoFIndex > &ind, bool bClear=true) const
bool is_def_in_subset(size_t fct, int si) const
int level() const
virtual ReferenceObjectID reference_object_id() const=0
static void compute(const GridObject *elem, size_t n_co, const MathVector< dim > vCornerCoords[], size_t base_co, const LocalVector &locLSF, MathVector< dim > &ext_grad)
Definition levset_lin_extrapol_impl.h:210
Definition levset_lin_extrapol_impl.h:138
static void compute(const GridObject *elem, size_t n_co, const MathVector< dim > vCornerCoords[], size_t base_co, const LocalVector &locLSF, MathVector< dim > &ext_grad)
Definition levset_lin_extrapol_impl.h:151
static const int ref_dim
Definition levset_lin_extrapol_impl.h:140
static const int dim
Definition levset_lin_extrapol_impl.h:139
algebra_type::vector_type vector_type
vector type (for the functions to extrapolate)
Definition levset_lin_extrapol.h:98
void extrapolate_by_lsf_in_(size_t num_co, size_t base_co, number *u, size_t fct) const
extrapolates a component of the solution to the vertices behind the interface (w.r....
Definition levset_lin_extrapol_impl.h:372
void sum_up_near_if_outer_values_for_(vector_type &u, size_t fct, const DoFDistribution *dd, number time, Grid::VertexAttachmentAccessor< ANumber > &aaBC, Grid::VertexAttachmentAccessor< AUInt > &aaNumElem)
sets the values at the outer vertices near the interface (for one type of the elements)
Definition levset_lin_extrapol_impl.h:896
number boundary_value(size_t fct) const
gets the BC value
Definition levset_lin_extrapol_impl.h:308
void clear_outer_vectors(LocalVector &locD, size_t base_co)
sets the values of the vector at the non-base vertices to 0
Definition levset_lin_extrapol_impl.h:520
void eliminate_extrapolated(LocalMatrix &locM, size_t base_co)
eliminates the matrix connections to the vertices behind the interface
Definition levset_lin_extrapol_impl.h:539
void extrapolate_sol_by_lsf(LocalVector &locU, size_t base_co) const
extrapolates all the components of the solution to the vertices behind the interface (w....
Definition levset_lin_extrapol_impl.h:331
void set_outer_matrices(matrix_type &A, const DoFDistribution *dd) const
sets the matrices at outer vertices to identity
Definition levset_lin_extrapol_impl.h:964
void prepare_grid_levels()
projects the level-set functions to the coarser grid levels
Definition levset_lin_extrapol_impl.h:695
void clear_outer_values(vector_type &d, const DoFDistribution *dd) const
sets the values at the outer vertices to 0
Definition levset_lin_extrapol_impl.h:745
int check_elem_lsf(size_t n_co, GridObject *pElem, int si, int g_level, bool use_hanging, const MathVector< dim > vCornerCoords[], number time)
checks whether the element is intersected by the interface, or what, and prepares the data
Definition levset_lin_extrapol_impl.h:234
void set_outer_values(vector_type &u, const DoFDistribution *dd, number time)
sets the values at the outer vertices to given values
Definition levset_lin_extrapol_impl.h:796
algebra_type::matrix_type matrix_type
matrix type
Definition levset_lin_extrapol.h:101
domain_type::position_accessor_type position_accessor_type
type of the position attachment accessor
Definition levset_lin_extrapol.h:113
void project_LSF()
projects the values of the LSF to the coarser levels
Definition levset_lin_extrapol_impl.h:732
TDomain::grid_type grid_type
grid type for the domain
Definition levset_lin_extrapol.h:89
void extrapolate_by_lsf(size_t num_co, size_t base_co, number *u, size_t fct) const
extrapolates a component of the solution to the vertices behind the interface (w.r....
Definition levset_lin_extrapol_impl.h:416
static void compute(const MathVector< dim > vCornerCoords[], size_t base_co, const LocalVector &locLSF, MathVector< dim > &ext_grad)
Definition levset_lin_extrapol_impl.h:120
Definition levset_lin_extrapol_impl.h:55
TElem elem_t
Definition levset_lin_extrapol_impl.h:56
static const int dim
Definition levset_lin_extrapol_impl.h:57
static void compute(const MathVector< dim > vCornerCoords[], size_t base_co, const LocalVector &locLSF, MathVector< dim > &ext_grad)
Definition levset_lin_extrapol_impl.h:69
static const int ref_dim
Definition levset_lin_extrapol_impl.h:58
size_t num_all_col_fct() const
size_t num_all_row_fct() const
number & value(size_t rowFct, size_t rowDoF, size_t colFct, size_t colDoF)
virtual void grads(std::vector< std::vector< grad_type > > &vvGrad, const std::vector< MathVector< dim > > &vLocPos) const=0
size_t num_all_fct() const
number & value(size_t fct, size_t dof)
size_t num_all_dof(size_t fct) const
int dimension() const
static const DimReferenceElement< dim > & get(ReferenceObjectID roid)
SmartPtr< TGrid > grid()
MathMatrix< N, M, T >::value_type RightInverse(MathMatrix< N, M, T > &mOut, const MathMatrix< M, N, T > &m)
#define PCL_RO_SUM
const NullSmartPtr SPNULL
#define UG_ASSERT(expr, msg)
#define UG_THROW(msg)
unsigned int uint
double number
void MatVecMult(vector_t_out &vOut, const matrix_t &m, const vector_t_in &v)
void VecScaleAppend(vector_t &vOut, typename vector_t::value_type s1, const vector_t &v1)
void VecSubtract(vector_t &vOut, const vector_t &v, typename vector_t::value_type s)
vector_t::value_type VecDot(const vector_t &v1, const vector_t &v2)
ReferenceObjectID
const number & DoFRef(const TMatrix &mat, const DoFIndex &iInd, const DoFIndex &jInd)
void SetDirichletRow(TMatrix &mat, const DoFIndex &ind)
const number & BlockRef(const number &m, size_t i)
void GetLocalVector(LocalVector &lvec, const TVector &vec)
void VecSet(vector_t &dest, number alpha, const std::vector< size_t > vIndex)
Class for the specification of the boundary conditions at the interface (for one component/function)
Definition levset_lin_extrapol.h:446
SmartPtr< CplUserData< number, dim > > func
variable Dirichlet value (for the Dirichlet BC)
Definition levset_lin_extrapol.h:448
number value
Dirichlet value (for the Dirichlet BC, if func is NULL)
Definition levset_lin_extrapol.h:449
helper class for the loop over all the element types
Definition levset_lin_extrapol.h:403