Flow123d  master-e663071
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 "tools/unit_converter.hh"
25 #include <boost/algorithm/string/replace.hpp>
26 #include <queue>
27 
28 
30 : mesh_(nullptr) {}
31 
32 
33 const Input::Type::Record & FieldSet::make_user_field_type(const std::string &equation_name) {
34  static Field<3, FieldValue<3>::Scalar> scalar_field;
35  static Field<3, FieldValue<3>::VectorFixed> vector_field;
36  static Field<3, FieldValue<3>::TensorFixed> tensor_field;
37  return Input::Type::Record( equation_name+":UserData", "Record to set fields of the equation: "+equation_name+".")
39  "Name of user defined field.")
40  .declare_key("is_boundary", Input::Type::Bool(), Input::Type::Default("false"),
41  "Type of field: boundary or bulk.")
42  .declare_key("scalar_field", scalar_field.get_input_type(),
43  "Instance of FieldAlgoBase ScalarField descendant.\n"
44  "One of keys 'scalar_field', 'vector_field', 'tensor_field' must be set.\n"
45  "If you set more than one of these keys, only first key is accepted.")
46  .declare_key("vector_field", vector_field.get_input_type(),
47  "Instance of FieldAlgoBase VectorField descendant. See above for details.")
48  .declare_key("tensor_field", tensor_field.get_input_type(),
49  "Instance of FieldAlgoBase TensorField descendant. See above for details.")
51  "Unit of the field values provided in the main input file, in the external file, or "
52  "by a function (FieldPython).")
53  .close();
54 }
55 
56 FieldSet &FieldSet::operator +=(FieldCommon &add_field) {
57  FieldCommon *found_field = field(add_field.name());
58  if (found_field) {
59  ASSERT_PERMANENT(&add_field==found_field)(add_field.name()).error("You cannot add field of the same name that exists in FieldSet!\n");
60  } else {
61  field_list.push_back(&add_field);
62  }
63  return *this;
64 }
65 
66 
67 
68 FieldSet &FieldSet::operator +=(const FieldSet &other) {
69  for(auto field_ptr : other.field_list) this->operator +=(*field_ptr);
70  return *this;
71 }
72 
73 
74 
75 FieldSet FieldSet::subset(std::vector<std::string> names) const {
76  FieldSet set;
77  set.set_mesh( *this->mesh_ );
78  for(auto name : names) set += (*this)[name];
79  return set;
80 }
81 
82 
83 
84 FieldSet FieldSet::subset( FieldFlag::Flags::Mask mask) const {
85  FieldSet set;
86  for(auto field : field_list)
87  if (field->flags().match(mask)) set += *field;
88  return set;
89 }
90 
91 
92 
93 Input::Type::Record FieldSet::make_field_descriptor_type(const std::string &equation_name) const {
94  string rec_name = equation_name + ":Data";
96  Input::Type::Record rec = Input::Type::Record(rec_name, desc)
98 
99  for(auto field : field_list) {
100  if ( field->flags().match(FieldFlag::declare_input) ) {
101  string description = field->description() + " (($[" + field->units().format_latex() + "]$))";
102 
103  // Adding units is not so simple.
104  // 1) It must be correct for Latex.
105  // 2) It should be consistent with rest of documentation.
106  // 3) Should be specified for all fields.
107  //if (units != "") description+= " [" +field->units() + "]";
108 
109  // TODO: temporary solution, see FieldCommon::multifield_
110 
111  std::shared_ptr<Input::Type::TypeBase> field_type_ptr;
112  if (field->is_multifield()) {
113  field_type_ptr = std::make_shared<Input::Type::Array>(field->get_multifield_input_type());
114  } else {
115  field_type_ptr = std::make_shared<Input::Type::Instance>(field->get_input_type());
116  }
117  ASSERT( field->units().is_def() )(field->input_name()).error("units not def.");
119  { {FlowAttribute::field_unit(), field->units().json() },
121  );
122  string default_val = field->input_default();
123  if (default_val != "") {
124  boost::replace_all(default_val, "\"", "\\\"");
125  key_attributes[FlowAttribute::field_default_value()] = "\"" + default_val + "\"";
126  }
127  rec.declare_key(field->input_name(), field_type_ptr, Input::Type::Default::optional(), description, key_attributes);
128  }
129 
130  }
131  return rec.close();
132 }
133 
134 
135 /*
136 Input::Type::Selection FieldSet::make_output_field_selection(const string &name, const string &desc)
137 {
138  namespace IT=Input::Type;
139  IT::Selection sel(name, desc);
140  int i=0;
141  // add value for each field excluding boundary fields
142  for( auto field : field_list)
143  {
144  if ( !field->is_bc() && field->flags().match( FieldFlag::allow_output) )
145  {
146  string desc = "Output of the field " + field->name() + " (($[" + field->units().format_latex()+"]$))";
147  if (field->description().length() > 0)
148  desc += " (" + field->description() + ").";
149  else
150  desc += ".";
151  DebugOut() << field->get_value_attribute();
152 
153  sel.add_value(i, field->name(), desc, { {FlowAttribute::field_value_shape(), field->get_value_attribute()} } );
154  i++;
155  }
156  }
157 
158  return sel;
159 }
160 */
161 
162 
163 void FieldSet::set_field(const std::string &dest_field_name, FieldCommon &source)
164 {
165  auto &field = (*this)[dest_field_name];
166  field.copy_from(source);
167 }
168 
169 
170 
171 FieldCommon *FieldSet::field(const std::string &field_name) const {
172  for(auto field : field_list)
173  if (field->name() ==field_name) return field;
174  return nullptr;
175 }
176 
177 
178 
179 FieldCommon &FieldSet::operator[](const std::string &field_name) const {
180  FieldCommon *found_field=field(field_name);
181  if (found_field) return *found_field;
182 
183  THROW(ExcUnknownField() << FieldCommon::EI_Field(field_name));
184  return *field_list[0]; // formal to prevent compiler warning
185 }
186 
187 
188 bool FieldSet::set_time(const TimeStep &time, LimitSide limit_side) {
189  bool changed_all=false;
190  for(auto field : field_list) changed_all = field->set_time(time, limit_side) || changed_all;
191  return changed_all;
192 }
193 
194 
195 
196 bool FieldSet::changed() const {
197  bool changed_all=false;
198  for(auto field : field_list) changed_all = changed_all || field->changed();
199  return changed_all;
200 }
201 
202 
203 
204 bool FieldSet::is_constant(Region reg) const {
205  bool const_all=true;
206  for(auto field : field_list) const_all = const_all && field->is_constant(reg);
207  return const_all;
208 }
209 
210 
212  bool is_jump = false;
213  for(auto field : field_list) is_jump = is_jump || field->is_jump_time();
214  return is_jump;
215 }
216 
217 
219  ASSERT_GT(region_field_update_order_.size(), 0).error("Variable 'region_dependency_list' is empty. Did you call 'set_dependency' method?\n");
220  for (unsigned int i_reg_patch=0; i_reg_patch<cache_map.n_regions(); ++i_reg_patch) {
221  for (const FieldCommon *field : region_field_update_order_[cache_map.region_idx_from_chunk_position(i_reg_patch)])
222  field->cache_update(cache_map, i_reg_patch);
223  }
224 }
225 
226 
227 void FieldSet::set_dependency(FieldSet &used_fieldset) {
229  std::unordered_set<const FieldCommon *> used_fields;
230 
231  for (unsigned int i_reg=0; i_reg<mesh_->region_db().size(); ++i_reg) {
232  for (FieldListAccessor f_acc : used_fieldset.fields_range()) {
233  topological_sort( f_acc.field(), i_reg, used_fields );
234  }
235  used_fields.clear();
236  }
237 }
238 
239 
240 void FieldSet::topological_sort(const FieldCommon *f, unsigned int i_reg, std::unordered_set<const FieldCommon *> &used_fields) {
241  if (used_fields.find(f) != used_fields.end() ) return; // field processed
242  used_fields.insert(f);
243  auto dep_vec = f->set_dependency(i_reg); // vector of dependent fields
244  for (auto f_dep : dep_vec) {
245  topological_sort(f_dep, i_reg, used_fields);
246  }
247  region_field_update_order_[i_reg].push_back(f);
248 }
249 
250 
252  *this += X_.name("X")
253  .units(UnitSI().m())
254  .input_default("0.0")
256  .description("Coordinates field.");
257 
258  *this += depth_.name("d")
259  .units(UnitSI().m())
260  .input_default("0.0")
262  .description("Depth field.");
263 
264  if (this->mesh_ != nullptr) {
265  X_.set_mesh(*this->mesh_);
266  depth_.set_mesh(*this->mesh_);
267  }
268 
270 }
271 
272 
274  auto bgn_it = make_iter<FieldListAccessor>( FieldListAccessor(field_list, 0) );
275  auto end_it = make_iter<FieldListAccessor>( FieldListAccessor(field_list, field_list.size()) );
276  return Range<FieldListAccessor>(bgn_it, end_it);
277 }
278 
279 
280 std::string FieldSet::print_dependency() const {
281  ASSERT_GT(region_field_update_order_.size(), 0).error("Variable 'region_dependency_list' is empty. Did you call 'set_dependency' method?\n");
282  std::stringstream s;
283  for (auto reg_it : region_field_update_order_) {
284  s << "\nregion_idx " << reg_it.first << ": ";
285  for (auto f_it : reg_it.second) {
286  s << f_it->name() << ", ";
287  }
288  }
289  return s.str();
290 }
291 
292 
293 std::ostream &operator<<(std::ostream &stream, const FieldSet &set) {
294  for(FieldCommon * field : set.field_list) {
295  stream << *field
296  << std::endl;
297  }
298  return stream;
299 }
FieldSet::make_user_field_type
static const Input::Type::Record & make_user_field_type(const std::string &equation_name)
Declare input record type of field defined by user.
Definition: field_set.cc:33
FieldCommon::units
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
Definition: field_common.hh:153
FieldSet::operator[]
FieldCommon & operator[](const std::string &field_name) const
Definition: field_set.cc:179
Input::Type::Bool
Class for declaration of the input of type Bool.
Definition: type_base.hh:452
ref_element.hh
Class RefElement defines numbering of vertices, sides, calculation of normal vectors etc.
ASSERT_GT
#define ASSERT_GT(a, b)
Definition of comparative assert macro (Greater Than) only for debug mode.
Definition: asserts.hh:317
FieldSet::is_jump_time
bool is_jump_time() const
Definition: field_set.cc:211
FieldSet::set_time
bool set_time(const TimeStep &time, LimitSide limit_side)
Definition: field_set.cc:188
FieldSet::is_constant
bool is_constant(Region reg) const
Definition: field_set.cc:204
FieldListAccessor
Definition: field_set.hh:61
MeshBase::region_db
const RegionDB & region_db() const
Definition: mesh.h:175
ASSERT
#define ASSERT(expr)
Definition: asserts.hh:351
ElementCacheMap
Directing class of FieldValueCache.
Definition: field_value_cache.hh:152
FieldSet::set_dependency
void set_dependency(FieldSet &used_fieldset)
Definition: field_set.cc:227
FieldCommon::copy_from
virtual void copy_from(const FieldCommon &other)=0
FieldCommon::set_dependency
virtual std::vector< const FieldCommon * > set_dependency(unsigned int i_reg) const =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:273
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:416
FieldSet::changed
bool changed() const
Definition: field_set.cc:196
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:192
Field::get_input_type
IT::Instance get_input_type() override
Definition: field.impl.hh:178
operator<<
std::ostream & operator<<(std::ostream &stream, const FieldSet &set)
Definition: field_set.cc:293
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:145
FieldSet::field_list
std::vector< FieldCommon * > field_list
List of all fields.
Definition: field_set.hh:405
FieldSet::X_
FieldCoords X_
Field holds coordinates for computing of FieldFormulas.
Definition: field_set.hh:422
Input::Type::Default
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
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:240
FieldSet::print_dependency
std::string print_dependency() const
Return order of evaluated fields by dependency and region_idx.
Definition: field_set.cc:280
FieldCommon::get_value_attribute
virtual std::string get_value_attribute() const =0
sys_profiler.hh
ASSERT_PERMANENT
#define ASSERT_PERMANENT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:348
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:408
Input::Type::Default::obligatory
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:110
bidirectional_map.hh
Implementation of bidirectional map.
FieldCommon
Common abstract parent of all Field<...> classes.
Definition: field_common.hh:77
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:251
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
FieldCoords::set_mesh
void set_mesh(const Mesh &mesh) override
Definition: field_coords.hh:66
FieldCommon::changed
bool changed() const
Definition: field_common.hh:364
LimitSide
LimitSide
Definition: field_common.hh:64
FieldSet::cache_update
void cache_update(ElementCacheMap &cache_map)
Definition: field_set.cc:218
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
UnitConverter::get_input_type
static const Input::Type::Record & get_input_type()
Definition: unit_converter.cc:100
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:139
Input::Type::Record
Record type proxy class.
Definition: type_record.hh:182
FieldCommon::is_multifield
bool is_multifield() const
Definition: field_common.hh:461
FieldDepth::set_mesh
void set_mesh(const Mesh &mesh) override
Definition: field_depth.hh:64
FieldCommon::input_default
FieldCommon & input_default(const string &input_default)
Definition: field_common.hh:140
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
Input::Type::String
Class for declaration of the input data that are in string format.
Definition: type_base.hh:582
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:285
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:283
FieldCommon::get_multifield_input_type
virtual IT::Array get_multifield_input_type()=0
unit_converter.hh
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:29
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:243
FieldCommon::is_jump_time
bool is_jump_time()
Definition: field_common.hh:307
FieldSet::set_field
void set_field(const std::string &dest_field_name, FieldCommon &source)
Definition: field_set.cc:163
FieldCommon::description
FieldCommon & description(const string &description)
Definition: field_common.hh:128
Field
Class template representing a field with values dependent on: point, element, and region.
Definition: field.hh:92
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:425
FieldSet::make_field_descriptor_type
Input::Type::Record make_field_descriptor_type(const std::string &equation_name) const
Definition: field_set.cc:93
ElementCacheMap::n_regions
unsigned int n_regions() const
Return number of stored regions.
Definition: field_value_cache.hh:245
FieldCommon::is_constant
virtual bool is_constant(Region reg)=0
FieldSet::field
FieldCommon * field(const std::string &field_name) const
Definition: field_set.cc:171
FieldCommon::name
FieldCommon & name(const string &name)
Definition: field_common.hh:121