Loading [MathJax]/extensions/tex2jax.js
ug4
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
err_est_data_impl.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014-2015: G-CSC, Goethe University Frankfurt
3 * Authors: Dmitry Logashenko, Markus Breit
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
33namespace ug{
34
35// ******** class SideFluxErrEstData ********
36
38template <typename TDomain>
40(
42 const GridLevel& gl
43)
44{
45// Get and check the grid level:
46 if (gl.type () != GridLevel::SURFACE)
47 UG_THROW("SideFluxErrEstData::alloc_err_est_data:"
48 " The error estimator can work only with grid functions of the SURFACE type.");
49
50// Copy the parameters to the object:
51 m_errEstGL = gl;
52 m_spSV = spSV;
53
54// Prepare the attachment for the jumps of the fluxes over the sides:
56 MultiGrid * pMG = (MultiGrid *) (spSV->subset_handler()->multi_grid());
57 pMG->template attach_to_dv<side_type,ANumber>(m_aFluxJumpOverSide, 0);
58 m_aaFluxJump.access(*pMG, m_aFluxJumpOverSide);
59};
60
62template <typename TDomain>
64{
66
67 const MultiGrid * pMG = m_spSV->subset_handler()->multi_grid();
68
69// Loop the rim sides and add the jumps
70 typedef typename SurfaceView::traits<side_type>::const_iterator t_iterator;
71 t_iterator end_rim_side_iter = m_spSV->template end<side_type> (m_errEstGL, SurfaceView::SHADOW_RIM);
72 for (t_iterator rim_side_iter = m_spSV->template begin<side_type> (m_errEstGL, SurfaceView::SHADOW_RIM);
73 rim_side_iter != end_rim_side_iter; ++rim_side_iter)
74 {
75 // Get the sides on both the levels
76 side_type * c_rim_side = *rim_side_iter;
77 if (pMG->template num_children<side_type>(c_rim_side) != 1) // we consider _NONCOPY only, no hanging nodes
78 UG_THROW ("SideFluxErrEstData::summarize_error_estimator:"
79 " The error estimator does not accept hanging nodes");
80 side_type * f_rim_side = pMG->template get_child<side_type> (c_rim_side, 0);
81
82 // Compute the total jump and save it for both the sides:
83 number & c_rim_flux = m_aaFluxJump[c_rim_side];
84 number & f_rim_flux = m_aaFluxJump[f_rim_side];
85 number flux_jump = f_rim_flux + c_rim_flux;
86 c_rim_flux = f_rim_flux = flux_jump;
87 }
88};
89
91template <typename TDomain>
93{
94// Release the attachment
96 MultiGrid * pMG = (MultiGrid *) (m_spSV->subset_handler()->multi_grid());
97 m_aaFluxJump.invalidate ();
98 pMG->template detach_from<side_type> (m_aFluxJumpOverSide);
99 //m_spSV = ConstSmartPtr<SurfaceView> (NULL); // this raises a rte
100};
101
102
103
104
105// ******** class SideAndElemErrEstData ********
106
107inline void check_subset_strings(std::vector<std::string> s)
108{
109 // remove white space
110 for (size_t i = 0; i < s.size(); i++)
112
113 // if no subset passed, clear subsets
114 if (s.size() == 1 && s[0].empty()) s.clear();
115
116 // if subsets passed with separator, but not all tokens filled, throw error
117 for (size_t i = 0; i < s.size(); i++)
118 {
119 if (s.empty())
120 {
121 UG_THROW("Error while setting subsets in SideAndElemErrEstData: Passed subset string lacks a "
122 "subset specification at position " << i << "(of " << s.size()-1 << ")");
123 }
124 }
125
126 if (s.size() == 0)
127 {
128 UG_LOG("Warning: SideAndElemErrEstData is constructed without definition of subsets. This is likely not to work.\n"
129 "Please specify a subset of the same dimension as your domain that the error estimator is supposed to work on.\n");
130 }
131}
132
133
134template <typename TDomain>
136(
137 size_t _sideOrder,
138 size_t _elemOrder,
139 const char* subsets
140) :
141 IErrEstData<TDomain>(),
142 sideOrder(_sideOrder), elemOrder(_elemOrder),
143 m_aSide(attachment_type("errEstSide")), m_aElem(attachment_type("errEstElem")),
146 m_spSV(SPNULL), m_errEstGL(GridLevel()),
147 m_type(H1_ERROR_TYPE)
148{
149 m_vSs = TokenizeString(subsets);
152}
153
154
155template <typename TDomain>
157(
158 size_t _sideOrder,
159 size_t _elemOrder,
160 std::vector<std::string> subsets
161) :
162 IErrEstData<TDomain>(),
163 sideOrder(_sideOrder), elemOrder(_elemOrder),
164 m_aSide(attachment_type("errEstSide")), m_aElem(attachment_type("errEstElem")),
167 m_spSV(SPNULL), m_errEstGL(GridLevel()),
168 m_type(H1_ERROR_TYPE)
169{
170 m_vSs = subsets;
173}
174
175template <typename TDomain>
177{
178 // get quadrature rules for sides and elems
179 boost::mpl::for_each<typename domain_traits<dim>::ManifoldElemList>(GetQuadRules<dim-1>(&quadRuleSide[0], sideOrder));
180 boost::mpl::for_each<typename domain_traits<dim>::DimElemList>(GetQuadRules<dim>(&quadRuleElem[0], elemOrder));
181
182 // fill in values for local side IPs (must be transformed from side local coords to elem local coords)
183 // and fill IP indexing structure along the way
184 for (ReferenceObjectID roid = ROID_VERTEX; roid != NUM_REFERENCE_OBJECTS; roid++)
185 {
186 // get reference element for roid
188 int ref_dim = re.dimension();
189 if (ref_dim != dim) continue;
190
191 // make a DimReferenceElement from roid (we need access to corner coords)
192 const DimReferenceElement<dim>& ref_elem = ReferenceElementProvider::get<dim>(roid);
193
194 // clear IP coords
195 m_SideIPcoords[roid].clear();
196
197 // loop sides of ref elem
198 for (size_t side = 0; side < ref_elem.num(ref_dim-1); side++)
199 {
200 // get side roid
201 ReferenceObjectID side_roid = ref_elem.roid(ref_dim-1, side);
202
203 // get number of IPs for this roid from quad rules
204 if (!quadRuleSide[side_roid])
205 UG_THROW("Requesting side IPs for roid " << roid << ", but no quadrature rule has been created for it.");
206 size_t nIPs = quadRuleSide[side_roid]->size();
207
208 // save start index for this side's IPs
209 if (side == 0) m_sideIPsStartIndex[roid][side] = 0;
210 else m_sideIPsStartIndex[roid][side] = m_sideIPsStartIndex[roid][side-1] + nIPs;
211
212 // get the side-local IPs
213 const MathVector<dim-1>* sideloc_IPs = quadRuleSide[side_roid]->points();
214
215 // fill vector of side corners (in element-dimensional coords)
216 size_t nCo = ref_elem.num(dim-1, side, 0);
217 std::vector<MathVector<dim> > side_corners(nCo);
218 for (size_t co = 0; co < ref_elem.num(dim-1, side, 0); co++)
219 {
220 size_t co_id = ref_elem.id(dim-1, side, 0, co);
221 side_corners[co] = ref_elem.corner(co_id);
222 }
223
224 // get reference mapping
225 DimReferenceMapping<dim-1,dim>& ref_map = ReferenceMappingProvider::get<dim-1,dim>(side_roid, &side_corners[0]);
226
227 // map IPs
228 for (size_t ip = 0; ip < nIPs; ip++)
229 {
230 m_SideIPcoords[roid].push_back(MathVector<TDomain::dim>());
231 ref_map.local_to_global(m_SideIPcoords[roid].back(), sideloc_IPs[ip]);
232 }
233 }
234 }
235}
236
237
239template <typename TDomain>
241{
242 try
243 {
244 return m_aaSide[pSide].at(ip);
245 }
246 catch (const std::out_of_range& oor)
247 {
248 UG_THROW("Requested attachment for side integration point " << ip <<
249 ", which does not appear to be allocated.");
250
251 }
252 UG_CATCH_THROW("Could not access error estimator side attachment for IP " << ip << ".");
253
254 // silence no return warning; this code is never reached
255 UG_THROW("Reached unreachable! This should be impossible. Check out why it is not!");
256 return m_aaSide[pSide].at(ip);
257}
258
259template <typename TDomain>
261{
262 try
263 {
264 return m_aaElem[pElem].at(ip);
265 }
266 catch (const std::out_of_range& oor)
267 {
268 UG_THROW("Requested attachment for elem integration point " << ip <<
269 ", which does not appear to be allocated.");
270
271 }
272 UG_CATCH_THROW("Could not access error estimator elem attachment for IP " << ip << ".");
273
274 // silence no return warning; this code is never reached
275 UG_THROW("Reached unreachable! This should be impossible. Check out why it is not!");
276 return m_aaElem[pElem].at(ip);
277}
278
279
280template <typename TDomain>
281template <int refDim>
283{
284 // the usual case: return all side IPs of an element (belonging to all sides)
285 if (TDomain::dim == refDim)
286 {
287 // check that IP series exists
288 if (m_SideIPcoords[roid].size() == 0)
289 UG_THROW("No side IP series available for roid " << roid << ".");
290
291 // cast is necessary, since TDomain::dim might be != refDim,
292 // but in that case, this return is not reached
293 return reinterpret_cast<const MathVector<refDim>*>(&m_SideIPcoords[roid][0]);
294 }
295 // special case (assembling over manifold, needed for inner_boundary): only IPs of one side
296 else if (TDomain::dim == refDim+1)
297 {
298 // check that quad rule exists
299 if (!quadRuleSide[roid])
300 UG_THROW("Requesting side IPs for roid " << roid << ", but no quadrature rule has been created for it.");
301
302 return reinterpret_cast<const MathVector<refDim>*>(quadRuleSide[roid]->points());
303 }
304
305 UG_THROW("Local IPs requested with the wrong dimension refDim." << std::endl
306 << "Either call with refDim == TDomain::dim and a TDomain::dim-dimensional roid "
307 "for the local side IPs of all of its sides" << std::endl
308 << "or with refDim == TDomain::dim-1 and a (TDomain::dim-1)-dimensional roid"
309 "for the local side IPs for a side of this roid.");
310
311 return NULL;
312}
313
314template <typename TDomain>
315template <int refDim>
317{
318// return NULL if dim is not fitting (not meaningful for the purpose of error estimation)
319 if (TDomain::dim != refDim) return NULL;
320
321// check that quad rule exists
322 UG_COND_THROW(!quadRuleElem[roid], "Requesting side IPs for roid " << roid << ", but no quadrature rule has been created for it.");
323// check that IP series exists
324 UG_COND_THROW(quadRuleElem[roid]->size() == 0, "No elem IP series available for roid " << roid << ".");
325
326 // cast is necessary, since TDomain::dim might be != refDim,
327 // but in that case, this return is not reached
328 return reinterpret_cast<const MathVector<refDim>*>(quadRuleElem[roid]->points());
329}
330
331template <typename TDomain>
333(
334 GridObject* elem,
335 const MathVector<dim> vCornerCoords[]
336)
337{
338 // get reference object ID
340
341 // get reference mapping
343 ReferenceMappingProvider::get<dim,dim>(roid, &vCornerCoords[0]);
344
345 // map IPs
346 try
347 {
348 m_sideGlobalIPcoords.resize(num_all_side_ips(roid));
349 ref_map.local_to_global(&m_sideGlobalIPcoords[0], &m_SideIPcoords[roid][0], m_SideIPcoords[roid].size());
350 }
351 catch (std::exception& e)
352 {
353 UG_THROW("Encountered exception while trying to fill array of global IPs: "
354 << std::endl << "'" << e.what() << "'");
355 }
356
357 return &m_sideGlobalIPcoords[0];
358}
359
360template <typename TDomain>
362(
363 GridObject* elem,
364 const MathVector<dim> vCornerCoords[]
365)
366{
367 // get reference object ID
369
370 // get reference mapping
371 DimReferenceMapping<dim-1,dim>& ref_map =
372 ReferenceMappingProvider::get<dim-1,dim>(roid, &vCornerCoords[0]);
373
374 // map IPs
375 try
376 {
377 m_singleSideGlobalIPcoords.resize(quadRuleSide[roid]->size());
378 ref_map.local_to_global(&m_singleSideGlobalIPcoords[0], quadRuleSide[roid]->points(), quadRuleSide[roid]->size());
379 }
380 catch (std::exception& e)
381 {
382 UG_THROW("Encountered exception while trying to fill array of global IPs: "
383 << std::endl << "'" << e.what() << "'");
384 }
385
386 return &m_singleSideGlobalIPcoords[0];
387}
388
389template <typename TDomain>
391(
392 GridObject* elem,
393 const MathVector<dim> vCornerCoords[]
394)
395{
396 // get reference object ID
398
399 // get reference mapping
401 ReferenceMappingProvider::get<dim,dim>(roid, &vCornerCoords[0]);
402
403 // map IPs
404 try
405 {
406 m_elemGlobalIPcoords.resize(num_elem_ips(roid));
407 ref_map.local_to_global(&m_elemGlobalIPcoords[0], quadRuleElem[roid]->points(), quadRuleElem[roid]->size());
408 }
409 catch (std::exception& e)
410 {
411 UG_THROW("Encountered exception while trying to fill array of global IPs: "
412 << std::endl << "'" << e.what() << "'");
413 }
414
415 return &m_elemGlobalIPcoords[0];
416}
417
418template <typename TDomain>
420{
421 return m_aaSide[pSide].size();
422}
423
424template <typename TDomain>
426{
427 // check that quad rule exists
428 UG_COND_THROW(!quadRuleSide[roid],
429 "Requesting number of side IPs for roid " << roid << ", but no quadrature rule has been created for it.");
430
431 return quadRuleSide[roid]->size();
432}
433
434template <typename TDomain>
436{
437 return m_sideIPsStartIndex[roid][side];
438}
439
440
441template <typename TDomain>
443{
444 return m_SideIPcoords[roid].size();
445}
446
447template <typename TDomain>
449{
450 // check that quad rule exists
451 UG_COND_THROW(!quadRuleElem[roid], "Requesting elem IPs for roid " << roid << ", but no quadrature rule has been created for it.");
452
453 return quadRuleElem[roid]->size();
454}
455
456template <typename TDomain>
458( const ReferenceObjectID roid,
459 const size_t side,
460 const size_t ip
461)
462{
463 // TODO: check validity of side index
464 return m_sideIPsStartIndex[roid][side];
465}
466
467
469template <typename TDomain>
471(
473 const GridLevel& gl
474)
475{
476// get and check the grid level
477 UG_COND_THROW(gl.type () != GridLevel::SURFACE, "SideFluxErrEstData::alloc_err_est_data:"
478 " The error estimator can work only with grid functions of the SURFACE type.");
479
480// get the subset handler
481 ConstSmartPtr<MGSubsetHandler> ssh = spSV->subset_handler();
482
483// copy the parameters to the object
484 m_errEstGL = gl;
485 m_spSV = spSV;
486
487// prepare the attachments and their accessors
488 MultiGrid* pMG = (MultiGrid*) (ssh->multi_grid());
489
490// sides
491 pMG->template attach_to_dv<side_type, attachment_type >(m_aSide, std::vector<number>(0));
492 m_aaSide.access(*pMG, m_aSide);
493
494// elems
495 pMG->template attach_to_dv<elem_type, attachment_type >(m_aElem, std::vector<number>(0));
496 m_aaElem.access(*pMG, m_aElem);
497
498// construct subset group from subset info
499 m_ssg.set_subset_handler(ssh);
500 if (m_vSs.size() == 0) m_ssg.add_all();
501 else m_ssg.add(m_vSs);
502
503// find out whether we work on an elem subset or a side subset
504 int ssDimMax = 0;
505 int ssDimMin = 4;
506 for (size_t si = 0; si < m_ssg.size(); si++)
507 {
508 const int dim_si = DimensionOfSubset(*ssh, m_ssg[si]);
509 if (dim_si > ssDimMax) ssDimMax = dim_si;
510 if (dim_si < ssDimMin) ssDimMin = dim_si;
511 }
512
513 UG_COND_THROW((ssDimMax != ssDimMin || ssDimMax != TDomain::dim),
514 "Subsets passed to an instance of SideAndElemErrEstData have varying or inadmissable dimension.\n"
515 "(NOTE: Only sets of subsets of the same dimension as the domain are allowed.)");
516
517
518 // iterate over elems and associated sides and resize the IP value vectors
519 for (size_t si = 0; si < m_ssg.size(); si++)
520 {
521 typedef typename SurfaceView::traits<elem_type>::const_iterator elem_iterator_type;
522 elem_iterator_type elem_iter_end = m_spSV->template end<elem_type>(m_ssg[si], m_errEstGL, SurfaceView::ALL);
523 for (elem_iterator_type elem_iter = m_spSV->template begin<elem_type>(m_ssg[si], m_errEstGL, SurfaceView::ALL);
524 elem_iter != elem_iter_end; ++elem_iter)
525 {
526 elem_type* elem = *elem_iter;
527
528 // get roid of elem
529 ReferenceObjectID roid = elem->reference_object_id();
530
531 // get number of IPs from quadrature rule for the roid and specified side quadrature order
532 size_t size = quadRuleElem[roid]->size();
533
534 // resize attachment accordingly
535 m_aaElem[elem].resize(size, 0.0);
536
537 // loop associated sides
539 pMG->associated_elements(side_list, elem);
540
541 for (size_t side = 0; side < side_list.size(); side++)
542 {
543 side_type* pSide = side_list[side];
544
545 // get roid of side
546 ReferenceObjectID roid = pSide->reference_object_id();
547
548 // get number of IPs from quadrature rule for the roid and specified side quadrature order
549 size_t size = quadRuleSide[roid]->size();
550
551 // resize attachment accordingly
552 if (m_aaSide[pSide].size() != size)
553 m_aaSide[pSide].resize(size, 0.0);
554 }
555 }
556 }
557
558 // equalize sizes at horizontal interface
559 // done by summing up, which, in a first step, will resize the smaller of the two vectors
560 // to the same size as the bigger one (cf. std_number_vector_attachment_reduce_traits)
561 // the actual summing does not hurt, since it performs 0 = 0 + 0;
562#ifdef UG_PARALLEL
563 typedef typename GridLayoutMap::Types<side_type>::Layout layout_type;
564 DistributedGridManager& dgm = *pMG->distributed_grid_manager();
565 GridLayoutMap& glm = dgm.grid_layout_map();
567
568 // sum all copies at the h-master attachment
569 ComPol_AttachmentReduce<layout_type, attachment_type> compolSumSideErr(*pMG, m_aSide, PCL_RO_SUM);
570 icom.exchange_data(glm, INT_H_SLAVE, INT_H_MASTER, compolSumSideErr);
571 icom.communicate();
572 icom.exchange_data(glm, INT_H_MASTER, INT_H_SLAVE, compolSumSideErr);
573 icom.communicate();
574
575 icom.exchange_data(glm, INT_V_SLAVE, INT_V_MASTER, compolSumSideErr);
576 icom.communicate();
577#endif
578
579 // for the case where subset border goes through SHADOW_RIM:
580 // resize SHADOW_RIM children if parent is resized and vice-versa
581 typedef typename Grid::traits<side_type>::const_iterator side_iter_type;
582 side_iter_type end_side = pMG->template end<side_type>();
583 for (side_iter_type side_iter = pMG->template begin<side_type>(); side_iter != end_side; ++side_iter)
584 {
585 // get the sides on both the levels (coarse and fine)
586 side_type* c_rim_side = *side_iter;
587
588 // if side is not SHADOW_RIM: do nothing
589 if (!m_spSV->surface_state(c_rim_side).partially_contains(SurfaceView::SHADOW_RIM)) continue;
590
591 // loop rim side children
592 bool resize_parent = false;
593 const size_t num_children = pMG->template num_children<side_type>(c_rim_side);
594 for (size_t ch = 0; ch < num_children; ch++)
595 {
596 side_type* child_side = pMG->template get_child<side_type>(c_rim_side, ch);
597
598 // get roid of side
599 ReferenceObjectID child_roid = child_side->reference_object_id();
600
601 // get number of IPs from quadrature rule for the roid and specified side quadrature order
602 size_t child_size = quadRuleSide[child_roid]->size();
603
604 // resize attachment accordingly
605 if (m_aaSide[child_side].size() != child_size && num_side_ips(c_rim_side) > 0)
606 m_aaSide[child_side].resize(child_size, 0.0);
607 else if (m_aaSide[child_side].size() == child_size && num_side_ips(c_rim_side) == 0)
608 resize_parent = true;
609 }
610
611 if (resize_parent)
612 {
613 // get roid of side
614 ReferenceObjectID roid = c_rim_side->reference_object_id();
615
616 // get number of IPs from quadrature rule for the roid and specified side quadrature order
617 size_t size = quadRuleSide[roid]->size();
618
619 // resize attachment accordingly
620 m_aaSide[c_rim_side].resize(size, 0.0);
621 }
622 }
623
624#ifdef UG_PARALLEL
625 icom.exchange_data(glm, INT_V_MASTER, INT_V_SLAVE, compolSumSideErr);
626 icom.communicate();
627#endif
628};
629
631
635template <typename TDomain>
637{
638 MultiGrid* pMG = spDomain->subset_handler()->multi_grid();
639
640 // STEP 1: Ensure consistency over horizontal interfaces.
641 // Add the IP values of horizontal interfaces. Care has to be taken in the case where a side
642 // is SHADOW_RIM, then it only has values from one side of the interface. This will be checked
643 // by calling size() of the IP value vector.
644#ifdef UG_PARALLEL
645 typedef typename GridLayoutMap::Types<side_type>::Layout layout_type;
647 GridLayoutMap& glm = dgm.grid_layout_map();
649
650 // sum all copies at the h-master attachment
652 icom.exchange_data(glm, INT_H_SLAVE, INT_H_MASTER, compolSumSideErr);
653 icom.communicate();
654
655 // copy the sum from the master to all of its slave-copies
656 ComPol_CopyAttachment<layout_type, attachment_type> compolCopySideErr(*pMG, m_aSide);
657 icom.exchange_data(glm, INT_H_MASTER, INT_H_SLAVE, compolCopySideErr);
658 icom.communicate();
659
660 // STEP 2: Ensure correct values in vertical master rim side children.
661 // since we're copying from vmasters to vslaves later on, we have to make
662 // sure, that also all v-masters contain the correct values.
663 // todo: communication to vmasters may not be necessary here...
664 // it is performed to make sure that all surface-rim-children
665 // contain their true value.
666 icom.exchange_data(glm, INT_V_SLAVE, INT_V_MASTER, compolCopySideErr);
667 icom.communicate();
668#endif
669
670 // STEP 3: Calculate values on rim sides.
671 // loop the rim sides and add the jumps
672 // TODO: not sure whether we cannot simply loop with
673 // m_spSV->template end<side_type> (m_errEstGL, SurfaceView::SHADOW_RIM)
674
675 //typedef typename SurfaceView::traits<side_type>::const_iterator t_iterator;
676 //t_iterator end_rim_side_iter = m_spSV->template end<side_type> (m_errEstGL, SurfaceView::SHADOW_RIM);
677 //for (t_iterator rim_side_iter = m_spSV->template begin<side_type> (m_errEstGL, SurfaceView::SHADOW_RIM);
678 // rim_side_iter != end_rim_side_iter; ++rim_side_iter)
679 typedef typename Grid::traits<side_type>::const_iterator side_iter_type;
680 side_iter_type end_side = pMG->template end<side_type>();
681 for (side_iter_type side_iter = pMG->template begin<side_type>(); side_iter != end_side; ++side_iter)
682 {
683 // get the sides on both the levels (coarse and fine)
684 side_type* c_rim_side = *side_iter;
685
686 // if side is not SHADOW_RIM: do nothing
687 if (!m_spSV->surface_state(c_rim_side).partially_contains(SurfaceView::SHADOW_RIM)) continue;
688
689 // if no ips registered on this side: do nothing
690 if (num_side_ips(c_rim_side) == 0) continue;
691
692 // distinguish hanging nodes and clozure elements by number of children
693 const size_t num_children = pMG->template num_children<side_type>(c_rim_side);
694
695 // closure elements
696 if (num_children == 1)
697 {
698 side_type* f_rim_side = pMG->template get_child<side_type>(c_rim_side, 0);
699
700 // add up total jump and save it for both sides
701 for (size_t i = 0; i < m_aaSide[c_rim_side].size(); i++)
702 {
703 number& c_rim_flux = m_aaSide[c_rim_side][i];
704 number& f_rim_flux = m_aaSide[f_rim_side][i];
705 number flux_jump = f_rim_flux + c_rim_flux;
706 c_rim_flux = f_rim_flux = flux_jump;
707 }
708 }
709
710 // hanging node
711 else
712 {
713 // TODO: This is a somehow dirty hack (but will converge with h->0),
714 // a correct interpolation with all given points would be preferable.
715 // And even if it is not: Check whether it could be beneficial to use structures like k-d tree,
716 // since this is the most naive implementation possible. I guess, the number of IPs
717 // is likely to be very low in most of the applications.
718
719 // The IPs are not in the same locations on both sides:
720 // Interpolate values for both sides, then add up and distribute.
721 // Interpolation is piecewise constant (use value of nearest neighbour).
722
723 // map coarse side local IPs to global
724 std::vector<MathVector<dim> > c_coCo;
725 CollectCornerCoordinates(c_coCo, c_rim_side, spDomain->position_accessor(), false);
726 MathVector<dim>* c_gloIPs = side_global_ips(c_rim_side, &c_coCo[0]);
727
728 // interpolate fine IPs on coarse side
729 for (size_t ch = 0; ch < num_children; ch++)
730 {
731 // get fine side
732 side_type* f_rim_side = pMG->template get_child<side_type>(c_rim_side, ch);
733
734 // map fine side local IPs to global
735 std::vector<MathVector<dim> > f_coCo;
736 CollectCornerCoordinates(f_coCo, f_rim_side, spDomain->position_accessor(), false);
737 MathVector<dim>* f_gloIPs = side_global_ips(f_rim_side, &f_coCo[0]);
738
739 // for each fine side IP, find nearest coarse side IP
740 for (size_t fip = 0; fip < m_aaSide[f_rim_side].size(); fip++)
741 {
742 if (m_aaSide[c_rim_side].size() < 1)
743 {UG_THROW("No IP defined for coarse side.");}
744
745 size_t nearest = 0;
746 MathVector<dim> diff;
747 VecSubtract(diff, f_gloIPs[fip], c_gloIPs[0]);
748 number dist = VecLengthSq(diff);
749
750 // loop coarse IPs
751 for (size_t cip = 1; cip < m_aaSide[c_rim_side].size(); cip++)
752 {
753 VecSubtract(diff, f_gloIPs[fip], c_gloIPs[cip]);
754 if (VecLengthSq(diff) < dist)
755 {
756 dist = VecLengthSq(diff);
757 nearest = cip;
758 }
759 }
760 m_aaSide[f_rim_side][fip] += m_aaSide[c_rim_side][nearest];
761 }
762 }
763
764 // interpolate coarse IPs on fine side:
765 for (size_t cip = 0; cip < m_aaSide[c_rim_side].size(); cip++)
766 {
767 MathVector<dim> diff;
768 number dist = std::numeric_limits<number>::infinity();
769 number val = 0.0;
770
771 // we have to loop all child sides
772 for (size_t ch = 0; ch < pMG->template num_children<side_type>(c_rim_side); ch++)
773 {
774 // get fine side
775 side_type* f_rim_side = pMG->template get_child<side_type>(c_rim_side, ch);
776
777 // map fine side local IPs to global
778 std::vector<MathVector<dim> > f_coCo;
779 CollectCornerCoordinates(f_coCo, f_rim_side, spDomain->position_accessor(), false);
780 MathVector<dim>* f_gloIPs = side_global_ips(f_rim_side, &f_coCo[0]);
781
782 // loop coarse IPs
783 for (size_t fip = 1; fip < m_aaSide[f_rim_side].size(); fip++)
784 {
785 VecSubtract(diff, f_gloIPs[fip], c_gloIPs[cip]);
786 if (VecLengthSq(diff) < dist)
787 {
788 dist = VecLengthSq(diff);
789 val = m_aaSide[f_rim_side][fip];
790 }
791 }
792 }
793
794 // the fine grid already contains the correct values
795 m_aaSide[c_rim_side][cip] = val;
796 }
797 }
798 }
799
800 // STEP 4: Ensure consistency in slave rim sides.
801 // Copy from v-masters to v-slaves, since there may be constrained sides which locally
802 // do not have a constraining element. Note that constrained V-Masters always have a local
803 // constraining element and thus contain the correct value.
804#ifdef UG_PARALLEL
805 compolCopySideErr.extract_on_constrained_elems_only(true);
806 icom.exchange_data(glm, INT_V_MASTER, INT_V_SLAVE, compolCopySideErr);
807 icom.communicate();
808#endif
809};
810
811
812template <typename TDomain>
814{
815
816// the indicator
817 number etaSq = 0.0;
818
819// elem terms
820 // info about reference element type
822 const DimReferenceElement<dim>& refElem = ReferenceElementProvider::get<dim>(roid);
823
824 // only take into account elem contributions of the subsets defined in the constructor
825 int ssi = surface_view()->subset_handler()->get_subset_index(pElem);
826 if (!m_ssg.contains(ssi)) return 0.0;
827
828 // check number of integration points
829 size_t nIPs = quadRuleElem[roid]->size();
830 std::vector<number>& integrand = m_aaElem[dynamic_cast<elem_type*>(pElem)];
831 if (nIPs != integrand.size())
832 UG_THROW("Element attachment vector does not have the required size for integration!");
833
834 // get reference element mapping
835 DimReferenceMapping<dim,dim>& mapping = ReferenceMappingProvider::get<dim,dim>(roid);
836 mapping.update(&vCornerCoords[0]);
837
838 // compute det of jacobian at each IP
839 std::vector<number> det(nIPs);
840 mapping.sqrt_gram_det(&det[0], quadRuleElem[roid]->points(), nIPs);
841
842 // integrate
843 number sum = 0.0;
844 for (size_t ip = 0; ip < nIPs; ip++)
845 sum += quadRuleElem[roid]->weight(ip) * std::pow(integrand[ip], 2.0) * det[ip];
846
847 // scale by diam^2(elem) (= h_T^2)
848 // c* vol(elem) >= diam^3(elem) >= vol(elem)
849 // therefore, up to a constant, error estimator can calculate diam(elem) as (vol(elem))^(1/3)
850 number diamSq = std::pow(ElementSize<dim>(roid, &vCornerCoords[0]), 2.0/dim);
851
852 // add to error indicator
853 etaSq += diamSq * sum;
854
855// side terms
856 // get the sides of the element
857 MultiGrid* pErrEstGrid = (MultiGrid*) (surface_view()->subset_handler()->multi_grid());
859 pErrEstGrid->associated_elements(side_list, pElem);
860
861 // loop sides
862 for (size_t side = 0; side < side_list.size(); side++)
863 {
864 side_type* pSide = side_list[side];
865
866 // info about reference side type
867 ReferenceObjectID side_roid = pSide->reference_object_id();
868
869 // check number of integration points
870 size_t nsIPs = quadRuleSide[side_roid]->size();
871 UG_COND_THROW(nsIPs != m_aaSide[pSide].size(),
872 "Side attachment vector does not have the required size for integration!");
873
874 // get side corners
875 std::vector<MathVector<dim> > vSideCornerCoords(0);
876 size_t nsCo = refElem.num(dim-1, side, 0);
877 for (size_t co = 0; co < nsCo; co++)
878 vSideCornerCoords.push_back(vCornerCoords[refElem.id(dim-1, side, 0, co)]);
879
880 // get reference element mapping
881 DimReferenceMapping<dim-1,dim>& mapping = ReferenceMappingProvider::get<dim-1,dim>(side_roid);
882 mapping.update(&vSideCornerCoords[0]);
883
884 // compute det of jacobian at each IP
885 det.resize(nsIPs);
886 mapping.sqrt_gram_det(&det[0], quadRuleSide[side_roid]->points(), nsIPs);
887
888 // integrate
889 number sum = 0.0;
890 for (size_t ip = 0; ip < nsIPs; ip++)
891 sum += quadRuleSide[side_roid]->weight(ip) * std::pow(m_aaSide[pSide][ip], 2.0) * det[ip];
892
893 // scale by diam(side) (= $h_E$)
894 // c* vol(side) >= diam^2(side) >= vol(side)
895 // therefore, up to a constant, error estimator can calculate diam as sqrt(vol(side))
896 number diamE;
897 if (dim==1) { diamE = 1.0; }
898 else if (dim==2) { diamE = ElementSize<dim>(side_roid, &vSideCornerCoords[0]); }
899 else if (dim==3) { diamE = std::sqrt(ElementSize<dim>(side_roid, &vSideCornerCoords[0])); }
900 else { UG_THROW("Unknown dimension: "<<dim <<"."); }
901
902 // add to error indicator
903 etaSq += diamE * sum;
904 }
905 etaSq = (m_type == SideAndElemErrEstData<TDomain>::L2_ERROR_TYPE) ? etaSq*diamSq : etaSq;
906 return etaSq;
907}
908
909
911template <typename TDomain>
913{
914// release the attachments
915 MultiGrid * pMG = (MultiGrid *) (m_spSV->subset_handler()->multi_grid());
916
917 m_aaSide.invalidate();
918 pMG->template detach_from<side_type>(m_aSide);
919
920 m_aaElem.invalidate();
921 pMG->template detach_from<elem_type>(m_aElem);
922 //m_spSV = ConstSmartPtr<SurfaceView> (NULL); // this raises a rte
923};
924
925
926
927// ******** class MultipleErrEstData ********
928
929template <typename TDomain, typename TErrEstData>
932{
933 // only called if consider_me()
934 for (size_t eed = 0; eed < num(); eed++)
935 m_vEed[eed]->alloc_err_est_data(spSV, gl);
936}
937
938template <typename TDomain, typename TErrEstData>
941{
942 // only called if consider_me()
943 for (size_t eed = 0; eed < num(); eed++)
944 m_vEed[eed]->summarize_err_est_data(spDomain);
945}
946
947template <typename TDomain, typename TErrEstData>
949get_elem_error_indicator(GridObject* elem, const MathVector<dim> vCornerCoords[])
950{
951 // only called if consider_me()
952 number sum = 0.0;
953 for (size_t eed = 0; eed < num(); eed++)
954 sum += m_vEed[eed]->get_elem_error_indicator(elem, vCornerCoords);
955
956 return sum;
957}
958
959template <typename TDomain, typename TErrEstData>
962{
963 // only called if consider_me()
964 for (size_t eed = 0; eed < num(); eed++)
965 m_vEed[eed]->release_err_est_data();
966}
967
968
969
970// ******** class MultipleSideAndElemErrEstData ********
971
972template <typename TDomain>
974add(SmartPtr<SideAndElemErrEstData<TDomain> > spEed, const char* fct)
975{
976 check_equal_order();
978}
979
980template <typename TDomain>
982{
983 check_equal_side_order();
984 check_equal_elem_order();
985}
986
987template <typename TDomain>
989{
990 m_bEqSideOrder = false;
991
992 if (this->m_vEed.size() == 0)
993 {
994 m_bEqSideOrder = true;
995 return;
996 }
997
998 size_t side_order = this->m_vEed[0]->side_order();
999
1000 for (size_t ee = 1; ee < this->m_vEed.size(); ee++)
1001 if (this->m_vEed[ee]->side_order() != side_order) return;
1002
1003 m_bEqSideOrder = true;
1004}
1005
1006template <typename TDomain>
1008{
1009 m_bEqElemOrder = false;
1010
1011 if (this->m_vEed.size() == 0)
1012 {
1013 m_bEqElemOrder = true;
1014 return;
1015 }
1016
1017 size_t elem_order = this->m_vEed[0]->elem_order();
1018
1019 for (size_t ee = 1; ee < this->m_vEed.size(); ee++)
1020 if (this->m_vEed[ee]->elem_order() != elem_order) return;
1021
1022 m_bEqElemOrder = true;
1023}
1024
1025
1026} // end of namespace ug
1027
1028/* End of File */
parameterString s
Definition smart_pointer.h:296
Definition smart_pointer.h:108
Performs communication between interfaces on different processes.
Definition pcl_interface_communicator.h:68
bool communicate(int tag=749345)
sends and receives the collected data.
Definition pcl_interface_communicator_impl.hpp:409
void exchange_data(const TLayoutMap &layoutMap, const typename TLayoutMap::Key &keyFrom, const typename TLayoutMap::Key &keyTo, ICommunicationPolicy< TLayout > &commPol)
internally calls send_data and receive_data with the specified layouts.
Definition pcl_interface_communicator_impl.hpp:213
Used to access data that has been attached to an attachment pipe.
Definition attachment_pipe.h:510
Performs reduce operations on the specified attachment.
Definition compol_attachment_reduce.h:274
copies values from a specified attachment to a stream and back.
Definition compol_copy_attachment.h:54
void extract_on_constrained_elems_only(bool enable)
Definition compol_copy_attachment.h:168
dimension dependent base class for reference elements
Definition reference_element.h:183
const MathVector< dim > & corner(size_t i) const
coordinates of reference corner (i = 0 ... num(0))
Definition reference_element.h:192
virtual base class for reference mappings
Definition reference_mapping_provider.h:53
virtual number sqrt_gram_det(const MathVector< dim > &locPos) const =0
returns the determinate of the jacobian
virtual void local_to_global(MathVector< worldDim > &globPos, const MathVector< dim > &locPos) const =0
map local coordinate to global coordinate
virtual void update(const MathVector< worldDim > *vCornerCoord)=0
refresh mapping for new set of corners
manages the layouts and interfaces which are associated with a distributed grid.
Definition distributed_grid.h:88
GridLayoutMap & grid_layout_map()
Definition distributed_grid.h:103
DistributedGridManager * distributed_grid_manager()
returns a pointer to the associated distributed grid manager.
Definition grid_impl.hpp:53
void associated_elements(traits< Vertex >::secure_container &elemsOut, TElem *e)
Puts all elements of type TAss which are contained in 'e' or which contain 'e' into elemsOut.
Definition grid_impl.hpp:466
lets you access layouts by type and key
Definition parallel_grid_layout.h:152
Definition grid_level.h:42
ViewType type() const
returns the type
Definition grid_level.h:77
@ SURFACE
Definition grid_level.h:48
The base class for all geometric objects, such as vertices, edges, faces, volumes,...
Definition grid_base_objects.h:157
virtual ReferenceObjectID reference_object_id() const =0
Base class for error estimator data.
Definition err_est_data.h:71
a mathematical Vector with N entries.
Definition math_vector.h:97
Definition multi_grid.h:72
Error estimator data class for discretizations with more than one unknown.
Definition err_est_data.h:423
virtual number get_elem_error_indicator(GridObject *elem, const MathVector< dim > vCornerCoords[])
calculate L2 integrals
Definition err_est_data_impl.h:949
virtual void alloc_err_est_data(ConstSmartPtr< SurfaceView > spSV, const GridLevel &gl)
virtual function to allocate data structures for the error estimator
Definition err_est_data_impl.h:931
virtual void release_err_est_data()
virtual function to release data structures for the error estimator
Definition err_est_data_impl.h:961
virtual void summarize_err_est_data(SmartPtr< TDomain > spDomain)
virtual function called after the computation of the error estimator data in all the elements
Definition err_est_data_impl.h:940
void check_equal_order()
Definition err_est_data_impl.h:981
void check_equal_elem_order()
Definition err_est_data_impl.h:1007
void check_equal_side_order()
Definition err_est_data_impl.h:988
virtual void add(SmartPtr< SideAndElemErrEstData< TDomain > > spEed, const char *fct)
Definition err_est_data_impl.h:974
base class for reference elements
Definition reference_element.h:70
size_t num(int dim) const
returns the number of geometric objects of dim
Definition reference_element.h:95
ReferenceObjectID roid() const
returns the reference object id
Definition reference_element.h:76
int id(int dim_i, size_t i, int dim_j, size_t j) const
id of object j in dimension dim_j of obj i in dimension dim_i
Definition reference_element.h:127
int dimension() const
returns the dimension where reference element lives
Definition reference_element.h:80
static const DimReferenceElement< dim > & get(ReferenceObjectID roid)
returns a dimension dependent Reference Element
Definition reference_element.h:280
static DimReferenceMapping< TDim, TWorldDim > & get(ReferenceObjectID roid)
returns a reference to a DimReferenceMapping
Definition reference_mapping_provider.h:225
Error estimator data class storing a number vector per side and per element.
Definition err_est_data.h:221
virtual void summarize_err_est_data(SmartPtr< TDomain > spDomain)
virtual function called after the computation of the error estimator data in all the elements
Definition err_est_data_impl.h:636
virtual void release_err_est_data()
virtual function to release data structures of the error estimator
Definition err_est_data_impl.h:912
size_t num_all_side_ips(const ReferenceObjectID roid)
get number of side IPs
Definition err_est_data_impl.h:442
void init_quadrature()
initialization of quadrature (to be called during construction)
Definition err_est_data_impl.h:176
std::vector< std::string > m_vSs
the subsets this error estimator will produce values for
Definition err_est_data.h:353
domain_traits< dim >::side_type side_type
type of the sides (face, edge) and the elems (volume, face)
Definition err_est_data.h:230
MathVector< TDomain::dim > * all_side_global_ips(GridObject *elem, const MathVector< dim > vCornerCoords[])
get all global side integration points
Definition err_est_data_impl.h:333
const MathVector< refDim > * elem_local_ips(const ReferenceObjectID roid)
get the local elem integration points for a specific roid
Definition err_est_data_impl.h:316
virtual void alloc_err_est_data(ConstSmartPtr< SurfaceView > spSV, const GridLevel &gl)
virtual function to allocate data structures for the error estimator
Definition err_est_data_impl.h:471
SideAndElemErrEstData(size_t _sideOrder, size_t _elemOrder, const char *subsets)
constructors
Definition err_est_data_impl.h:136
MathVector< TDomain::dim > * elem_global_ips(GridObject *elem, const MathVector< dim > vCornerCoords[])
get the global elem integration points for a specific roid
Definition err_est_data_impl.h:391
number & operator()(side_type *pSide, size_t ip)
get the data reference for a given side and ip
Definition err_est_data_impl.h:240
const MathVector< refDim > * side_local_ips(const ReferenceObjectID roid)
get the local side integration points for a specific roid
Definition err_est_data_impl.h:282
size_t side_ip_index(const ReferenceObjectID roid, const size_t side, const size_t ip)
get index of specific side IP in sideIP array returned by side_local_ips
Definition err_est_data_impl.h:458
domain_traits< dim >::element_type elem_type
Definition err_est_data.h:231
size_t first_side_ips(const ReferenceObjectID roid, const size_t side)
get number of first IP belonging to a specific side
Definition err_est_data_impl.h:435
size_t num_side_ips(const side_type *pSide)
get number of side IPs of a specific side
Definition err_est_data_impl.h:419
MathVector< TDomain::dim > * side_global_ips(GridObject *elem, const MathVector< dim > vCornerCoords[])
get the global side integration points for a specific side roid
Definition err_est_data_impl.h:362
virtual number get_elem_error_indicator(GridObject *elem, const MathVector< dim > vCornerCoords[])
calculate L2 integrals
Definition err_est_data_impl.h:813
size_t num_elem_ips(const ReferenceObjectID roid)
get number of elem IPs
Definition err_est_data_impl.h:448
virtual void release_err_est_data()
virtual function to release data structures of the error estimator
Definition err_est_data_impl.h:92
virtual void alloc_err_est_data(ConstSmartPtr< SurfaceView > spSV, const GridLevel &gl)
virtual function to allocate data structures for the error estimator
Definition err_est_data_impl.h:40
virtual void summarize_err_est_data(SmartPtr< TDomain > spDomain)
virtual function called after the computation of the error estimator data in all the elements
Definition err_est_data_impl.h:63
domain_traits< dim >::side_type side_type
type of the sides (face, edge) and the elems (volume, face)
Definition err_est_data.h:147
@ SHADOW_RIM
Definition surface_view.h:98
@ ALL
Definition surface_view.h:102
void CollectCornerCoordinates(std::vector< typename TAAPos::ValueType > &vCornerCoordsOut, const TElem &elem, const TAAPos &aaPos, bool clearContainer=true)
returns the corner coordinates of a geometric object
Definition domain_util_impl.h:75
#define PCL_RO_SUM
Definition pcl_methods.h:63
void RemoveWhitespaceFromString(std::string &str)
removes all white space from a string, also within the string
Definition string_util.cpp:50
const NullSmartPtr SPNULL
The equivalent to NULL for smart pointers.
Definition smart_pointer.h:90
#define UG_CATCH_THROW(msg)
Definition error.h:64
#define UG_THROW(msg)
Definition error.h:57
#define UG_LOG(msg)
Definition log.h:367
#define UG_COND_THROW(cond, msg)
UG_COND_THROW(cond, msg) : performs a UG_THROW(msg) if cond == true.
Definition error.h:61
double number
Definition types.h:124
void VecSubtract(vector_t &vOut, const vector_t &v1, const vector_t &v2)
subtracts v2 from v1 and stores the result in a vOut
Definition math_vector_functions_common_impl.hpp:226
vector_t::value_type VecLengthSq(const vector_t &v)
returns the squared length of v. Faster than VecLength.
Definition math_vector_functions_common_impl.hpp:324
the ug namespace
ReferenceObjectID
these ids are used to identify the shape of a geometric object.
Definition grid_base_objects.h:74
@ NUM_REFERENCE_OBJECTS
Definition grid_base_objects.h:85
@ ROID_VERTEX
Definition grid_base_objects.h:76
void TokenizeString(const string &str, vector< string > &vToken, const char delimiter)
Definition string_util.cpp:56
void check_subset_strings(std::vector< std::string > s)
Definition err_est_data_impl.h:107
@ INT_V_MASTER
vertical master node
Definition parallel_grid_layout.h:106
@ INT_H_MASTER
horizontal master node
Definition parallel_grid_layout.h:104
@ INT_H_SLAVE
horizontal slave node
Definition parallel_grid_layout.h:105
@ INT_V_SLAVE
vertical slave node
Definition parallel_grid_layout.h:107
int DimensionOfSubset(const ISubsetHandler &sh, int si)
returns the current dimension of the subset
Definition subset_dim_util.cpp:89
bool resize(size_t newRows, size_t newCols)
The traits class holds some important types for each element-type.
Definition grid.h:136
geometry_traits< TElem >::const_iterator const_iterator
Definition grid.h:144
pcl::MultiLevelLayout< Interface > Layout
Definition parallel_grid_layout.h:161
helper struct for getting quadrature rules by use of mpl::lists
Definition err_est_data.h:334
ConstSurfaceViewElementIterator< TElem > const_iterator
Definition surface_view.h:300
Definition domain_traits.h:53