Flow123d  JS_before_hm-2208-gb971e62bf
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 "fields/bc_field.hh"
20 #include "system/sys_profiler.hh"
22 #include "fem/mapping_p1.hh"
23 #include "mesh/ref_element.hh"
25 #include <boost/algorithm/string/replace.hpp>
26 #include <queue>
27 
28 
30 : mesh_(nullptr) {}
31 
32 
33 const Input::Type::Record & FieldSet::get_user_field(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(), Input::Type::Default::obligatory(),
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.")
50  .close();
51 }
52 
53 FieldSet &FieldSet::operator +=(FieldCommon &add_field) {
54  FieldCommon *found_field = field(add_field.name());
55  if (found_field) {
56  OLD_ASSERT(&add_field==found_field, "Another field of the same name exists when adding field: %s\n",
57  add_field.name().c_str());
58  } else {
59  field_list.push_back(&add_field);
60  }
61  return *this;
62 }
63 
64 
65 
66 FieldSet &FieldSet::operator +=(const FieldSet &other) {
67  for(auto field_ptr : other.field_list) this->operator +=(*field_ptr);
68  return *this;
69 }
70 
71 
72 
73 FieldSet FieldSet::subset(std::vector<std::string> names) const {
74  FieldSet set;
75  set.set_mesh( *this->mesh_ );
76  for(auto name : names) set += (*this)[name];
77  return set;
78 }
79 
80 
81 
82 FieldSet FieldSet::subset( FieldFlag::Flags::Mask mask) const {
83  FieldSet set;
84  for(auto field : field_list)
85  if (field->flags().match(mask)) set += *field;
86  return set;
87 }
88 
89 
90 
91 Input::Type::Record FieldSet::make_field_descriptor_type(const std::string &equation_name) const {
92  string rec_name = equation_name + ":Data";
94  Input::Type::Record rec = Input::Type::Record(rec_name, desc)
96 
97  for(auto field : field_list) {
98  if ( field->flags().match(FieldFlag::declare_input) ) {
99  string description = field->description() + " (($[" + field->units().format_latex() + "]$))";
100 
101  // Adding units is not so simple.
102  // 1) It must be correct for Latex.
103  // 2) It should be consistent with rest of documentation.
104  // 3) Should be specified for all fields.
105  //if (units != "") description+= " [" +field->units() + "]";
106 
107  // TODO: temporary solution, see FieldCommon::multifield_
108 
109  std::shared_ptr<Input::Type::TypeBase> field_type_ptr;
110  if (field->is_multifield()) {
111  field_type_ptr = std::make_shared<Input::Type::Array>(field->get_multifield_input_type());
112  } else {
113  field_type_ptr = std::make_shared<Input::Type::Instance>(field->get_input_type());
114  }
115  ASSERT( field->units().is_def() )(field->input_name()).error("units not def.");
117  { {FlowAttribute::field_unit(), field->units().json() },
119  );
120  string default_val = field->input_default();
121  if (default_val != "") {
122  boost::replace_all(default_val, "\"", "\\\"");
123  key_attributes[FlowAttribute::field_default_value()] = "\"" + default_val + "\"";
124  }
125  rec.declare_key(field->input_name(), field_type_ptr, Input::Type::Default::optional(), description, key_attributes);
126  }
127 
128  }
129  return rec.close();
130 }
131 
132 
133 /*
134 Input::Type::Selection FieldSet::make_output_field_selection(const string &name, const string &desc)
135 {
136  namespace IT=Input::Type;
137  IT::Selection sel(name, desc);
138  int i=0;
139  // add value for each field excluding boundary fields
140  for( auto field : field_list)
141  {
142  if ( !field->is_bc() && field->flags().match( FieldFlag::allow_output) )
143  {
144  string desc = "Output of the field " + field->name() + " (($[" + field->units().format_latex()+"]$))";
145  if (field->description().length() > 0)
146  desc += " (" + field->description() + ").";
147  else
148  desc += ".";
149  DebugOut() << field->get_value_attribute();
150 
151  sel.add_value(i, field->name(), desc, { {FlowAttribute::field_value_shape(), field->get_value_attribute()} } );
152  i++;
153  }
154  }
155 
156  return sel;
157 }
158 */
159 
160 
161 void FieldSet::set_field(const std::string &dest_field_name, FieldCommon &source)
162 {
163  auto &field = (*this)[dest_field_name];
164  field.copy_from(source);
165 }
166 
167 
168 
169 FieldCommon *FieldSet::field(const std::string &field_name) const {
170  for(auto field : field_list)
171  if (field->name() ==field_name) return field;
172  return nullptr;
173 }
174 
175 
176 
177 FieldCommon *FieldSet::user_field(const std::string &field_name, const TimeStep &time) {
178  auto it = user_fields_input_.find(field_name);
179  if (it != user_fields_input_.end()) {
180  uint new_index = user_field_list_.size();
181  bool is_bdr = it->second.val<bool>("is_boundary");
182 
183  Input::AbstractRecord field_arec;
184  if (it->second.opt_val("scalar_field", field_arec)) {
185  Field<3, FieldValue<3>::Scalar> * scalar_field;
186  if (is_bdr)
187  scalar_field = new BCField<3, FieldValue<3>::Scalar>();
188  else
189  scalar_field = new Field<3, FieldValue<3>::Scalar>();
190  *this+=scalar_field
191  ->name(field_name)
192  .description("")
194  scalar_field->set_mesh(*mesh_);
195  scalar_field->set( it->second.val<Input::AbstractRecord>("scalar_field"), time.end());
196  user_field_list_.push_back( scalar_field );
197  } else if (it->second.opt_val("vector_field", field_arec)) {
198  Field<3, FieldValue<3>::VectorFixed> * vector_field;
199  if (is_bdr)
200  vector_field = new BCField<3, FieldValue<3>::VectorFixed>();
201  else
202  vector_field = new Field<3, FieldValue<3>::VectorFixed>();
203  *this+=vector_field
204  ->name(field_name)
205  .description("")
207  vector_field->set_mesh(*mesh_);
208  vector_field->set( it->second.val<Input::AbstractRecord>("scalar_field"), time.end());
209  user_field_list_.push_back( vector_field );
210  } else if (it->second.opt_val("tensor_field", field_arec)) {
211  Field<3, FieldValue<3>::TensorFixed> * tensor_field;
212  if (is_bdr)
213  tensor_field = new BCField<3, FieldValue<3>::TensorFixed>();
214  else
215  tensor_field = new Field<3, FieldValue<3>::TensorFixed>();
216  *this+=tensor_field
217  ->name(field_name)
218  .description("")
220  tensor_field->set_mesh(*mesh_);
221  tensor_field->set( it->second.val<Input::AbstractRecord>("scalar_field"), time.end());
222  user_field_list_.push_back( tensor_field );
223  } else {
224  THROW(ExcFieldNotSet() << FieldCommon::EI_Field(field_name));
225  }
226 
227  FieldCommon &user_field = *user_field_list_[new_index];
229  return &user_field;
230  } else
231  return nullptr;
232 }
233 
234 
235 
236 FieldCommon &FieldSet::operator[](const std::string &field_name) const {
237  FieldCommon *found_field=field(field_name);
238  if (found_field) return *found_field;
239 
240  THROW(ExcUnknownField() << FieldCommon::EI_Field(field_name));
241  return *field_list[0]; // formal to prevent compiler warning
242 }
243 
244 
245 bool FieldSet::set_time(const TimeStep &time, LimitSide limit_side) {
246  bool changed_all=false;
247  for(auto field : field_list) changed_all = field->set_time(time, limit_side) || changed_all;
248  return changed_all;
249 }
250 
251 
252 
253 bool FieldSet::changed() const {
254  bool changed_all=false;
255  for(auto field : field_list) changed_all = changed_all || field->changed();
256  return changed_all;
257 }
258 
259 
260 
261 bool FieldSet::is_constant(Region reg) const {
262  bool const_all=true;
263  for(auto field : field_list) const_all = const_all && field->is_constant(reg);
264  return const_all;
265 }
266 
267 
269  bool is_jump = false;
270  for(auto field : field_list) is_jump = is_jump || field->is_jump_time();
271  return is_jump;
272 }
273 
274 
276  ASSERT_GT_DBG(region_field_update_order_.size(), 0).error("Variable 'region_dependency_list' is empty. Did you call 'set_dependency' method?\n");
277  for (unsigned int i_reg_patch=0; i_reg_patch<cache_map.n_regions(); ++i_reg_patch) {
278  for (const FieldCommon *field : region_field_update_order_[cache_map.region_idx_from_chunk_position(i_reg_patch)])
279  field->cache_update(cache_map, i_reg_patch);
280  }
281 }
282 
283 
284 void FieldSet::set_dependency(FieldSet &used_fieldset) {
286  std::unordered_set<const FieldCommon *> used_fields;
287 
288  for (unsigned int i_reg=0; i_reg<mesh_->region_db().size(); ++i_reg) {
289  for (FieldListAccessor f_acc : used_fieldset.fields_range()) {
290  topological_sort( f_acc.field(), i_reg, used_fields );
291  }
292  used_fields.clear();
293  }
294 }
295 
296 
297 void FieldSet::topological_sort(const FieldCommon *f, unsigned int i_reg, std::unordered_set<const FieldCommon *> &used_fields) {
298  if (used_fields.find(f) != used_fields.end() ) return; // field processed
299  used_fields.insert(f);
300  auto dep_vec = f->set_dependency(*this, i_reg); // vector of dependent fields
301  for (auto f_dep : dep_vec) {
302  topological_sort(f_dep, i_reg, used_fields);
303  }
304  region_field_update_order_[i_reg].push_back(f);
305 }
306 
307 
309  *this += X_.name("X")
310  .units(UnitSI().m())
311  .input_default("0.0")
313  .description("Coordinates field.");
314 
315  *this += depth_.name("d")
316  .units(UnitSI().m())
317  .input_default("0.0")
319  .description("Depth field.");
320 
321  if (this->mesh_ != nullptr) {
322  X_.set_mesh(*this->mesh_);
323  depth_.set_mesh(*this->mesh_);
324  }
325 
327 }
328 
329 
331  auto bgn_it = make_iter<FieldListAccessor>( FieldListAccessor(field_list, 0) );
332  auto end_it = make_iter<FieldListAccessor>( FieldListAccessor(field_list, field_list.size()) );
333  return Range<FieldListAccessor>(bgn_it, end_it);
334 }
335 
336 
337 std::string FieldSet::print_dependency() const {
338  ASSERT_GT_DBG(region_field_update_order_.size(), 0).error("Variable 'region_dependency_list' is empty. Did you call 'set_dependency' method?\n");
339  std::stringstream s;
340  for (auto reg_it : region_field_update_order_) {
341  s << "\nregion_idx " << reg_it.first << ": ";
342  for (auto f_it : reg_it.second) {
343  s << f_it->name() << ", ";
344  }
345  }
346  return s.str();
347 }
348 
349 
351  this->user_fields_input_.clear();
353  it != input_list.end();
354  ++it) {
355  std::string name = it->val<std::string>("name");
356  user_fields_input_[name] = *it;
357  }
358 }
359 
360 
361 std::ostream &operator<<(std::ostream &stream, const FieldSet &set) {
362  for(FieldCommon * field : set.field_list) {
363  stream << *field
364  << std::endl;
365  }
366  return stream;
367 }
FieldCommon::units
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
Definition: field_common.hh:152
bc_field.hh
FieldSet::set_user_fields_map
void set_user_fields_map(Input::Array input_list)
Definition: field_set.cc:350
FieldSet::operator[]
FieldCommon & operator[](const std::string &field_name) const
Definition: field_set.cc:236
Input::Type::Bool
Class for declaration of the input of type Bool.
Definition: type_base.hh:452
FieldSet::get_user_field
const Input::Type::Record & get_user_field(const std::string &equation_name)
Declare input record type of field defined by user.
Definition: field_set.cc:33
ref_element.hh
Class RefElement defines numbering of vertices, sides, calculation of normal vectors etc.
UnitSI::dimensionless
static UnitSI & dimensionless()
Returns dimensionless unit.
Definition: unit_si.cc:55
FieldSet::user_field_list_
std::vector< FieldCommon * > user_field_list_
List of fields defined by user.
Definition: field_set.hh:404
FieldSet::is_jump_time
bool is_jump_time() const
Definition: field_set.cc:268
FieldSet::set_time
bool set_time(const TimeStep &time, LimitSide limit_side)
Definition: field_set.cc:245
FieldSet::is_constant
bool is_constant(Region reg) const
Definition: field_set.cc:261
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
MeshBase::region_db
const RegionDB & region_db() const
Definition: mesh.h:171
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:151
FieldSet::set_dependency
void set_dependency(FieldSet &used_fieldset)
Definition: field_set.cc:284
FieldCommon::copy_from
virtual void copy_from(const FieldCommon &other)=0
FieldSet::user_field
FieldCommon * user_field(const std::string &field_name, const TimeStep &time)
Definition: field_set.cc:177
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:330
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:415
FieldSet::changed
bool changed() const
Definition: field_set.cc:253
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:191
Field::get_input_type
IT::Instance get_input_type() override
Definition: field.impl.hh:178
uint
unsigned int uint
Definition: mh_dofhandler.hh:101
operator<<
std::ostream & operator<<(std::ostream &stream, const FieldSet &set)
Definition: field_set.cc:361
FlowAttribute::field_value_shape
static string field_value_shape()
Definition: flow_attribute_lib.hh:47
Input::Array::begin
Iterator< ValueType > begin() const
Definition: accessors_impl.hh:145
FlowAttribute::field_unit
static string field_unit()
Definition: flow_attribute_lib.hh:38
FieldSet::user_fields_input_
std::unordered_map< std::string, Input::Record > user_fields_input_
Map assigns Input::Record to each field defined in optional Input::Array 'user_fields'.
Definition: field_set.hh:427
FieldCommon::field_descriptor_record
static IT::Record field_descriptor_record(const string &record_name)
Definition: field_common.cc:60
Region
Definition: region.hh:146
Input::Iterator
Definition: accessors.hh:143
FieldSet::field_list
std::vector< FieldCommon * > field_list
List of all fields.
Definition: field_set.hh:401
FieldSet::X_
FieldCoords X_
Field holds coordinates for computing of FieldFormulas.
Definition: field_set.hh:421
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
LimitSide::left
@ left
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:297
FieldSet::print_dependency
std::string print_dependency() const
Return order of evaluated fields by dependency and region_idx.
Definition: field_set.cc:337
TimeStep::end
double end() const
Definition: time_governor.hh:161
FieldCommon::get_value_attribute
virtual std::string get_value_attribute() const =0
Input::Record
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
sys_profiler.hh
Field::set
void set(FieldBasePtr field, double time, std::vector< std::string > region_set_names={"ALL"})
Definition: field.impl.hh:244
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:407
Input::AbstractRecord
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:458
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:76
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:308
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
FieldCoords::set_mesh
void set_mesh(const Mesh &mesh) override
Definition: field_coords.hh:66
FieldCommon::changed
bool changed() const
Definition: field_common.hh:363
LimitSide
LimitSide
Definition: field_common.hh:63
FieldSet::cache_update
void cache_update(ElementCacheMap &cache_map)
Definition: field_set.cc:275
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:467
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:139
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
Field::set_mesh
void set_mesh(const Mesh &mesh) override
Definition: field.impl.hh:205
OLD_ASSERT
#define OLD_ASSERT(...)
Definition: global_defs.h:108
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:269
Input::Array
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
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:281
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: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:242
FieldCommon::is_jump_time
bool is_jump_time()
Definition: field_common.hh:306
BCField
Definition: bc_field.hh:32
FieldSet::set_field
void set_field(const std::string &dest_field_name, FieldCommon &source)
Definition: field_set.cc:161
FieldCommon::description
FieldCommon & description(const string &description)
Definition: field_common.hh:127
Field
Class template representing a field with values dependent on: point, element, and region.
Definition: field.hh:93
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
Input::Array::end
IteratorBase end() const
Definition: accessors_impl.hh:157
FieldSet::depth_
FieldDepth depth_
Field holds surface depth for computing of FieldFormulas.
Definition: field_set.hh:424
FieldSet::make_field_descriptor_type
Input::Type::Record make_field_descriptor_type(const std::string &equation_name) const
Definition: field_set.cc:91
ElementCacheMap::n_regions
unsigned int n_regions() const
Return number of stored regions.
Definition: field_value_cache.hh:229
FieldCommon::is_constant
virtual bool is_constant(Region reg)=0
FieldSet::field
FieldCommon * field(const std::string &field_name) const
Definition: field_set.cc:169
FieldCommon::name
FieldCommon & name(const string &name)
Definition: field_common.hh:120