Flow123d  release_2.2.0-20-gb8056ca
field_elementwise.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_elementwise.cc
15  * @brief
16  */
17 
18 
20 #include "fields/field_instances.hh" // for instantiation macros
21 #include "system/file_path.hh"
22 #include "input/input_type.hh"
23 #include "io/msh_gmshreader.h"
24 #include "io/reader_instances.hh"
25 
26 /// Implementation.
27 
28 namespace IT = Input::Type;
29 
30 FLOW123D_FORCE_LINK_IN_CHILD(field_elementwise)
31 
32 
33 template <int spacedim, class Value>
34 const Input::Type::Record & FieldElementwise<spacedim, Value>::get_input_type()
35 {
36  return IT::Record("FieldElementwise", FieldAlgorithmBase<spacedim,Value>::template_name()+" Field piecewise constant on mesh elements.")
40  "Input file with ASCII GMSH file format.")
42  "The values of the Field are read from the ```$ElementData``` section with field name given by this key.")
43  //.declare_key("unit", FieldAlgorithmBase<spacedim, Value>::get_input_type_unit_si(), IT::Default::optional(),
44  // "Definition of unit.")
45  .close();
46 }
47 
48 
49 template <int spacedim, class Value>
51  Input::register_class< FieldElementwise<spacedim, Value>, unsigned int >("FieldElementwise") +
53 
54 
55 
56 template <int spacedim, class Value>
58 : FieldAlgorithmBase<spacedim, Value>(n_comp),
59  internal_raw_data(true), mesh_(NULL), unit_si_( UnitSI::dimensionless() )
60 
61 {
62  n_components_ = this->value_.n_rows() * this->value_.n_cols();
63 }
64 
65 
66 
67 template <int spacedim, class Value>
69  unsigned int n_components)
70 : FieldAlgorithmBase<spacedim, Value>(n_components),
71 internal_raw_data(false), mesh_(NULL), unit_si_( UnitSI::dimensionless() )
72 {
73  n_components_ = this->value_.n_rows() * this->value_.n_cols();
74  data_ = data;
75  this->scale_and_check_limits();
76 }
77 
78 
79 
80 
81 template <int spacedim, class Value>
83  this->init_unit_conversion_coefficient(rec, init_data);
84  this->in_rec_ = rec;
85  this->unit_si_ = init_data.unit_si_;
86  this->limits_ = init_data.limits_;
87 
88  DebugOut() << "Reader file: " << string(reader_file_);
89  ASSERT(internal_raw_data).error("Trying to initialize internal FieldElementwise from input.");
90  ASSERT(reader_file_ == FilePath()).error("Multiple call of init_from_input.");
91  reader_file_ = FilePath( rec.val<FilePath>("gmsh_file") );
92 
93  field_name_ = rec.val<std::string>("field_name");
94 }
95 
96 
97 
98 /*template <int spacedim, class Value>
99 void FieldElementwise<spacedim, Value>::set_data_row(unsigned int boundary_idx, typename Value::return_type &value) {
100  Value ref(value);
101  OLD_ASSERT( this->value_.n_cols() == ref.n_cols(), "Size of variable vectors do not match.\n" );
102  OLD_ASSERT( mesh_, "Null mesh pointer of elementwise field: %s, did you call set_mesh()?\n", field_name_.c_str());
103  OLD_ASSERT( boundary_domain_ , "Method set_data_row can be used only for boundary fields.");
104  unsigned int vec_pos = boundary_idx * n_components_;
105  std::vector<typename Value::element_type> &vec = *( data_.get() );
106  for(unsigned int row=0; row < ref.n_rows(); row++)
107  for(unsigned int col=0; col < ref.n_cols(); col++, vec_pos++)
108  vec[vec_pos] = ref(row,col);
109 
110 }*/
111 
112 
113 template <int spacedim, class Value>
115  OLD_ASSERT(mesh_, "Null mesh pointer of elementwise field: %s, did you call set_mesh()?\n", field_name_.c_str());
116  if ( reader_file_ == FilePath() ) return false;
117 
118  //walkaround for the steady time governor - there is no data to be read in time==infinity
119  //TODO: is it possible to check this before calling set_time?
120  //if (time.end() == numeric_limits< double >::infinity()) return false;
121 
122  data_ = ReaderInstances::instance()->get_reader(reader_file_)-> template get_element_data<typename Value::element_type>(
124  this->scale_and_check_limits();
125  return true;
126 }
127 
128 
129 
130 template <int spacedim, class Value>
131 void FieldElementwise<spacedim, Value>::set_mesh(const Mesh *mesh, bool boundary_domain) {
132  // set mesh only once or to same value
133  OLD_ASSERT(mesh_ == nullptr || mesh_ == mesh, "Trying to change mesh of the FieldElementwise.");
134  boundary_domain_ = boundary_domain;
135 
136  mesh_=mesh;
137  if (boundary_domain_) {
139  } else {
141  }
142 
143  // allocate
144  if (!data_) {
145  data_ = std::make_shared<std::vector<typename Value::element_type>>();
146  data_->resize(n_entities_ * n_components_);
147  }
148 
149  if ( reader_file_ == FilePath() ) return;
150  ReaderInstances::instance()->get_reader(reader_file_)->check_compatible_mesh( const_cast<Mesh &>(*mesh) );
151 }
152 
153 
154 
155 /**
156  * Returns one value in one given point. ResultType can be used to avoid some costly calculation if the result is trivial.
157  */
158 template <int spacedim, class Value>
159 typename Value::return_type const & FieldElementwise<spacedim, Value>::value(const Point &p, const ElementAccessor<spacedim> &elm)
160 {
161  OLD_ASSERT( elm.is_elemental(), "FieldElementwise works only for 'elemental' ElementAccessors.\n");
162  OLD_ASSERT( elm.is_boundary() == boundary_domain_, "Trying to get value of FieldElementwise '%s' for wrong ElementAccessor type (boundary/bulk).\n", field_name_.c_str() );
163 
164  unsigned int idx = n_components_*elm.idx();
166 
167  return Value::from_raw(this->r_value_, (typename Value::element_type *)(&vec[idx]));
168 }
169 
170 
171 
172 /**
173  * Returns std::vector of scalar values in several points at once.
174  */
175 template <int spacedim, class Value>
178 {
179  OLD_ASSERT( elm.is_elemental(), "FieldElementwise works only for 'elemental' ElementAccessors.\n");
180  OLD_ASSERT( elm.is_boundary() == boundary_domain_, "Trying to get value of FieldElementwise '%s' for wrong ElementAccessor type (boundary/bulk).\n", field_name_.c_str() );
181  OLD_ASSERT_EQUAL( point_list.size(), value_list.size() );
183  unsigned int idx = n_components_*elm.idx();
185 
186  typename Value::return_type const &ref = Value::from_raw(this->r_value_, (typename Value::element_type *)(&vec[idx]));
187  for(unsigned int i=0; i< value_list.size(); i++) {
188  OLD_ASSERT( Value(value_list[i]).n_rows()==this->value_.n_rows(),
189  "value_list[%d] has wrong number of rows: %d; should match number of components: %d\n",
190  i, Value(value_list[i]).n_rows(),this->value_.n_rows());
191 
192  value_list[i] = ref;
193  }
194  } else {
195  xprintf(UsrErr, "FieldElementwise is not implemented for discrete return types.\n");
196  }
197 }
198 
199 
200 
201 template <int spacedim, class Value>
203 {
204  if (Value::is_scalable()) {
206  bool printed_warning = false;
207  for(unsigned int i=0; i<vec.size(); ++i) {
208  vec[i] *= this->unit_conversion_coefficient_;
209  if ( !printed_warning && ((vec[i] < limits_.first) || (vec[i] > limits_.second)) ) {
210  printed_warning = true;
211  WarningOut().fmt("Values of some elements of FieldElementwise '{}' at address '{}' is out of limits: <{}, {}>\n"
212  "Unit of the Field: [{}]\n",
214  }
215  }
216  }
217 }
218 
219 
220 
221 template <int spacedim, class Value>
223 
224 
225 // Instantiations of FieldElementwise
void init_unit_conversion_coefficient(const Input::Record &rec, const struct FieldAlgoBaseInitData &init_data)
Init value of unit_conversion_coefficient_ from input.
std::shared_ptr< std::vector< typename Value::element_type > > data_
Raw buffer of n_entities rows each containing Value::size() doubles.
std::string format_text() const
Definition: unit_si.cc:127
std::pair< double, double > limits_
Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm) override
unsigned int component_idx_
Specify if the field is part of a MultiField and which component it is.
bool is_boundary() const
We need this method after replacing Region by RegionIdx, and movinf RegionDB instance into particular...
Definition: accessors.hh:109
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:110
#define INSTANCE_ALL(field)
Definition: mesh.h:97
Helper struct stores data for initizalize descentants of FieldAlgorithmBase.
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:346
Value::return_type r_value_
virtual void init_from_input(const Input::Record &rec, const struct FieldAlgoBaseInitData &init_data) override
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:303
std::shared_ptr< BaseMeshReader > get_reader(const FilePath &file_name)
static constexpr bool value
Definition: json.hpp:87
double unit_conversion_coefficient_
Coeficient of conversion of user-defined unit.
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:195
unsigned int size() const
Returns size of the container. This is independent of the allocated space.
Definition: sys_vector.hh:391
#define OLD_ASSERT(...)
Definition: global_defs.h:131
unsigned int n_elements() const
Definition: mesh.h:141
bool is_elemental() const
Definition: accessors.hh:75
bool set_time(const TimeStep &time) override
void scale_and_check_limits()
Multiply data_ with unit_conversion_coefficient_ and check limits of field.
static FileName input()
The factory function for declaring type FileName for input files.
Definition: type_base.cc:526
Accessor to the data with type Type::Record.
Definition: accessors.hh:292
const Ret val(const string &key) const
#define xprintf(...)
Definition: system.hh:92
FieldElementwise(unsigned int n_comp=0)
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:490
ElementVector bc_elements
Definition: mesh.h:236
double end() const
Space< spacedim >::Point Point
Record & copy_keys(const Record &other)
Copy keys from other record.
Definition: type_record.cc:215
Dedicated class for storing path to input and output files.
Definition: file_path.hh:54
Definition: system.hh:64
unsigned int n_components_
Size of Value.
const UnitSI & unit_si_
void set_mesh(const Mesh *mesh, bool boundary_domain) override
Value value_
Last value, prevents passing large values (vectors) by value.
unsigned int n_entities_
Number of rows in data_ buffer.
#define WarningOut()
Macro defining &#39;warning&#39; record of log.
Definition: logger.hh:236
void value_list(const std::vector< Point > &point_list, const ElementAccessor< spacedim > &elm, std::vector< typename Value::return_type > &value_list) override
#define OLD_ASSERT_EQUAL(a, b)
Definition: global_defs.h:133
std::pair< double, double > limits_
Record type proxy class.
Definition: type_record.hh:182
Input::Record in_rec_
Accessor to Input::Record.
Class for representation SI units of Fields.
Definition: unit_si.hh:40
static ReaderInstances * instance()
Returns singleton instance.
#define DebugOut()
Macro defining &#39;debug&#39; record of log.
Definition: logger.hh:242
unsigned int idx() const
Definition: accessors.hh:113
Class for declaration of the input data that are in string format.
Definition: type_base.hh:588
Representation of one time step..
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Definition: global_defs.h:180
string address_string() const
Definition: accessors.cc:184