Plugins
Loading...
Searching...
No Matches
level_set_pos_impl.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025 Gesellschaft fuer Anlagen- und Reaktorsicherheit gGmbH
3 * SPDX-License-Identifier: EUPL-1.2
4 * SPDX-FileContributor: Dmitry Logashenko
5 * SPDX-FileContributor: Goethe Universität Frankfurt
6 * SPDX-FileType: SOURCE
7 *
8 * This file is part of d3f++.
9 * d3f++ is an extension for UG4. Licensing information and citation requirements of UG4 are provided in LICENSES/UG4-LGPL_2.1
10 */
11
12
13/*
14 * Tools for determining the position of the level set: Implementation
15 */
16#include <limits>
17
20
21#ifdef UG_PARALLEL
24#endif
25
26namespace ug{
27namespace d3f{
28
29/*----- Class template 'LSPositionZ': -----*/
30
37template<typename TGridFunction>
39(
40 size_t noc,
41 number lsf []
42)
43{
44 int pos = 0, neg = 0;
45 for (size_t co = 0; co < noc; co++)
46 {
47 if (lsf [co] >= m_level_set_zero - lsf_threshold ()
48 && lsf [co] <= m_level_set_zero + lsf_threshold ())
49 return 0; // we consider such elements as intersected; this is important for computation of the gradients
50 if (lsf [co] < m_level_set_zero) neg = 1;
51 else pos = 1;
52 }
53 return pos - neg;
54}
55
57template <typename TGridFunction>
59{
61 typedef typename TGridFunction::template dim_traits<dim>::const_iterator t_elem_iter;
62
63// reset the array
64 m_vpCut.clear ();
65
66// if no LSF then nothing to do
67 if (! m_spLSF.valid ()) return;
68
69 LocalIndices locInd;
70 LocalVector locLSF;
71
72// loop the vertices
73 t_elem_iter iterEnd = m_spLSF->template end<elem_type> ();
74 for (t_elem_iter iter = m_spLSF->template begin<elem_type> (); iter != iterEnd; ++iter)
75 {
76 elem_type * elem = *iter;
77 size_t noc = elem->num_vertices ();
78 number lsf [maxNumCorners];
79
80 // local values of the LSF
81 m_spLSF->indices (elem, locInd);
82 locLSF.resize (locInd);
83 GetLocalVector (locLSF, *m_spLSF);
84 for (size_t i = 0; i < noc; i++) lsf[i] = locLSF (m_lsf_fct, i);
85
86 // check the sign of the lsf
87 if (lsf_sign (noc, lsf) == 0)
88 m_vpCut.push_back (elem);
89 }
90}
91
93template <typename TGridFunction>
95(
96 const MathVector<dim-1> & xy
97)
98{
99 MathVector<dim> origin, dir;
100
101// prepare the full-dimensional vectors
102 VecSet (dir, 0); dir[dim-1] = 1;
103 for (size_t i = 0; i < dim-1; i++) origin[i] = xy[i];
104 origin[dim-1] = 0;
105
106// get the intersections
107 m_intersections.clear ();
108 if (! RayElementIntersections (m_intersectionRecords, m_tree, origin, dir))
109 return false;
110 for (size_t i = 0; i < m_intersectionRecords.size (); i++)
111 {
112 intersect_rec_type & r = m_intersectionRecords[i];
113 m_intersections.push_back (elem_intersect_data (r.elem,
114 PointOnRay(origin, dir, r.smin), PointOnRay(origin, dir, r.smax)));
115 }
116 return true;
117}
118
120template <typename TGridFunction>
122(
123 std::vector<number> & z,
124 number small_z
125)
126{
127 LocalIndices locInd;
128 LocalVector locLSF;
129 std::vector<number> vShape;
130
131 for (size_t i = 0; i < m_intersections.size (); i++)
132 {
133 elem_intersect_data & e_data = m_intersections[i];
134 elem_type * elem = e_data.elem;
135
136 // get corners of element
137 std::vector<MathVector<dim> > vCornerCoords;
138 CollectCornerCoordinates (vCornerCoords, *elem, *m_spLSF->domain ());
139
140 // reference object id, the reference mapping and the trial space
141 const ReferenceObjectID roid = elem->reference_object_id ();
143 = ReferenceMappingProvider::get<dim, dim> (roid, vCornerCoords);
144 const LocalShapeFunctionSet<dim>& rTrialSpace
145 = LocalFiniteElementProvider::get<dim> (roid, m_spLSF->local_finite_element_id (m_lsf_fct));
146
147 // get local position of DoF
148 MathVector<dim> locPos [2];
149 VecSet (locPos[0], 0.5); VecSet (locPos[1], 0.5);
150 map.global_to_local(locPos, e_data.pnt, 2, m_traNI, m_traTol);
151
152 // local values of the LSF
153 m_spLSF->indices (elem, locInd);
154 locLSF.resize (locInd);
155 GetLocalVector (locLSF, *m_spLSF);
156
157 // process the points
158 number lsf_value [2]; // these are the level-set values with the interface at 0 (independently on m_level_set_zero value)
159 for (size_t j = 0; j < 2; j++)
160 {
161 // evaluate at shapes at the point
162 rTrialSpace.shapes (vShape, locPos[j]);
163
164 // compute value of the LSF at the point
165 lsf_value[j] = - m_level_set_zero; // we shift the values here to 0 to the the interpolation coeffs.
166 for(size_t sh = 0; sh < vShape.size(); sh++)
167 lsf_value[j] += locLSF (m_lsf_fct, sh) * vShape[sh];
168
169 // "correct" the value if approx. 0
170 if (fabs (lsf_value[j]) < 1e-10)
171 lsf_value[j] = 0;
172 }
173
174 // check if the element contains the intersection of the level set with the line
175 if (lsf_value[0] * lsf_value[1] > 0) // stricktly ">" not to loose the intersections at faces
176 continue;
177
178 // find the intersection (assume the linearity of the LSF along the line)
179 number elem_z;
180 if (lsf_value[0] == lsf_value[1]) // only possible if both are 0 (i.e. the original diff. < 2e-10 in abs. val.)
181 elem_z = e_data.pnt[1][dim-1]; // in this case e_data.pnt[0] == e_data.pnt[1]
182 else
183 elem_z = (lsf_value[0] * e_data.pnt[1][dim-1] - lsf_value[1] * e_data.pnt[0][dim-1])
184 / (lsf_value[0] - lsf_value[1]);
185
186 // check if we have already this value
187 size_t k;
188 for (k = 0; k < z.size (); k++)
189 if (std::fabs (z[k] - elem_z) < small_z) break;
190 if (k >= z.size ()) // i.e. if none found
191 z.push_back (elem_z);
192 }
193}
194
195/*----- Auxiliary class template 'LSPosZData_ElemEvalPnt': -----*/
196
205template <int WDim, typename TAAPos, typename TElem>
207{
208 static const int dim = WDim;
209 typedef TAAPos pos_acc_t;
210 typedef TElem elem_t;
212
213public:
214
215 static inline void get
216 (
217 elem_t * elem,
218 pos_acc_t & aa_pos,
219 MathVector<dim> & eval_pnt
220 )
221 {
222 // get the 'center' of the element
223 eval_pnt = aa_pos [elem->vertex (0)];
224 for (size_t i = 1; i < (size_t) ref_elem_t::numCorners; i++)
225 eval_pnt += aa_pos [elem->vertex (i)];
226 eval_pnt /= ref_elem_t::numCorners;
228};
229
233template <int WDim, typename TAAPos>
235{
236 static const int dim = WDim;
237 typedef TAAPos pos_acc_t;
239
240public:
241
242 static inline void get
243 (
244 elem_t * elem,
245 pos_acc_t & aa_pos,
246 MathVector<dim> & eval_pnt
247 )
248 {
249 // return the coordinates of the vertex itself
250 eval_pnt = aa_pos [elem];
251 }
252};
253
254/*----- Class template 'LSPosZData': -----*/
255
259template <typename TGridFunction>
261(
262 SmartPtr<measurer_type>& sp_ls_pos_z,
263 const char * subsetNames
264)
265: m_sp_ls_pos_z (sp_ls_pos_z), m_use_ss_z_as_default (true), m_elem_dim (-1)
266{
267 if (! sp_ls_pos_z.valid ())
268 UG_THROW ("LSPosZData: The measurer not specified.");
269
270 SmartPtr<gf_type> spLSF (m_sp_ls_pos_z->lsf ());
271 m_SsGrp.set_subset_handler (spLSF->domain()->subset_handler ());
272 m_SsGrp.add (TokenizeString (subsetNames));
273}
274
278template <typename TGridFunction>
280{
281 detach_for (m_elem_dim);
282}
283
287template <typename TGridFunction>
288template <typename TElem>
290(
291 MathVector<wDim-1> * xy_pos,
292 number * z_pos
293)
294{
295 typedef typename gf_type::template traits<TElem>::const_iterator elem_iter_t;
296 typedef typename geometry_traits<TElem>::grid_base_object base_elem_t;
298
299 SmartPtr<gf_type> spLSF (m_sp_ls_pos_z->lsf ());
300 pos_acc_type aa_pos = spLSF->domain()->position_accessor ();
301 num_aa_t aa_elem_num (* spLSF->domain()->grid (), m_a_elem_num);
302
303 for (size_t i = 0; i < m_SsGrp.size (); i++)
304 {
305 int si = m_SsGrp[i];
306 for (elem_iter_t iter = spLSF->template begin<TElem> (si);
307 iter != spLSF->template end<TElem> (si); ++iter)
308 {
309 TElem * elem = * iter;
310
311 // get the 'center' of the element
314
315 // get the position of the level set at the center
316 const size_t index = aa_elem_num [(base_elem_t *) elem];
317 MathVector<wDim-1> & xy = xy_pos [index];
318 for (size_t k = 0; k < wDim - 1; k++) xy[k] = xyz[k];
319 if (z_pos != NULL) z_pos [index] = xyz [wDim-1];
320 }
321 }
322}
323
328template <typename TGridFunction>
329template <int elemDim>
331{
332 typedef typename grid_dim_traits<elemDim>::grid_base_object elem_t;
333 typedef typename gf_type::template traits<elem_t>::const_iterator elem_iter_t;
334 typedef typename Grid::AttachmentAccessor<elem_t, num_a_type> num_aa_t;
335 typedef typename domain_traits<elemDim>::DimElemList ElemList;
336
337 SmartPtr<gf_type> spLSF (m_sp_ls_pos_z->lsf ());
338 bool default_used = false;
339
340 if (m_elem_dim != elemDim)
341 {
342 detach_for (m_elem_dim);
343 spLSF->domain()->grid()->template attach_to_dv<elem_t> (m_a_elem_num, (size_t) -1);
344 m_elem_dim = elemDim;
345 }
346
347// initialize the attachment
348 num_aa_t aa_elem_num (* spLSF->domain()->grid (), m_a_elem_num);
349 size_t elem_num = 0;
350 for (size_t i = 0; i < m_SsGrp.size (); i++)
351 {
352 int si = m_SsGrp[i];
353 for (elem_iter_t iter = spLSF->template begin<elem_t> (si);
354 iter != spLSF->template end<elem_t> (si); ++iter)
355 aa_elem_num [*iter] = elem_num++;
356 }
357
358# ifndef UG_PARALLEL
359 {
360 // initialize the values
361 m_elem_z.resize (elem_num);
362 std::vector<MathVector<wDim-1> > eval_pos (elem_num);
363 std::vector<number> z_pos; number * z_pos_ptr = NULL;
364 if (m_use_ss_z_as_default)
365 {
366 z_pos.resize (elem_num);
367 z_pos_ptr = & (z_pos[0]);
368 }
369 boost::mpl::for_each<ElemList> (GetXYForElements (this, & (eval_pos[0]), z_pos_ptr));
370 for (size_t j = 0; j < eval_pos.size (); j++)
371 if (! m_sp_ls_pos_z->get_height_at (eval_pos[j], m_elem_z[j]))
372 {
373 m_elem_z [j] = m_use_ss_z_as_default? z_pos[j] : m_default_height;
374 default_used = true;
375 }
376 }
377
378# else // i.e. ifdef UG_PARALLEL
379
380 {
381 pcl::ProcessCommunicator proc_comm;
382
383 // get the points where the values must be computed
384 std::vector<MathVector<wDim-1> > proc_pos (elem_num);
385 std::vector<number> z_pos; number * z_pos_ptr = NULL;
386 if (m_use_ss_z_as_default)
387 {
388 z_pos.resize (elem_num);
389 z_pos_ptr = & (z_pos[0]);
390 }
391 boost::mpl::for_each<ElemList> (GetXYForElements (this, & (proc_pos[0]), z_pos_ptr));
392
393 std::vector<MathVector<wDim-1> > all_pos;
394 std::vector<int> offset;
395 proc_comm.allgatherv (all_pos, proc_pos, NULL, &offset);
396
397 // compute the values at all the positions
398 std::vector<number> tmp_elem_z (all_pos.size ());
399 for (size_t j = 0; j < tmp_elem_z.size (); j++)
400 if (! m_sp_ls_pos_z->get_height_at (all_pos[j], tmp_elem_z [j]))
401 tmp_elem_z [j] = - std::numeric_limits<number>::max (); // the position is not covered by the free surface in this process
402
403 // compose the common values
404 std::vector<number> all_elem_z (tmp_elem_z.size ());
405 proc_comm.allreduce (tmp_elem_z, all_elem_z, PCL_RO_MAX);
406
407 // extract the values from the common array
408 m_elem_z.resize (elem_num);
409 int my_offset = offset [proc_comm.get_local_proc_id ()];
410 if (! m_use_ss_z_as_default)
411 {
412 for (size_t j = 0; j < elem_num; j++)
413 {
414 number z_val = all_elem_z [my_offset + j];
415 if (z_val == - std::numeric_limits<number>::max ()) // i.e. is not set in any process
416 {
417 m_elem_z [j] = m_default_height;
418 default_used = true;
419 }
420 else
421 m_elem_z [j] = z_val;
422 }
423 }
424 else
425 {
426 for (size_t i = 0; i < m_SsGrp.size (); i++)
427 {
428 int si = m_SsGrp[i];
429 for (elem_iter_t iter = spLSF->template begin<elem_t> (si);
430 iter != spLSF->template end<elem_t> (si); ++iter)
431 {
432 elem_t * vrt = * iter;
433 size_t j = aa_elem_num [vrt];
434 number z_val = all_elem_z [my_offset + j];
435 if (z_val == - std::numeric_limits<number>::max ()) // i.e. is not set in any process
436 {
437 m_elem_z [j] = z_pos[j];
438 default_used = true;
439 }
440 else
441 m_elem_z [j] = z_val;
442 }
443 }
444 }
445 }
446
447# endif // UG_PARALLEL
448
449 if (default_used)
450 {
451 UG_LOG ("LSPosZData::reinit: Some parts of the level set is not under the specified subsets.");
452 if (m_use_ss_z_as_default)
453 {
454 UG_LOG (" Position of the subsets is used instead.\n");
455 }
456 else
457 {
458 UG_LOG (" Default value " << m_default_height << " used.\n");
459 }
460 }
461}
462
466template <typename TGridFunction>
467template <int elemDim>
469{
470 typedef typename grid_dim_traits<elemDim>::grid_base_object elem_type;
471 m_sp_ls_pos_z->lsf()->domain()->grid()->template detach_from<elem_type> (m_a_elem_num);
472}
473
477template <typename TGridFunction>
479(
480 int dim
481)
482{
483 if (dim == 0) detach_for_<0> ();
484 else if (dim == 1) detach_for_<1> ();
485#if defined (UG_DIM_2) || defined (UG_DIM_3)
486 else if (dim == 2) detach_for_<2> ();
487#endif
488#if defined (UG_DIM_3)
489 else if (dim == 3) detach_for_<3> ();
490#endif
491}
492
497template <typename TGridFunction>
499(
500 int dim
501)
502{
503 if (dim < 0) reinit (); // restart with the correct dimensionality
504 else if (dim == 0) reinit_for_<0> ();
505 else if (dim == 1) reinit_for_<1> ();
506#if defined (UG_DIM_2) || defined (UG_DIM_3)
507 else if (dim == 2) reinit_for_<2> ();
508#endif
509#if defined (UG_DIM_3)
510 else if (dim == 3) reinit_for_<3> ();
511#endif
512 else
513 UG_THROW ("LSPosZData::reinit_for: Illegal dimensionality " << dim << " specified.");
514}
515
520template <typename TGridFunction>
522{
523// get the highest dimension of the subset elements
524 int dim = m_SsGrp.get_highest_subset_dimension ();
525
526# ifdef UG_PARALLEL
527 {
528 pcl::ProcessCommunicator proc_comm;
529 dim = proc_comm.allreduce (dim, PCL_RO_MAX);
530 }
531# endif
532
533// reinit for the computed dimensionality
534 reinit_for (dim);
535}
536
540template <typename TGridFunction>
541template <int refDim>
543(
544 number vValue[],
545 const MathVector<wDim> vGlobIP[],
546 number time,
547 int si,
548 GridObject* grid_obj,
549 const MathVector<wDim> vCornerCoords[],
550 const MathVector<refDim> vLocIP[],
551 const size_t nip,
552 LocalVector* u,
553 bool bDeriv,
554 int s,
555 std::vector<std::vector<number> > vvvDeriv[],
556 const MathMatrix<refDim, wDim>* vJT
557)
558{
559 typedef typename gf_type::template dim_traits<refDim>::grid_base_object elem_type;
560
561// May be used only on the specified subsets!
562 if (! m_SsGrp.contains (si))
563 UG_THROW ("LSPosZData: Attempt to get the value for a subset that has not been specified.");
564
565// Interpolate the values
566
567 const ReferenceObjectID roid = grid_obj->reference_object_id ();
568 const elem_type * elem = dynamic_cast<elem_type *> (grid_obj);
569
570 const LocalShapeFunctionSet<refDim> & rTrialSpace =
571 LocalFiniteElementProvider::get<refDim> (roid, LFEID (LFEID::LAGRANGE, refDim, 1));
572
573 if (m_elem_dim == refDim)
574 {
575 typedef typename grid_dim_traits<refDim>::grid_base_object base_elem_t;
577 num_aa_t aa_elem_num (* m_sp_ls_pos_z->lsf()->domain()->grid (), m_a_elem_num);
578 size_t elem_no = aa_elem_num [elem];
579 if (elem_no == (size_t) -1)
580 UG_THROW ("LSPosZData: The object is not properly initialized.");
581 number z_val = m_elem_z [elem_no];
582 for (size_t ip = 0; ip < nip; ip++)
583 vValue [ip] = z_val;
584 if (bDeriv)
585 UG_THROW ("LSPosZData: No derivative for " << m_elem_dim << "d > 0d.");
586 }
587 else if (m_elem_dim == 0)
588 {
589 Grid::VertexAttachmentAccessor<num_a_type> aa_vrt_num (* m_sp_ls_pos_z->lsf()->domain()->grid (), m_a_elem_num);
590 std::vector<number> shape;
591
592 for (size_t ip = 0; ip < nip; ip++)
593 {
594 // evaluate at shapes at ip
595 rTrialSpace.shapes (shape, vLocIP [ip]);
596 UG_ASSERT (shape.size () == elem->num_vertices (), "LSPosZData: Hanging nodes are not supported!");
597
598 // compute solution at integration point
599 vValue [ip] = 0;
600 for(size_t sh = 0; sh < shape.size (); sh++)
601 {
602 const Vertex * vrt = elem->vertex (sh);
603 size_t vrt_no = aa_vrt_num [vrt];
604 if (vrt_no == (size_t) -1)
605 UG_THROW ("LSPosZData: The object is not properly initialized.");
606 vValue [ip] += m_elem_z [vrt_no] * shape [sh];
607 }
608 }
609
610 if (bDeriv)
611 {
612 for (size_t ip = 0; ip < nip; ip++)
613 {
614 rTrialSpace.shapes(shape, vLocIP [ip]);
615 for (size_t sh = 0; sh < shape.size(); sh++) vvvDeriv [ip] [0] [sh] = shape [sh];
616 }
617 }
618 }
619 else
620 UG_THROW ("LSPosZData: The object is reinitialized for a wrong dimensionality " << m_elem_dim << ".");
621}
622
623/*----- Class template 'LSPosZCellToVrtData': -----*/
624
628template <typename TGridFunction>
630(
631 SmartPtr<measurer_type>& sp_ls_pos_z,
632 const char * subsetNames
633)
634: m_sp_ls_pos_z (sp_ls_pos_z), m_use_ss_z_as_default (true), m_elem_dim (-1)
635{
636 if (! sp_ls_pos_z.valid ())
637 UG_THROW ("LSPosZCellToVrtData: The measurer not specified.");
638
639 SmartPtr<gf_type> spLSF (m_sp_ls_pos_z->lsf ());
640 m_SsGrp.set_subset_handler (spLSF->domain()->subset_handler ());
641 m_SsGrp.add (TokenizeString (subsetNames));
642
643 grid_type & grid = * spLSF->domain()->grid ();
644 grid.template attach_to_dv<Vertex> (m_a_vrt_div, 0);
645 grid.template attach_to_dv<Vertex> (m_a_height, 0);
646}
647
651template <typename TGridFunction>
653{
654 grid_type & grid = * m_sp_ls_pos_z->lsf()->domain()->grid ();
655
656 grid.template detach_from<Vertex> (m_a_vrt_div);
657 grid.template detach_from<Vertex> (m_a_height);
658}
659
663template <typename TGridFunction>
664template <typename TElem>
666(
667 num_a_type & a_elem_num,
668 MathVector<wDim-1> * xy_pos,
669 number * z_pos
670)
671{
672 typedef typename gf_type::template traits<TElem>::const_iterator elem_iter_t;
673 typedef typename geometry_traits<TElem>::grid_base_object base_elem_t;
675
676 SmartPtr<gf_type> spLSF (m_sp_ls_pos_z->lsf ());
677 pos_acc_type aa_pos = spLSF->domain()->position_accessor ();
678 num_aa_t aa_elem_num (* spLSF->domain()->grid (), a_elem_num);
679
680 for (size_t i = 0; i < m_SsGrp.size (); i++)
681 {
682 int si = m_SsGrp[i];
683 for (elem_iter_t iter = spLSF->template begin<TElem> (si);
684 iter != spLSF->template end<TElem> (si); ++iter)
685 {
686 TElem * elem = * iter;
687
688 // get the 'center' of the element
691
692 // get the position of the level set at the center
693 const size_t index = aa_elem_num [(base_elem_t *) elem];
694 MathVector<wDim-1> & xy = xy_pos [index];
695 for (size_t k = 0; k < wDim - 1; k++) xy[k] = xyz[k];
696 if (z_pos != NULL) z_pos [index] = xyz [wDim-1];
697 }
698 }
699}
700
707template <typename TGridFunction>
708template <int elemDim>
710{
711 typedef typename grid_dim_traits<elemDim>::grid_base_object elem_t;
712 typedef typename gf_type::template traits<elem_t>::const_iterator elem_iter_t;
713 typedef typename gf_type::template traits<Vertex>::const_iterator vert_iter_t;
714 typedef typename Grid::AttachmentAccessor<elem_t, num_a_type> num_aa_t;
715 typedef typename domain_traits<elemDim>::DimElemList ElemList;
716
717 SmartPtr<gf_type> spLSF (m_sp_ls_pos_z->lsf ());
718 bool default_used = false;
719
720 m_elem_dim = elemDim;
721
722 grid_type & grid = * spLSF->domain()->grid ();
723
724// initialize the vertex attachments
725
726 cnt_aa_t aa_vrt_div (grid, m_a_vrt_div);
727 SetAttachmentValues (aa_vrt_div, spLSF->template begin<Vertex> (), spLSF->template end<Vertex> (), 0);
728
729 h_aa_t aa_height (grid, m_a_height);
730 SetAttachmentValues (aa_height, spLSF->template begin<Vertex> (), spLSF->template end<Vertex> (), 0);
731
732// initialize the element attachment
733 num_a_type a_elem_num; // attachment keeping a numbering of the elements (vertices etc.) in the subsets
734 grid.template attach_to_dv<elem_t> (a_elem_num, (size_t) -1);
735 num_aa_t aa_elem_num (grid, a_elem_num);
736 size_t elem_num = 0;
737 for (size_t i = 0; i < m_SsGrp.size (); i++)
738 {
739 int si = m_SsGrp[i];
740 for (elem_iter_t iter = spLSF->template begin<elem_t> (si);
741 iter != spLSF->template end<elem_t> (si); ++iter)
742 aa_elem_num [*iter] = elem_num++;
743 }
744
745// array for the depths
746 std::vector<number> elem_z;
747
748# ifndef UG_PARALLEL
749 {
750 // initialize the values
751 elem_z.resize (elem_num);
752 std::vector<MathVector<wDim-1> > eval_pos (elem_num);
753 std::vector<number> z_pos; number * z_pos_ptr = NULL;
754 if (m_use_ss_z_as_default)
755 {
756 z_pos.resize (elem_num);
757 z_pos_ptr = & (z_pos[0]);
758 }
759 boost::mpl::for_each<ElemList> (GetXYForElements (this, a_elem_num, & (eval_pos[0]), z_pos_ptr));
760 for (size_t j = 0; j < eval_pos.size (); j++)
761 if (! m_sp_ls_pos_z->get_height_at (eval_pos[j], elem_z[j]))
762 {
763 elem_z [j] = m_use_ss_z_as_default? z_pos[j] : m_default_height;
764 default_used = true;
765 }
766 }
767
768# else // i.e. ifdef UG_PARALLEL
769
770 {
771 pcl::ProcessCommunicator proc_comm;
772
773 // get the points where the values must be computed
774 std::vector<MathVector<wDim-1> > proc_pos (elem_num);
775 std::vector<number> z_pos; number * z_pos_ptr = NULL;
776 if (m_use_ss_z_as_default)
777 {
778 z_pos.resize (elem_num);
779 z_pos_ptr = & (z_pos[0]);
780 }
781 boost::mpl::for_each<ElemList> (GetXYForElements (this, a_elem_num, & (proc_pos[0]), z_pos_ptr));
782
783 std::vector<MathVector<wDim-1> > all_pos;
784 std::vector<int> offset;
785 proc_comm.allgatherv (all_pos, proc_pos, NULL, &offset);
786
787 // compute the values at all the positions
788 std::vector<number> tmp_elem_z (all_pos.size ());
789 for (size_t j = 0; j < tmp_elem_z.size (); j++)
790 if (! m_sp_ls_pos_z->get_height_at (all_pos[j], tmp_elem_z [j]))
791 tmp_elem_z [j] = - std::numeric_limits<number>::max (); // the position is not covered by the free surface in this process
792
793 // compose the common values
794 std::vector<number> all_elem_z (tmp_elem_z.size ());
795 proc_comm.allreduce (tmp_elem_z, all_elem_z, PCL_RO_MAX);
796
797 // extract the values from the common array
798 elem_z.resize (elem_num);
799 int my_offset = offset [proc_comm.get_local_proc_id ()];
800 if (! m_use_ss_z_as_default)
801 {
802 for (size_t j = 0; j < elem_num; j++)
803 {
804 number z_val = all_elem_z [my_offset + j];
805 if (z_val == - std::numeric_limits<number>::max ()) // i.e. is not set in any process
806 {
807 elem_z [j] = m_default_height;
808 default_used = true;
809 }
810 else
811 elem_z [j] = z_val;
812 }
813 }
814 else
815 {
816 for (size_t i = 0; i < m_SsGrp.size (); i++)
817 {
818 int si = m_SsGrp[i];
819 for (elem_iter_t iter = spLSF->template begin<elem_t> (si);
820 iter != spLSF->template end<elem_t> (si); ++iter)
821 {
822 elem_t * vrt = * iter;
823 size_t j = aa_elem_num [vrt];
824 number z_val = all_elem_z [my_offset + j];
825 if (z_val == - std::numeric_limits<number>::max ()) // i.e. is not set in any process
826 {
827 elem_z [j] = z_pos[j];
828 default_used = true;
829 }
830 else
831 elem_z [j] = z_val;
832 }
833 }
834 }
835 }
836
837# endif // UG_PARALLEL
838
839// average the values in the vertices
840 for (size_t i = 0; i < m_SsGrp.size (); i++)
841 {
842 int si = m_SsGrp[i];
843 for (elem_iter_t iter = spLSF->template begin<elem_t> (si);
844 iter != spLSF->template end<elem_t> (si); ++iter)
845 {
846 elem_t * elem = *iter;
847 for (size_t j = 0; j < elem->size (); j++)
848 {
849 aa_height [(* elem) [j]] += elem_z [aa_elem_num [elem]];
850 aa_vrt_div [(* elem) [j]] ++;
851 }
852 }
853 }
854
855# ifdef UG_PARALLEL
856 AttachmentAllReduce<Vertex> (grid, m_a_vrt_div, PCL_RO_SUM);
857 AttachmentAllReduce<Vertex> (grid, m_a_height, PCL_RO_SUM);
858# endif
859
860 for (vert_iter_t v_iter = spLSF->template begin<Vertex> ();
861 v_iter != spLSF->template end<Vertex> (); ++v_iter)
862 {
863 Vertex * v = *v_iter;
864 if (aa_vrt_div [v] != 0) // otherwise we did not visit that vertex
865 aa_height [v] /= aa_vrt_div [v];
866 }
867
868// detach the element attachment
869 grid.template detach_from<elem_t> (a_elem_num);
870
871// warn about the default values if used
872 if (default_used)
873 {
874 UG_LOG ("LSPosZData::reinit: Some parts of the level set is not under the specified subsets.");
875 if (m_use_ss_z_as_default)
876 {
877 UG_LOG (" Position of the subsets is used instead.\n");
878 }
879 else
880 {
881 UG_LOG (" Default value " << m_default_height << " used.\n");
882 }
883 }
884}
885
890template <typename TGridFunction>
892(
893 int dim
894)
895{
896 if (dim < 0) reinit (); // restart with the correct dimensionality
897 else if (dim == 0)
898 {
899 UG_THROW ("LSPosZCellToVrtData::reinit_for is not implemented for vertices (0d). Use LSPosZData instead.");
900 }
901 else if (dim == 1) reinit_for_<1> ();
902#if defined (UG_DIM_2) || defined (UG_DIM_3)
903 else if (dim == 2) reinit_for_<2> ();
904#endif
905#if defined (UG_DIM_3)
906 else if (dim == 3) reinit_for_<3> ();
907#endif
908 else
909 UG_THROW ("LSPosZCellToVrtData::reinit_for: Illegal dimensionality " << dim << " specified.");
910}
911
916template <typename TGridFunction>
918{
919// get the highest dimension of the subset elements
920 int dim = m_SsGrp.get_highest_subset_dimension ();
921
922# ifdef UG_PARALLEL
923 {
924 pcl::ProcessCommunicator proc_comm;
925 dim = proc_comm.allreduce (dim, PCL_RO_MAX);
926 }
927# endif
928
929// reinit for the computed dimensionality
930 reinit_for (dim);
931}
932
936template <typename TGridFunction>
937template <int refDim>
939(
940 number vValue[],
941 const MathVector<wDim> vGlobIP[],
942 number time,
943 int si,
944 GridObject* grid_obj,
945 const MathVector<wDim> vCornerCoords[],
946 const MathVector<refDim> vLocIP[],
947 const size_t nip,
948 LocalVector* u,
949 bool bDeriv,
950 int s,
951 std::vector<std::vector<number> > vvvDeriv[],
952 const MathMatrix<refDim, wDim>* vJT
953)
954{
955 typedef typename gf_type::template dim_traits<refDim>::grid_base_object elem_type;
956
957// May be used only on the specified subsets!
958 if (! m_SsGrp.contains (si))
959 UG_THROW ("LSPosZCellToVrtData: Attempt to get the value for a subset that has not been specified.");
960
961// Interpolate the values
962
963 const ReferenceObjectID roid = grid_obj->reference_object_id ();
964 const elem_type * elem = dynamic_cast<elem_type *> (grid_obj);
965
966 const LocalShapeFunctionSet<refDim> & rTrialSpace =
967 LocalFiniteElementProvider::get<refDim> (roid, LFEID (LFEID::LAGRANGE, refDim, 1));
968
969 cnt_aa_t aa_vrt_div (* m_sp_ls_pos_z->lsf()->domain()->grid (), m_a_vrt_div);
970 h_aa_t aa_vrt_h (* m_sp_ls_pos_z->lsf()->domain()->grid (), m_a_height);
971 std::vector<number> shape;
972
973 for (size_t ip = 0; ip < nip; ip++)
974 {
975 // evaluate at shapes at ip
976 rTrialSpace.shapes (shape, vLocIP [ip]);
977 UG_ASSERT (shape.size () == elem->num_vertices (), "LSPosZCellToVrtData: Hanging nodes are not supported!");
978
979 // compute solution at integration point
980 vValue [ip] = 0;
981 for(size_t sh = 0; sh < shape.size (); sh++)
982 {
983 const Vertex * vrt = elem->vertex (sh);
984 if (aa_vrt_div [vrt] == 0)
985 UG_THROW ("LSPosZCellToVrtData: Attempt to get the position of the level set in a subset where the object is not initialized");
986 number vrt_h = aa_vrt_h [vrt];
987 vValue [ip] += vrt_h * shape [sh];
988 }
989 }
990
991 if (bDeriv)
992 {
993 for (size_t ip = 0; ip < nip; ip++)
994 {
995 rTrialSpace.shapes(shape, vLocIP [ip]);
996 for (size_t sh = 0; sh < shape.size(); sh++) vvvDeriv [ip] [0] [sh] = shape [sh];
997 }
998 }
999}
1000
1001/*----- Class template 'LSPositionAtPoints': -----*/
1002
1006template <typename TLSPosZ>
1008(
1009 std::istream & in,
1010 bool z_given
1011)
1012{
1013 std::string input_line;
1014 std::istringstream line_stream;
1015
1016 line_stream.exceptions (std::istream::failbit | std::istream::badbit);
1017
1018 while (! in.eof ())
1019 {
1020 MathVector<dim-1> xy;
1021 number z_spec = 0;
1022
1023 if (in.fail ())
1024 UG_THROW ("LSPositionAtPoints: Could not load the points from the file!");
1025 std::getline (in, input_line);
1026 if (input_line.length () == 0)
1027 continue;
1028 try
1029 {
1030 line_stream.str (input_line);
1031 line_stream.clear ();
1032 for (size_t i = 0; i < dim-1; i++)
1033 line_stream >> xy[i];
1034 if (z_given)
1035 line_stream >> z_spec;
1036 }
1037 catch (std::istream::failure & e)
1038 {
1039 UG_THROW ("LSPositionAtPoints: Failed to parse line '" << input_line << "' in the input file.");
1040 };
1041
1042 add_pnt (xy, z_spec, z_given);
1043 }
1044}
1045
1049template <typename TLSPosZ>
1051(
1052 const char * file_name,
1053 bool z_given
1054)
1055{
1056 std::string full_file_name = FindFileInStandardPaths (file_name);
1057 UG_COND_THROW (full_file_name.empty (), "LSPositionAtPoints: Coulnd't locate file '" << file_name << "'.");
1058
1059 std::ifstream input (full_file_name.c_str (), std::ifstream::in);
1060 UG_COND_THROW (input.fail (), "LSPositionAtPoints: Cannot open data file '" << full_file_name << "' for input!");
1061 load_points_from (input, z_given);
1062}
1063
1067template <typename TLSPosZ>
1069{
1070 if (m_sp_ls_measurer.invalid ())
1071 UG_THROW ("LSPositionAtPoints: The measurer is not specified!");
1072
1073# ifndef UG_PARALLEL
1074
1075 for (size_t i = 0; i < m_v_points.size (); i++)
1076 {
1077 t_pnt_data & pnt = m_v_points[i];
1078 pnt.valid = m_sp_ls_measurer->get_height_at (pnt.xy, pnt.z);
1079 }
1080
1081# else // i.e. ifdef UG_PARALLEL
1082
1083 {
1084 pcl::ProcessCommunicator proc_comm;
1085 std::vector<number> loc_z (m_v_points.size ()), red_z (m_v_points.size ());
1086
1087 for (size_t i = 0; i < m_v_points.size (); i++)
1088 if (! m_sp_ls_measurer->get_height_at (m_v_points[i].xy, loc_z[i]))
1089 loc_z[i] = - std::numeric_limits<number>::max (); // the position is not covered by the free surface in this process
1090
1091 proc_comm.allreduce (loc_z, red_z, PCL_RO_MAX);
1092 for (size_t i = 0; i < m_v_points.size (); i++)
1093 {
1094 t_pnt_data & pnt = m_v_points[i];
1095 number z_val = red_z[i];
1096 if (z_val != - std::numeric_limits<number>::max ()) // i.e. is not set in any process
1097 {
1098 pnt.z = z_val;
1099 pnt.valid = true;
1100 }
1101 else
1102 pnt.valid = false;
1103 }
1104 }
1105
1106# endif // UG_PARALLEL
1107}
1108
1112template <typename TLSPosZ>
1114(
1115 std::ostream & out,
1116 bool print_difference
1117)
1118{
1119 if (m_sp_ls_measurer.invalid ())
1120 UG_THROW ("LSPositionAtPoints: The measurer is not specified!");
1121
1122 for (size_t i = 0; i < m_v_points.size (); i++)
1123 {
1124 const t_pnt_data & pnt = m_v_points[i];
1125 for (size_t j = 0; j < dim - 1; j++)
1126 out << pnt.xy[j] << '\t';
1127 if (pnt.valid)
1128 out << pnt.z;
1129 else
1130 out << "nAn";
1131 if (pnt.z_given)
1132 {
1133 out << '\t' << pnt.z_spec;
1134 if (print_difference)
1135 {
1136 if (pnt.valid)
1137 out << '\t' << pnt.z - pnt.z_spec;
1138 else
1139 out << "\tnAn";
1140 }
1141 }
1142 out << std::endl;
1143 }
1144}
1145
1149template <typename TLSPosZ>
1151(
1152 const char * file_name,
1153 bool print_difference
1154)
1155{
1156# ifdef UG_PARALLEL
1157 pcl::ProcessCommunicator proc_comm;
1158 if (pcl::ProcRank () != proc_comm.get_proc_id (0))
1159 return; // only the master process should print
1160# endif
1161
1162 std::ofstream output (file_name, std::ofstream::out);
1163 UG_COND_THROW (output.fail (), "LSPositionAtPoints: Cannot open data file '" << file_name << "' for output!");
1164 print_to (output, print_difference);
1165}
1166
1170template <typename TLSPosZ>
1172(
1173 const char * file_name,
1174 size_t step,
1175 number time
1176)
1177{
1178# ifdef UG_PARALLEL
1179 pcl::ProcessCommunicator proc_comm;
1180 if (pcl::ProcRank () != proc_comm.get_proc_id (0))
1181 return; // only the master process should print
1182# endif
1183
1184 std::ofstream out (file_name, std::ofstream::app);
1185 UG_COND_THROW (out.fail (), "LSPositionAtPoints: Cannot open data file '" << file_name << "' for output!");
1186
1187 out.unsetf (std::ios::fixed | std::ios::scientific);
1188 out.precision (16);
1189
1190 for (size_t i = 0; i < m_v_points.size (); i++)
1191 {
1192 out << step << '\t' << time << '\t';
1193 const t_pnt_data & pnt = m_v_points[i];
1194 if (pnt.valid)
1195 out << pnt.z;
1196 else
1197 out << "nAn";
1198 out << std::endl;
1199 }
1200}
1201
1205template <typename TLSPosZ>
1207(
1208 const char * file_name
1209)
1210{
1211# ifdef UG_PARALLEL
1212 pcl::ProcessCommunicator proc_comm;
1213 if (pcl::ProcRank () != proc_comm.get_proc_id (0))
1214 return; // only the master process should print
1215# endif
1216
1217 std::ofstream out (file_name, std::ofstream::out);
1218 UG_COND_THROW (out.fail (), "LSPositionAtPoints: Cannot open data file '" << file_name << "' for output!");
1219
1220 out.unsetf (std::ios::fixed | std::ios::scientific);
1221 out.precision (8);
1222
1223 for (size_t k = 0; k < dim - 1; k++)
1224 {
1225 out << "# ----\t----";
1226 for (size_t i = 0; i < m_v_points.size (); i++)
1227 {
1228 const t_pnt_data & pnt = m_v_points[i];
1229 out << '\t' << pnt.xy[k];
1230 }
1231 out << std::endl;
1232 }
1233 out << "# step\ttime";
1234 for (size_t i = 0; i < m_v_points.size (); i++)
1235 {
1236 const t_pnt_data & pnt = m_v_points[i];
1237 if (pnt.z_given)
1238 out << '\t' << pnt.z_spec;
1239 else
1240 out << '\t' << "----";
1241 }
1242 out << std::endl;
1243}
1244
1245} // end namespace d3f
1246} // end namespace ug
1247
1248/* End of File */
parameterString s
Definition Biogas.lua:2
bool valid() const
size_t allreduce(const size_t &t, pcl::ReduceOperation op) const
int get_proc_id(size_t index) const
void allgatherv(const void *sendBuf, int sendCount, DataType sendType, void *recBuf, int *recCounts, int *displs, DataType recType) const
int get_local_proc_id(int globalProcID=pcl::ProcRank()) const
virtual void global_to_local(MathVector< dim > &locPos, const MathVector< worldDim > &globPos, const size_t maxIter=1000, const number tol=1e-10) const=0
virtual ReferenceObjectID reference_object_id() const=0
virtual void shapes(std::vector< std::vector< shape_type > > &vvShape, const std::vector< MathVector< dim > > &vLocPos) const=0
void resize(const LocalIndices &ind)
void add(const char *name)
void set_subset_handler(ConstSmartPtr< ISubsetHandler > sh)
domain_type::grid_type grid_type
grid type
Definition level_set_pos.h:449
SmartPtr< measurer_type > m_sp_ls_pos_z
the object to measure the z-coordinate of the level set
Definition level_set_pos.h:563
LSPosZCellToVrtData(SmartPtr< measurer_type > &sp_ls_pos_z, const char *subsets)
Constructor.
Definition level_set_pos_impl.h:630
~LSPosZCellToVrtData()
Destructor.
Definition level_set_pos_impl.h:652
void reinit_for(int dim)
Initializer (should be called before every use). Reinialize the measurer before running this reinit!
Definition level_set_pos_impl.h:892
void reinit_for_()
Initializer for the constant dimensionality.
Definition level_set_pos_impl.h:709
h_a_type m_a_height
attachment keeping the averaged height at the vertex
Definition level_set_pos.h:570
domain_type::position_accessor_type pos_acc_type
position attachment accessor type
Definition level_set_pos.h:452
void reinit()
Initializer (should be called before every use). Reinialize the measurer before running this reinit!
Definition level_set_pos_impl.h:917
void eval_and_deriv(number vValue[], const MathVector< wDim > vGlobIP[], number time, int si, GridObject *elem, const MathVector< wDim > vCornerCoords[], const MathVector< refDim > vLocIP[], const size_t nip, LocalVector *u, bool bDeriv, int s, std::vector< std::vector< number > > vvvDeriv[], const MathMatrix< refDim, wDim > *vJT=NULL)
Performs the main computations:
Definition level_set_pos_impl.h:939
SubsetGroup m_SsGrp
(low-dimensional) subsets to compute the coordinates over
Definition level_set_pos.h:561
cnt_a_type m_a_vrt_div
attachment keeping the number of the elements adjecent to a vertex
Definition level_set_pos.h:569
void get_xy_for_all_(num_a_type &a_elem_num, MathVector< wDim-1 > *xy_pos, number *z_pos)
Computes the xy-coordinates of the evaluation points for all elements of the given type.
Definition level_set_pos_impl.h:666
static void get(elem_t *elem, pos_acc_t &aa_pos, MathVector< dim > &eval_pnt)
Definition level_set_pos_impl.h:243
RegularVertex elem_t
Definition level_set_pos_impl.h:238
TAAPos pos_acc_t
Definition level_set_pos_impl.h:237
Definition level_set_pos_impl.h:207
static void get(elem_t *elem, pos_acc_t &aa_pos, MathVector< dim > &eval_pnt)
Definition level_set_pos_impl.h:216
reference_element_traits< elem_t >::reference_element_type ref_elem_t
Definition level_set_pos_impl.h:211
TAAPos pos_acc_t
Definition level_set_pos_impl.h:209
TElem elem_t
Definition level_set_pos_impl.h:210
static const int dim
Definition level_set_pos_impl.h:208
void reinit()
Initializer (should be called before every use). Reinialize the measurer before running this reinit!
Definition level_set_pos_impl.h:521
SmartPtr< measurer_type > m_sp_ls_pos_z
the object to measure the z-coordinate of the level set
Definition level_set_pos.h:408
domain_type::position_accessor_type pos_acc_type
position attachment accessor type
Definition level_set_pos.h:301
LSPosZData(SmartPtr< measurer_type > &sp_ls_pos_z, const char *subsets)
Constructor.
Definition level_set_pos_impl.h:261
~LSPosZData()
Destructor.
Definition level_set_pos_impl.h:279
void reinit_for(int dim)
Initializer (should be called before every use). Reinialize the measurer before running this reinit!
Definition level_set_pos_impl.h:499
void eval_and_deriv(number vValue[], const MathVector< wDim > vGlobIP[], number time, int si, GridObject *elem, const MathVector< wDim > vCornerCoords[], const MathVector< refDim > vLocIP[], const size_t nip, LocalVector *u, bool bDeriv, int s, std::vector< std::vector< number > > vvvDeriv[], const MathMatrix< refDim, wDim > *vJT=NULL)
Performs the main computations:
Definition level_set_pos_impl.h:543
void get_xy_for_all_(MathVector< wDim-1 > *xy_pos, number *z_pos)
Computes the xy-coordinates of the evaluation points for all elements of the given type.
Definition level_set_pos_impl.h:290
void detach_for_()
Destroys the attachment (for the templated dimensionality)
Definition level_set_pos_impl.h:468
void reinit_for_()
Initializer for the constant dimensionality.
Definition level_set_pos_impl.h:330
SubsetGroup m_SsGrp
(low-dimensional) subsets to compute the coordinates over
Definition level_set_pos.h:406
void detach_for(int dim)
Destroys the attachment (for a variable dimensionality)
Definition level_set_pos_impl.h:479
void append_to_table(const char *file_name, size_t step, number time)
appends the data to a given file
Definition level_set_pos_impl.h:1172
void compute()
compute the z-coordinates
Definition level_set_pos_impl.h:1068
void load_points_from(std::istream &in, bool z_given=false)
load points from a stream
Definition level_set_pos_impl.h:1008
void print_table_header(const char *file_name)
prints the table header to a given file
Definition level_set_pos_impl.h:1207
void print_to(std::ostream &out, bool print_difference=false)
prints the table of the points into a given stream
Definition level_set_pos_impl.h:1114
TGridFunction::element_type elem_type
generic element type
Definition level_set_pos.h:61
void get_z(std::vector< number > &z, number small_z=1e-12)
get the point at the level set
Definition level_set_pos_impl.h:122
int lsf_sign(size_t noc, number lsf[])
sign of the LSF in the element
Definition level_set_pos_impl.h:39
bool get_intersected(const MathVector< dim-1 > &xy)
get the elements intersected by the ray
Definition level_set_pos_impl.h:95
void fill_cut()
get the elements cut by the level set
Definition level_set_pos_impl.h:58
SmartPtr< TGrid > grid()
void CollectCornerCoordinates(int base_object_id, std::vector< typename TDomain::position_type > &vCornerCoordsOut, GridObject &elem, const TDomain &domain, bool clearContainer)
void SetAttachmentValues(TAttachmentAccessor &aaVal, TIter elemsBegin, TIter elemsEnd, const TVal &val)
#define PCL_RO_SUM
int ProcRank()
#define PCL_RO_MAX
std::string FindFileInStandardPaths(const char *filename)
vector< string > TokenizeString(const char *str, const char delimiter=',')
#define UG_ASSERT(expr, msg)
#define UG_THROW(msg)
#define UG_LOG(msg)
#define UG_COND_THROW(cond, msg)
double number
vector_t PointOnRay(const vector_t &from, const vector_t &dir, number s)
ReferenceObjectID
bool RayElementIntersections(std::vector< RayElemIntersectionRecord< typename tree_t::elem_t > > &intersectionsOut, const tree_t &tree, const typename tree_t::vector_t &rayFrom, const typename tree_t::vector_t &rayDir, const number small=1.e-12)
void GetLocalVector(LocalVector &lvec, const TVector &vec)
void VecSet(vector_t &dest, number alpha, const std::vector< size_t > vIndex)
Helper class for computation of the position of the level set in all the elements.
Definition level_set_pos.h:542
Helper class for computation of the position of the level set in all the elements.
Definition level_set_pos.h:378
type of point data
Definition level_set_pos.h:710
number z
computed value of the z-coordiate
Definition level_set_pos.h:712
bool z_given
iff z is specified
Definition level_set_pos.h:714
number z_spec
expected value of z-coordinate
Definition level_set_pos.h:713
MathVector< dim-1 > xy
low-dim coordinate of the point
Definition level_set_pos.h:711
bool valid
if not computed or the level set is not covered by the top surface
Definition level_set_pos.h:716
a structure to get the intersection points of an element
Definition level_set_pos.h:83
MathVector< dim > pnt[2]
the intersection points
Definition level_set_pos.h:85
elem_type * elem
the intersected element
Definition level_set_pos.h:84