Line data Source code
1 : /*
2 : * Copyright (c) 2013-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Andreas Vogel
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 "dof_count.h"
34 : #ifdef UG_PARALLEL
35 : #include "pcl/pcl_process_communicator.h"
36 : #endif
37 :
38 : namespace ug{
39 :
40 : ////////////////////////////////////////////////////////////////////////////////
41 : // DoFCount
42 : ////////////////////////////////////////////////////////////////////////////////
43 :
44 0 : DoFCount::DoFCount(const GridLevel& gl, ConstSmartPtr<DoFDistributionInfo> spDDInfo)
45 0 : : DoFDistributionInfoProvider(spDDInfo), m_gridLevel(gl)
46 : {
47 0 : vvCmpSubset.resize(num_fct());
48 0 : for(size_t fct = 0; fct < vvCmpSubset.size(); ++fct)
49 0 : vvCmpSubset[fct].resize(num_subsets());
50 0 : }
51 :
52 0 : void DoFCount::add(int fct, int si, SurfaceView::SurfaceState ss, byte is, uint64 numDoF)
53 : {
54 0 : if(!(fct < (int)vvCmpSubset.size()))
55 0 : UG_THROW("DoFCount: fct index "<<fct<<" invalid. NumFct: "<<vvCmpSubset.size());
56 :
57 0 : if(!(si < (int)vvCmpSubset[fct].size()))
58 0 : UG_THROW("DoFCount: subset index "<<si<<" invalid. NumSubset: "<<vvCmpSubset[fct].size());
59 :
60 0 : vvCmpSubset[fct][si].add(numDoF, ss, is);
61 0 : }
62 :
63 0 : void DoFCount::sum_values_over_procs(int proc)
64 : {
65 : PROFILE_FUNC();
66 : #ifdef UG_PARALLEL
67 : pcl::ProcessCommunicator commWorld;
68 :
69 : // collect all serial values
70 : std::vector<uint64> vNumLocal;
71 : collect_values(vNumLocal);
72 :
73 : // sum
74 : if(proc == -1){
75 : std::vector<uint64> vNumGlobal(vNumLocal.size());
76 : commWorld.allreduce(&vNumLocal[0], &vNumGlobal[0], vNumLocal.size(),
77 : PCL_DT_UNSIGNED_LONG_LONG, PCL_RO_SUM);
78 : set_values(vNumGlobal);
79 : }
80 : else{
81 : std::vector<uint64> vNumGlobal(vNumLocal.size());
82 : commWorld.reduce(&vNumLocal[0], &vNumGlobal[0], vNumLocal.size(),
83 : PCL_DT_UNSIGNED_LONG_LONG, PCL_RO_SUM, proc);
84 : set_values(vNumGlobal);
85 : }
86 : #endif
87 0 : }
88 :
89 0 : void DoFCount::collect_values(std::vector<uint64>& vNum) const
90 : {
91 : PROFILE_FUNC();
92 0 : for(size_t fct = 0; fct < vvCmpSubset.size(); ++fct)
93 0 : for(size_t si = 0; si < vvCmpSubset[fct].size(); ++si)
94 0 : vvCmpSubset[fct][si].collect_values(vNum);
95 0 : }
96 :
97 0 : void DoFCount::set_values(const std::vector<uint64>& vNum)
98 : {
99 : PROFILE_FUNC();
100 0 : size_t cnt = 0;
101 0 : for(size_t fct = 0; fct < vvCmpSubset.size(); ++fct)
102 0 : for(size_t si = 0; si < vvCmpSubset[fct].size(); ++si)
103 0 : vvCmpSubset[fct][si].set_values(vNum, cnt);
104 0 : }
105 :
106 0 : uint64 DoFCount::num(int fct, int si, SurfaceView::SurfaceState ss, byte is) const
107 : {
108 0 : if(fct == ALL_FCT){
109 : uint64 cnt = 0;
110 0 : for(size_t fct = 0; fct < vvCmpSubset.size(); ++fct)
111 0 : cnt += num(fct, si, ss, is);
112 0 : return cnt;
113 : }
114 :
115 0 : if(si == ALL_SUBSET){
116 : uint64 cnt = 0;
117 0 : for(size_t si = 0; si < vvCmpSubset[fct].size(); ++si)
118 0 : cnt += num(fct, si, ss, is);
119 0 : return cnt;
120 : }
121 :
122 0 : return vvCmpSubset[fct][si].num(ss, is);
123 : }
124 :
125 0 : uint64 DoFCount::num_contains(int fct, int si, SurfaceView::SurfaceState ss, byte is) const
126 : {
127 0 : if(fct == ALL_FCT){
128 : uint64 cnt = 0;
129 0 : for(size_t fct = 0; fct < vvCmpSubset.size(); ++fct)
130 0 : cnt += num_contains(fct, si, ss, is);
131 0 : return cnt;
132 : }
133 :
134 0 : if(si == ALL_SUBSET){
135 : uint64 cnt = 0;
136 0 : for(size_t si = 0; si < vvCmpSubset[fct].size(); ++si)
137 0 : cnt += num_contains(fct, si, ss, is);
138 0 : return cnt;
139 : }
140 :
141 0 : return vvCmpSubset[fct][si].num_contains(ss, is);
142 : }
143 :
144 :
145 : ////////////////////////////////////////////////////////////////////////////////
146 : // DoFCount::Cnt
147 : ////////////////////////////////////////////////////////////////////////////////
148 :
149 0 : DoFCount::Cnt::Cnt()
150 : {
151 0 : vNumSS.resize(DoFCount::SS_MAX + 1);
152 0 : }
153 :
154 0 : void DoFCount::Cnt::collect_values(std::vector<uint64>& vNum) const
155 : {
156 : PROFILE_FUNC();
157 0 : vNumSS[SurfaceView::MG_SHADOW_PURE].collect_values(vNum);
158 0 : vNumSS[SurfaceView::MG_SURFACE_PURE].collect_values(vNum);
159 0 : vNumSS[SurfaceView::MG_SURFACE_RIM].collect_values(vNum);
160 0 : vNumSS[SurfaceView::MG_SHADOW_RIM_COPY].collect_values(vNum);
161 0 : vNumSS[SurfaceView::MG_SHADOW_RIM_NONCOPY].collect_values(vNum);
162 0 : }
163 :
164 0 : void DoFCount::Cnt::set_values(const std::vector<uint64>& vNum, size_t& cnt)
165 : {
166 : PROFILE_FUNC();
167 0 : vNumSS[SurfaceView::MG_SHADOW_PURE].set_values(vNum, cnt);
168 0 : vNumSS[SurfaceView::MG_SURFACE_PURE].set_values(vNum, cnt);
169 0 : vNumSS[SurfaceView::MG_SURFACE_RIM].set_values(vNum, cnt);
170 0 : vNumSS[SurfaceView::MG_SHADOW_RIM_COPY].set_values(vNum, cnt);
171 0 : vNumSS[SurfaceView::MG_SHADOW_RIM_NONCOPY].set_values(vNum, cnt);
172 0 : }
173 :
174 :
175 0 : void DoFCount::Cnt::add(uint64 num, SurfaceView::SurfaceState ss, byte is)
176 : {
177 : // restrict to only considered flags:
178 0 : size_t ss_index = (size_t)(ss & SS_MAX)();
179 0 : size_t is_index = (size_t)(is & ES_MAX);
180 :
181 0 : if(!(ss_index < vNumSS.size()))
182 0 : UG_THROW("Something wrong with surface state storage: is: "<<
183 : ss_index<<", max: "<<vNumSS.size());
184 :
185 0 : if(!(is_index < vNumSS[ss_index].vNumIS.size()))
186 0 : UG_THROW("Something wrong with interface state storage: is: "<<
187 : is_index<<", max: "<<vNumSS[ss_index].vNumIS.size());
188 :
189 0 : vNumSS[ss_index].vNumIS[is_index] += num;
190 0 : }
191 :
192 :
193 0 : uint64 DoFCount::Cnt::num(SurfaceView::SurfaceState ss, byte is) const
194 : {
195 0 : if(ss == ALL_SS){
196 : uint64 cnt = 0;
197 0 : for(byte l = 0; l <= SS_MAX; ++l)
198 0 : cnt += num(l, is);
199 0 : return cnt;
200 : }
201 :
202 0 : if(ss == UNIQUE_SS){
203 0 : return num(SurfaceView::MG_SHADOW_PURE, is)
204 0 : + num(SurfaceView::MG_SURFACE_PURE, is)
205 0 : + num(SurfaceView::MG_SURFACE_RIM, is)
206 : // + num(SurfaceView::SHADOW_COPY, is) // copies not counted
207 0 : + num(SurfaceView::MG_SHADOW_RIM_NONCOPY, is);
208 : }
209 :
210 0 : return vNumSS[ss()].num(is);
211 : }
212 :
213 0 : uint64 DoFCount::Cnt::num_contains(SurfaceView::SurfaceState ss, byte is) const
214 : {
215 0 : if(ss == ALL_SS){
216 : uint64 cnt = 0;
217 0 : for(byte l = 0; l <= SS_MAX; ++l)
218 0 : cnt += vNumSS[l].num_contains(is);
219 0 : return cnt;
220 : }
221 :
222 0 : if(ss == UNIQUE_SS){
223 0 : return vNumSS[SurfaceView::MG_SHADOW_PURE].num_contains(is)
224 0 : + vNumSS[SurfaceView::MG_SURFACE_PURE].num_contains(is)
225 0 : + vNumSS[SurfaceView::MG_SURFACE_RIM].num_contains(is)
226 : // + vNumSS[SurfaceView::SHADOW_COPY].num_contains(is) // copies not counted
227 0 : + vNumSS[SurfaceView::MG_SHADOW_RIM_NONCOPY].num_contains(is);
228 : }
229 :
230 : uint64 cnt = 0;
231 0 : for(byte l = 0; l <= SS_MAX; ++l){
232 0 : if(l & is)
233 0 : cnt += vNumSS[l].num_contains(is);
234 : }
235 : return cnt;
236 : }
237 :
238 : ////////////////////////////////////////////////////////////////////////////////
239 : // DoFCount::Cnt::PCnt
240 : ////////////////////////////////////////////////////////////////////////////////
241 :
242 0 : uint64 DoFCount::Cnt::PCnt::num(byte is) const
243 : {
244 0 : if(is == ALL_ES){
245 : uint64 cnt = 0;
246 0 : for(byte l = 0; l <= ES_MAX; ++l)
247 0 : cnt += num(l);
248 0 : return cnt;
249 : }
250 :
251 0 : if(is == UNIQUE_ES){
252 0 : return num(ES_NONE) // one-proc-only dofs
253 0 : + num(ES_V_SLAVE) // pure vert. slaves
254 0 : + num(ES_V_SLAVE | ES_V_MASTER) // pure vert.
255 0 : + num_contains(ES_H_MASTER); // all horiz. masters
256 : }
257 :
258 0 : return vNumIS[is];
259 : }
260 :
261 0 : uint64 DoFCount::Cnt::PCnt::num_contains(byte is) const
262 : {
263 0 : if(is == ALL_ES){
264 : uint64 cnt = 0;
265 0 : for(byte l = 0; l <= ES_MAX; ++l)
266 0 : cnt += vNumIS[l];
267 0 : return cnt;
268 : }
269 :
270 0 : if(is == UNIQUE_ES){
271 0 : return num(ES_NONE) // one-proc-only dofs
272 0 : + num(ES_V_SLAVE) // pure vert. slaves
273 0 : + num(ES_V_SLAVE | ES_V_MASTER) // pure vert.
274 0 : + num_contains(ES_H_MASTER); // all horiz. masters
275 : }
276 :
277 : uint64 cnt = 0;
278 0 : for(byte l = 0; l <= ES_MAX; ++l){
279 0 : if(l & is)
280 0 : cnt += vNumIS[l];
281 : }
282 : return cnt;
283 : }
284 :
285 0 : DoFCount::Cnt::PCnt::PCnt()
286 : {
287 0 : vNumIS.resize(DoFCount::ES_MAX + 1, 0);
288 0 : }
289 :
290 0 : void DoFCount::Cnt::PCnt::collect_values(std::vector<uint64>& vNum) const
291 : {
292 : PROFILE_FUNC();
293 0 : for(byte l = 0; l <= ES_MAX; ++l){
294 : // I think one shouldn't continue for (ES_V_MASTER | ES_V_SLAVE) here, since those
295 : // guys may actually exist in a distributed grid. That's why I commented the line.
296 : // It should be completely removed somewhen soon...(sreiter)
297 : //if((l & (ES_V_MASTER | ES_V_SLAVE)) == (ES_V_MASTER | ES_V_SLAVE)) continue;
298 0 : if((l & (ES_H_MASTER | ES_H_SLAVE)) == (ES_H_MASTER | ES_H_SLAVE)) continue;
299 :
300 0 : vNum.push_back(vNumIS[l]);
301 : }
302 0 : }
303 :
304 0 : void DoFCount::Cnt::PCnt::set_values(const std::vector<uint64>& vNum, size_t& cnt)
305 : {
306 : PROFILE_FUNC();
307 0 : for(byte l = 0; l <= ES_MAX; ++l){
308 : // I think one shouldn't continue for (ES_V_MASTER | ES_V_SLAVE) here, since those
309 : // guys may actually exist in a distributed grid. That's why I commented the line.
310 : // It should be completely removed somewhen soon...(sreiter)
311 : //if((l & (ES_V_MASTER | ES_V_SLAVE)) == (ES_V_MASTER | ES_V_SLAVE)) continue;
312 0 : if((l & (ES_H_MASTER | ES_H_SLAVE)) == (ES_H_MASTER | ES_H_SLAVE)) continue;
313 :
314 0 : vNumIS[l] = vNum[cnt++];
315 : }
316 0 : }
317 :
318 : } // end namespace ug
|