Flow123d  JS_before_hm-1717-gd762018d2
field_set.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file field_set.cc
15  * @brief
16  */
17 
18 #include "fields/field_set.hh"
19 #include "system/sys_profiler.hh"
21 #include "fem/mapping_p1.hh"
22 #include "mesh/ref_element.hh"
24 #include <boost/algorithm/string/replace.hpp>
25 #include <queue>
26 
27 
29 {}
30 
31 FieldSet &FieldSet::operator +=(FieldCommon &add_field) {
32  FieldCommon *found_field = field(add_field.name());
33  if (found_field) {
34  OLD_ASSERT(&add_field==found_field, "Another field of the same name exists when adding field: %s\n",
35  add_field.name().c_str());
36  } else {
37  field_list.push_back(&add_field);
38  }
39  return *this;
40 }
41 
42 
43 
44 FieldSet &FieldSet::operator +=(const FieldSet &other) {
45  for(auto field_ptr : other.field_list) this->operator +=(*field_ptr);
46  return *this;
47 }
48 
49 
50 
51 FieldSet FieldSet::subset(std::vector<std::string> names) const {
52  FieldSet set;
53  set.set_mesh( *this->mesh_ );
54  for(auto name : names) set += (*this)[name];
55  return set;
56 }
57 
58 
59 
60 FieldSet FieldSet::subset( FieldFlag::Flags::Mask mask) const {
61  FieldSet set;
62  for(auto field : field_list)
63  if (field->flags().match(mask)) set += *field;
64  return set;
65 }
66 
67 
68 
69 Input::Type::Record FieldSet::make_field_descriptor_type(const std::string &equation_name) const {
70  string rec_name = equation_name + ":Data";
72  Input::Type::Record rec = Input::Type::Record(rec_name, desc)
74 
75  for(auto field : field_list) {
76  if ( field->flags().match(FieldFlag::declare_input) ) {
77  string description = field->description() + " (($[" + field->units().format_latex() + "]$))";
78 
79  // Adding units is not so simple.
80  // 1) It must be correct for Latex.
81  // 2) It should be consistent with rest of documentation.
82  // 3) Should be specified for all fields.
83  //if (units != "") description+= " [" +field->units() + "]";
84 
85  // TODO: temporary solution, see FieldCommon::multifield_
86 
87  std::shared_ptr<Input::Type::TypeBase> field_type_ptr;
88  if (field->is_multifield()) {
89  field_type_ptr = std::make_shared<Input::Type::Array>(field->get_multifield_input_type());
90  } else {
91  field_type_ptr = std::make_shared<Input::Type::Instance>(field->get_input_type());
92  }
93  ASSERT( field->units().is_def() )(field->input_name()).error("units not def.");
95  { {FlowAttribute::field_unit(), field->units().json() },
97  );
98  string default_val = field->input_default();
99  if (default_val != "") {
100  boost::replace_all(default_val, "\"", "\\\"");
101  key_attributes[FlowAttribute::field_default_value()] = "\"" + default_val + "\"";
102  }
103  rec.declare_key(field->input_name(), field_type_ptr, Input::Type::Default::optional(), description, key_attributes);
104  }
105 
106  }
107  return rec.close();
108 }
109 
110 
111 /*
112 Input::Type::Selection FieldSet::make_output_field_selection(const string &name, const string &desc)
113 {
114  namespace IT=Input::Type;
115  IT::Selection sel(name, desc);
116  int i=0;
117  // add value for each field excluding boundary fields
118  for( auto field : field_list)
119  {
120  if ( !field->is_bc() && field->flags().match( FieldFlag::allow_output) )
121  {
122  string desc = "Output of the field " + field->name() + " (($[" + field->units().format_latex()+"]$))";
123  if (field->description().length() > 0)
124  desc += " (" + field->description() + ").";
125  else
126  desc += ".";
127  DebugOut() << field->get_value_attribute();
128 
129  sel.add_value(i, field->name(), desc, { {FlowAttribute::field_value_shape(), field->get_value_attribute()} } );
130  i++;
131  }
132  }
133 
134  return sel;
135 }
136 */
137 
138 
139 void FieldSet::set_field(const std::string &dest_field_name, FieldCommon &source)
140 {
141  auto &field = (*this)[dest_field_name];
142  field.copy_from(source);
143 }
144 
145 
146 
147 FieldCommon *FieldSet::field(const std::string &field_name) const {
148  for(auto field : field_list)
149  if (field->name() ==field_name) return field;
150  return nullptr;
151 }
152 
153 
154 
155 FieldCommon &FieldSet::operator[](const std::string &field_name) const {
156  FieldCommon *found_field=field(field_name);
157  if (found_field) return *found_field;
158 
159  THROW(ExcUnknownField() << FieldCommon::EI_Field(field_name));
160  return *field_list[0]; // formal to prevent compiler warning
161 }
162 
163 
164 bool FieldSet::set_time(const TimeStep &time, LimitSide limit_side) {
165  bool changed_all=false;
166  for(auto field : field_list) changed_all = field->set_time(time, limit_side) || changed_all;
167  return changed_all;
168 }
169 
170 
171 
172 bool FieldSet::changed() const {
173  bool changed_all=false;
174  for(auto field : field_list) changed_all = changed_all || field->changed();
175  return changed_all;
176 }
177 
178 
179 
180 bool FieldSet::is_constant(Region reg) const {
181  bool const_all=true;
182  for(auto field : field_list) const_all = const_all && field->is_constant(reg);
183  return const_all;
184 }
185 
186 
188  bool is_jump = false;
189  for(auto field : field_list) is_jump = is_jump || field->is_jump_time();
190  return is_jump;
191 }
192 
193 
195  ASSERT_GT_DBG(region_field_update_order_.size(), 0).error("Variable 'region_dependency_list' is empty. Did you call 'set_dependency' method?\n");
196  for (unsigned int i_reg_patch=0; i_reg_patch<cache_map.n_regions(); ++i_reg_patch) {
197  for (const FieldCommon *field : region_field_update_order_[cache_map.region_idx_from_chunk_position(i_reg_patch)])
198  field->cache_update(cache_map, i_reg_patch);
199  }
200 }
201 
202 
203 void FieldSet::set_dependency(FieldSet &used_fieldset) {
205  std::unordered_set<const FieldCommon *> used_fields;
206 
207  unordered_map<std::string, unsigned int>::iterator it;
208  for (unsigned int i_reg=0; i_reg<mesh_->region_db().size(); ++i_reg) {
209  for (FieldListAccessor f_acc : used_fieldset.fields_range()) {
210  topological_sort( f_acc.field(), i_reg, used_fields );
211  }
212  used_fields.clear();
213  }
214 }
215 
216 
217 void FieldSet::topological_sort(const FieldCommon *f, unsigned int i_reg, std::unordered_set<const FieldCommon *> &used_fields) {
218  if (used_fields.find(f) != used_fields.end() ) return; // field processed
219  used_fields.insert(f);
220  auto dep_vec = f->set_dependency(*this, i_reg); // vector of dependent fields
221  for (auto f_dep : dep_vec) {
222  topological_sort(f_dep, i_reg, used_fields);
223  }
224  region_field_update_order_[i_reg].push_back(f);
225 }
226 
227 
229  *this += X_.name("X")
230  .units(UnitSI().m())
231  .input_default("0.0")
233  .description("Coordinates field.");
234 
235  *this += depth_.name("d")
236  .units(UnitSI().m())
237  .input_default("0.0")
239  .description("Depth field.");
240 
242 }
243 
244 
246  auto bgn_it = make_iter<FieldListAccessor>( FieldListAccessor(field_list, 0) );
247  auto end_it = make_iter<FieldListAccessor>( FieldListAccessor(field_list, field_list.size()) );
248  return Range<FieldListAccessor>(bgn_it, end_it);
249 }
250 
251 
252 std::string FieldSet::print_dependency() const {
253  ASSERT_GT_DBG(region_field_update_order_.size(), 0).error("Variable 'region_dependency_list' is empty. Did you call 'set_dependency' method?\n");
254  std::stringstream s;
255  for (auto reg_it : region_field_update_order_) {
256  s << "\nregion_idx " << reg_it.first << ": ";
257  for (auto f_it : reg_it.second) {
258  s << f_it->name() << ", ";
259  }
260  }
261  return s.str();
262 }
263 
264 
265 std::ostream &operator<<(std::ostream &stream, const FieldSet &set) {
266  for(FieldCommon * field : set.field_list) {
267  stream << *field
268  << std::endl;
269  }
270  return stream;
271 }
FieldCommon::units
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
Definition: field_common.hh:150
FieldSet::operator[]
FieldCommon & operator[](const std::string &field_name) const
Definition: field_set.cc:155
ref_element.hh
Class RefElement defines numbering of vertices, sides, calculation of normal vectors etc.
FieldSet::is_jump_time
bool is_jump_time() const
Definition: field_set.cc:187
FieldSet::set_time
bool set_time(const TimeStep &time, LimitSide limit_side)
Definition: field_set.cc:164
FieldSet::is_constant
bool is_constant(Region reg) const
Definition: field_set.cc:180
FieldListAccessor
Definition: field_set.hh:61
ASSERT_GT_DBG
#define ASSERT_GT_DBG(a, b)
Definition of comparative assert macro (Greater Than) only for debug mode.
Definition: asserts.hh:316
ASSERT
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:347
ElementCacheMap
Directing class of FieldValueCache.
Definition: field_value_cache.hh:141
FieldSet::set_dependency
void set_dependency(FieldSet &used_fieldset)
Definition: field_set.cc:203
FieldCommon::copy_from
virtual void copy_from(const FieldCommon &other)=0
field_set.hh
THROW
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
FieldSet::fields_range
Range< FieldListAccessor > fields_range() const
Returns range of Fields held in field_list.
Definition: field_set.cc:245
std::vector< std::string >
FieldSet::region_field_update_order_
std::map< unsigned int, std::vector< const FieldCommon * > > region_field_update_order_
Definition: field_set.hh:394
FieldSet::changed
bool changed() const
Definition: field_set.cc:172
FieldCommon::set_time
virtual bool set_time(const TimeStep &time, LimitSide limit_side)=0
FieldCommon::flags
FieldCommon & flags(FieldFlag::Flags::Mask mask)
Definition: field_common.hh:189
operator<<
std::ostream & operator<<(std::ostream &stream, const FieldSet &set)
Definition: field_set.cc:265
FlowAttribute::field_value_shape
static string field_value_shape()
Definition: flow_attribute_lib.hh:47
FlowAttribute::field_unit
static string field_unit()
Definition: flow_attribute_lib.hh:38
FieldCommon::field_descriptor_record
static IT::Record field_descriptor_record(const string &record_name)
Definition: field_common.cc:60
Region
Definition: region.hh:146
FieldSet::field_list
std::vector< FieldCommon * > field_list
List of all fields.
Definition: field_set.hh:383
FieldSet::X_
FieldCoords X_
Field holds coordinates for computing of FieldFormulas.
Definition: field_set.hh:397
Input::Type::TypeBase::attribute_map
std::map< std::string, json_string > attribute_map
Defines map of Input::Type attributes.
Definition: type_base.hh:101
FieldSet::topological_sort
void topological_sort(const FieldCommon *f, unsigned int i_reg, std::unordered_set< const FieldCommon * > &used_fields)
Helper method sort used fields by dependency.
Definition: field_set.cc:217
FieldSet::print_dependency
std::string print_dependency() const
Return order of evaluated fields by dependency and region_idx.
Definition: field_set.cc:252
FieldCommon::get_value_attribute
virtual std::string get_value_attribute() const =0
sys_profiler.hh
flow_attribute_lib.hh
TimeStep
Representation of one time step..
Definition: time_governor.hh:123
FieldSet::mesh_
const Mesh * mesh_
Pointer to the mesh.
Definition: field_set.hh:386
bidirectional_map.hh
Implementation of bidirectional map.
FieldCommon
Common abstract parent of all Field<...> classes.
Definition: field_common.hh:74
UnitSI
Class for representation SI units of Fields.
Definition: unit_si.hh:40
FieldSet::add_coords_field
void add_coords_field()
Definition: field_set.cc:228
Mesh::region_db
const RegionDB & region_db() const
Definition: mesh.h:160
FieldCommon::set_dependency
virtual std::vector< const FieldCommon * > set_dependency(FieldSet &field_set, unsigned int i_reg) const =0
FieldCommon::field_descriptor_record_description
static const std::string field_descriptor_record_description(const string &record_name)
Definition: field_common.cc:73
Input::Type::Record::declare_key
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
FieldCommon::changed
bool changed() const
Definition: field_common.hh:349
LimitSide
LimitSide
Definition: field_common.hh:61
FieldSet::cache_update
void cache_update(ElementCacheMap &cache_map)
Definition: field_set.cc:194
FieldSet
Container for various descendants of FieldCommonBase.
Definition: field_set.hh:159
std::map< std::string, json_string >
FieldFlag::input_copy
static constexpr Mask input_copy
Definition: field_flag.hh:44
Input::Type::Record::close
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
FieldDepth::set_field_coords
void set_field_coords(FieldCoords *field_coords)
Setter of field_coords data member.
Definition: field_depth.hh:143
Input::Type
Definition: balance.hh:41
Input::Type::Record
Record type proxy class.
Definition: type_record.hh:182
FieldCommon::is_multifield
bool is_multifield() const
Definition: field_common.hh:452
FieldCommon::input_default
FieldCommon & input_default(const string &input_default)
Definition: field_common.hh:137
FieldCommon::get_input_type
virtual IT::Instance get_input_type()=0
Input::Type::Record::copy_keys
Record & copy_keys(const Record &other)
Copy keys from other record.
Definition: type_record.cc:216
Range
Range helper class.
Definition: range_wrapper.hh:65
OLD_ASSERT
#define OLD_ASSERT(...)
Definition: global_defs.h:108
ElementCacheMap::region_idx_from_chunk_position
unsigned int region_idx_from_chunk_position(unsigned int chunk_pos) const
Return begin position of region chunk specified by position in map.
Definition: field_value_cache.hh:252
FlowAttribute::field_default_value
static string field_default_value()
Definition: flow_attribute_lib.hh:65
FieldSet::set_mesh
void set_mesh(const Mesh &mesh)
Definition: field_set.hh:274
FieldCommon::get_multifield_input_type
virtual IT::Array get_multifield_input_type()=0
FieldFlag::declare_input
static constexpr Mask declare_input
The field can be set from input. The key in input field descriptor is declared. (default on)
Definition: field_flag.hh:35
FieldSet::FieldSet
FieldSet()
Default constructor.
Definition: field_set.cc:28
mapping_p1.hh
Class MappingP1 implements the affine transformation of the unit cell onto the actual cell.
FieldCommon::input_name
const std::string & input_name() const
Definition: field_common.hh:240
FieldCommon::is_jump_time
bool is_jump_time()
Definition: field_common.hh:292
FieldSet::set_field
void set_field(const std::string &dest_field_name, FieldCommon &source)
Definition: field_set.cc:139
FieldCommon::description
FieldCommon & description(const string &description)
Definition: field_common.hh:125
FieldCommon::cache_update
virtual void cache_update(ElementCacheMap &cache_map, unsigned int region_patch_idx) const =0
Input::Type::Default::optional
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:124
FieldSet::depth_
FieldDepth depth_
Field holds surface depth for computing of FieldFormulas.
Definition: field_set.hh:400
FieldSet::make_field_descriptor_type
Input::Type::Record make_field_descriptor_type(const std::string &equation_name) const
Definition: field_set.cc:69
ElementCacheMap::n_regions
unsigned int n_regions() const
Return number of stored regions.
Definition: field_value_cache.hh:212
FieldCommon::is_constant
virtual bool is_constant(Region reg)=0
FieldSet::field
FieldCommon * field(const std::string &field_name) const
Definition: field_set.cc:147
FieldCommon::name
FieldCommon & name(const string &name)
Definition: field_common.hh:118