Plugins
Loading...
Searching...
No Matches
ls_integral_impl.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021: 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
39#ifdef UG_PARALLEL
41#endif
42
43#include "ls_volume.h"
44
45namespace ug{
46namespace LevelSet{
47
48/*---- Class 'LSIntegral': ----*/
49
53template <typename TGridFunc>
55(
56 SmartPtr<gf_type> sp_gf,
57 const char * fct_name
58)
59{
60// The full-dim. grid element types for this dimension:
61 typedef typename domain_traits<dim>::DimElemList ElemList;
62
63 m_sp_gf = sp_gf;
64 if ((m_fct = sp_gf->fct_id_by_name (fct_name)) >= sp_gf->num_fct ())
65 UG_THROW ("LSIntegral: Function space does not contain any function with name '" << fct_name << "'.");
66
67 if (sp_gf->local_finite_element_id (m_fct) != LFEID(LFEID::LAGRANGE, dim, 1))
68 UG_THROW ("LSIntegral: Only vertex-centered grid functions are supported.");
69
70 int n_ss = m_spLSF->num_subsets ();
71
72// sum up all the integrals
73 m_integral = 0;
74 m_ss_integral.resize (n_ss);
75 for (int si = 0; si < n_ss; si++) m_ss_integral[si] = 0;
76 boost::mpl::for_each<ElemList> (AddIntegrals (this));
77
78#ifdef UG_PARALLEL
79// sum up the volumes from different processes
81 m_integral = procComm.allreduce (m_integral, PCL_RO_SUM);
82
83 for (int si = 0; si < n_ss; si++)
84 m_ss_integral[si] = procComm.allreduce (m_ss_integral[si], PCL_RO_SUM);
85#endif
86}
87
91template <typename TGridFunc>
93(
94 const char * ss_names
95) const
96{
97 SubsetGroup ss_grp (m_spLSF->domain()->subset_handler ());
98 ss_grp.add (TokenizeString (ss_names));
99
100 number ss_integral = 0;
101 for (size_t i = 0; i < ss_grp.size (); i++)
102 ss_integral += m_ss_integral[ss_grp[i]];
103 return ss_integral;
104}
105
109template <typename TGridFunc>
110template <typename TElem>
112{
113 typedef typename gf_type::template traits<TElem>::const_iterator ElemIter;
115
116 static const size_t num_corners = ref_elem_t::numCorners;
117
118 const ls_gf_type & lsf = * m_spLSF;
119 const gf_type & integrand = * m_sp_gf;
120 const position_accessor_type & aaPos = lsf.domain()->position_accessor ();
121 std::vector<DoFIndex> ind (1);
122 MathVector<dim> corners [num_corners];
123 number lsf_values [num_corners];
124
125 for (int si = 0; si < lsf.num_subsets (); si++)
126 {
127 if (m_ssGrp.subset_handler().valid () && ! m_ssGrp.contains (si))
128 continue; // skip this subset: it is not mentioned in the specified list
129
130 number ss_integral = 0;
131 ElemIter iterEnd = lsf.template end<TElem> (si);
132 for (ElemIter iter = lsf.template begin<TElem> (si); iter != iterEnd; ++iter)
133 {
134 TElem * elem = *iter;
135
136 // get the corner coordinates ans the values of the LSF
137 for (size_t i = 0; i < num_corners; i++)
138 {
139 Vertex * vrt = elem->vertex (i);
140 corners [i] = aaPos [vrt];
141 if (lsf.inner_dof_indices (vrt, 0, ind) != 1)
142 UG_THROW ("LSIntegral: Not a scalar grid function for the LSF!");
143 lsf_values [i] = DoFRef (lsf, ind [0]);
144 }
145
146 // compute the volumes
147 number vol_plus, vol_minus;
148 if (LSElementSize<ref_elem_t, dim>::compute (corners, lsf_values, vol_plus, vol_minus) > 0)
149 continue;
150
151 // get the average of the integrand
152 number ave_integrand = 0;
153 size_t n_co_minus = 0;
154 for (size_t i = 0; i < num_corners; i++)
155 if (lsf_values [i] < 0)
156 {
157 Vertex * vrt = elem->vertex (i);
158 if (integrand.inner_dof_indices (vrt, m_fct, ind) != 1)
159 UG_THROW ("LSIntegral: Not a scalar grid function for the integrand!");
160 ave_integrand += DoFRef (integrand, ind[0]);
161 n_co_minus++;
162 }
163 if (n_co_minus == 0) // this can happen because of the treatment of pos/neg nodes in LSElementSize
164 continue;
165
166 // add the contribution to the subset
167 ss_integral += vol_minus * ave_integrand / n_co_minus;
168 }
169 m_ss_integral[si] += ss_integral;
170 m_integral += ss_integral;
171 }
172}
173
174/*---- Class 'LSHeavisideIntegral': ----*/
175
179template <typename TGridFunc>
181(
182 SmartPtr<gf_type> sp_gf,
183 const char * fct_name,
184 number limval
185)
186{
187// The full-dim. grid element types for this dimension:
188 typedef typename domain_traits<dim>::DimElemList ElemList;
189
190 m_sp_gf = sp_gf; m_limval = limval;
191 if ((m_fct = sp_gf->fct_id_by_name (fct_name)) >= sp_gf->num_fct ())
192 UG_THROW ("LSHeavisideIntegral: Function space does not contain any function with name '" << fct_name << "'.");
193
194 if (sp_gf->local_finite_element_id (m_fct) != LFEID(LFEID::LAGRANGE, dim, 1))
195 UG_THROW ("LSHeavisideIntegral: Only vertex-centered grid functions are supported.");
196
197 int n_ss = m_spLSF->num_subsets ();
198
199// sum up all the integrals
200 m_levol = m_gevol = 0;
201 m_ss_levol.resize (n_ss); m_ss_gevol.resize (n_ss);
202 for (int si = 0; si < n_ss; si++) m_ss_levol[si] = m_ss_gevol[si] = 0;
203 boost::mpl::for_each<ElemList> (AddIntegrals (this));
204
205#ifdef UG_PARALLEL
206// sum up the volumes from different processes
208 m_levol = procComm.allreduce (m_levol, PCL_RO_SUM);
209 m_gevol = procComm.allreduce (m_gevol, PCL_RO_SUM);
210
211 for (int si = 0; si < n_ss; si++)
212 {
213 m_ss_levol[si] = procComm.allreduce (m_ss_levol[si], PCL_RO_SUM);
214 m_ss_gevol[si] = procComm.allreduce (m_ss_gevol[si], PCL_RO_SUM);
215 }
216#endif
217}
218
222template <typename TGridFunc>
224(
225 const char * ss_names
226) const
227{
228 SubsetGroup ss_grp (m_spLSF->domain()->subset_handler ());
229 ss_grp.add (TokenizeString (ss_names));
230
231 number ss_levol = 0;
232 for (size_t i = 0; i < ss_grp.size (); i++)
233 ss_levol += m_ss_levol[ss_grp[i]];
234 return ss_levol;
235}
236
240template <typename TGridFunc>
242(
243 const char * ss_names
244) const
245{
246 SubsetGroup ss_grp (m_spLSF->domain()->subset_handler ());
247 ss_grp.add (TokenizeString (ss_names));
248
249 number ss_gevol = 0;
250 for (size_t i = 0; i < ss_grp.size (); i++)
251 ss_gevol += m_ss_gevol[ss_grp[i]];
252 return ss_gevol;
253}
254
258template <typename TGridFunc>
259template <typename TElem>
261{
262 typedef typename gf_type::template traits<TElem>::const_iterator ElemIter;
264
265 static const size_t num_corners = ref_elem_t::numCorners;
266
267 const ls_gf_type & lsf = * m_spLSF;
268 const gf_type & integrand = * m_sp_gf;
269 const position_accessor_type & aaPos = lsf.domain()->position_accessor ();
270 std::vector<DoFIndex> ind (1);
271 MathVector<dim> corners [num_corners];
272 number lsf_values [num_corners];
273
274 for (int si = 0; si < lsf.num_subsets (); si++)
275 {
276 if (m_ssGrp.subset_handler().valid () && ! m_ssGrp.contains (si))
277 continue; // skip this subset: it is not mentioned in the specified list
278
279 number ss_levol = 0, ss_gevol = 0;
280 ElemIter iterEnd = lsf.template end<TElem> (si);
281 for (ElemIter iter = lsf.template begin<TElem> (si); iter != iterEnd; ++iter)
282 {
283 TElem * elem = *iter;
284
285 // get the corner coordinates ans the values of the LSF
286 for (size_t i = 0; i < num_corners; i++)
287 {
288 Vertex * vrt = elem->vertex (i);
289 corners [i] = aaPos [vrt];
290 if (lsf.inner_dof_indices (vrt, 0, ind) != 1)
291 UG_THROW ("LSHeavisideIntegral: Not a scalar grid function for the LSF!");
292 lsf_values [i] = DoFRef (lsf, ind [0]);
293 }
294
295 // compute the volumes
296 number vol_plus, vol_minus;
297 if (LSElementSize<ref_elem_t, dim>::compute (corners, lsf_values, vol_plus, vol_minus) > 0)
298 continue;
299
300 // get the averaged integrand
301 size_t sum_integrand = 0;
302 size_t n_co_minus = 0;
303 for (size_t i = 0; i < num_corners; i++)
304 if (lsf_values [i] < 0)
305 {
306 Vertex * vrt = elem->vertex (i);
307 if (integrand.inner_dof_indices (vrt, m_fct, ind) != 1)
308 UG_THROW ("LSHeavisideIntegral: Not a scalar grid function for the integrand!");
309 number gf_val = DoFRef (integrand, ind[0]);
310 if (gf_val <= m_limval)
311 sum_integrand += 1;
312 n_co_minus++;
313 }
314 if (n_co_minus == 0) // this can happen because of the treatment of pos/neg nodes in LSElementSize
315 continue;
316
317 // add the contribution to the subset
318 ss_levol += (vol_minus * sum_integrand) / n_co_minus;
319 ss_gevol += (vol_minus * (n_co_minus - sum_integrand)) / n_co_minus;
320 }
321 m_ss_levol[si] += ss_levol; m_ss_gevol[si] += ss_gevol;
322 m_levol += ss_levol; m_gevol += ss_gevol;
323 }
324}
325
326/*---- Class 'FVLSIntegral': ----*/
327
331template <typename TGridFunc>
333(
334 SmartPtr<gf_type> sp_gf,
335 const char * fct_name
336)
337{
338// The full-dim. grid element types for this dimension:
339 typedef typename domain_traits<dim>::DimElemList ElemList;
340
341 m_sp_gf = sp_gf;
342 if ((m_fct = sp_gf->fct_id_by_name (fct_name)) >= sp_gf->num_fct ())
343 UG_THROW ("FVLSIntegral: Function space does not contain any function with name '" << fct_name << "'.");
344
345 if (sp_gf->local_finite_element_id (m_fct) != LFEID(LFEID::LAGRANGE, dim, 1))
346 UG_THROW ("FVLSIntegral: Only vertex-centered grid functions are supported.");
347
348 int n_ss = m_spLSF->num_subsets ();
349
350// sum up all the integrals
351 m_integral = 0;
352 m_ss_integral.resize (n_ss);
353 for (int si = 0; si < n_ss; si++) m_ss_integral[si] = 0;
354 boost::mpl::for_each<ElemList> (AddIntegrals (this));
355
356#ifdef UG_PARALLEL
357// sum up the volumes from different processes
359 m_integral = procComm.allreduce (m_integral, PCL_RO_SUM);
360
361 for (int si = 0; si < n_ss; si++)
362 m_ss_integral[si] = procComm.allreduce (m_ss_integral[si], PCL_RO_SUM);
363#endif
364}
365
369template <typename TGridFunc>
371(
372 const char * ss_names
373) const
374{
375 SubsetGroup ss_grp (m_spLSF->domain()->subset_handler ());
376 ss_grp.add (TokenizeString (ss_names));
377
378 number ss_integral = 0;
379 for (size_t i = 0; i < ss_grp.size (); i++)
380 ss_integral += m_ss_integral[ss_grp[i]];
381 return ss_integral;
382}
383
387template <typename TGridFunc>
388template <typename TElem>
390{
391 typedef typename gf_type::template traits<TElem>::const_iterator ElemIter;
393 typedef FV1Geometry<TElem, dim> TFVGeom;
394
395 static const size_t num_corners = ref_elem_t::numCorners;
396
397 const ls_gf_type & lsf = * m_spLSF;
398 const gf_type & integrand = * m_sp_gf;
399 const position_accessor_type & aaPos = lsf.domain()->position_accessor ();
400 std::vector<DoFIndex> ind (1);
401 MathVector<dim> corners [num_corners];
402 number lsf_values [num_corners];
403
404 for (int si = 0; si < lsf.num_subsets (); si++)
405 {
406 if (m_ssGrp.subset_handler().valid () && ! m_ssGrp.contains (si))
407 continue; // skip this subset: it is not mentioned in the specified list
408
409 number ss_integral = 0;
410 ElemIter iterEnd = lsf.template end<TElem> (si);
411 for (ElemIter iter = lsf.template begin<TElem> (si); iter != iterEnd; ++iter)
412 {
413 TElem * elem = *iter;
414
415 // get the corner coordinates ans the values of the LSF
416 bool elem_to_compute = false;
417 for (size_t i = 0; i < num_corners; i++)
418 {
419 Vertex * vrt = elem->vertex (i);
420 corners [i] = aaPos [vrt];
421 if (lsf.inner_dof_indices (vrt, 0, ind) != 1)
422 UG_THROW ("FVLSIntegral: Not a scalar grid function for the LSF!");
423 lsf_values [i] = DoFRef (lsf, ind [0]);
424 if (lsf_values [i] <= 0) elem_to_compute = true;
425 }
426 if (! elem_to_compute)
427 continue;
428
429 // compute the FV geometry
430 static TFVGeom& geo = GeomProvider<TFVGeom>::get ();
431 try
432 {
433 geo.update (elem, corners);
434 }
435 UG_CATCH_THROW ("FVLSIntegral: Cannot update Finite Volume Geometry.");
436
437 // get the average of the integrand
438 for (size_t i = 0; i < num_corners; i++)
439 if (lsf_values [i] <= 0)
440 {
441 Vertex * vrt = elem->vertex (i);
442 if (integrand.inner_dof_indices (vrt, m_fct, ind) != 1)
443 UG_THROW ("FVLSIntegral: Not a scalar grid function for the integrand!");
444 const number dof_val = DoFRef (integrand, ind[0]);
445 const number scv_vol = geo.scv(i).volume ();
446 ss_integral += scv_vol * dof_val;
447 }
448 }
449 m_ss_integral[si] += ss_integral;
450 m_integral += ss_integral;
451 }
452}
453
454} // end namespace LevelSet
455} // end namespace ug
456
457/* End of File */
size_t allreduce(const size_t &t, pcl::ReduceOperation op) const
static TGeom & get()
size_t inner_dof_indices(TElem *elem, size_t fct, std::vector< DoFIndex > &ind, bool bClear=true) const
SmartPtr< TDomain > domain()
void compute_for(SmartPtr< gf_type > sp_gf, const char *fct_name)
computes the integrals
Definition ls_integral_impl.h:333
void add_integrals_of_all()
adds contributions of all elements of a given type
Definition ls_integral_impl.h:389
domain_type::position_accessor_type position_accessor_type
type of the position accessor
Definition ls_integral.h:328
TGridFunction gf_type
type of the grid function
Definition ls_integral.h:316
number integral_over_subsets(const char *ss_names) const
returns the integral over the negative part of subsets
Definition ls_integral_impl.h:371
Definition ls_volume.h:246
TGridFunction gf_type
type of the grid function
Definition ls_integral.h:187
domain_type::position_accessor_type position_accessor_type
type of the position accessor
Definition ls_integral.h:199
number ge_vol_over_subsets(const char *ss_names) const
returns the volume for gf >= limval over the given subsets
Definition ls_integral_impl.h:242
number le_vol_over_subsets(const char *ss_names) const
returns the volume for gf <= limval over the given subsets
Definition ls_integral_impl.h:224
void add_integrals_of_all()
adds contributions of all elements of a given type
Definition ls_integral_impl.h:260
void compute_for(SmartPtr< gf_type > sp_gf, const char *fct_name, number limval)
computes the integrals
Definition ls_integral_impl.h:181
number integral_over_subsets(const char *ss_names) const
returns the integral over the negative part of subsets
Definition ls_integral_impl.h:93
domain_type::position_accessor_type position_accessor_type
type of the position accessor
Definition ls_integral.h:84
TGridFunction gf_type
type of the grid function
Definition ls_integral.h:72
void add_integrals_of_all()
adds contributions of all elements of a given type
Definition ls_integral_impl.h:111
void compute_for(SmartPtr< gf_type > sp_gf, const char *fct_name)
computes the integrals
Definition ls_integral_impl.h:55
void add(const char *name)
size_t size() const
#define PCL_RO_SUM
vector< string > TokenizeString(const char *str, const char delimiter=',')
#define UG_CATCH_THROW(msg)
#define UG_THROW(msg)
double number
const number & DoFRef(const TMatrix &mat, const DoFIndex &iInd, const DoFIndex &jInd)
helper class for the computation of the volumes
Definition ls_integral.h:389
helper class for the computation of the volumes
Definition ls_integral.h:273
helper class for the computation of the volumes
Definition ls_integral.h:145