Flow123d  build_with_4.0.3-01443f6
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 
34  return Input::Type::Selection("User_fields_shape", "Allowed shapes of user fields.")
35  .add_value(FieldSet::scalar, "scalar", "Scalar user field.")
36  .add_value(FieldSet::vector, "vector", "Vector user field.")
37  .add_value(FieldSet::tensor, "tensor", "Tensor user field.")
38  .close();
39 }
40 
41 const Input::Type::Record & FieldSet::make_user_field_type(const std::string &equation_name) {
42  static Field<3, FieldValue<3>::Scalar> scalar_field;
43  static Field<3, FieldValue<3>::VectorFixed> vector_field;
44  static Field<3, FieldValue<3>::TensorFixed> tensor_field;
45  return Input::Type::Record( equation_name+":UserData", "Record to set fields of the equation: "+equation_name+".")
47  "Name of user defined field.")
48  .declare_key("shape_type", FieldSet::get_user_field_shape_selection(), Input::Type::Default("\"scalar\""), "Shape of user field.")
50  "Instance of FieldAlgoBase descendant.\n"
51  "Please specify shape of field in 'shape_type' key.")
53  "Unit of the field values provided in the main input file, in the external file, or "
54  "by a function (FieldPython).")
55  .close();
56 }
57 
58 FieldSet &FieldSet::operator +=(FieldCommon &add_field) {
59  FieldCommon *found_field = field(add_field.name());
60  if (found_field) {
61  ASSERT_PERMANENT(&add_field==found_field)(add_field.name()).error("You cannot add field of the same name that exists in FieldSet!\n");
62  } else {
63  field_list.push_back(&add_field);
64  }
65  return *this;
66 }
67 
68 
69 
70 FieldSet &FieldSet::operator +=(const FieldSet &other) {
71  for(auto field_ptr : other.field_list) this->operator +=(*field_ptr);
72  return *this;
73 }
74 
75 
76 
77 FieldSet FieldSet::subset(std::vector<std::string> names) const {
78  FieldSet set;
79  set.set_mesh( *this->mesh_ );
80  for(auto name : names) set += (*this)[name];
81  return set;
82 }
83 
84 
85 
86 FieldSet FieldSet::subset( FieldFlag::Flags::Mask mask) const {
87  FieldSet set;
88  for(auto field : field_list)
89  if (field->flags().match(mask)) set += *field;
90  return set;
91 }
92 
93 
94 
95 Input::Type::Record FieldSet::make_field_descriptor_type(const std::string &equation_name) const {
96  string rec_name = equation_name + ":Data";
98  Input::Type::Record rec = Input::Type::Record(rec_name, desc)
100 
101  for(auto field : field_list) {
102  if ( field->flags().match(FieldFlag::declare_input) ) {
103  string description = field->description() + " (($[" + field->units().format_latex() + "]$))";
104 
105  // Adding units is not so simple.
106  // 1) It must be correct for Latex.
107  // 2) It should be consistent with rest of documentation.
108  // 3) Should be specified for all fields.
109  //if (units != "") description+= " [" +field->units() + "]";
110 
111  // TODO: temporary solution, see FieldCommon::multifield_
112 
113  std::shared_ptr<Input::Type::TypeBase> field_type_ptr;
114  if (field->is_multifield()) {
115  field_type_ptr = std::make_shared<Input::Type::Array>(field->get_multifield_input_type());
116  } else {
117  field_type_ptr = std::make_shared<Input::Type::Instance>(field->get_input_type());
118  }
119  ASSERT( field->units().is_def() )(field->input_name()).error("units not def.");
121  { {FlowAttribute::field_unit(), field->units().json() },
123  );
124  string default_val = field->input_default();
125  if (default_val != "") {
126  boost::replace_all(default_val, "\"", "\\\"");
127  key_attributes[FlowAttribute::field_default_value()] = "\"" + default_val + "\"";
128  }
129  rec.declare_key(field->input_name(), field_type_ptr, Input::Type::Default::optional(), description, key_attributes);
130  }
131 
132  }
133  return rec.close();
134 }
135 
136 
137 /*
138 Input::Type::Selection FieldSet::make_output_field_selection(const string &name, const string &desc)
139 {
140  namespace IT=Input::Type;
141  IT::Selection sel(name, desc);
142  int i=0;
143  // add value for each field excluding boundary fields
144  for( auto field : field_list)
145  {
146  if ( field->flags().match( FieldFlag::allow_output) )
147  {
148  string desc = "Output of the field " + field->name() + " (($[" + field->units().format_latex()+"]$))";
149  if (field->description().length() > 0)
150  desc += " (" + field->description() + ").";
151  else
152  desc += ".";
153  DebugOut() << field->get_value_attribute();
154 
155  sel.add_value(i, field->name(), desc, { {FlowAttribute::field_value_shape(), field->get_value_attribute()} } );
156  i++;
157  }
158  }
159 
160  return sel;
161 }
162 */
163 
164 
165 void FieldSet::set_field(const std::string &dest_field_name, FieldCommon &source)
166 {
167  auto &field = (*this)[dest_field_name];
168  field.copy_from(source);
169 }
170 
171 
172 
173 FieldCommon *FieldSet::field(const std::string &field_name) const {
174  for(auto field : field_list)
175  if (field->name() ==field_name) return field;
176  return nullptr;
177 }
178 
179 
180 
181 FieldCommon &FieldSet::operator[](const std::string &field_name) const {
182  FieldCommon *found_field=field(field_name);
183  if (found_field) return *found_field;
184 
185  THROW(ExcUnknownField() << FieldCommon::EI_Field(field_name) << EI_FieldType("FieldSet"));
186  return *field_list[0]; // formal to prevent compiler warning
187 }
188 
189 
190 bool FieldSet::set_time(const TimeStep &time, LimitSide limit_side) {
191  bool changed_all=false;
192  for(auto field : field_list) changed_all = field->set_time(time, limit_side) || changed_all;
193  return changed_all;
194 }
195 
196 
197 
198 bool FieldSet::changed() const {
199  bool changed_all=false;
200  for(auto field : field_list) changed_all = changed_all || field->changed();
201  return changed_all;
202 }
203 
204 
205 
206 bool FieldSet::is_constant(Region reg) const {
207  bool const_all=true;
208  for(auto field : field_list) const_all = const_all && field->is_constant(reg);
209  return const_all;
210 }
211 
212 
214  bool is_jump = false;
215  for(auto field : field_list) is_jump = is_jump || field->is_jump_time();
216  return is_jump;
217 }
218 
219 
221  ASSERT_GT(region_field_update_order_.size(), 0).error("Variable 'region_dependency_list' is empty. Did you call 'set_dependency' method?\n");
222  for (unsigned int i_reg_patch=0; i_reg_patch<cache_map.n_regions(); ++i_reg_patch) {
223  for (const FieldCommon *field : region_field_update_order_[cache_map.region_idx_from_chunk_position(i_reg_patch)])
224  field->cache_update(cache_map, i_reg_patch);
225  }
226 }
227 
228 
229 void FieldSet::set_dependency(FieldSet &used_fieldset) {
231  std::unordered_set<const FieldCommon *> used_fields;
232 
233  for (unsigned int i_reg=0; i_reg<mesh_->region_db().size(); ++i_reg) {
234  for (FieldListAccessor f_acc : used_fieldset.fields_range()) {
235  topological_sort( f_acc.field(), i_reg, used_fields );
236  }
237  used_fields.clear();
238  }
239 }
240 
241 
242 void FieldSet::topological_sort(const FieldCommon *f, unsigned int i_reg, std::unordered_set<const FieldCommon *> &used_fields) {
243  if (used_fields.find(f) != used_fields.end() ) return; // field processed
244  used_fields.insert(f);
245  auto dep_vec = f->set_dependency(i_reg); // vector of dependent fields
246  for (auto f_dep : dep_vec) {
247  topological_sort(f_dep, i_reg, used_fields);
248  }
249  region_field_update_order_[i_reg].push_back(f);
250 }
251 
252 
254  *this += X_.name("X")
255  .units(UnitSI().m())
256  .input_default("0.0")
258  .description("Coordinates field.");
259 
260  *this += depth_.name("d")
261  .units(UnitSI().m())
262  .input_default("0.0")
264  .description("Depth field.");
265 
266  if (this->mesh_ != nullptr) {
267  X_.set_mesh(*this->mesh_);
268  depth_.set_mesh(*this->mesh_);
269  }
270 
272 }
273 
274 
276  auto bgn_it = make_iter<FieldListAccessor>( FieldListAccessor(field_list, 0) );
277  auto end_it = make_iter<FieldListAccessor>( FieldListAccessor(field_list, field_list.size()) );
278  return Range<FieldListAccessor>(bgn_it, end_it);
279 }
280 
281 
282 std::string FieldSet::print_dependency() const {
283  ASSERT_GT(region_field_update_order_.size(), 0).error("Variable 'region_dependency_list' is empty. Did you call 'set_dependency' method?\n");
284  std::stringstream s;
285  for (auto reg_it : region_field_update_order_) {
286  s << "\nregion_idx " << reg_it.first << ": ";
287  for (auto f_it : reg_it.second) {
288  s << f_it->name() << ", ";
289  }
290  }
291  return s.str();
292 }
293 
294 
295 std::ostream &operator<<(std::ostream &stream, const FieldSet &set) {
296  for(FieldCommon * field : set.field_list) {
297  stream << *field
298  << std::endl;
299  }
300  return stream;
301 }
#define ASSERT(expr)
Definition: asserts.hh:351
#define ASSERT_PERMANENT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:348
#define ASSERT_GT(a, b)
Definition of comparative assert macro (Greater Than) only for debug mode.
Definition: asserts.hh:317
Implementation of bidirectional map.
Directing class of FieldValueCache.
unsigned int n_regions() const
Return number of stored regions.
unsigned int region_idx_from_chunk_position(unsigned int chunk_pos) const
Return begin position of region chunk specified by position in map.
Common abstract parent of all Field<...> classes.
Definition: field_common.hh:77
virtual IT::Instance get_input_type()=0
bool changed() const
static IT::Record field_descriptor_record(const string &record_name)
Definition: field_common.cc:59
static const std::string field_descriptor_record_description(const string &record_name)
Definition: field_common.cc:72
bool is_jump_time()
virtual bool set_time(const TimeStep &time, LimitSide limit_side)=0
const std::string & input_name() const
virtual bool is_constant(Region reg)=0
virtual std::string get_value_attribute() const =0
virtual void cache_update(ElementCacheMap &cache_map, unsigned int region_patch_idx) const =0
FieldCommon & description(const string &description)
FieldCommon & flags(FieldFlag::Flags::Mask mask)
virtual std::vector< const FieldCommon * > set_dependency(unsigned int i_reg) const =0
FieldCommon & name(const string &name)
bool is_multifield() const
virtual IT::Array get_multifield_input_type()=0
virtual void copy_from(const FieldCommon &other)=0
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
FieldCommon & input_default(const string &input_default)
void set_mesh(const Mesh &mesh) override
Definition: field_coords.hh:66
void set_field_coords(FieldCoords *field_coords)
Setter of field_coords data member.
Definition: field_depth.hh:139
void set_mesh(const Mesh &mesh) override
Definition: field_depth.hh:64
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
static constexpr Mask input_copy
Definition: field_flag.hh:44
Container for various descendants of FieldCommonBase.
Definition: field_set.hh:159
FieldCommon & operator[](const std::string &field_name) const
Definition: field_set.cc:181
std::map< unsigned int, std::vector< const FieldCommon * > > region_field_update_order_
Definition: field_set.hh:430
void add_coords_field()
Definition: field_set.cc:253
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:41
void set_mesh(const Mesh &mesh)
Definition: field_set.hh:297
Range< FieldListAccessor > fields_range() const
Returns range of Fields held in field_list.
Definition: field_set.cc:275
FieldDepth depth_
Field holds surface depth for computing of FieldFormulas.
Definition: field_set.hh:439
FieldSet()
Default constructor.
Definition: field_set.cc:29
const Mesh * mesh_
Pointer to the mesh.
Definition: field_set.hh:422
bool changed() const
Definition: field_set.cc:198
FieldCoords X_
Field holds coordinates for computing of FieldFormulas.
Definition: field_set.hh:436
std::string print_dependency() const
Return order of evaluated fields by dependency and region_idx.
Definition: field_set.cc:282
bool is_constant(Region reg) const
Definition: field_set.cc:206
void cache_update(ElementCacheMap &cache_map)
Definition: field_set.cc:220
FieldCommon * field(const std::string &field_name) const
Definition: field_set.cc:173
static const Input::Type::Selection & get_user_field_shape_selection()
Input selection of user field shape.
Definition: field_set.cc:33
bool set_time(const TimeStep &time, LimitSide limit_side)
Definition: field_set.cc:190
bool is_jump_time() const
Definition: field_set.cc:213
void set_field(const std::string &dest_field_name, FieldCommon &source)
Definition: field_set.cc:165
std::vector< FieldCommon * > field_list
List of all fields.
Definition: field_set.hh:419
void set_dependency(FieldSet &used_fieldset)
Definition: field_set.cc:229
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:242
Input::Type::Record make_field_descriptor_type(const std::string &equation_name) const
Definition: field_set.cc:95
Class template representing a field with values dependent on: point, element, and region.
Definition: field.hh:92
IT::Instance get_input_type() override
Definition: field.impl.hh:176
static string field_unit()
static string field_value_shape()
static string field_default_value()
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
Record type proxy class.
Definition: type_record.hh:182
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
Record & copy_keys(const Record &other)
Copy keys from other record.
Definition: type_record.cc:216
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
Template for classes storing finite set of named values.
Selection & add_value(const int value, const std::string &key, const std::string &description="", TypeBase::attribute_map attributes=TypeBase::attribute_map())
Adds one new value with name given by key to the Selection.
const Selection & close() const
Close the Selection, no more values can be added.
Class for declaration of the input data that are in string format.
Definition: type_base.hh:582
std::map< std::string, json_string > attribute_map
Defines map of Input::Type attributes.
Definition: type_base.hh:101
const RegionDB & region_db() const
Definition: mesh.h:175
Range helper class.
Representation of one time step..
static const Input::Type::Record & get_input_type()
Class for representation SI units of Fields.
Definition: unit_si.hh:40
LimitSide
Definition: field_common.hh:64
std::ostream & operator<<(std::ostream &stream, const FieldSet &set)
Definition: field_set.cc:295
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
Class MappingP1 implements the affine transformation of the unit cell onto the actual cell.
Class RefElement defines numbering of vertices, sides, calculation of normal vectors etc.