Flow123d  master-f44eb46
region_set.cc
Go to the documentation of this file.
1 /*
2  * region_set.cc
3  *
4  * Created on: Nov 27, 2012
5  * Author: jb
6  */
7 
8 #include "mesh/region_set.hh"
9 #include "mesh/mesh.h"
10 #include <string>
11 #include <sstream>
12 
13 
14 namespace IT = Input::Type;
15 
16 
17 /*******************************************************************
18  * implementation of RegionSetBase
19  */
20 
22 : region_db_(*mesh->region_db_),
23  el_to_reg_map_(mesh->region_db_->el_to_reg_map_) {}
24 
26  return IT::Abstract("Region", "Abstract record for Region.")
27  .close();
28 }
29 
30 
31 
32 /*******************************************************************
33  * implementation of RegionSetFromId
34  */
35 
37 : RegionSetBase(mesh)
38 {
39  Region reg;
40  string region_label = rec.val<string>("name");
41  unsigned int region_id = rec.val<unsigned int>("id");
42 
43  try {
44  reg = mesh->region_db().find_id(region_id);
45  } catch(RegionDB::ExcUniqueRegionId &e) {
46  e << rec.ei_address();
47  }
48  if ( reg.is_valid() ) {
49  try {
50  region_db_.rename_region(reg, region_label);
51  } catch (RegionDB::ExcNonuniqueLabel &e) {
52  e << rec.ei_address();
53  throw;
54  }
55  } else {
56  unsigned int dim = rec.val<unsigned int>("dim", RegionDB::undefined_dim);
57  try {
58  region_db_.add_region(region_id, region_label, dim, rec.address_string() );
59  } catch (RegionDB::ExcNonuniqueLabel &e) {
60  e << rec.ei_address();
61  throw;
62  } catch (RegionDB::ExcAddingIntoClosed &e) {
63  e << rec.ei_address();
64  throw;
65  } catch (RegionDB::ExcCantAdd &e) {
66  e << rec.ei_address();
67  throw;
68  }
69  }
70 }
71 
72 
73 
75 {
76  return IT::Record("From_Id", "Elementary region declared by its id.\n"
77  "It allows to create a new region with given id and name, "
78  "or to rename an existing region of given id.")
81  "Name (label) of the region. It has to be unique per single mesh.")
83  "Id of the region to which you assign the name.")
85  "Dimension of the region to which you assign the name.\n"
86  "The value is taken into account only if a new region is created.")
87  .close();
88 }
89 
90 
91 
93  Input::register_class< RegionSetFromId, const Input::Record &, Mesh * >("From_Id") +
95 
96 
97 
98 /*******************************************************************
99  * implementation of RegionSetFromLabel
100  */
101 
103 : RegionSetBase(mesh)
104 {
105  string new_name = rec.val<string>("name");
106  string mesh_label = rec.val<string>("mesh_label");
107  bool allow_empty = rec.val<bool>("allow_empty");
108 
109  Region reg = mesh->region_db().find_label(mesh_label);
110  if ( reg.is_valid() ) {
111  try {
112  region_db_.rename_region(reg, new_name);
113  } catch (RegionDB::ExcNonuniqueLabel &e) {
114  e << rec.ei_address();
115  throw;
116  }
117  } else {
118  if(allow_empty){
119  try
120  {
121  uint new_region_id = this->get_max_region_id();
122  region_db_.add_region(new_region_id, new_name, 0, rec.address_string());
123  }
124  catch (RegionDB::ExcNonuniqueLabel &e) {
125  e << rec.ei_address();
126  throw;
127  } catch (RegionDB::ExcAddingIntoClosed &e) {
128  e << rec.ei_address();
129  throw;
130  } catch (RegionDB::ExcCantAdd &e) {
131  e << rec.ei_address();
132  throw;
133  }
134  }
135  else
136  WarningOut().fmt("Unknown region in mesh with label '{}'\n", mesh_label);
137  }
138 }
139 
140 
141 
143 {
144  return IT::Record("From_Label", "Elementary region declared by its name (label).\n"
145  "It gives a new name to an elementary region "
146  "with the original name (in the mesh file) given by the ```mesh_label.```")
149  "New name (label) of the region. It has to be unique per single mesh.")
150  .declare_key("mesh_label", IT::String(), IT::Default::obligatory(),
151  "The original region name in the input file, e.g. a physical volume name in the GMSH format.")
152  .declare_key("allow_empty", IT::Bool(), IT::Default("false"),
153  "If true it allows to the region set to be empty (no elements).")
154  .close();
155 }
156 
157 
158 
160  Input::register_class< RegionSetFromLabel, const Input::Record &, Mesh * >("From_Label") +
162 
163 
164 
165 /*******************************************************************
166  * implementation of RegionSetFromElements
167  */
168 
170 : RegionSetBase(mesh)
171 {
172  unsigned int region_id;
173  string region_label = rec.val<string>("name");
174  Input::Iterator<unsigned int> it = rec.find<unsigned int>("id");
175 
176  if (it) {
177  region_id = (*it);
178  } else {
179  region_id = this->get_max_region_id();
180  }
181 
182  try {
183  region_db_.add_region(region_id, region_label, RegionDB::undefined_dim, rec.address_string() );
184  } catch (RegionDB::ExcNonuniqueLabel &e) {
185  e << rec.ei_address();
186  throw;
187  } catch (RegionDB::ExcAddingIntoClosed &e) {
188  e << rec.ei_address();
189  throw;
190  } catch (RegionDB::ExcCantAdd &e) {
191  e << rec.ei_address();
192  throw;
193  }
194 
195  Input::Array element_list = rec.val<Input::Array>("element_list");
196  for (Input::Iterator<unsigned int> it_element = element_list.begin<unsigned int>();
197  it_element != element_list.end();
198  ++it_element) {
200  if (it_map != el_to_reg_map_.end()) {
201  WarningOut().fmt("Region assigned to element with id {} will be rewritten.\n", (*it_element));
202  }
203  el_to_reg_map_.insert( std::make_pair((*it_element), region_id) );
204 
205  }
206 }
207 
208 
209 
211 {
212  return IT::Record("From_Elements", "Elementary region declared by a list of elements.\n"
213  "The new region is assigned to the list of elements specified by the key "
214  "```element_list```.")
217  "Name (label) of the region. It has to be unique per single mesh.")
219  "Id of the region. "
220  "If unset, a unique id will be generated automatically.")
221  .declare_key("element_list", IT::Array( IT::Integer(0), 1 ), IT::Default::obligatory(),
222  "List of ids of elements.")
223  .close();
224 }
225 
226 
227 
229  Input::register_class< RegionSetFromElements, const Input::Record &, Mesh * >("From_Elements") +
231 
232 
233 
234 /*******************************************************************
235  * implementation of RegionSetBoundary
236  * Need new implementation, will be solved later.
237  */
238 
239 // RegionSetBoundary::RegionSetBoundary(const Input::Record &rec, Mesh *mesh) : RegionSetBase(mesh) {}
240 
241 // const IT::Record & RegionSetBoundary::get_region_input_type() {}
242 
243 //const int RegionSetBoundary::registrar =
244 // Input::register_class< RegionSetBoundary, const Input::Record &, Mesh * >("Region_Boundary") +
245 // RegionSetBoundary::get_region_input_type().size();
246 
247 
248 
249 /*******************************************************************
250  * implementation of RegionSetUnion
251  */
252 
254 : RegionSetBase(mesh)
255 {
256  string name_of_set = rec.val<string>("name");
257  Input::Iterator<Input::Array> region_ids = rec.find<Input::Array>("region_ids");
258  Input::Iterator<Input::Array> regions = rec.find<Input::Array>("regions");
259  std::vector<string> set_names;
260 
261  if (regions) {
262  set_names = region_db_.get_and_check_operands(*regions);
263  }
264  if (region_ids) {
265  for (Input::Iterator<unsigned int> it_ids = region_ids->begin<unsigned int>();
266  it_ids != region_ids->end();
267  ++it_ids) {
268  Region reg;
269  try {
270  reg = region_db_.find_id(*it_ids);
271  } catch(RegionDB::ExcUniqueRegionId &e) {
272  e << region_ids->ei_address();
273  throw;
274  }
275  if (!reg.is_valid()) {
276  std::string label = region_db_.create_label_from_id(*it_ids);
277  reg = region_db_.add_region(*it_ids, label, RegionDB::undefined_dim, rec.address_string() );
278  }
279  set_names.push_back( reg.label() );
280  }
281 
282  }
283 
284  RegionSet region_set = region_db_.union_set(set_names);
285  if (region_set.size() == 0) {
286  THROW( ExcEmptyRegionSetResult() << EI_Operation_Type("Union") << rec.ei_address() );
287  }
288  region_db_.add_set(name_of_set, region_set);
289 }
290 
291 
292 
294 {
295  return IT::Record("Union", "Defines a new region (set) as a union of two or more regions. "
296  "The regions can be given by their names or ids or both.")
299  "Name (label) of the new region. It has to be unique per single mesh.")
300  .declare_key("region_ids", IT::Array( IT::Integer(0)),
301  "List of region ids to be added to the new region set.")
302  .declare_key("regions", IT::Array( IT::String() ),
303  "List of region names (labels) to be added to the new region set.")
304  .close();
305 }
306 
307 
308 
309 const int RegionSetUnion::registrar =
310  Input::register_class< RegionSetUnion, const Input::Record &, Mesh * >("Union") +
312 
313 
314 
315 /*******************************************************************
316  * implementation of RegionSetDifference
317  */
318 
320 : RegionSetBase(mesh)
321 {
322  string name_of_set = rec.val<string>("name");
323  Input::Iterator<Input::Array> labels = rec.find<Input::Array>("regions");
324 
325  std::vector<string> set_names = mesh->region_db().get_and_check_operands(*labels);
326  ASSERT_PERMANENT_EQ(set_names.size(), 2).error("Wrong number of operands. Expect 2.\n" );
327 
328  RegionSet set_1 = region_db_.get_region_set( set_names[0] );
329  RegionSet set_2 = region_db_.get_region_set( set_names[1] );
330  RegionSet set_diff;
331 
332  std::stable_sort(set_1.begin(), set_1.end(), Region::comp);
333  std::stable_sort(set_2.begin(), set_2.end(), Region::comp);
334  set_diff.resize(set_1.size() + set_2.size());
335 
336  RegionSet::iterator it = std::set_difference(set_1.begin(), set_1.end(), set_2.begin(), set_2.end(), set_diff.begin(), Region::comp);
337  set_diff.resize(it - set_diff.begin());
338 
339  if (set_diff.size() == 0) {
340  THROW( ExcEmptyRegionSetResult() << EI_Operation_Type("Difference") << rec.ei_address() );
341  }
342  region_db_.add_set(name_of_set, set_diff);
343 }
344 
345 
346 
348 {
349  return IT::Record("Difference", "Defines a new region (set) as a difference of two regions (sets), given by their names.")
352  "Name (label) of the new region. It has to be unique per single mesh.")
353  .declare_key("regions", IT::Array( IT::String(), 2, 2 ), IT::Default::obligatory(),
354  "List of exactly two region (set) names.\n"
355  "Supposing region sets r1, r2, the result includes all regions of r1 that are not in r2.")
356  .close();
357 }
358 
359 
360 
362  Input::register_class< RegionSetDifference, const Input::Record &, Mesh * >("Difference") +
364 
365 
366 
367 /*******************************************************************
368  * implementation of RegionSetIntersection
369  */
370 
372 : RegionSetBase(mesh)
373 {
374  string name_of_set = rec.val<string>("name");
375  Input::Iterator<Input::Array> regions = rec.find<Input::Array>("regions");
376  std::vector<string> set_names = mesh->region_db().get_and_check_operands(*regions);
377 
378  RegionSet region_set = region_db_.get_region_set(set_names[0]);
379  for (unsigned int i=1; i<set_names.size(); i++) {
380  region_set = this->intersection( region_set, set_names[i] );
381  }
382 
383  if (region_set.size() == 0) {
384  THROW( ExcEmptyRegionSetResult() << EI_Operation_Type("Intersection") << rec.ei_address() );
385  }
386  region_db_.add_set(name_of_set, region_set);
387 }
388 
389 
390 
392 {
393  return IT::Record("Intersection", "Defines a new region (set) as an intersection of two or more regions (sets)"
394  ", given by their names.")
397  "Name (label) of the new region. It has to be unique per single mesh.")
399  "List of two or more region (set) names.")
400  .close();
401 }
402 
403 
405  Input::register_class< RegionSetIntersection, const Input::Record &, Mesh * >("Intersection") +
407 
408 
409 RegionSet RegionSetIntersection::intersection( RegionSet target_set, const string & source_set_name) const {
410  RegionSet set_insec;
411  RegionSet source_set = region_db_.get_region_set( source_set_name );
412  RegionSet::iterator it;
413 
414  std::stable_sort(target_set.begin(), target_set.end(), Region::comp);
415  std::stable_sort(source_set.begin(), source_set.end(), Region::comp);
416 
417  set_insec.resize(target_set.size() + source_set.size());
418  it = std::set_intersection(target_set.begin(), target_set.end(), source_set.begin(), source_set.end(), set_insec.begin(), Region::comp);
419  set_insec.resize(it - set_insec.begin());
420 
421  return set_insec;
422 }
#define ASSERT_PERMANENT_EQ(a, b)
Definition of comparative assert macro (EQual)
Definition: asserts.hh:329
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
Iterator< ValueType > begin() const
IteratorBase end() const
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
string address_string() const
Definition: accessors.cc:184
EI_Address ei_address() const
Definition: accessors.cc:178
const Ret val(const string &key) const
Iterator< Ret > find(const string &key) const
Class for declaration of polymorphic Record.
Abstract & close()
Close the Abstract and add its to type repository (see TypeRepository::add_type).
Class for declaration of inputs sequences.
Definition: type_base.hh:339
Class for declaration of the input of type Bool.
Definition: type_base.hh:452
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:110
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:124
Class for declaration of the integral input data.
Definition: type_base.hh:483
Record type proxy class.
Definition: type_record.hh:182
unsigned int size() const
Returns number of keys in the Record.
Definition: type_record.hh:602
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:196
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
Record & declare_key(const string &key, std::shared_ptr< TypeBase > type, const Default &default_value, const string &description, TypeBase::attribute_map key_attributes=TypeBase::attribute_map())
Declares a new key of the Record.
Definition: type_record.cc:503
Class for declaration of the input data that are in string format.
Definition: type_base.hh:582
const RegionDB & region_db() const
Definition: mesh.h:175
Definition: mesh.h:362
Region add_region(unsigned int id, const std::string &label, unsigned int dim, const std::string &address="implicit")
Definition: region.cc:85
Region rename_region(Region reg, const std::string &new_label)
Definition: region.cc:109
std::string create_label_from_id(unsigned int id) const
Definition: region.cc:337
Region find_label(const std::string &label) const
Definition: region.cc:169
Region find_id(unsigned int id, unsigned int dim) const
Definition: region.cc:180
RegionSet get_region_set(const std::string &set_name) const
Definition: region.cc:328
void add_set(const std::string &set_name, const RegionSet &set)
Definition: region.cc:293
static const unsigned int undefined_dim
Definition: region.hh:331
std::vector< std::string > get_and_check_operands(const Input::Array &operands) const
Definition: region.cc:312
RegionSet union_set(std::vector< std::string > set_names) const
Definition: region.cc:482
bool is_valid() const
Returns false if the region has undefined/invalid value.
Definition: region.hh:77
RegionSetBase(Mesh *mesh)
Constructor.
Definition: region_set.cc:21
RegionDB & region_db_
Reference to region_db_ of Mesh.
Definition: region_set.hh:49
unsigned int get_max_region_id()
Definition: region_set.hh:53
RegionDB::MapElementIDToRegionID & el_to_reg_map_
Reference to map stored relevance of elements to regions.
Definition: region_set.hh:51
static Input::Type::Abstract & get_input_type()
Definition: region_set.cc:25
static const Input::Type::Record & get_region_input_type()
Definition: region_set.cc:347
static const int registrar
Registrar of class to factory.
Definition: region_set.hh:199
RegionSetDifference(const Input::Record &rec, Mesh *mesh)
Constructor.
Definition: region_set.cc:319
RegionSetFromElements(const Input::Record &rec, Mesh *mesh)
Constructor.
Definition: region_set.cc:169
static const int registrar
Registrar of class to factory.
Definition: region_set.hh:128
static const Input::Type::Record & get_region_input_type()
Definition: region_set.cc:210
static const Input::Type::Record & get_region_input_type()
Definition: region_set.cc:74
static const int registrar
Registrar of class to factory.
Definition: region_set.hh:80
RegionSetFromId(const Input::Record &rec, Mesh *mesh)
Constructor.
Definition: region_set.cc:36
static const int registrar
Registrar of class to factory.
Definition: region_set.hh:103
static const Input::Type::Record & get_region_input_type()
Definition: region_set.cc:142
RegionSetFromLabel(const Input::Record &rec, Mesh *mesh)
Constructor.
Definition: region_set.cc:102
RegionSet intersection(RegionSet target_set, const std::string &source_set_name) const
Definition: region_set.cc:409
static const Input::Type::Record & get_region_input_type()
Definition: region_set.cc:391
static const int registrar
Registrar of class to factory.
Definition: region_set.hh:223
RegionSetIntersection(const Input::Record &rec, Mesh *mesh)
Constructor.
Definition: region_set.cc:371
static const int registrar
Registrar of class to factory.
Definition: region_set.hh:175
RegionSetUnion(const Input::Record &rec, Mesh *mesh)
Constructor.
Definition: region_set.cc:253
static const Input::Type::Record & get_region_input_type()
Definition: region_set.cc:293
static bool comp(const Region &a, const Region &b)
Comparative method of two regions.
Definition: region.hh:172
std::string label() const
Returns label of the region (using RegionDB)
Definition: region.cc:32
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
#define WarningOut()
Macro defining 'warning' record of log.
Definition: logger.hh:278
unsigned int uint