Flow123d  jenkins-Flow123d-windows-release-multijob-285
region.cc
Go to the documentation of this file.
1 /*
2  * material_dispatch.cc
3  *
4  * Created on: Nov 27, 2012
5  * Author: jb
6  */
7 
8 #include <string>
9 #include <sstream>
10 
11 #include "mesh/region.hh"
12 #include "system/exceptions.hh"
13 
14 #include "input/input_type.hh"
15 #include "input/type_base.hh"
16 #include "input/accessors.hh"
17 #include <boost/foreach.hpp>
18 
19 using namespace std;
20 
21 
22 
23 std::string Region::label() const
24  { return db_->get_label(idx_); }
25 
26 
27 
28 unsigned int Region::id() const
29  { return db_->get_id(idx_); }
30 
31 
32 
33 unsigned int Region::dim() const
34  { return db_->get_dim(idx_); }
35 
36 /**************************************************************************************************
37  * Implementation of RegionDB
38  */
39 
40 
41 namespace IT=Input::Type;
42 
43 
44 
46  IT::Record("Region", "Definition of region of elements.")
48  "Label (name) of the region. Has to be unique in one mesh.\n")
50  "The ID of the region to which you assign label.")
51  .declare_key("element_list", IT::Array( IT::Integer(0) ), IT::Default::optional(),
52  "Specification of the region by the list of elements. This is not recomended")
53  .close();
54 
56  IT::Record("RegionSet", "Definition of one region set.")
58  "Unique name of the region set.")
59  .declare_key("region_ids", IT::Array( IT::Integer(0)),
60  "List of region ID numbers that has to be added to the region set.")
61  .declare_key("region_labels", IT::Array( IT::String()),
62  "List of labels of the regions that has to be added to the region set.")
63  .declare_key("union", IT::Array( IT::String(), 2,2),
64  "Defines region set as a union of given pair of sets. Overrides previous keys.")
65  .declare_key("intersection", IT::Array( IT::String(), 2,2),
66  "Defines region set as an intersection of given pair of sets. Overrides previous keys.")
67  .declare_key("difference", IT::Array( IT::String(), 2,2),
68  "Defines region set as a difference of given pair of sets. Overrides previous keys.")
69  .close();
70 
71 const unsigned int RegionDB::undefined_dim = 10;
72 
73 
74 /// Default constructor
76 : closed_(false), n_boundary_(0), n_bulk_(0) {
77 
78  // adding implicit boundary and bulk regions
79  // How to deal with dimension, clean solution is to have implicit region for every
80  // dimension, or we can allow regions of mixed dimension
81  //implicit_bulk_ = add_region(Region::undefined-1, "IMPLICIT BULK", 0, Region::bulk);
82  //implicit_boundary_ = ;
83 
84 }
85 
86 
89  if ( it_id!=region_set_.get<DimId>().end() ) {
90  return Region(it_id->index, *this);
91  }
92 
93  return insert_region(Region::undefined-2, "IMPLICIT BOUNDARY", undefined_dim, Region::boundary);
94 }
95 
96 
97 Region RegionDB::add_region( unsigned int id, const std::string &label, unsigned int dim) {
98  bool boundary = is_boundary(label);
99  DimIDIter it_id = region_set_.get<DimId>().find(DimID(dim,id));
100  if (it_id != region_set_.get<DimId>().end() ) {
101  // Find existing region
102  return find_by_dimid(it_id, id, label, boundary);
103  }
104 
105  DimIDIter it_undef_dim = region_set_.get<DimId>().find(DimID(undefined_dim,id));
106  if (it_undef_dim != region_set_.get<DimId>().end() ) {
107  // Region with same ID and undefined_dim exists, replace undefined_dim
108  return replace_region_dim(it_undef_dim, dim, boundary);
109  }
110 
111  LabelIter it_label = region_set_.get<Label>().find(label);
112  if (it_label != region_set_.get<Label>().end() ) {
113  // ID is free, not label
114  THROW(ExcNonuniqueLabel() << EI_Label(label) << EI_ID(id) << EI_IDOfOtherLabel(it_label->get_id()) );
115  }
116 
117  return insert_region(id, label, dim, boundary);
118 }
119 
120 
121 Region RegionDB::add_region(unsigned int id, const std::string &label) {
122  bool boundary = is_boundary(label);
123  if (label.size() == 0) create_label_from_id(label, id);
124 
125  DimIDIter it_id = region_set_.get<DimId>().find(DimID(undefined_dim,id));
126  if (it_id != region_set_.get<DimId>().end() ) {
127  // Find existing region
128  return find_by_dimid(it_id, id, label, boundary);
129  }
130 
131  LabelIter it_label = region_set_.get<Label>().find(label);
132  if (it_label != region_set_.get<Label>().end() ) {
133  // ID is free, not label
134  THROW(ExcNonuniqueLabel() << EI_Label(label) << EI_ID(id) << EI_IDOfOtherLabel(it_label->get_id()) );
135  }
136 
137  return insert_region(id, label, undefined_dim, boundary);
138 }
139 
140 
141 Region RegionDB::add_region(unsigned int id, unsigned int dim) {
142  DimIDIter it_id = region_set_.get<DimId>().find(DimID(dim,id));
143  if ( it_id!=region_set_.get<DimId>().end() ) {
144  return Region(it_id->index, *this);
145  }
146 
147  DimIDIter it_undef_dim = region_set_.get<DimId>().find(DimID(undefined_dim,id));
148  if (it_undef_dim != region_set_.get<DimId>().end() ) {
149  // Region with same ID and undefined_dim exists, replace undefined_dim
150  bool boundary = is_boundary(it_undef_dim->label);
151  return replace_region_dim(it_undef_dim, dim, boundary);
152  }
153 
154  // else
155  stringstream ss;
156  ss << "region_" << id;
157  return insert_region(id, ss.str(), dim, false);
158 }
159 
160 
161 
162 Region RegionDB::find_label(const std::string &label) const
163 {
164  LabelIter it_label = region_set_.get<Label>().find(label);
165  if (it_label==region_set_.get<Label>().end() ) return Region();
166  return Region(it_label->index, *this);
167 }
168 
169 
170 
171 
172 
173 Region RegionDB::find_id(unsigned int id, unsigned int dim) const
174 {
175  DimIDIter it_id = region_set_.get<DimId>().find(DimID(dim, id));
176  if ( it_id==region_set_.get<DimId>().end() ) return Region();
177  return Region(it_id->index, *this);
178 }
179 
180 
181 
182 
183 Region RegionDB::find_id(unsigned int id) const
184 {
185  if (region_set_.get<OnlyID>().count(id) > 1) {
186  THROW( ExcUniqueRegionId() << EI_ID( id ) );
187  }
188  OnlyIDIter it_id = region_set_.get<OnlyID>().find(id);
189  if ( it_id==region_set_.get<OnlyID>().end() ) return Region();
190  return Region(it_id->index, *this);
191 }
192 
193 
194 
195 
196 const std::string & RegionDB::get_label(unsigned int idx) const {
197  RegionTable::index<Index>::type::iterator it = region_set_.get<Index>().find(idx);
198  ASSERT( it!= region_set_.get<Index>().end(), "No region with index: %u\n", idx);
199  return it->label;
200 }
201 
202 
203 
204 unsigned int RegionDB::get_id(unsigned int idx) const {
205  RegionTable::index<Index>::type::iterator it = region_set_.get<Index>().find(idx);
206  ASSERT( it!= region_set_.get<Index>().end(), "No region with index: %u\n", idx);
207  return it->get_id();
208 }
209 
210 
211 
212 unsigned int RegionDB::get_dim(unsigned int idx) const {
213  RegionTable::index<Index>::type::iterator it = region_set_.get<Index>().find(idx);
214  ASSERT( it!= region_set_.get<Index>().end(), "No region with index: %u\n", idx);
215  return it->dim();
216 }
217 
218 
219 
221  closed_=true;
222  // set default sets
223  for(unsigned int i=0; i< size(); i++) {
224  Region reg(i, *this);
225 
226  if (reg.is_boundary() && (reg.boundary_idx() < boundary_size()) ) {
227  add_to_set("BOUNDARY", reg );
228  add_to_set("ALL", reg);
229  } else
230  if ( (! reg.is_boundary()) && (reg.bulk_idx() < bulk_size()) ) {
231  add_to_set("BULK", reg );
232  add_to_set("ALL", reg);
233  }
234  }
235 }
236 
237 
238 unsigned int RegionDB::size() const {
239  ASSERT(closed_, "RegionDB not closed yet.\n");
240  return 2* max(n_boundary_, n_bulk_);
241 }
242 
243 
244 
245 unsigned int RegionDB::boundary_size() const {
246  ASSERT(closed_, "RegionDB not closed yet.\n");
247  return n_boundary_;
248 }
249 
250 
251 
252 unsigned int RegionDB::bulk_size() const {
253  ASSERT(closed_, "RegionDB not closed yet.\n");
254  return n_bulk_;
255 }
256 
257 
258 
259 
260 void RegionDB::add_to_set( const string& set_name, Region region) {
262 
263  if (it == sets_.end()) {
264  RegionSet set;
265  set.push_back(region);
266 
267  sets_.insert( std::make_pair(set_name, set) );
268  } else {
269  RegionSet & set = (*it).second;
270  if ( std::find(set.begin(), set.end(), region)==set.end() ) {
271  set.push_back(region); // add region if doesn't exist
272  }
273  }
274 }
275 
276 
277 void RegionDB::add_set( const string& set_name, const RegionSet & set) {
278  // add region only if it is not in the set
279  if (sets_.find(set_name) == sets_.end()) {
280  sets_.insert( std::make_pair(set_name, set) );
281  }
282 }
283 
284 
285 RegionSet RegionDB::union_sets( const string & set_name_1, const string & set_name_2) {
286  RegionSet set_union;
287  RegionSet set_1, set_2;
288  RegionSet::iterator it;
289 
290  prepare_sets(set_name_1, set_name_2, set_1, set_2);
291  set_union.resize(set_1.size() + set_2.size());
292  it = std::set_union(set_1.begin(), set_1.end(), set_2.begin(), set_2.end(), set_union.begin(), Region::comp);
293  set_union.resize(it - set_union.begin());
294 
295  return set_union;
296 }
297 
298 
299 RegionSet RegionDB::intersection( const string & set_name_1, const string & set_name_2) {
300  RegionSet set_insec;
301  RegionSet set_1, set_2;
302  RegionSet::iterator it;
303 
304  prepare_sets(set_name_1, set_name_2, set_1, set_2);
305  set_insec.resize(set_1.size() + set_2.size());
306  it = std::set_intersection(set_1.begin(), set_1.end(), set_2.begin(), set_2.end(), set_insec.begin(), Region::comp);
307  set_insec.resize(it - set_insec.begin());
308 
309  return set_insec;
310 }
311 
312 
313 RegionSet RegionDB::difference( const string & set_name_1, const string & set_name_2) {
314  RegionSet set_diff;
315  RegionSet set_1, set_2;
316  RegionSet::iterator it;
317 
318  prepare_sets(set_name_1, set_name_2, set_1, set_2);
319  set_diff.resize(set_1.size() + set_2.size());
320  it = std::set_difference(set_1.begin(), set_1.end(), set_2.begin(), set_2.end(), set_diff.begin(), Region::comp);
321  set_diff.resize(it - set_diff.begin());
322 
323  return set_diff;
324 }
325 
326 
327 void RegionDB::prepare_sets( const string & set_name_1, const string & set_name_2,
328  RegionSet & set_1, RegionSet & set_2) {
329  std::map<std::string, RegionSet>::iterator it_1 = sets_.find(set_name_1);
330  std::map<std::string, RegionSet>::iterator it_2 = sets_.find(set_name_2);
331 
332  if ( it_1 == sets_.end() ) { THROW(ExcUnknownSet() << EI_Label(set_name_1)); }
333  if ( it_2 == sets_.end() ) { THROW(ExcUnknownSet() << EI_Label(set_name_2)); }
334 
335  set_1 = (*it_1).second;
336  set_2 = (*it_2).second;
337 
338  std::stable_sort(set_1.begin(), set_1.end(), Region::comp);
339  std::stable_sort(set_2.begin(), set_2.end(), Region::comp);
340 }
341 
342 
343 
344 pair<string,string> RegionDB::get_and_check_operands(const Input::Array & operands)
345 {
346  vector<string> names;
347  operands.copy_to(names);
348  if ( names.size() != 2 ) THROW(ExcWrongOpNumber() << EI_NumOp(names.size()) << operands.ei_address() );
349  auto ret_names = pair<string,string>(names[0], names[1]);
350  if ( sets_.find( ret_names.first ) == sets_.end() )
351  THROW( ExcUnknownSet() << EI_Label( ret_names.first )
352  << operands.ei_address() );
353  if ( sets_.find( ret_names.second ) == sets_.end() )
354  THROW( ExcUnknownSet() << EI_Label( ret_names.second )
355  << operands.ei_address() );
356  return ret_names;
357 }
358 
359 
360 
361 RegionSet RegionDB::get_region_set(const string & set_name) const {
363  if ( it == sets_.end() ) {
364  return RegionSet();
365  }
366  return (*it).second;
367 }
368 
369 
372  it != arr.end();
373  ++it) {
374 
375  Input::Record rec = (*it);
376  string set_name;
377  Input::Array region_ids, region_labels;
378  Input::Array union_names, intersection_names, difference_names;
379  RegionSet region_set;
380 
381  rec.opt_val("name", set_name);
382 
383  if (rec.opt_val("region_ids", region_ids) ) {
384  for (Input::Iterator<unsigned int> it_ids = region_ids.begin<unsigned int>();
385  it_ids != region_ids.end();
386  ++it_ids) {
387  try {
388  Region reg = find_id(*it_ids);
389  if (reg.is_valid()) {
390  if ( std::find(region_set.begin(), region_set.end(), reg)==region_set.end() ) {
391  region_set.push_back(reg); // add region if doesn't exist
392  }
393  } else {
394  xprintf(Warn, "Region with id %d doesn't exist. Skipping\n", (*it_ids));
395  }
396  } catch(ExcUniqueRegionId &e) {
397  e << region_ids.ei_address();
398  throw;
399  }
400  }
401  }
402 
403  if (rec.opt_val("region_labels", region_labels) ) {
404  for (Input::Iterator<string> it_labels = region_labels.begin<string>();
405  it_labels != region_labels.end();
406  ++it_labels) {
407  Region reg = find_label(*it_labels);
408  if (reg.is_valid()) {
409  if ( std::find(region_set.begin(), region_set.end(), reg)==region_set.end() ) {
410  region_set.push_back(reg); // add region if doesn't exist
411  }
412  } else {
413  xprintf(Warn, "Region with label %s doesn't exist. Skipping\n", (*it_labels).c_str());
414  }
415  }
416  }
417 
418  Input::Iterator<Input::Array> operands = rec.find<Input::Array>("union");
419  if ( operands ) {
420 
421  if (region_set.size() != 0) {
422  xprintf(Warn, "Overwriting previous initialization of region set '%s' by union operation.\n", set_name.c_str());
423  }
424 
425  pair<string,string> set_names = get_and_check_operands(*operands);
426  region_set = union_sets( set_names.first, set_names.second );
427  }
428 
429  operands = rec.find<Input::Array>("intersection");
430  if (operands) {
431 
432  if (region_set.size() != 0) {
433  xprintf(Warn, "Overwriting previous initialization of region set '%s' by intersection operation.\n", set_name.c_str());
434  }
435 
436  pair<string,string> set_names = get_and_check_operands(*operands);
437  region_set = intersection( set_names.first, set_names.second );
438  }
439 
440  operands = rec.find<Input::Array>("difference");
441  if (operands) {
442 
443  if (region_set.size() != 0) {
444  xprintf(Warn, "Overwriting previous initialization of region set '%s' by difference operation.\n", set_name.c_str());
445  }
446 
447  pair<string,string> set_names = get_and_check_operands(*operands);
448  region_set = difference( set_names.first, set_names.second );
449  }
450 
451  add_set(set_name, region_set);
452  }
453 }
454 
456  map.clear();
457 
459  it != region_list.end();
460  ++it) {
461 
462  Input::Record rec = (*it);
463  string region_name = rec.val<string>("name");
464  unsigned int region_id = rec.val<unsigned int>("id");
465  add_region(region_id, region_name);
466 
467  Input::Array element_list;
468  if (rec.opt_val("element_list", element_list) ) {
469  for (Input::Iterator<unsigned int> it_element = element_list.begin<unsigned int>();
470  it_element != element_list.end();
471  ++it_element) {
472 
473  std::map<unsigned int, unsigned int>::iterator it_map = map.find((*it_element));
474  if (it_map == map.end()) {
475  map.insert( std::make_pair((*it_element), region_id) );
476  } else {
477  xprintf(Warn, "Element with id %u can't be added more than once.\n", (*it_element));
478  }
479  }
480  }
481  }
482 }
483 
484 void RegionDB::create_label_from_id(const string & label, unsigned int id) {
485  stringstream ss;
486  ss << "region_" << id;
487  ss.str(label);
488 }
489 
490 Region RegionDB::insert_region(unsigned int id, const std::string &label, unsigned int dim, bool boundary) {
491  if (closed_) THROW( ExcAddingIntoClosed() << EI_Label(label) << EI_ID(id) );
492 
493  unsigned int index;
494  if (boundary) {
495  index = (n_boundary_ <<1);
496  n_boundary_++;
497  } else {
498  index = (n_bulk_ << 1)+1;
499  n_bulk_++;
500  }
501  if (index >= max_n_regions) xprintf(UsrErr, "Too many regions, more then %d\n", max_n_regions);
502  if ( ! region_set_.insert( RegionItem(index, id, label, dim) ).second )
503  THROW( ExcCantAdd() << EI_Label(label) << EI_ID(id) );
504  return Region(index, *this);
505 }
506 
507 Region RegionDB::replace_region_dim(DimIDIter it_undef_dim, unsigned int dim, bool boundary) {
508  ASSERT( it_undef_dim->dim() == undefined_dim,
509  "Dimension of replaced region with id=%u must be undefined_dim, actually is: %u\n", it_undef_dim->get_id(), it_undef_dim->dim());
510 
511  unsigned int index = it_undef_dim->index;
512 
513  RegionItem item(index, it_undef_dim->get_id(), it_undef_dim->label, dim);
514  region_set_.replace(
515  region_set_.get<Index>().find(index),
516  item);
517 
518  Region r_id=Region(index, *this);
519  // check boundary
520  if ( r_id.is_boundary() != boundary )
521  THROW(ExcInconsistentBoundary() << EI_Label(it_undef_dim->label) << EI_ID(it_undef_dim->get_id()) );
522 
523  return r_id;
524 }
525 
526 Region RegionDB::find_by_dimid(DimIDIter it_id, unsigned int id, const std::string &label, bool boundary) {
527  unsigned int index = it_id->index;
528  LabelIter it_label = region_set_.get<Label>().find(label);
529  if ( it_label == region_set_.get<Label>().end() || index != it_label->index )
530  THROW(ExcNonuniqueID() << EI_Label(label) << EI_ID(id) << EI_LabelOfOtherID(it_id->label) );
531 
532  Region r_id=Region(index, *this);
533  // check boundary
534  if ( r_id.is_boundary() != boundary )
535  THROW(ExcInconsistentBoundary() << EI_Label(label) << EI_ID(id) );
536 
537  return r_id;
538 }
std::map< std::string, RegionSet > sets_
Map of region sets.
Definition: region.hh:565
void prepare_sets(const string &set_name_1, const string &set_name_2, RegionSet &set_1, RegionSet &set_2)
Definition: region.cc:327
Iterator< ValueType > begin() const
unsigned int size() const
Definition: region.cc:238
const std::string & get_label(unsigned int idx) const
Definition: region.cc:196
pair< string, string > get_and_check_operands(const Input::Array &operands)
Definition: region.cc:344
void read_regions_from_input(Input::Array region_list, MapElementIDToRegionID &map)
Definition: region.cc:455
Accessor to input data conforming to declared Array.
Definition: accessors.hh:558
EI_Address ei_address() const
Definition: accessors.cc:297
bool is_boundary() const
Returns true if it is a Boundary region and false if it is a Bulk region.
Definition: region.hh:63
void read_sets_from_input(Input::Array arr)
Definition: region.cc:370
std::vector< Region > RegionSet
Definition: equation.hh:44
RegionSet union_sets(const string &set_name_1, const string &set_name_2)
Definition: region.cc:285
unsigned int bulk_size() const
Definition: region.cc:252
static Default obligatory()
Definition: type_record.hh:89
RegionSet get_region_set(const string &set_name) const
Definition: region.cc:361
Iterator< Ret > find(const string &key) const
static bool comp(const Region &a, const Region &b)
Comparative method of two regions.
Definition: region.hh:179
void add_set(const string &set_name, const RegionSet &set)
Definition: region.cc:277
static const unsigned int undefined
index for undefined region
Definition: region.hh:108
Region replace_region_dim(DimIDIter it_undef_dim, unsigned int dim, bool boundary)
Definition: region.cc:507
Class for declaration of the integral input data.
Definition: type_base.hh:355
One item in region database.
Definition: region.hh:509
Class for declaration of inputs sequences.
Definition: type_base.hh:239
void create_label_from_id(const string &label, unsigned int id)
Definition: region.cc:484
IteratorBase end() const
unsigned int boundary_idx() const
Returns index of the region in the boundary set.
Definition: region.hh:75
static Default optional()
Definition: type_record.hh:102
bool opt_val(const string &key, Ret &value) const
#define ASSERT(...)
Definition: global_defs.h:121
Definition: system.hh:72
Region find_by_dimid(DimIDIter it_id, unsigned int id, const std::string &label, bool boundary)
Definition: region.cc:526
Region find_id(unsigned int id, unsigned int dim) const
Definition: region.cc:173
Accessor to the data with type Type::Record.
Definition: accessors.hh:327
void add_to_set(const string &set_name, Region region)
Definition: region.cc:260
const Ret val(const string &key) const
#define xprintf(...)
Definition: system.hh:100
RegionTable::index< Label >::type::iterator LabelIter
Definition: region.hh:549
bool is_boundary(const std::string &label)
Definition: region.hh:614
void close()
Definition: region.cc:220
const Record & close() const
Definition: type_record.cc:314
Region implicit_boundary_region()
Definition: region.cc:87
unsigned int n_bulk_
Number of bulk regions.
Definition: region.hh:562
std::pair< unsigned int, unsigned int > DimID
Definition: region.hh:506
RegionDB()
Default constructor.
Definition: region.cc:75
Region add_region(unsigned int id, const std::string &label, unsigned int dim)
Definition: region.cc:97
RegionTable::index< OnlyID >::type::iterator OnlyIDIter
Definition: region.hh:551
Region insert_region(unsigned int id, const std::string &label, unsigned int dim, bool boundary)
Definition: region.cc:490
RegionSet boundary
Definition: region.hh:568
RegionTable::index< DimId >::type::iterator DimIDIter
Definition: region.hh:550
Definition: system.hh:72
void copy_to(Container &out) const
static const unsigned int max_n_regions
Definition: region.hh:332
unsigned int get_id(unsigned int idx) const
Definition: region.cc:204
RegionSet difference(const string &set_name_1, const string &set_name_2)
Definition: region.cc:313
static Input::Type::Record region_input_type
Definition: region.hh:294
unsigned int boundary_size() const
Definition: region.cc:245
RegionSet intersection(const string &set_name_1, const string &set_name_2)
Definition: region.cc:299
unsigned int get_dim(unsigned int idx) const
Definition: region.cc:212
RegionTable region_set_
Database of all regions (both boundary and bulk).
Definition: region.hh:555
unsigned int bulk_idx() const
Returns index of the region in the bulk set.
Definition: region.hh:80
Record type proxy class.
Definition: type_record.hh:169
static const unsigned int undefined_dim
Definition: region.hh:336
Region find_label(const std::string &label) const
Definition: region.cc:162
bool is_valid() const
Returns false if the region has undefined/invalid value.
Definition: region.hh:67
std::string label() const
Returns label of the region (using RegionDB)
Definition: region.cc:23
static Input::Type::Record region_set_input_type
Definition: region.hh:298
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:34
bool closed_
flag for closed database, no regions can be added, but you can add region sets
Definition: region.hh:558
unsigned int n_boundary_
Number of boundary regions.
Definition: region.hh:560
unsigned int id() const
Returns id of the region (using RegionDB)
Definition: region.cc:28
unsigned int dim() const
Returns dimension of the region.
Definition: region.cc:33
Record & declare_key(const string &key, const KeyType &type, const Default &default_value, const string &description)
Definition: type_record.cc:430