Flow123d  JS_before_hm-1626-gde32303
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 }
std::vector< FieldCommon * > field_list
List of all fields.
Definition: field_set.hh:383
Class MappingP1 implements the affine transformation of the unit cell onto the actual cell...
unsigned int size() const
Definition: region.cc:254
FieldDepth depth_
Field holds surface depth for computing of FieldFormulas.
Definition: field_set.hh:400
bool is_jump_time() const
Definition: field_set.cc:187
Common abstract parent of all Field<...> classes.
Definition: field_common.hh:74
Container for various descendants of FieldCommonBase.
Definition: field_set.hh:159
std::map< unsigned int, std::vector< const FieldCommon * > > region_field_update_order_
Definition: field_set.hh:394
virtual void copy_from(const FieldCommon &other)=0
const Mesh * mesh_
Pointer to the mesh.
Definition: field_set.hh:386
FieldCommon & operator[](const std::string &field_name) const
Definition: field_set.cc:155
FieldCoords X_
Field holds coordinates for computing of FieldFormulas.
Definition: field_set.hh:397
void set_field_coords(FieldCoords *field_coords)
Setter of field_coords data member.
Definition: field_depth.hh:143
void set_dependency(FieldSet &used_fieldset)
Definition: field_set.cc:203
virtual bool is_constant(Region reg)=0
Implementation of bidirectional map.
Range helper class.
virtual std::string get_value_attribute() const =0
virtual IT::Instance get_input_type()=0
Directing class of FieldValueCache.
virtual bool set_time(const TimeStep &time, LimitSide limit_side)=0
static string field_default_value()
const RegionDB & region_db() const
Definition: mesh.h:160
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:347
static const std::string field_descriptor_record_description(const string &record_name)
Definition: field_common.cc:73
#define ASSERT_GT_DBG(a, b)
Definition of comparative assert macro (Greater Than) only for debug mode.
Definition: asserts.hh:316
std::string print_dependency() const
Return order of evaluated fields by dependency and region_idx.
Definition: field_set.cc:252
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
unsigned int n_regions() const
Return number of stored regions.
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
unsigned int region_idx_from_chunk_position(unsigned int chunk_pos) const
Return begin position of region chunk specified by position in map.
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:124
#define OLD_ASSERT(...)
Definition: global_defs.h:108
FieldCommon * field(const std::string &field_name) const
Definition: field_set.cc:147
Range< FieldListAccessor > fields_range() const
Returns range of Fields held in field_list.
Definition: field_set.cc:245
static constexpr Mask input_copy
Definition: field_flag.hh:44
FieldCommon & input_default(const string &input_default)
static IT::Record field_descriptor_record(const string &record_name)
Definition: field_common.cc:60
std::map< std::string, json_string > attribute_map
Defines map of Input::Type attributes.
Definition: type_base.hh:101
virtual std::vector< const FieldCommon * > set_dependency(FieldSet &field_set, unsigned int i_reg) const =0
void set_field(const std::string &dest_field_name, FieldCommon &source)
Definition: field_set.cc:139
static string field_value_shape()
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
bool is_multifield() const
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
Record & copy_keys(const Record &other)
Copy keys from other record.
Definition: type_record.cc:216
bool is_jump_time()
FieldCommon & description(const string &description)
void add_coords_field()
Definition: field_set.cc:228
virtual IT::Array get_multifield_input_type()=0
void cache_update(ElementCacheMap &cache_map)
Definition: field_set.cc:194
bool set_time(const TimeStep &time, LimitSide limit_side)
Definition: field_set.cc:164
bool is_constant(Region reg) const
Definition: field_set.cc:180
FieldCommon & name(const string &name)
Class RefElement defines numbering of vertices, sides, calculation of normal vectors etc...
static string field_unit()
bool changed() const
void set_mesh(const Mesh &mesh)
Definition: field_set.hh:274
friend std::ostream & operator<<(std::ostream &stream, const FieldSet &set)
Definition: field_set.cc:265
Record type proxy class.
Definition: type_record.hh:182
FieldCommon & flags(FieldFlag::Flags::Mask mask)
const std::string & input_name() const
Class for representation SI units of Fields.
Definition: unit_si.hh:40
virtual void cache_update(ElementCacheMap &cache_map, unsigned int region_patch_idx) const =0
FieldSet()
Default constructor.
Definition: field_set.cc:28
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
Representation of one time step..
bool changed() const
Definition: field_set.cc:172
LimitSide
Definition: field_common.hh:61
Input::Type::Record make_field_descriptor_type(const std::string &equation_name) const
Definition: field_set.cc:69
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