Line data Source code
1 : /*
2 : * Copyright (c) 2012-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 "approximation_space.h"
34 : #include "lib_disc/domain.h"
35 : #include "lib_disc/common/groups_util.h"
36 : #include "common/util/string_util.h"
37 : #include "common/profiler/profiler.h"
38 :
39 : #ifdef UG_PARALLEL
40 : #include "pcl/pcl.h"
41 : #endif
42 :
43 : #include "lib_disc/dof_manager/dof_distribution.h"
44 : #include "grid_function.h"
45 :
46 : #include <algorithm> // std::sort
47 : #include <sstream> // std::stringstream
48 : using namespace std;
49 :
50 : // for debugging only:
51 : //#include "lib_grid/file_io/file_io.h"
52 : //#define APPROX_SPACE_PERFORM_CHANGED_GRID_DEBUG_SAVES
53 : //#define APPROX_SPACE_PERFORM_DISTRIBUTED_GRID_DEBUG_SAVES
54 :
55 : namespace ug{
56 :
57 : ////////////////////////////////////////////////////////////////////////////////
58 : // IApproximationSpace
59 : ////////////////////////////////////////////////////////////////////////////////
60 :
61 0 : IApproximationSpace::
62 : IApproximationSpace(SmartPtr<subset_handler_type> spMGSH,
63 : SmartPtr<grid_type> spMG,
64 0 : const AlgebraType& algebraType)
65 : {
66 0 : init(spMGSH, spMG, algebraType);
67 0 : }
68 :
69 0 : IApproximationSpace::
70 : IApproximationSpace(SmartPtr<subset_handler_type> spMGSH,
71 0 : SmartPtr<grid_type> spMG)
72 : {
73 0 : init(spMGSH, spMG, DefaultAlgebra::get());
74 0 : }
75 :
76 0 : void IApproximationSpace::
77 : init(SmartPtr<subset_handler_type> spMGSH,
78 : SmartPtr<grid_type> spMG,
79 : const AlgebraType& algebraType)
80 : {
81 0 : m_spMG = spMG;
82 0 : m_spMGSH = spMGSH;
83 0 : m_spDoFDistributionInfo = SmartPtr<DoFDistributionInfo>(new DoFDistributionInfo(spMGSH));
84 0 : m_algebraType = algebraType;
85 0 : m_bAdaptionIsActive = false;
86 0 : m_RevCnt = RevisionCounter(this);
87 :
88 0 : this->set_dof_distribution_info(m_spDoFDistributionInfo);
89 :
90 : // get blocksize of algebra
91 : const int blockSize = m_algebraType.blocksize();
92 :
93 : // a) If blocksize fixed and > 1, we need grouping in dof manager. Thus,
94 : // the dofmanager hopefully fits (i.e. same number of grouped
95 : // dofs everywhere.)
96 0 : if(blockSize > 1) m_bGrouped = true;
97 : // b) If blocksize flexible, we group
98 0 : else if (blockSize == AlgebraType::VariableBlockSize) m_bGrouped = true;
99 : // c) If blocksize == 1, we do not group. This will allow us to handle
100 : // this case for any problem.
101 0 : else if (blockSize == 1) m_bGrouped = false;
102 : else
103 0 : UG_THROW("Cannot determine blocksize of Algebra.");
104 :
105 : // this class listens to the grid-adaption-messages
106 0 : register_at_adaption_msg_hub();
107 0 : }
108 :
109 :
110 0 : IApproximationSpace::
111 : ~IApproximationSpace()
112 : {
113 0 : if(m_spSurfaceView.valid())
114 0 : m_spSurfaceView = SmartPtr<SurfaceView>(NULL);
115 0 : }
116 :
117 : template <typename TElem>
118 0 : bool MightContainGhosts(const GridLayoutMap& layoutMap, int lvl)
119 : {
120 0 : if(!layoutMap.has_layout<TElem>(INT_V_MASTER)) return false;
121 0 : if(lvl >= (int)layoutMap.get_layout<TElem>(INT_V_MASTER).num_levels()) return false;
122 0 : if(layoutMap.get_layout<TElem>(INT_V_MASTER).empty(lvl)) return false;
123 :
124 : typedef typename GridLayoutMap::Types<TElem>::Layout::LevelLayout TLayout;
125 : typedef typename TLayout::const_iterator InterfaceIterator;
126 :
127 0 : const TLayout& elemLayout = layoutMap.get_layout<TElem>(INT_V_MASTER).layout_on_level(lvl);
128 0 : for(InterfaceIterator iIter = elemLayout.begin(); iIter != elemLayout.end(); ++iIter){
129 0 : if(!elemLayout.interface(iIter).empty())
130 : return true;
131 : }
132 :
133 : return false;
134 : }
135 :
136 0 : bool IApproximationSpace::might_contain_ghosts(int lvl) const
137 : {
138 0 : if(lvl < 0 || lvl > (int)num_levels()-1)
139 0 : UG_THROW("ApproximationSpace: Level not contained.");
140 :
141 : const DistributedGridManager* pDistGridMgr = m_spMG->distributed_grid_manager();
142 0 : if(!pDistGridMgr) return false;
143 :
144 : bool bGhosts = false;
145 : const GridLayoutMap& layoutMap = pDistGridMgr->grid_layout_map();
146 0 : if(max_dofs(VERTEX)) bGhosts |= MightContainGhosts<Vertex>(layoutMap, lvl);
147 0 : if(max_dofs(EDGE)) bGhosts |= MightContainGhosts<Edge>(layoutMap, lvl);
148 0 : if(max_dofs(FACE)) bGhosts |= MightContainGhosts<Face>(layoutMap, lvl);
149 0 : if(max_dofs(VOLUME)) bGhosts |= MightContainGhosts<Volume>(layoutMap, lvl);
150 :
151 : return bGhosts;
152 : }
153 :
154 0 : bool IApproximationSpace::might_contain_ghosts() const
155 : {
156 : bool bGhosts = false;
157 0 : for(int lvl = 0; lvl < (int)num_levels(); ++lvl)
158 0 : bGhosts |= might_contain_ghosts(lvl);
159 :
160 0 : return bGhosts;
161 : }
162 :
163 : ////////////////////////////////////////////////////////////////////////////////
164 : // add
165 : ////////////////////////////////////////////////////////////////////////////////
166 :
167 0 : void IApproximationSpace::
168 : add(const std::vector<std::string>& vName, const char* fetype, int order)
169 : {
170 0 : const int dim = DimensionOfSubsets(*m_spMGSH);
171 0 : if(dim == DIM_SUBSET_EMPTY_GRID)
172 0 : UG_THROW("ApproximationSpace: Cannot find dimension of grid. Maybe your grid is empty?");
173 :
174 0 : add(vName, ConvertStringToLFEID(fetype, dim, order));
175 0 : }
176 :
177 0 : void IApproximationSpace::
178 : add(const std::vector<std::string>& vName, const char* fetype)
179 : {
180 0 : const int dim = DimensionOfSubsets(*m_spMGSH);
181 0 : if(dim == DIM_SUBSET_EMPTY_GRID)
182 0 : UG_THROW("ApproximationSpace: Cannot find dimension of grid. Maybe your grid is empty?");
183 :
184 0 : add(vName, ConvertStringToLFEID(fetype, dim));
185 0 : }
186 :
187 0 : void IApproximationSpace::
188 : add(const char* name, const char* fetype, int order)
189 : {
190 0 : add(TokenizeTrimString(name), fetype, order);
191 0 : }
192 :
193 0 : void IApproximationSpace::
194 : add(const char* name, const char* fetype)
195 : {
196 0 : add(TokenizeTrimString(name), fetype);
197 0 : }
198 :
199 :
200 0 : void IApproximationSpace::
201 : add(const std::vector<std::string>& vName, const char* fetype, int order,
202 : const std::vector<std::string>& vSubsets)
203 : {
204 0 : SubsetGroup ssGrp(m_spMGSH, vSubsets);
205 0 : const int dim = ssGrp.get_highest_subset_dimension();
206 :
207 : // check
208 0 : if(dim == DIM_SUBSET_EMPTY_GRID)
209 0 : UG_THROW("ApproximationSpace: Cannot find dimension for new function on"
210 : "the subsets. Maybe your grid is empty?");
211 :
212 0 : add(vName, ConvertStringToLFEID(fetype, dim, order), vSubsets);
213 0 : }
214 :
215 0 : void IApproximationSpace::
216 : add(const std::vector<std::string>& vName, const char* fetype,
217 : const std::vector<std::string>& vSubsets)
218 : {
219 0 : SubsetGroup ssGrp(m_spMGSH, vSubsets);
220 0 : const int dim = ssGrp.get_highest_subset_dimension();
221 :
222 : // check
223 0 : if(dim == DIM_SUBSET_EMPTY_GRID)
224 0 : UG_THROW("ApproximationSpace: Cannot find dimension for new function on"
225 : "the subsets. Maybe your grid is empty?");
226 :
227 0 : add(vName, ConvertStringToLFEID(fetype, dim), vSubsets);
228 0 : }
229 :
230 0 : void IApproximationSpace::
231 : add(const char* name, const char* fetype, int order, const char* subsets)
232 : {
233 0 : add(TokenizeTrimString(name), fetype, order, TokenizeTrimString(subsets));
234 0 : }
235 :
236 0 : void IApproximationSpace::
237 : add(const char* name, const char* fetype, const char* subsets)
238 : {
239 0 : add(TokenizeTrimString(name), fetype, TokenizeTrimString(subsets));
240 0 : }
241 :
242 : ////////////////////////////////////////////////////////////////////////////////
243 : // DoFDistributions
244 : ////////////////////////////////////////////////////////////////////////////////
245 :
246 : SmartPtr<DoFDistribution>
247 0 : IApproximationSpace::dof_distribution(const GridLevel& gl, bool bCreate)
248 : {
249 0 : for(size_t i = 0; i < m_vDD.size(); ++i)
250 : if(m_vDD[i]->grid_level() == gl)
251 : return m_vDD[i];
252 :
253 0 : if(!bCreate)
254 0 : UG_THROW("ApproxSpace: Could not create the DoFDistribution to GridLevel "<<gl);
255 :
256 0 : create_dof_distribution(gl);
257 :
258 0 : return dof_distribution(gl, false);
259 : }
260 :
261 : SmartPtr<DoFDistribution>
262 0 : IApproximationSpace::dd(const GridLevel& gl, bool bCreate)
263 : {
264 0 : return dof_distribution(gl, bCreate);
265 : }
266 :
267 : ConstSmartPtr<DoFDistribution>
268 0 : IApproximationSpace::dof_distribution(const GridLevel& gl, bool bCreate) const
269 : {
270 0 : return const_cast<IApproximationSpace*>(this)->dof_distribution(gl, bCreate);
271 : }
272 :
273 : ConstSmartPtr<DoFDistribution>
274 0 : IApproximationSpace::dd(const GridLevel& gl, bool bCreate) const
275 : {
276 0 : return dof_distribution(gl, bCreate);
277 : }
278 :
279 : std::vector<SmartPtr<DoFDistribution> >
280 0 : IApproximationSpace::dof_distributions() const
281 : {
282 0 : return m_vDD;
283 : }
284 :
285 :
286 0 : void IApproximationSpace::init_levels()
287 : {
288 : PROFILE_FUNC();
289 0 : for(size_t lvl = 0; lvl < num_levels(); ++lvl){
290 0 : dof_distribution(GridLevel(lvl, GridLevel::LEVEL, false));
291 0 : dof_distribution(GridLevel(lvl, GridLevel::LEVEL, true));
292 : }
293 0 : }
294 :
295 0 : void IApproximationSpace::init_surfaces()
296 : {
297 : PROFILE_FUNC();
298 0 : for(size_t lvl = 0; lvl < num_levels(); ++lvl)
299 0 : dof_distribution(GridLevel(lvl, GridLevel::SURFACE, false));
300 :
301 0 : init_top_surface();
302 0 : }
303 :
304 0 : void IApproximationSpace::init_top_surface()
305 : {
306 : PROFILE_FUNC();
307 0 : dof_distribution(GridLevel(GridLevel::TOP, GridLevel::SURFACE, false));
308 0 : }
309 :
310 : ////////////////////////////////////////////////////////////////////////////////
311 : // DoFDistribution Creation
312 : ////////////////////////////////////////////////////////////////////////////////
313 :
314 0 : bool SortDD(SmartPtr<DoFDistribution> spDD1, SmartPtr<DoFDistribution> spDD2){
315 0 : return spDD1->grid_level() < spDD2->grid_level();
316 : }
317 :
318 0 : void IApproximationSpace::create_dof_distribution(const GridLevel& gl)
319 : {
320 :
321 0 : dof_distribution_info_required();
322 0 : surface_view_required();
323 :
324 : // get DoFIndexStorage if it is reusable
325 : SmartPtr<DoFIndexStorage> spIndexStrg;
326 0 : if(gl.is_level()){
327 0 : if(gl.ghosts()){
328 0 : if(m_spDoFIndexStrgForLevelWithGhost.invalid())
329 0 : m_spDoFIndexStrgForLevelWithGhost = SmartPtr<DoFIndexStorage>(
330 0 : new DoFIndexStorage(m_spMG, m_spDoFDistributionInfo));
331 0 : spIndexStrg = m_spDoFIndexStrgForLevelWithGhost;
332 : }
333 : else{
334 0 : if(m_spDoFIndexStrgForLevelNoGhost.invalid())
335 0 : m_spDoFIndexStrgForLevelNoGhost = SmartPtr<DoFIndexStorage>(
336 0 : new DoFIndexStorage(m_spMG, m_spDoFDistributionInfo));
337 0 : spIndexStrg = m_spDoFIndexStrgForLevelNoGhost;
338 : }
339 : }
340 :
341 : // create DoFDistribution
342 : SmartPtr<DoFDistribution> spDD = SmartPtr<DoFDistribution>(new
343 : DoFDistribution(m_spMG, m_spMGSH, m_spDoFDistributionInfo,
344 0 : m_spSurfaceView, gl, m_bGrouped, spIndexStrg));
345 :
346 : // add to list and sort
347 0 : m_vDD.push_back(spDD);
348 0 : std::sort(m_vDD.begin(), m_vDD.end(), SortDD);
349 0 : }
350 :
351 0 : void IApproximationSpace::surface_view_required()
352 : {
353 : // allocate surface view if needed
354 0 : if(!m_spSurfaceView.valid())
355 0 : m_spSurfaceView = SmartPtr<SurfaceView>(new SurfaceView(m_spMGSH));
356 0 : }
357 :
358 0 : void IApproximationSpace::dof_distribution_info_required()
359 : {
360 : // init dd-info (and fix the function pattern by that)
361 0 : m_spDoFDistributionInfo->init();
362 :
363 : // check that used algebra-type matches requirements
364 : // get blocksize of algebra
365 : const int blockSize = m_algebraType.blocksize();
366 :
367 : // if blockSize is 1, we're fine if dd is non-grouped
368 0 : if(blockSize == 1){
369 0 : if(m_bGrouped == true)
370 0 : UG_THROW("ApproximationSpace: Using grouped DD, but Algebra is 1x1.")
371 : }
372 :
373 : // if variable block algebra
374 0 : else if(blockSize == AlgebraType::VariableBlockSize){
375 0 : UG_THROW("ApproximationSpace: Variable algebra currently not supported.")
376 : }
377 :
378 : // if block algebra, check that number of sub-elements is zero or == blockSize
379 0 : else if(blockSize > 1){
380 0 : for(int r = 0; r < NUM_REFERENCE_OBJECTS; ++r){
381 : const ReferenceObjectID roid = (ReferenceObjectID)r;
382 :
383 0 : for(int si = 0; si < m_spDDI->num_subsets(); ++si){
384 0 : const int numDoFs = m_spDDI->num_dofs(roid, si);
385 :
386 0 : if(numDoFs != 0 && numDoFs != blockSize)
387 0 : UG_THROW("ApproximationSpace: Using Block-Algebra with "
388 : "Blocksize "<<blockSize<<". Therefore, the number of"
389 : " dofs on each ReferenceObject must equal the blocksize"
390 : " or be zero. But number of dofs on "<<roid<<" in "
391 : "subset "<<si<<" is "<<numDoFs<<".");
392 : }
393 : }
394 : }
395 :
396 : // catch other (invalid) settings
397 : else
398 0 : UG_THROW("Cannot determine blocksize of Algebra.");
399 0 : }
400 :
401 : ////////////////////////////////////////////////////////////////////////////////
402 : // Grid-Change Handling
403 : ////////////////////////////////////////////////////////////////////////////////
404 :
405 0 : void IApproximationSpace::reinit()
406 : {
407 : PROFILE_FUNC();
408 : // update surface view
409 0 : if(m_spSurfaceView.valid())
410 0 : m_spSurfaceView->refresh_surface_states();
411 :
412 : // reinit all existing dof distributions
413 0 : for(size_t i = 0; i < m_vDD.size(); ++i){
414 0 : m_vDD[i]->reinit();
415 : }
416 :
417 : // increase revision counter
418 0 : ++m_RevCnt;
419 0 : }
420 :
421 0 : void IApproximationSpace::register_at_adaption_msg_hub()
422 : {
423 : // register function for grid adaption
424 : SPMessageHub msgHub = m_spMGSH->multi_grid()->message_hub();
425 : m_spGridAdaptionCallbackID =
426 0 : msgHub->register_class_callback(this,
427 0 : &ug::IApproximationSpace::grid_changed_callback);
428 :
429 : m_spGridDistributionCallbackID =
430 0 : msgHub->register_class_callback(this,
431 0 : &ug::IApproximationSpace::grid_distribution_callback);
432 0 : }
433 :
434 0 : void IApproximationSpace::
435 : grid_changed_callback(const GridMessage_Adaption& msg)
436 : {
437 0 : if(msg.adaption_begins())
438 0 : m_bAdaptionIsActive = true;
439 :
440 0 : else if(m_bAdaptionIsActive){
441 0 : if(msg.adaption_ends())
442 : {
443 0 : reinit();
444 0 : m_bAdaptionIsActive = false;
445 :
446 : #ifdef APPROX_SPACE_PERFORM_CHANGED_GRID_DEBUG_SAVES
447 : {
448 : static int counter = 0;
449 : std::stringstream ss;
450 : ss << "grid-changed-surface-view" << counter << "-p" << pcl::ProcRank() << ".ugx";
451 : UG_LOG("PERFORMING SURFACE VIEW DEBUG SAVE IN IApproximationSpace::grid_changed_callback: " << ss.str() << "\n");
452 : SaveSurfaceViewTransformed(*m_spMG, *m_spSurfaceView, ss.str().c_str(), 0.1);
453 : ++counter;
454 : }
455 : {
456 : #ifdef UG_PARALLEL
457 : static int counter = 0;
458 : std::stringstream ss;
459 : ss << "grid-changed-parallel-layout-" << counter << "-p" << pcl::ProcRank() << ".ugx";
460 : UG_LOG("PERFORMING GRID LAYOUT DEBUG SAVE IN IApproximationSpace::grid_changed_callback: " << ss.str() << "\n");
461 : SaveParallelGridLayout(*m_spMG, ss.str().c_str(), 0.1);
462 : ++counter;
463 : #endif
464 : }
465 : #endif
466 : }
467 : }
468 :
469 : else{
470 0 : UG_THROW("Before any grid-adaption may be performed, the approximation"
471 : " space has to be informed that grid-adaption shall begin. "
472 : "You may use IRefiner::grid_adaption_begins() or schedule "
473 : "an appropriate message to the associated grids message-hub.");
474 : }
475 0 : }
476 :
477 0 : void IApproximationSpace::
478 : grid_distribution_callback(const GridMessage_Distribution& msg)
479 : {
480 : PROFILE_FUNC();
481 0 : switch(msg.msg()){
482 : case GMDT_DISTRIBUTION_STARTS:
483 : break;
484 :
485 0 : case GMDT_DISTRIBUTION_STOPS:
486 0 : reinit();
487 : #ifdef APPROX_SPACE_PERFORM_DISTRIBUTED_GRID_DEBUG_SAVES
488 : {
489 : static int counter = 0;
490 : std::stringstream ss;
491 : ss << "grid-distributed-surface-view" << counter << "-p" << pcl::ProcRank() << ".ugx";
492 : UG_LOG("PERFORMING SURFACE VIEW DEBUG SAVE IN IApproximationSpace::grid_distribution_callback: " << ss.str() << "\n");
493 : SaveSurfaceViewTransformed(*m_spMG, *m_spSurfaceView, ss.str().c_str(), 0.1);
494 : ++counter;
495 : }
496 : {
497 : #ifdef UG_PARALLEL
498 : static int counter = 0;
499 : std::stringstream ss;
500 : ss << "grid-distributed-parallel-layout-" << counter << "-p" << pcl::ProcRank() << ".ugx";
501 : UG_LOG("PERFORMING GRID LAYOUT DEBUG SAVE IN IApproximationSpace::grid_distribution_callback: " << ss.str() << "\n");
502 : SaveParallelGridLayout(*m_spMG, ss.str().c_str(), 0.1);
503 : ++counter;
504 : #endif
505 : }
506 : #endif
507 0 : break;
508 :
509 : default:
510 : break;
511 : }
512 0 : }
513 :
514 : ////////////////////////////////////////////////////////////////////////////////
515 : // Statistic
516 : ////////////////////////////////////////////////////////////////////////////////
517 :
518 0 : void PrintDoFCount(const vector<DoFCount>& vDC,
519 : const string& sInfo,
520 : const string& sAlgebra,
521 : const string& sflags)
522 : {
523 : const bool bPrintCmps = (sflags.find("component") != string::npos);
524 : const bool bPrintInterface = (sflags.find("interface") != string::npos);
525 : const bool bPrintSurface = (sflags.find("surface") != string::npos);
526 : const bool bPrintSubset = (sflags.find("subset") != string::npos);
527 :
528 : // check for output
529 0 : if(vDC.size() == 0)
530 0 : UG_THROW("Expected something to print.")
531 :
532 : // constants for size of output
533 : static const int LEVEL = 14;
534 : static const int COMPONENT = 7;
535 : static const int INTERFACE = 8;
536 : static const int SURFACE = 12;
537 : static const int NUMBER = 12;
538 : static const char* sSep = " | ";
539 : static const char* sLeft = "| ";
540 : static const char* sRight = " |";
541 :
542 : // constants for selection
543 : static const int ALL_FCT = DoFCount::ALL_FCT;
544 : static const int ALL_SUBSET = DoFCount::ALL_SUBSET;
545 : static const byte ALL_ES = DoFCount::ALL_ES;
546 : static const byte ALL_SS = DoFCount::ALL_SS;
547 : static const byte UNIQUE_ES = DoFCount::UNIQUE_ES;
548 : static const byte UNIQUE_SS = DoFCount::UNIQUE_SS;
549 :
550 : // Table Header
551 0 : stringstream ssHead;
552 0 : ssHead << setw(LEVEL) << "GridLevel " << sSep;
553 :
554 : // Components
555 : vector<pair<string,int> > vCmp;
556 0 : vCmp.push_back(pair<string,int>("all", ALL_FCT));
557 0 : if(bPrintCmps){
558 0 : ssHead << setw(COMPONENT) << "Comps" << sSep;
559 0 : for(int fct = 0; fct < (int)vDC[0].num_fct(); ++fct){
560 0 : stringstream name; name << fct << ": "<< vDC[0].name(fct);
561 0 : vCmp.push_back(pair<string,int>(SnipString(name.str(), COMPONENT, 2), fct));
562 0 : }
563 : }
564 :
565 : // Interface
566 0 : if(bPrintInterface) {
567 0 : ssHead << setw(INTERFACE) << "Parallel" << sSep;
568 : }
569 :
570 : // Surface
571 0 : if(bPrintSurface) {
572 0 : ssHead << setw(SURFACE) << "Surface" << sSep;
573 : }
574 :
575 : // Subsets
576 0 : ssHead << setw(NUMBER) << "Domain";
577 0 : vector<int> vSubset; vSubset.push_back(ALL_SUBSET);
578 0 : if(bPrintSubset) {
579 0 : for(int si = 0; si < vDC[0].num_subsets(); ++si){
580 0 : stringstream name; name << si << ": "<< vDC[0].subset_name(si);
581 0 : ssHead << sSep << setw(NUMBER) << SnipString(name.str(), NUMBER, 2);
582 0 : vSubset.push_back(si);
583 0 : }
584 : }
585 :
586 : // size of a line
587 0 : int LINE = ssHead.str().size();
588 0 : if(LINE < 76) LINE = 76;
589 :
590 0 : UG_LOG(sLeft << repeat('-', LINE) << sRight << endl);
591 0 : UG_LOG(sLeft << left << setw(LINE) << sInfo << right << sRight << endl);
592 0 : UG_LOG(sLeft << left << setw(LINE) << sAlgebra << right << sRight << endl);
593 0 : UG_LOG(sLeft << setw(LINE) << "" << sRight << endl);
594 0 : UG_LOG(sLeft << setw(LINE) << left << ssHead.str() << right << sRight << endl);
595 0 : UG_LOG(sLeft << repeat('-', LINE) << sRight << endl);
596 :
597 :
598 : // Loop Level
599 0 : for(size_t i = 0; i < vDC.size(); ++i){
600 :
601 : const DoFCount& dc = vDC[i];
602 0 : const GridLevel gl = dc.grid_level();
603 0 : stringstream ssGL; ssGL << gl;
604 :
605 : // always print unique (w.r.t interface) number
606 : vector<pair<string, byte> > vInIS;
607 0 : vInIS.push_back(pair<string,byte>("unique",UNIQUE_ES));
608 : vector<pair<string, byte> > vContainsIS;
609 :
610 : // if PrintInterface: add more output
611 0 : if(bPrintInterface){
612 0 : vContainsIS.push_back(pair<string,byte>("m (&)",ES_H_MASTER));
613 0 : vContainsIS.push_back(pair<string,byte>("s (&)",ES_H_SLAVE));
614 0 : vInIS.push_back(pair<string,byte>("all",ALL_ES));
615 :
616 : // if grid level with ghost: add more output
617 0 : if(gl.is_level() && gl.ghosts()){
618 0 : vContainsIS.push_back(pair<string,byte>("vm (&)",ES_V_MASTER));
619 0 : vContainsIS.push_back(pair<string,byte>("vs (&)",ES_V_SLAVE));
620 0 : vInIS.push_back(pair<string,byte>("no (x)",ES_NONE));
621 0 : vInIS.push_back(pair<string,byte>("m (x)",ES_H_MASTER));
622 0 : vInIS.push_back(pair<string,byte>("s (x)",ES_H_SLAVE));
623 0 : vInIS.push_back(pair<string,byte>("vm (x)",ES_V_MASTER));
624 0 : vInIS.push_back(pair<string,byte>("vs (x)", ES_V_SLAVE));
625 0 : vInIS.push_back(pair<string,byte>("m+vm (x)", ES_H_MASTER | ES_V_MASTER));
626 0 : vInIS.push_back(pair<string,byte>("m+vs (x)", ES_H_MASTER | ES_V_SLAVE));
627 0 : vInIS.push_back(pair<string,byte>("s+vm (x)", ES_H_SLAVE | ES_V_MASTER));
628 0 : vInIS.push_back(pair<string,byte>("s+vs (x)", ES_H_SLAVE | ES_V_SLAVE));
629 : }
630 : }
631 :
632 : // always print unique (w.r.t. surface) number
633 : vector<pair<string, byte> > vInSS;
634 0 : if(gl.is_surface())
635 0 : vInSS.push_back(pair<string,byte>("unique",UNIQUE_SS));
636 : else
637 0 : vInSS.push_back(pair<string,byte>("---",UNIQUE_SS));
638 :
639 : // if PrintSurface and a surface level: add more output
640 0 : if(bPrintSurface && gl.is_surface()){
641 0 : vInSS.push_back(pair<string,byte>("all",ALL_SS));
642 0 : vInSS.push_back(pair<string,byte>("pure",SurfaceView::MG_SURFACE_PURE));
643 0 : vInSS.push_back(pair<string,byte>("shadowing",SurfaceView::MG_SURFACE_RIM));
644 0 : vInSS.push_back(pair<string,byte>("shadow-cpy",SurfaceView::MG_SHADOW_RIM_COPY));
645 0 : vInSS.push_back(pair<string,byte>("shadow-nocpy",SurfaceView::MG_SHADOW_RIM_NONCOPY));
646 : }
647 :
648 0 : UG_LOG(sLeft<<setw(LEVEL) << left << ssGL.str() << right);
649 0 : stringstream ss; ss << sLeft<<setw(LEVEL)<<"";
650 : string LvlBegin(ss.str());
651 :
652 : // Loop Comps
653 0 : for(size_t cmp = 0; cmp < vCmp.size(); ++cmp){
654 :
655 : string LineBegin(LvlBegin);
656 :
657 : // write component at first appearance
658 0 : const int fct = vCmp[cmp].second;
659 0 : if(bPrintCmps) {
660 0 : if(cmp > 0) UG_LOG(LvlBegin);
661 0 : UG_LOG(sSep<<setw(COMPONENT) << left << vCmp[cmp].first << right);
662 0 : stringstream ss; ss <<sSep << setw(COMPONENT)<<"";
663 0 : LineBegin.append(ss.str());
664 0 : }
665 :
666 : bool bPrintBegin = false;
667 :
668 : // print interface numbers
669 0 : for(size_t is = 0; is < vInIS.size(); ++is){
670 0 : for(size_t ss = 0; ss < vInSS.size(); ++ss){
671 0 : if(bPrintBegin) {UG_LOG(LineBegin);} else bPrintBegin = true;
672 0 : if(bPrintInterface) UG_LOG(sSep << setw(INTERFACE) << vInIS[is].first);
673 0 : if(bPrintSurface) UG_LOG(sSep << setw(SURFACE) << vInSS[ss].first);
674 0 : for(size_t si = 0; si < vSubset.size(); ++si)
675 0 : UG_LOG(sSep << setw(NUMBER) << ConvertNumber(dc.num(fct,vSubset[si],vInSS[ss].second,vInIS[is].second),NUMBER,4));
676 0 : UG_LOG(sRight << endl);
677 : }
678 : }
679 :
680 0 : for(size_t is = 0; is < vContainsIS.size(); ++is){
681 0 : for(size_t ss = 0; ss < vInSS.size(); ++ss){
682 0 : if(bPrintBegin) {UG_LOG(LineBegin);} else bPrintBegin = true;
683 0 : if(bPrintInterface) UG_LOG(sSep << setw(INTERFACE) << vContainsIS[is].first);
684 0 : if(bPrintSurface) UG_LOG(sSep << setw(SURFACE) << vInSS[ss].first);
685 0 : for(size_t si = 0; si < vSubset.size(); ++si)
686 0 : UG_LOG(sSep << setw(NUMBER) << ConvertNumber(dc.num_contains(fct,vSubset[si],vInSS[ss].second,vContainsIS[is].second),NUMBER,4));
687 0 : UG_LOG(sRight << endl);
688 : }
689 : }
690 : }
691 0 : }
692 :
693 0 : UG_LOG(sLeft << repeat('-', LINE) << sRight << endl);
694 :
695 : UG_LOG(left);
696 0 : if(sflags.find("legend") != string::npos){
697 0 : UG_LOG(sLeft<<setw(LINE)<<" GridLevel: underlying grid part"<<sRight<<endl);
698 0 : UG_LOG(sLeft<<setw(LINE)<<" lev = level view (all elems in a grid level)"<<sRight<<endl);
699 0 : UG_LOG(sLeft<<setw(LINE)<<" surf = surface view of a level"<<sRight<<endl);
700 0 : UG_LOG(sLeft<<setw(LINE)<<" = all elems in level + elems without child in lower levels"<<sRight<<endl);
701 0 : UG_LOG(sLeft<<setw(LINE)<<" top = top surface (leaf elems)"<<sRight<<endl);
702 0 : UG_LOG(sLeft<<setw(LINE)<<" g = with ghost elems"<<sRight<<endl);
703 :
704 0 : if(bPrintCmps){
705 0 : UG_LOG(sLeft<<setw(LINE)<<" Comps: DoFs in single components"<<sRight<<endl);
706 : }
707 :
708 0 : if(bPrintInterface){
709 0 : UG_LOG(sLeft<<setw(LINE)<<" Parallel: DoFs in parallel interfaces"<<sRight<<endl);
710 0 : UG_LOG(sLeft<<setw(LINE)<<" (x) = DoFs exactly matching parallel state"<<sRight<<endl);
711 0 : UG_LOG(sLeft<<setw(LINE)<<" (&) = DoFs containing parallel state"<<sRight<<endl);
712 0 : UG_LOG(sLeft<<setw(LINE)<<" m = (horiz.) master, s = (horiz.) slave"<<sRight<<endl);
713 0 : UG_LOG(sLeft<<setw(LINE)<<" vm = vert. master, vs = vert. slave"<<sRight<<endl);
714 0 : UG_LOG(sLeft<<setw(LINE)<<" no = not contained in interface"<<sRight<<endl);
715 0 : UG_LOG(sLeft<<setw(LINE)<<" all = all DoFs"<<sRight<<endl);
716 0 : UG_LOG(sLeft<<setw(LINE)<<" unique = neglecting DoF copies (as if serial run)"<<sRight<<endl);
717 0 : UG_LOG(sLeft<<setw(LINE)<<" = no + m (&) + vs (x)"<<sRight<<endl);
718 : }
719 :
720 0 : if(bPrintSurface){
721 0 : UG_LOG(sLeft<<setw(LINE)<<" Surface: DoFs in surface states (matching state exactly)"<<sRight<<endl);
722 0 : UG_LOG(sLeft<<setw(LINE)<<" pure = inner surface DoF"<<sRight<<endl);
723 0 : UG_LOG(sLeft<<setw(LINE)<<" shadowing = Shadowing"<<sRight<<endl);
724 0 : UG_LOG(sLeft<<setw(LINE)<<" shadow-cpy = Shadow Copy (i.e. has same type shadowing)"<<sRight<<endl);
725 0 : UG_LOG(sLeft<<setw(LINE)<<" shadow-nocpy = Shadow Non-Copy (i.e. has not same type shadowing)"<<sRight<<endl);
726 0 : UG_LOG(sLeft<<setw(LINE)<<" all = all DoFs"<<sRight<<endl);
727 0 : UG_LOG(sLeft<<setw(LINE)<<" unique = number of uniquely numbered DoFs"<<sRight<<endl);
728 0 : UG_LOG(sLeft<<setw(LINE)<<" = pure + shadowing + shadow-nocpy"<<sRight<<endl);
729 : }
730 :
731 0 : UG_LOG(sLeft<<setw(LINE)<<" Domain: DoFs on whole domain"<<sRight<<endl);
732 0 : if(bPrintSubset){
733 0 : UG_LOG(sLeft<<setw(LINE)<<" Subset: DoFs on subset only"<<sRight<<endl);
734 : }
735 :
736 0 : UG_LOG(sLeft<<setw(LINE)<<""<<sRight<<endl);
737 0 : UG_LOG(sLeft<<setw(LINE)<<" Call options: print_statistic(\"opt1, opt2, ...\")"<<sRight<<endl);
738 0 : UG_LOG(sLeft<<setw(LINE)<<" proc: show DoFs for single proc"<<sRight<<endl);
739 0 : UG_LOG(sLeft<<setw(LINE)<<" subset: show DoFs per subset"<<sRight<<endl);
740 0 : UG_LOG(sLeft<<setw(LINE)<<" interface: show DoFs per parallel interface"<<sRight<<endl);
741 0 : UG_LOG(sLeft<<setw(LINE)<<" surface: show DoFs per surface state"<<sRight<<endl);
742 0 : UG_LOG(sLeft<<setw(LINE)<<" component: show DoFs per component"<<sRight<<endl);
743 0 : UG_LOG(sLeft<<setw(LINE)<<" legend: show this legend"<<sRight<<endl);
744 0 : UG_LOG(sLeft<<setw(LINE)<<" all: enable all options"<<sRight<<endl);
745 : } else {
746 0 : UG_LOG(sLeft << setw(LINE) << "For Legend and Options: print_statistic(\"legend\")."<< sRight << endl);
747 : }
748 : UG_LOG(right);
749 :
750 0 : UG_LOG(sLeft << repeat('-', LINE) << sRight << endl);
751 0 : }
752 :
753 0 : void IApproximationSpace::print_statistic() const
754 : {
755 0 : print_statistic("subset");
756 0 : }
757 :
758 0 : void IApproximationSpace::print_statistic(std::string flags) const
759 : {
760 : PROFILE_FUNC();
761 :
762 : // if nothing printed
763 0 : if(m_vDD.empty()){
764 : static const char* sLeft = " | ";
765 : static const char* sRight = " | ";
766 : const int LINE = 60;
767 0 : UG_LOG(" --" << repeat('-', LINE) << "-- " << endl);
768 : UG_LOG(left);
769 0 : UG_LOG(sLeft << setw(LINE) << "No DoFDistributions created."<<sRight<<endl);
770 0 : UG_LOG(sLeft << setw(LINE) << "NOTE: DoFDistributions are created only on request."<<sRight<<endl);
771 0 : UG_LOG(sLeft << setw(LINE) << " However, you may force creation using:"<<sRight<<endl);
772 0 : UG_LOG(sLeft << setw(LINE) << " - ApproximationSpace::init_levels()"<<sRight<<endl);
773 0 : UG_LOG(sLeft << setw(LINE) << " - ApproximationSpace::init_surfaces()"<<sRight<<endl);
774 0 : UG_LOG(sLeft << setw(LINE) << " - ApproximationSpace::init_top_surface()"<<sRight<<endl);
775 : UG_LOG(right);
776 0 : UG_LOG(" --" << repeat('-', LINE) << "-- " << endl);
777 0 : return;
778 : }
779 :
780 : // Get DoF Counts
781 : PROFILE_BEGIN(CountLocalDoFStatistic);
782 0 : vector<DoFCount> vDC(m_vDD.size());
783 0 : for(size_t i = 0; i < vDC.size(); ++i)
784 0 : vDC[i] = m_vDD[i]->dof_count();
785 : PROFILE_END();
786 :
787 0 : string sflags = ToLower(flags);
788 0 : if(sflags.find("all") != string::npos)
789 0 : sflags = string("proc, subset, interface, surface, component, legend");
790 :
791 0 : stringstream ssDDOneProc; ssDDOneProc<<" Number of DoFs";
792 : int numProcs = 1;
793 : #ifdef UG_PARALLEL
794 : numProcs = pcl::NumProcs();
795 : ssDDOneProc<<" (Proc: "<<pcl::ProcRank()<<" of "<< pcl::NumProcs()<<")";
796 : #endif
797 :
798 : bool bPrintOneProc = false;
799 : if(sflags.find("proc") != string::npos) bPrintOneProc = true;
800 : if(numProcs == 1) bPrintOneProc = false;
801 :
802 : // Algebra Info
803 : const int blockSize = DefaultAlgebra::get().blocksize();
804 0 : stringstream ssAlgebra; ssAlgebra << " Algebra: ";
805 0 : if(blockSize != AlgebraType::VariableBlockSize)
806 0 : ssAlgebra<<"Block "<<blockSize<<" (divide by "<<blockSize<<" for #Index)";
807 0 : else ssAlgebra <<"Flex";
808 :
809 : // Print infos
810 : PROFILE_BEGIN(PrintLocalDoFStatistic);
811 : if(bPrintOneProc)
812 : PrintDoFCount(vDC, ssDDOneProc.str(), ssAlgebra.str(), sflags);
813 : PROFILE_END();
814 :
815 : PROFILE_BEGIN(CountGlobalDoFStatistic);
816 0 : for(size_t i = 0; i < vDC.size(); ++i)
817 0 : vDC[i].sum_values_over_procs(ug::GetLogAssistant().get_output_process());
818 : PROFILE_END();
819 :
820 : PROFILE_BEGIN(PrintGlobalDoFStatistic);
821 0 : PrintDoFCount(vDC, " Number of DoFs (All Procs)", ssAlgebra.str(), sflags);
822 : PROFILE_END();
823 0 : }
824 :
825 :
826 : #ifdef UG_PARALLEL
827 : static size_t NumIndices(const IndexLayout& Layout)
828 : {
829 : size_t sum = 0;
830 : for(IndexLayout::const_iterator iter = Layout.begin();
831 : iter != Layout.end(); ++iter)
832 : sum += Layout.interface(iter).size();
833 : return sum;
834 : }
835 : #endif
836 :
837 0 : void IApproximationSpace::print_layout_statistic() const
838 : {
839 : #ifdef UG_PARALLEL
840 : static const int LEVEL = 14;
841 : static const int NUMBER = 12;
842 : static const int SEP = 3;
843 : static const int LINE = LEVEL + 4*NUMBER + 4*SEP;
844 : static const char* sSep = " | ";
845 :
846 : // Write header line
847 : UG_LOG(" --" << repeat('-', LINE) << "-- " << endl);
848 : stringstream ss; ss << " Index Layouts on Proc " <<
849 : GetLogAssistant().get_output_process() << " of "<< pcl::NumProcs()
850 : << " Procs: " << repeat(' ', 15);
851 : UG_LOG(sSep << setw(LINE)<<ss.str() << sSep << endl);
852 :
853 : UG_LOG(sSep << setw(LEVEL) << "GridLevel " << sSep);
854 : UG_LOG(setw(NUMBER) << "Master " << sSep);
855 : UG_LOG(setw(NUMBER) << "Slave " << sSep);
856 : UG_LOG(setw(NUMBER) << "vert. Master" << sSep);
857 : UG_LOG(setw(NUMBER) << "vert. Slave" << sSep << endl);
858 : UG_LOG(" |-" << repeat('-', LINE) << "-| " << endl);
859 :
860 : // Write Infos for Levels
861 : for(size_t i = 0; i < m_vDD.size(); ++i){
862 : stringstream ss; ss << m_vDD[i]->grid_level();
863 : UG_LOG(sSep << setw(LEVEL) << left << ss.str() << right << sSep);
864 : UG_LOG(setw(NUMBER) << NumIndices(m_vDD[i]->layouts()->master()) << sSep);
865 : UG_LOG(setw(NUMBER) << NumIndices(m_vDD[i]->layouts()->slave()) << sSep);
866 : UG_LOG(setw(NUMBER) << NumIndices(m_vDD[i]->layouts()->vertical_master()) << sSep);
867 : UG_LOG(setw(NUMBER) << NumIndices(m_vDD[i]->layouts()->vertical_slave()) << sSep << endl);
868 : }
869 : UG_LOG(" --" << repeat('-', LINE) << "-- " << endl);
870 :
871 : #else
872 : UG_LOG(" No Layouts in sequential code.\n");
873 : #endif
874 0 : }
875 :
876 : ////////////////////////////////////////////////////////////////////////////////
877 : // ApproximationSpace
878 : ////////////////////////////////////////////////////////////////////////////////
879 :
880 : template <typename TDomain>
881 0 : ApproximationSpace<TDomain>::
882 : ApproximationSpace(SmartPtr<domain_type> domain)
883 : : IApproximationSpace(domain->subset_handler(), domain->grid()),
884 0 : m_spDomain(domain)
885 : {
886 0 : if(!m_spDomain.valid())
887 0 : UG_THROW("Domain, passed to ApproximationSpace, is invalid.");
888 0 : if(!m_spMGSH.valid())
889 0 : UG_THROW("SubsetHandler, passed to ApproximationSpace, is invalid.");
890 0 : };
891 :
892 : template <typename TDomain>
893 0 : ApproximationSpace<TDomain>::
894 : ApproximationSpace(SmartPtr<domain_type> domain, const AlgebraType& algebraType)
895 : : IApproximationSpace(domain->subset_handler(), domain->grid(), algebraType),
896 0 : m_spDomain(domain)
897 : {
898 0 : if(!m_spDomain.valid())
899 0 : UG_THROW("Domain, passed to ApproximationSpace, is invalid.");
900 0 : if(!m_spMGSH.valid())
901 0 : UG_THROW("SubsetHandler, passed to ApproximationSpace, is invalid.");
902 0 : };
903 :
904 : } // end namespace ug
905 :
906 : #ifdef UG_DIM_1
907 : template class ug::ApproximationSpace<ug::Domain1d>;
908 : #endif
909 : #ifdef UG_DIM_2
910 : template class ug::ApproximationSpace<ug::Domain2d>;
911 : #endif
912 : #ifdef UG_DIM_3
913 : template class ug::ApproximationSpace<ug::Domain3d>;
914 : #endif
|