Plugins
Loading...
Searching...
No Matches
levset_simple_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_simple_extrapol.h
35 */
36
37// ug4 headers
38#ifdef UG_PARALLEL
40#endif
41
42namespace ug {
43namespace LevelSet {
44
45/*-------- class LevSetGFsimpleExtrapolation --------*/
46
54template <typename TDomain, typename TAlgebra>
56(
57 size_t n_co,
58 GridObject * pElem,
59 int si,
60 int g_level,
61 bool use_hanging,
62 const MathVector<dim> vCornerCoords [],
63 number time
64)
65{
66 if (m_spLSF.invalid ()) return 1; // "no LSF" == "completely inside"
67
68// Hanging nodes are not supported
69 if (use_hanging)
70 UG_THROW ("LevSetGFsimpleExtrapolation: Hanging nodes are not supported.");
71
72// the level-set function on the level
73 UG_ASSERT (g_level >= 0 && (size_t) g_level < m_vGLData.size (), "Grid level of the level-set function mismatch!");
74 SmartPtr<ls_grid_func_type> spLSF = m_vGLData[g_level].lsf_on_gl;
75
76// keep the current element
77 m_pElem = pElem; m_si = si; m_vCornerCoords = vCornerCoords;
78 m_time = time;
79
80// get the corner values of the LSF:
81 spLSF->indices (pElem, m_indLSF, false);
82 m_locLSF.resize (m_indLSF);
83 GetLocalVector (m_locLSF, *spLSF);
84
85// check if the element is inside, or outside, or intersected
86 int inside, outside;
87
88 inside = outside = 0;
89 for (size_t co = 0; co < n_co; co++)
90 {
91 if (corner_inside (co))
92 inside = 1;
93 else
94 outside = 1;
95 }
96
97 inside -= outside;
98
99 if (inside != 0)
100 return inside; // not intersected
101
102// for an intersected element, compute the center
103 m_elemCenter = vCornerCoords[0];
104 for (size_t co = 1; co < n_co; co++)
105 m_elemCenter += vCornerCoords[co];
106 m_elemCenter /= (number) n_co;
107
108// get the corners
109 if (m_excl_ssg.size () != 0)
110 {
111 Grid::vertex_traits::secure_container corner_list;
112 m_excl_ssg.subset_handler()->grid()->associated_elements (corner_list, pElem);
113 if (corner_list.size () != n_co) // hanging nodes?
114 UG_THROW ("LevSetGFsimpleExtrapolation: Hanging nodes are not supported. - Illegal number of vertices in an element.");
115 for (size_t co = 0; co < n_co; co++)
116 m_co_excluded [co] = m_excl_ssg.contains (m_excl_ssg.subset_handler()->get_subset_index (corner_list [co]));
117 }
118 else
119 for (size_t co = 0; co < max_num_corners; co++)
120 m_co_excluded [co] = false;
121
122 return 0;
123}
124
128template <typename TDomain, typename TAlgebra>
130(
131 size_t fct
132) const
133{
134 const ICData & ic_data = m_vICData[fct];
135
136 if (ic_data.func.invalid ())
137 return ic_data.value;
138
139 number val;
140 (* ic_data.func) (val, m_elemCenter, m_time, m_si);
141 return val;
142}
143
150template <typename TDomain, typename TAlgebra>
151template <typename TElem>
153(
154 LocalVector& locU,
155 size_t base_co
156) const
157{
158 for (size_t fct = 0; fct < locU.num_all_fct (); fct++)
159 if (locU.num_all_dof (fct) != TElem::NUM_VERTICES)
160 UG_THROW ("LevSetGFsimpleExtrapolation:"
161 " Hanging nodes are not currently supported for the ghost-fluid method");
162
163 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
164 if ((! corner_inside (co)) && (! corner_excluded (co))) /* extrapolate */
165 {
166 number t = m_locLSF.value (0, co) / m_locLSF.value (0, base_co);
167 for (size_t fct = 0; fct < locU.num_all_fct (); fct++)
168 switch (m_vICData[fct].bc_kind)
169 {
170 case DIRICHLET_BC:
171 locU.value (fct, co) = locU.value (fct, base_co) * t + boundary_value (fct) * (1 - t);
172 break;
173
174 case DIRICHLET_PLAIN_BC:
175 locU.value (fct, co) = boundary_value (fct);
176 break;
177
178 case NEUMANN_0_BC:
179 locU.value (fct, co) = locU.value (fct, base_co);
180 break;
181
182 default:
183 UG_THROW ("LevSetGFsimpleExtrapolation: Unknown interface condition type.");
184 }
185 }
186 // else use the original values (at the corners 'inside')
187}
188
195template <typename TDomain, typename TAlgebra>
197(
198 size_t num_co,
199 size_t base_co,
200 number * u,
201 size_t fct
202) const
203{
204 if (fct < 0 || fct >= m_vICData.size ())
205 UG_THROW ("LevSetGFsimpleExtrapolation: Wrong function index.");
206
207 t_fs_bc bc_kind = m_vICData[fct].bc_kind;
208 number interface_val = boundary_value (fct);
209
210 for (size_t co = 0; co < num_co; co++)
211 if ((! corner_inside (co)) && (! corner_excluded (co))) /* extrapolate */
212 switch (bc_kind)
213 {
214 case DIRICHLET_BC:
215 {
216 number t = m_locLSF.value (0, co) / m_locLSF.value (0, base_co);
217 u [co] = u [base_co] * t + interface_val * (1 - t);
218 }
219 break;
220
221 case DIRICHLET_PLAIN_BC:
222 u [co] = interface_val;
223 break;
224
225 case NEUMANN_0_BC:
226 u [co] = u [base_co];
227 break;
228
229 default:
230 UG_THROW ("LevSetGFsimpleExtrapolation: Unknown interface condition type.");
231 }
232 // else use the original values (at the corners 'outside')
233}
234
241template <typename TDomain, typename TAlgebra>
243(
244 size_t num_co,
245 number * u,
246 size_t fct
247) const
248{
249 if (fct < 0 || fct >= m_vICData.size ())
250 UG_THROW ("LevSetGFsimpleExtrapolation: Wrong function index.");
251
252 t_fs_bc bc_kind = m_vICData[fct].bc_kind;
253 number interface_val = boundary_value (fct);
254
255 for (size_t co = 0; co < num_co; co++)
256 if ((! corner_inside (co)) && (! corner_excluded (co))) /* extrapolate */
257 {
258 size_t n_base_co = 0;
259 u [co] = 0;
260 for (size_t base_co = 0; base_co < num_co; base_co++)
261 if (corner_inside (base_co)) /* use this corner to extrapolate */
262 {
263 switch (bc_kind)
264 {
265 case DIRICHLET_BC:
266 {
267 number t = m_locLSF.value (0, co) / m_locLSF.value (0, base_co);
268 u [co] += u [base_co] * t + interface_val * (1 - t);
269 }
270 break;
271
272 case DIRICHLET_PLAIN_BC:
273 u [co] += interface_val;
274 break;
275
276 case NEUMANN_0_BC:
277 u [co] += u [base_co];
278 break;
279
280 default:
281 UG_THROW ("LevSetGFsimpleExtrapolation: Unknown interface condition type.");
282 }
283 n_base_co++;
284 }
285 UG_ASSERT (n_base_co != 0, "LevSetGFsimpleExtrapolation:"
286 "Attempt to interpolate in an element that is not cut.");
287 u [co] /= n_base_co;
288 }
289 // else use the original values (at the corners 'outside')
290}
291
295template <typename TDomain, typename TAlgebra>
296template <typename TElem>
298(
299 LocalVector& locD,
300 size_t base_co
301)
302{
303 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
304 if (co != base_co)
305 for (size_t fct = 0; fct < locD.num_all_fct (); fct++)
306 locD.value (fct, co) = 0;
307}
308
314template <typename TDomain, typename TAlgebra>
315template <typename TElem>
317(
318 LocalMatrix& locM,
319 size_t base_co
320)
321{
322// eliminate
323 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
324 if ((! corner_inside (co)) && (! corner_excluded (co)))
325 {
326 number t = m_locLSF.value (0, co) / m_locLSF.value (0, base_co);
327 for (size_t row_fct = 0; row_fct < locM.num_all_row_fct (); row_fct++)
328 for (size_t col_fct = 0; col_fct < locM.num_all_col_fct (); col_fct++)
329 {
330 number & a_ij = locM.value (row_fct, base_co, col_fct, co);
331 switch (m_vICData[col_fct].bc_kind)
332 {
333 case DIRICHLET_BC:
334 locM.value (row_fct, base_co, col_fct, base_co) += a_ij * t;
335 break;
336
337 case DIRICHLET_PLAIN_BC:
338 // noting to do: the contribution does not depend on the unknowns
339 break;
340
341 case NEUMANN_0_BC:
342 locM.value (row_fct, base_co, col_fct, base_co) += a_ij;
343 break;
344
345 default:
346 UG_THROW ("LevSetGFsimpleExtrapolation: Unknown interface condition type.");
347 }
348 a_ij = 0;
349 }
350 }
351
352// clear
353 for (size_t row_co = 0; row_co < TElem::NUM_VERTICES; row_co++)
354 if (row_co != base_co)
355 for (size_t col_co = 0; col_co < TElem::NUM_VERTICES; col_co++)
356 for (size_t row_fct = 0; row_fct < locM.num_all_row_fct (); row_fct++)
357 for (size_t col_fct = 0; col_fct < locM.num_all_col_fct (); col_fct++)
358 locM.value (row_fct, row_co, col_fct, col_co) = 0;
359}
360
368template <typename TDomain, typename TAlgebra>
369template <typename TElem>
371(
372 LocalMatrix& locM,
373 LocalVector& locB,
374 size_t base_co
375)
376{
377// eliminate
378 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
379 if ((! corner_inside (co)) && (! corner_excluded (co)))
380 {
381 number t = m_locLSF.value (0, co) / m_locLSF.value (0, base_co);
382 for (size_t row_fct = 0; row_fct < locM.num_all_row_fct (); row_fct++)
383 for (size_t col_fct = 0; col_fct < locM.num_all_col_fct (); col_fct++)
384 {
385 number & a_ij = locM.value (row_fct, base_co, col_fct, co);
386 switch (m_vICData[col_fct].bc_kind)
387 {
388 case DIRICHLET_BC:
389 locM.value (row_fct, base_co, col_fct, base_co) += a_ij * t;
390 locB.value (row_fct, base_co) -= a_ij * boundary_value (col_fct) * (1 - t);
391 break;
392
393 case DIRICHLET_PLAIN_BC:
394 locB.value (row_fct, base_co) -= a_ij * boundary_value (col_fct);
395 break;
396
397 case NEUMANN_0_BC:
398 locM.value (row_fct, base_co, col_fct, base_co) += a_ij;
399 break;
400
401 default:
402 UG_THROW ("LevSetGFsimpleExtrapolation: Unknown interface condition type.");
403 }
404 a_ij = 0;
405 }
406 }
407
408// clear
409 for (size_t row_co = 0; row_co < TElem::NUM_VERTICES; row_co++)
410 if (row_co != base_co)
411 for (size_t row_fct = 0; row_fct < locM.num_all_row_fct (); row_fct++)
412 {
413 locB.value (row_fct, row_co) = 0;
414 for (size_t col_co = 0; col_co < TElem::NUM_VERTICES; col_co++)
415 for (size_t col_fct = 0; col_fct < locM.num_all_col_fct (); col_fct++)
416 locM.value (row_fct, row_co, col_fct, col_co) = 0;
417 }
418}
419
429template <typename TDomain, typename TAlgebra>
430template <typename TElem>
432(
433 LocalMatrix& locM,
434 LocalVector& locB
435)
436{
437// eliminate
438 for (size_t base_co = 0; base_co < TElem::NUM_VERTICES; base_co++)
439 if (corner_inside (base_co))
440 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
441 if ((! corner_inside (co)) && (! corner_excluded (co)))
442 {
443 number t = m_locLSF.value (0, co) / m_locLSF.value (0, base_co);
444 for (size_t row_fct = 0; row_fct < locM.num_all_row_fct (); row_fct++)
445 for (size_t col_fct = 0; col_fct < locM.num_all_col_fct (); col_fct++)
446 {
447 number & a_ij = locM.value (row_fct, base_co, col_fct, co);
448 switch (m_vICData[col_fct].bc_kind)
449 {
450 case DIRICHLET_BC:
451 locM.value (row_fct, base_co, col_fct, base_co) += a_ij * t;
452 locB.value (row_fct, base_co) -= a_ij * boundary_value (col_fct) * (1 - t);
453 break;
454
455 case DIRICHLET_PLAIN_BC:
456 locB.value (row_fct, base_co) -= a_ij * boundary_value (col_fct);
457 break;
458
459 case NEUMANN_0_BC:
460 locM.value (row_fct, base_co, col_fct, base_co) += a_ij;
461 break;
462
463 default:
464 UG_THROW ("LevSetGFsimpleExtrapolation: Unknown interface condition type.");
465 }
466 a_ij = 0;
467 }
468 }
469
470// clear
471 for (size_t row_co = 0; row_co < TElem::NUM_VERTICES; row_co++)
472 if (! corner_inside (row_co))
473 for (size_t row_fct = 0; row_fct < locM.num_all_row_fct (); row_fct++)
474 {
475 locB.value (row_fct, row_co) = 0;
476 for (size_t col_co = 0; col_co < TElem::NUM_VERTICES; col_co++)
477 for (size_t col_fct = 0; col_fct < locM.num_all_col_fct (); col_fct++)
478 locM.value (row_fct, row_co, col_fct, col_co) = 0;
479 }
480}
481
486template <typename TDomain, typename TAlgebra>
488{
489 m_vGLData.resize (0); // to deallocate the old data
490 if (! m_spLSF.valid ()) return; // no level-set function
491
492 int finest_lev = m_spLSF->grid_level().level ();
493 GridLevel::ViewType view_type = m_spLSF->grid_level().type (); //TODO: Is it correct, to preserve the view type?
494 SmartPtr<ApproximationSpace<domain_type> > approx_space = m_spLSF->approx_space ();
495
496 if (finest_lev == GridLevel::TOP)
497 finest_lev = approx_space->num_levels () - 1;
498 UG_ASSERT (finest_lev >= 0, "Wrong finest grid level!");
499
500// the finest grid level (as specified by the original LSF)
501 m_vGLData.resize (finest_lev + 1);
502 m_vGLData[finest_lev].lsf_on_gl = m_spLSF;
503 m_vGLData[finest_lev].inject = SPNULL;
504
505// coarser grid levels
506 for (int fine_lev = finest_lev; fine_lev > 0; fine_lev--)
507 {
508 int coarse_lev = fine_lev - 1;
509 GridLevel fine_gl (fine_lev, view_type);
510 GridLevel coarse_gl (coarse_lev, view_type);
511
512 m_vGLData[coarse_lev].lsf_on_gl = SmartPtr<ls_grid_func_type> (new ls_grid_func_type (approx_space, coarse_gl, false));
513
514 m_vGLData[coarse_lev].inject = SmartPtr<projection_type> (new projection_type (approx_space));
515 m_vGLData[coarse_lev].inject->set_levels (coarse_gl, fine_gl);
516 m_vGLData[coarse_lev].inject->init ();
517 }
518}
519
523template <typename TDomain, typename TAlgebra>
525{
526 if (m_vGLData.size () < 2) return; // nothing to project
527 for (int coarse_lev = m_vGLData.size () - 2; coarse_lev >= 0; coarse_lev--)
528 m_vGLData[coarse_lev].inject->do_restrict
529 (* m_vGLData[coarse_lev].lsf_on_gl, * m_vGLData[coarse_lev + 1].lsf_on_gl);
530}
531
535template <typename TDomain, typename TAlgebra>
537(
538 vector_type & d,
539 const DoFDistribution * dd
540) const
541{
542 typedef typename DoFDistribution::traits<Vertex>::const_iterator t_vert_iterator;
543
544// If no LSF given, do nothing
545 if (m_spLSF.invalid ()) return;
546
547// Grid level of the dof distribution, and the correct level-set function
548 int level = dd->grid_level().level ();
549 if (level == GridLevel::TOP)
550 level = dd->multi_grid()->top_level ();
551 if (level < 0 || (size_t) level >= m_vGLData.size ())
552 UG_THROW ("Attempt to assemble on a grid level where the LSF is undefined.");
553 SmartPtr<ls_grid_func_type> spLSF = m_vGLData[level].lsf_on_gl;
554
555// Arrays for the indices in the grid functions:
556 std::vector<size_t> vLSFVertInd (1);
557 std::vector<size_t> vDefVertInd;
558
559// Loop the vertices
560 t_vert_iterator iter = dd->template begin<Vertex> ();
561 t_vert_iterator iterEnd = dd->template end<Vertex> ();
562 for (; iter != iterEnd; iter++)
563 {
564 Vertex * pVertex = *iter;
565
566 // Check if the vertex is excluded:
567 if (m_excl_ssg.size () != 0 && m_excl_ssg.contains (m_excl_ssg.subset_handler()->get_subset_index (pVertex)))
568 continue;
569
570 // Get the multiindex of the LSF and check the value of the LSF
571 if (spLSF->inner_algebra_indices (pVertex, vLSFVertInd) != 1)
572 UG_THROW ("LevSetGFsimpleExtrapolation: Non-scalar Level-Set Function.");
573 if (lsf_inside (BlockRef ((* spLSF) [vLSFVertInd[0]], 0)))
574 continue;
575
576 // Get the multiindices of the grid function and set the values:
577 size_t n_dofs = dd->inner_algebra_indices (pVertex, vDefVertInd);
578 for (size_t dof = 0; dof < n_dofs; dof++)
579 d [vDefVertInd[dof]] = 0;
580 }
581}
582
586template <typename TDomain, typename TAlgebra>
588(
589 vector_type & u,
590 const DoFDistribution * dd,
591 number time
592)
593{
594 typedef typename DoFDistribution::traits<Vertex>::const_iterator t_vert_iterator;
595
596// If no LSF given, do nothing
597 if (m_spLSF.invalid ()) return;
598
599// Grid level of the dof distribution, and the correct level-set function
600 int level = dd->grid_level().level ();
601 if (level == GridLevel::TOP)
602 level = dd->multi_grid()->top_level ();
603 if (level < 0 || (size_t) level >= m_vGLData.size ())
604 UG_THROW ("LevSetGFsimpleExtrapolation: Attempt to assemble on a grid level where the LSF is undefined.");
605 SmartPtr<ls_grid_func_type> spLSF = m_vGLData[level].lsf_on_gl;
606
607 std::vector<size_t> vLSFVertInd (1);
608 std::vector<DoFIndex> multInd (1);
609
610 ANumber aBC;
611 AUInt aNumElem;
612 grid_type & grid = * (grid_type *) (dd->multi_grid().get ()); // we cancel the 'const' specifier here!
613 grid.attach_to_vertices (aBC);
614 grid.attach_to_vertices (aNumElem);
616 Grid::VertexAttachmentAccessor<AUInt> aaNumElem (grid, aNumElem);
617 typedef typename domain_traits<dim>::DimElemList AssembleElemList;
618
619// Initialize the outer vertices near the interface: Sum up the extrapolated values
620 for (size_t fct = 0; fct < dd->num_fct (); fct++)
621 {
622 // Prepare the attachments
623 t_vert_iterator iter = dd->template begin<Vertex> ();
624 t_vert_iterator iterEnd = dd->template end<Vertex> ();
625 for (; iter != iterEnd; iter++)
626 {
627 Vertex * pVertex = *iter;
628 aaBC [pVertex] = 0;
629 aaNumElem [pVertex] = 0;
630 }
631
632 // Sup up and count the values
633 boost::mpl::for_each<AssembleElemList> (SumUpNearIfOuterValues (this, u, fct, dd, time, aaBC, aaNumElem));
634# ifdef UG_PARALLEL
635 AttachmentAllReduce<Vertex> (grid, aBC, PCL_RO_SUM);
636 AttachmentAllReduce<Vertex> (grid, aNumElem, PCL_RO_SUM);
637# endif
638
639 // Average the extrapolated values
640 for (int si = 0; si < dd->num_subsets (); si++)
641 {
642 // Check if the function index is defined in this subset
643 if (! dd->is_def_in_subset (fct, si))
644 continue;
645
646 // Check if the subset is excluded:
647 if (m_excl_ssg.size () != 0 && m_excl_ssg.contains (si))
648 continue;
649
650 // Loop the vertices
651 t_vert_iterator iter = dd->template begin<Vertex> (si);
652 t_vert_iterator iterEnd = dd->template end<Vertex> (si);
653 for (; iter != iterEnd; iter++)
654 {
655 Vertex * pVertex = *iter;
656
657 // Get the multiindex of the LSF and check the value of the LSF
658 if (spLSF->inner_algebra_indices (pVertex, vLSFVertInd) != 1)
659 UG_THROW ("LevSetGFsimpleExtrapolation: Non-scalar Level-Set Function.");
660 if (lsf_inside (BlockRef ((* spLSF) [vLSFVertInd[0]], 0)))
661 continue; // we do not reset the values that are inside
662
663 if (dd->inner_dof_indices (pVertex, fct, multInd) != 1)
664 UG_THROW ("LevSetGFsimpleExtrapolation: More than one DoF per vertex for a component. Not the Lagrange element?");
665
666 const uint nElem = aaNumElem [pVertex];
667 if (nElem != 0) // if 0, the values have not been extrapolated at this vertex
668 {
669 const number bcVal = aaBC [pVertex];
670 DoFRef (u, multInd[0]) = bcVal / nElem;
671 }
672 else
673 DoFRef (u, multInd[0]) = 0;
674 }
675 }
676 }
677
678 grid.detach_from_vertices (aNumElem);
679 grid.detach_from_vertices (aBC);
680}
681
685template <typename TDomain, typename TAlgebra>
686template <typename TElem>
688(
689 vector_type & u,
690 size_t fct,
691 const DoFDistribution * dd,
692 number time,
695)
696{
697 typedef typename DoFDistribution::traits<TElem>::const_iterator t_elem_iterator;
698
699// get the position accessor (here only available in the LSF)
700 position_accessor_type & aaPos = m_spLSF->domain()->position_accessor ();
701
702// grid level of the dof distribution, and the correct level-set function
703 int level = dd->grid_level().level ();
704 if (level == GridLevel::TOP)
705 level = dd->multi_grid()->top_level ();
706 SmartPtr<ls_grid_func_type> spLSF = m_vGLData[level].lsf_on_gl;
707
708// loop the subsets and the elements in every subset
709 std::vector<DoFIndex> multInd (1);
710 for (int si = 0; si < dd->num_subsets (); si++)
711 {
712 t_elem_iterator iterEnd = dd->template end<TElem> (si);
713 for (t_elem_iterator iter = dd->template begin<TElem> (si); iter != iterEnd; iter++)
714 {
715 TElem * pElem = *iter;
716
717 // get the corners of the element
718 Vertex * vVertex [TElem::NUM_VERTICES];
719 MathVector<dim> vCornerCoords [TElem::NUM_VERTICES];
720 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
721 vCornerCoords[co] = aaPos[vVertex[co] = pElem->vertex (co)];
722
723 // check whether we are inside
724 if (check_elem_lsf
725 (TElem::NUM_VERTICES, pElem, si, level, false, vCornerCoords, time) != 0)
726 continue; // this element is not cut, do not consider it
727
728 // get/extrapolate the values of the grid function there
729 number vValue [TElem::NUM_VERTICES];
730
731 // get the original values at the corners that are inside
732 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
733 {
734 if (dd->inner_dof_indices (vVertex[co], fct, multInd) != 1)
735 UG_THROW ("LevSetGFsimpleExtrapolation: More than one DoF per vertex for a component. Not the Lagrange element?");
736 if (corner_inside (co))
737 vValue[co] = DoFRef (u, multInd[0]);
738 }
739 // extrapolate values to the corners that are outside and add the contribution
740 extrapolate_by_lsf (TElem::NUM_VERTICES, vValue, fct);
741 for (size_t co = 0; co < TElem::NUM_VERTICES; co++)
742 if (! corner_inside (co))
743 {
744 aaBC[vVertex[co]] += vValue[co]; // add the value
745 (aaNumElem[vVertex[co]])++; // increase the counter
746 }
747 }
748 }
749}
750
754template <typename TDomain, typename TAlgebra>
756(
757 matrix_type & A,
758 const DoFDistribution * dd
759) const
760{
761 typedef typename DoFDistribution::traits<Vertex>::const_iterator t_vert_iterator;
762
763// If no LSF given, do nothing
764 if (m_spLSF.invalid ()) return;
765
766// Grid level of the dof distribution, and the correct level-set function
767 int level = dd->grid_level().level ();
768 if (level == GridLevel::TOP)
769 level = dd->multi_grid()->top_level ();
770 if (level < 0 || (size_t) level >= m_vGLData.size ())
771 UG_THROW ("Attempt to assemble on a grid level where the LSF is undefined.");
772 SmartPtr<ls_grid_func_type> spLSF = m_vGLData[level].lsf_on_gl;
773
774// Arrays for the indices in the grid functions:
775 std::vector<size_t> vLSFVertInd (1);
776 std::vector<size_t> vMatVertInd;
777
778// Loop the vertices
779 t_vert_iterator iter = dd->template begin<Vertex> ();
780 t_vert_iterator iterEnd = dd->template end<Vertex> ();
781 for (; iter != iterEnd; iter++)
782 {
783 Vertex * pVertex = *iter;
784
785 // Check if the vertex is excluded:
786 if (m_excl_ssg.size () != 0 && m_excl_ssg.contains (m_excl_ssg.subset_handler()->get_subset_index (pVertex)))
787 continue;
788
789 // Get the multiindex of the LSF and check the value of the LSF
790 if (spLSF->inner_algebra_indices (pVertex, vLSFVertInd) != 1)
791 UG_THROW ("LevSetGFsimpleExtrapolation: Non-scalar Level-Set Function.");
792 if (lsf_inside (BlockRef ((* spLSF) [vLSFVertInd[0]], 0)))
793 continue;
794
795 // Get the multiindices of the grid function and set the values:
796 size_t n_dofs = dd->inner_algebra_indices (pVertex, vMatVertInd);
797 for (size_t dof = 0; dof < n_dofs; dof++)
798 SetDirichletRow (A, vMatVertInd[dof]);
799 }
800}
801
802} // namespace LevelSet
803} // end namespace ug
804
805/* End of File */
bool invalid() const
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
void eliminate_extrapolated(LocalMatrix &locM, size_t base_co)
eliminates the matrix connections to the vertices behind the interface
Definition levset_simple_extrapol_impl.h:317
void set_outer_values(vector_type &u, const DoFDistribution *dd, number time)
sets the values at the outer vertices to given values
Definition levset_simple_extrapol_impl.h:588
void set_outer_matrices(matrix_type &A, const DoFDistribution *dd) const
sets the matrices at outer vertices to identity
Definition levset_simple_extrapol_impl.h:756
t_fs_bc
types of boundary conditions at the moving boundary
Definition levset_simple_extrapol.h:121
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_simple_extrapol_impl.h:197
void project_LSF()
projects the values of the LSF to the coarser levels
Definition levset_simple_extrapol_impl.h:524
void clear_outer_values(vector_type &d, const DoFDistribution *dd) const
sets the values at the outer vertices to 0
Definition levset_simple_extrapol_impl.h:537
domain_type::position_accessor_type position_accessor_type
type of the position attachment accessor
Definition levset_simple_extrapol.h:112
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 not, and prepares the data
Definition levset_simple_extrapol_impl.h:56
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_simple_extrapol_impl.h:153
algebra_type::vector_type vector_type
vector type (for the functions to extrapolate)
Definition levset_simple_extrapol.h:97
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_simple_extrapol_impl.h:688
algebra_type::matrix_type matrix_type
matrix type
Definition levset_simple_extrapol.h:100
TDomain::grid_type grid_type
grid type for the domain
Definition levset_simple_extrapol.h:88
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_simple_extrapol_impl.h:298
number boundary_value(size_t fct) const
gets the BC value
Definition levset_simple_extrapol_impl.h:130
void prepare_grid_levels()
projects the level-set functions to the coarser grid levels
Definition levset_simple_extrapol_impl.h:487
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)
size_t num_all_fct() const
number & value(size_t fct, size_t dof)
size_t num_all_dof(size_t fct) const
SmartPtr< TGrid > grid()
#define PCL_RO_SUM
const NullSmartPtr SPNULL
#define UG_ASSERT(expr, msg)
#define UG_THROW(msg)
unsigned int uint
double number
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)
Class for the specification of the boundary conditions at the interface (for one component/function)
Definition levset_simple_extrapol.h:454
SmartPtr< CplUserData< number, dim > > func
variable value (for the BC)
Definition levset_simple_extrapol.h:456
number value
value (for the Dirichlet BC, if func is NULL)
Definition levset_simple_extrapol.h:457
helper class for the loop over all the element types
Definition levset_simple_extrapol.h:411