Line data Source code
1 : /*
2 : * Copyright (c) 2011-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Sebastian Reiter
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #include <vector>
34 : #include <queue>
35 : #include "fractured_media_refiner.h"
36 : #include "common/assert.h"
37 :
38 : using namespace std;
39 :
40 : namespace ug{
41 :
42 : template <class TGrid, class TAPosition>
43 0 : FracturedMediaRefiner<TGrid, TAPosition>::
44 : FracturedMediaRefiner(SPRefinementProjector projector) :
45 : BaseClass(projector),
46 0 : m_aspectRatioThreshold(SMALL)
47 : {
48 0 : }
49 :
50 : template <class TGrid, class TAPosition>
51 0 : FracturedMediaRefiner<TGrid, TAPosition>::
52 : FracturedMediaRefiner(TGrid& g, SPRefinementProjector projector) :
53 : BaseClass(g, projector),
54 0 : m_aspectRatioThreshold(SMALL)
55 : {
56 0 : }
57 :
58 : template <class TGrid, class TAPosition>
59 0 : FracturedMediaRefiner<TGrid, TAPosition>::
60 : ~FracturedMediaRefiner()
61 : {
62 0 : }
63 :
64 : template <class TGrid, class TAPosition>
65 : void
66 0 : FracturedMediaRefiner<TGrid, TAPosition>::
67 : set_aspect_ratio_threshold(number threshold)
68 : {
69 0 : m_aspectRatioThreshold = threshold;
70 0 : }
71 :
72 : template <class TGrid, class TAPosition>
73 : void
74 0 : FracturedMediaRefiner<TGrid, TAPosition>::
75 : set_position_attachment(TAPosition& aPos)
76 : {
77 : UG_ASSERT(BaseClass::get_associated_grid(),
78 : "The refiner has to be registered at a grid");
79 : m_aaPos.access(*BaseClass::get_associated_grid(), aPos);
80 0 : }
81 :
82 : template <class TGrid, class TAPosition>
83 : bool
84 0 : FracturedMediaRefiner<TGrid, TAPosition>::
85 : mark(Face* f, RefinementMark refMark)
86 : {
87 : // make sure that the position accessor is valid
88 : UG_ASSERT(m_aaPos.valid(),
89 : "Set a position attachment before refining!");
90 :
91 0 : bool wasMarked = BaseClass::is_marked(f);
92 0 : if(!BaseClass::mark(f, refMark))
93 : return false;
94 :
95 0 : if(!wasMarked){
96 0 : if(aspect_ratio(f) < m_aspectRatioThreshold)
97 : m_queDegeneratedFaces.push(f);
98 : }
99 : return true;
100 : }
101 :
102 : template <class TGrid, class TAPosition>
103 0 : number FracturedMediaRefiner<TGrid, TAPosition>::
104 : aspect_ratio(Face* f)
105 : {
106 0 : if(!m_aaPos.valid())
107 0 : UG_THROW("A position attachment has to be specified before this method is called.");
108 :
109 0 : EdgeDescriptor ed;
110 0 : f->edge_desc(0, ed);
111 :
112 0 : number eMin = EdgeLength(&ed, m_aaPos);
113 : number eMax = eMin;
114 :
115 0 : for(size_t i = 1; i < f->num_edges(); ++i){
116 0 : f->edge_desc(i, ed);
117 0 : number len = EdgeLength(&ed, m_aaPos);
118 0 : if(len < eMin)
119 : eMin = len;
120 0 : else if(len > eMax)
121 : eMax = len;
122 : }
123 :
124 0 : if(eMax <= 0)
125 : return 0;
126 :
127 0 : return eMin / eMax;
128 : }
129 :
130 : template <class TGrid, class TAPosition>
131 : void
132 0 : FracturedMediaRefiner<TGrid, TAPosition>::
133 : collect_objects_for_refine()
134 : {
135 : // get the grid on which we'll operate
136 0 : if(!BaseClass::get_associated_grid())
137 0 : UG_THROW("No grid has been set for the refiner.");
138 :
139 : Grid& grid = *BaseClass::get_associated_grid();
140 :
141 : // make sure that the position accessor is valid
142 0 : if(!m_aaPos.valid())
143 0 : UG_THROW("A position attachment has to be specified before this method is called.");
144 :
145 : // push all marked degenerated faces to a queue.
146 : // pop elements from that queue, mark them anisotropic and unmark associated
147 : // degenerated edges.
148 : // Furthermore we'll push degenerated faces, which are connected to the current
149 : // face through a regular edge to the queue (only unprocessed ones).
150 :
151 : typename BaseClass::selector_t& sel = BaseClass::get_refmark_selector();
152 :
153 : // some helpers
154 : vector<Edge*> edges;
155 : vector<Face*> faces;
156 :
157 : // we need two while-loops. The outer is required to process changes which
158 : // stem from the base-class implementation.
159 : //todo: This is a lot of processing due to repeated calls to collect_objects_for_refine.
160 : do{
161 0 : while(!m_queDegeneratedFaces.empty())
162 : {
163 0 : Face* f = m_queDegeneratedFaces.front();
164 : m_queDegeneratedFaces.pop();
165 :
166 : // mark as anisotropic
167 0 : if(BaseClass::get_mark(f) != RM_ANISOTROPIC)
168 0 : BaseClass::mark(f, RM_ANISOTROPIC);
169 :
170 : // check edges
171 : CollectAssociated(edges, grid, f);
172 :
173 : // get the edge with the maximal length
174 : number eMax = 0;
175 0 : for(size_t i_edge = 0; i_edge < edges.size(); ++i_edge){
176 0 : number len = EdgeLength(edges[i_edge], m_aaPos);
177 0 : if(len > eMax)
178 : eMax = len;
179 : }
180 :
181 0 : if(eMax <= 0)
182 : eMax = SMALL;
183 :
184 : // degenerated neighbors of non-degenerated edges have to be selected.
185 : // degenerated edges may not be selected
186 : size_t numDeg = 0;
187 0 : for(size_t i_edge = 0; i_edge< edges.size(); ++i_edge){
188 0 : Edge* e = edges[i_edge];
189 0 : if(EdgeLength(e, m_aaPos) / eMax >= m_aspectRatioThreshold){
190 : // non-degenerated edge
191 : // make sure it is selected
192 0 : if(BaseClass::get_mark(e) != RM_REFINE)
193 0 : BaseClass::mark(e, RM_REFINE);
194 :
195 : // this edge possibly connects to an unselected degenerated neighbor.
196 : // If this is the case, we'll have to mark it and push it to the queue.
197 : CollectAssociated(faces, grid, e);
198 0 : for(size_t i_face = 0; i_face < faces.size(); ++i_face){
199 0 : Face* nbr = faces[i_face];
200 0 : if(!sel.is_selected(nbr)){
201 0 : if(aspect_ratio(f) < m_aspectRatioThreshold){
202 : // push it to the queue.
203 : m_queDegeneratedFaces.push(nbr);
204 : }
205 : }
206 : }
207 : }
208 : else{
209 : // degenerated edge. unmark it
210 0 : BaseClass::mark(e, RM_NONE);
211 0 : ++numDeg;
212 : }
213 : }
214 :
215 : // if all edges are degenerate, we will have to perform regular refinement
216 0 : if(numDeg == edges.size()){
217 0 : BaseClass::mark(f, RM_REFINE);
218 0 : for(size_t i = 0; i < edges.size(); ++i)
219 0 : BaseClass::mark(edges[i], RM_REFINE);
220 : }
221 : }
222 :
223 : // now call the base implementation. If degenerated faces are selected during
224 : // that step, then we have to process them too.
225 0 : BaseClass::collect_objects_for_refine();
226 0 : }while(!m_queDegeneratedFaces.empty());
227 0 : }
228 :
229 :
230 : ////////////////////////////////////
231 : // explicit instantiation
232 : template class FracturedMediaRefiner<Grid, APosition>;
233 : template class FracturedMediaRefiner<Grid, APosition2>;
234 : template class FracturedMediaRefiner<Grid, APosition1>;
235 :
236 : template class FracturedMediaRefiner<MultiGrid, APosition>;
237 : template class FracturedMediaRefiner<MultiGrid, APosition2>;
238 : template class FracturedMediaRefiner<MultiGrid, APosition1>;
239 :
240 : }// end of namespace
|