Flow123d  JS_before_hm-1754-g1847fd3ed
equation_output.cc
Go to the documentation of this file.
1 /*
2  * equation_output.cc
3  *
4  * Created on: Jul 8, 2016
5  * Author: jb
6  */
7 
8 #include "tools/time_marks.hh"
9 #include "input/input_type.hh"
10 #include "input/accessors.hh"
12 #include "fields/field.hh"
13 #include "io/output_time_set.hh"
15 #include <memory>
16 
17 
18 namespace IT = Input::Type;
19 
20 
21 
23 
24  static const IT::Selection &interpolation_sel =
25  IT::Selection("Discrete_output", "Discrete type of output. Determines type of output data (element, node, native etc).")
26  .add_value(OutputTime::NODE_DATA, "P1_average", "Node data / point data.")
27  .add_value(OutputTime::CORNER_DATA, "D1_value", "Corner data.")
28  .add_value(OutputTime::ELEM_DATA, "P0_value", "Element data / cell data.")
29  .add_value(OutputTime::NATIVE_DATA, "Native", "Native data (Flow123D data).")
30  .close();
31 
32  static const IT::Record &field_output_setting =
33  IT::Record("FieldOutputSetting", "Setting of the field output. The field name, output times, output interpolation (future).")
34  .allow_auto_conversion("field")
35  .declare_key("field", IT::Parameter("output_field_selection"), IT::Default::obligatory(),
36  "The field name (from selection).")
38  "Output times specific to particular field.")
39  .declare_key("interpolation", IT::Array( interpolation_sel ), IT::Default::read_time("Interpolation type of output data."),
40  "Optional value. Implicit value is given by field and can be changed.")
41  .close();
42 
43  return IT::Record("EquationOutput",
44  "Output of the equation's fields."
45  "The output is done through the output stream of the associated balance law equation."
46  "The stream defines output format for the full space information in selected times and "
47  "observe points for the full time information. The key 'fields' select the fields for the full spatial output."
48  "The set of output times may be specified per field otherwise common time set 'times' is used. If even this is not provided"
49  "the time set of the output_stream is used. The initial time of the equation is automatically added "
50  "to the time set of every selected field. The end time of the equation is automatically added "
51  "to the common output time set.")
54  "Output times used for the output fields without is own time series specification.")
55  .declare_key("add_input_times", IT::Bool(), IT::Default("false"),
56  "Add all input time points of the equation, mentioned in the 'input_fields' list, also as the output points.")
57  .declare_key("fields", IT::Array(field_output_setting), IT::Default("[]"),
58  "Array of output fields and their individual output settings.")
59  .declare_key("observe_fields", IT::Array( IT::Parameter("output_field_selection")), IT::Default("[]"),
60  "Array of the fields evaluated in the observe points of the associated output stream.")
61  .close();
62 }
63 
64 
65 
67  const string &additional_description)
68 {
69  string selection_name = equation_name + ":OutputFields";
70  string description = "Selection of output fields for the " + equation_name + " model.\n" + additional_description;
71  IT::Selection sel(selection_name, description );
72  int i=0;
73  // add value for each field excluding boundary fields
74  for( FieldCommon * field : field_list)
75  {
76  //DebugOut().fmt("type for field: {}\n", field->name());
77  if ( !field->is_bc() && field->flags().match( FieldFlag::allow_output) )
78  {
79  string desc = "(($[" + field->units().format_latex()+"]$)) "; + "Output of: the field " + field->name() + " ";
81  desc += "Input field: ";
82  if (field->description().length() > 0)
83  desc += field->description();
84  sel.add_value(i, field->name(), desc, { {FlowAttribute::field_value_shape(), field->get_value_attribute()} });
85  i++;
86  }
87  }
88 
89  return sel.close();
90 }
91 
92 const IT::Instance &EquationOutput::make_output_type(const string &equation_name, const string &additional_description)
93 {
94  return make_output_type_from_record(get_input_type(), equation_name, additional_description);
95 }
96 
98  const string &equation_name,
99  const string &additional_description)
100 {
101  const IT::Selection &output_field_selection = create_output_field_selection(equation_name, additional_description);
102 
104  param_vec.push_back( std::make_pair("output_field_selection", std::make_shared< IT::Selection >(output_field_selection) ) );
105  return IT::Instance(in_rec, param_vec).close();
106 }
107 
108 
109 void EquationOutput::initialize(std::shared_ptr<OutputTime> stream, Mesh *mesh, Input::Record in_rec, const TimeGovernor & tg)
110 {
111  stream_ = stream;
112  mesh_ = mesh;
115  read_from_input(in_rec, tg);
116 }
117 
118 
119 
121 {
122  ASSERT(stream_).error("The 'set_stream' method must be called before the 'read_from_input'.");
123  auto &marks = TimeGovernor::marks();
124 
125  Input::Array times_array;
126  if (in_rec.opt_val("times", times_array) ) {
127  common_output_times_.read_from_input(times_array, tg);
128  } else {
129  // take times from the output_stream if key times is missing
130  auto times_array_it = stream_->get_time_set_array();
131  if (times_array_it) {
132  common_output_times_.read_from_input(*times_array_it, tg);
133  }
134  }
135  // always add the end time
137 
138  if (in_rec.val<bool>("add_input_times")) {
139  // copy time marks in order to prevent invalidation of the iterator
140  TimeMarks marks_copy = TimeGovernor::marks();
141  for(auto time_mark_it = marks_copy.begin(equation_type_ | marks.type_input());
142  time_mark_it != marks_copy.end(equation_type_ | marks.type_input());
143  ++time_mark_it) {
144  common_output_times_.add(time_mark_it->time(), equation_fixed_type_);
145  }
146  }
147  auto fields_array = in_rec.val<Input::Array>("fields");
148  for(auto it = fields_array.begin<Input::Record>(); it != fields_array.end(); ++it) {
149  string field_name = it -> val< Input::FullEnum >("field");
150  FieldCommon *found_field = field(field_name);
151 
152  Input::Array interpolations;
154  if (it->opt_val("interpolation", interpolations)) {
155  // process interpolations
156  for(auto it_interp = interpolations.begin<OutputTime::DiscreteSpace>(); it_interp != interpolations.end(); ++it_interp) {
157  interpolation[ *it_interp ] = true;
158  }
159  } else {
160  OutputTime::set_discrete_flag(interpolation, found_field->get_output_type());
161  }
162  Input::Array field_times_array;
163  if (it->opt_val("times", field_times_array)) {
164  OutputTimeSet field_times;
165  field_times.read_from_input(field_times_array, tg);
166  field_output_times_[field_name].output_set_ = field_times;
167  } else {
168  field_output_times_[field_name].output_set_ = common_output_times_;
169  }
170  field_output_times_[field_name].space_flags_ = interpolation;
171  // Add init time as the output time for every output field.
172  field_output_times_[field_name].output_set_.add(tg.init_time(), equation_fixed_type_);
173  }
174  auto observe_fields_array = in_rec.val<Input::Array>("observe_fields");
175  for(auto it = observe_fields_array.begin<Input::FullEnum>(); it != observe_fields_array.end(); ++it) {
176  observe_fields_.insert(string(*it));
177  }
178 
179  // register interpolation type of fields to OutputStream
180  for(FieldCommon * field : this->field_list) {
181  auto output_types = field_output_times_[field->name()].space_flags_;
182  for (uint i=0; i<OutputTime::N_DISCRETE_SPACES; ++i)
183  if (output_types[i]) used_interpolations_.insert( OutputTime::DiscreteSpace(i) );
184  }
185 }
186 
188 {
189  auto &marks = TimeGovernor::marks();
190  auto field_times_it = field_output_times_.find(field.name());
191  if (field_times_it == field_output_times_.end()) return false;
192  ASSERT( step.eq(field.time()) )(step.end())(field.time())(field.name()).error("Field is not set to the output time.");
193  auto current_mark_it = marks.current(step, equation_type_ | marks.type_output() );
194  if (current_mark_it == marks.end(equation_type_ | marks.type_output()) ) return false;
195  return (field_times_it->second.output_set_.contains(*current_mark_it) );
196 }
197 
198 
200 {
201  ASSERT_PTR(mesh_).error();
202 
203  // automatically call of stream_->write_time_frame if the time in the TimeStep is higher then in output stream
204  if (step.end() > stream_->registered_time()) {
205  stream_->write_time_frame();
206  }
207 
208  // make observe points if not already done
209  auto observe_ptr = stream_->observe(mesh_);
210 
211  this->make_output_mesh( stream_->is_parallel() );
212 
213  for(FieldCommon * field : this->field_list) {
214 
215  if ( field->flags().match( FieldFlag::allow_output) ) {
216  if (is_field_output_time(*field, step)) {
218  }
219  // observe output
220  if (observe_fields_.find(field->name()) != observe_fields_.end()) {
221  field->observe_output( observe_ptr );
222  }
223  }
224  }
225 }
226 
227 
228 void EquationOutput::add_output_times(double begin, double step, double end)
229 {
230  common_output_times_.add(begin,step, end, equation_fixed_type_ );
231 }
232 
233 
235 {
236  // already computed
237  if (stream_->is_output_data_caches_init()) return;
238 
239  // Read optional error control field name
240  bool need_refinment = stream_->get_output_mesh_record();
241 
242  if(need_refinment) {
243  if(stream_->enable_refinement()) {
244  // create output meshes from input record
245  output_mesh_ = std::make_shared<OutputMeshDiscontinuous>(*mesh_, *stream_->get_output_mesh_record());
246 
247  // possibly set error control field for refinement
248  auto ecf = select_error_control_field();
249  output_mesh_->set_error_control_field(ecf);
250 
251  // actually compute refined mesh
252  output_mesh_->create_refined_sub_mesh();
253  output_mesh_->make_serial_master_mesh();
254 
255  stream_->set_output_data_caches(output_mesh_);
256  return;
257  }
258  else
259  {
260  // skip creation of output mesh (use computational one)
261  WarningOut() << "Ignoring output mesh record.\n Output in GMSH format available only on computational mesh!";
262  }
263  }
264 
265  // create output mesh identical with the computational one
266  bool discont = need_refinment | (used_interpolations_.find(OutputTime::CORNER_DATA) != used_interpolations_.end());
267  //discont |= parallel;
268  if (discont) {
269  output_mesh_ = std::make_shared<OutputMeshDiscontinuous>(*mesh_);
270  } else {
271  output_mesh_ = std::make_shared<OutputMesh>(*mesh_);
272  }
273  output_mesh_->create_sub_mesh();
274  if (!parallel) {
275  output_mesh_->make_serial_master_mesh();
276  } else {
277  output_mesh_->make_parallel_master_mesh();
278  }
279  stream_->set_output_data_caches(output_mesh_);
280 }
281 
282 
284 {
285  std::string error_control_field_name = "";
286  // Read optional error control field name
287  auto it = stream_->get_output_mesh_record()->find<std::string>("error_control_field");
288  if(it) error_control_field_name = *it;
289 
290  if(error_control_field_name!="")
291  {
292  FieldCommon* field = this->field(error_control_field_name);
293  // throw input exception if the field is unknown
294  if(field == nullptr){
295  THROW(FieldSet::ExcUnknownField()
296  << FieldCommon::EI_Field(error_control_field_name));
297  }
298 
299  // throw input exception if the field is not scalar
300  if( typeid(*field) == typeid(Field<3,FieldValue<3>::Scalar>) ) {
301 
302  Field<3,FieldValue<3>::Scalar>* error_control_field = static_cast<Field<3,FieldValue<3>::Scalar>*>(field);
303  DebugOut() << "Error control field for output mesh set: " << error_control_field_name << ".";
304  auto lambda_function =
305  [error_control_field](const Armor::array &point_list, const ElementAccessor<OutputMeshBase::spacedim> &elm, std::vector<double> &value_list)->void
306  { error_control_field->value_list(point_list, elm, value_list); };
307 
308  OutputMeshBase::ErrorControlFieldFunc func = lambda_function;
309  return func;
310 
311  }
312  else{
313  THROW(ExcFieldNotScalar()
314  << FieldCommon::EI_Field(error_control_field_name));
315  }
316  }
318 }
FieldCommon::units
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
Definition: field_common.hh:150
FieldSet::mesh
const Mesh * mesh() const
Returns pointer to mesh.
Definition: field_set.hh:370
FieldCommon::observe_output
virtual void observe_output(std::shared_ptr< Observe > observe)=0
Input::Type::Bool
Class for declaration of the input of type Bool.
Definition: type_base.hh:452
Input::FullEnum
Definition: accessors.hh:129
FieldCommon::get_output_type
OutputTime::DiscreteSpace get_output_type() const
Definition: field_common.hh:263
TimeGovernor::end_time
double end_time() const
End time.
Definition: time_governor.hh:584
EquationOutput::initialize
void initialize(std::shared_ptr< OutputTime > stream, Mesh *mesh, Input::Record in_rec, const TimeGovernor &tg)
Definition: equation_output.cc:109
Input::Type::Instance::close
const Instance & close() const
Used for set Instance to TypeRepository.
Definition: type_generic.cc:108
EquationOutput::select_error_control_field
OutputMeshBase::ErrorControlFieldFunc select_error_control_field()
Selects the error control field out of output field set according to input record.
Definition: equation_output.cc:283
ASSERT
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:347
EquationOutput::create_output_field_selection
const Input::Type::Selection & create_output_field_selection(const string &equation_name, const string &additional_description)
Definition: equation_output.cc:66
TimeGovernor::equation_fixed_mark_type
TimeMark::Type equation_fixed_mark_type() const
Definition: time_governor.hh:474
Input::Record::val
const Ret val(const string &key) const
Definition: accessors_impl.hh:31
Input::Type::Selection::close
const Selection & close() const
Close the Selection, no more values can be added.
Definition: type_selection.cc:65
EquationOutput::is_field_output_time
bool is_field_output_time(const FieldCommon &field, TimeStep step) const
Definition: equation_output.cc:187
OutputTimeSet::add
void add(double begin, TimeMark::Type mark_type)
Definition: output_time_set.cc:77
THROW
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
std::vector
Definition: doxy_dummy_defs.hh:7
Input::Type::Default::read_time
static Default read_time(const std::string &description)
The factory function to make an default value that will be specified at the time when a key will be r...
Definition: type_record.hh:97
ElementAccessor
Definition: dh_cell_accessor.hh:32
TimeMarks::end
TimeMarks::iterator end(TimeMark::Type mask) const
Iterator for the end mimics container-like of TimeMarks.
Definition: time_marks.cc:206
OutputTime::ELEM_DATA
@ ELEM_DATA
Definition: output_time.hh:111
FieldCommon::flags
FieldCommon & flags(FieldFlag::Flags::Mask mask)
Definition: field_common.hh:189
FieldFlag::allow_output
static constexpr Mask allow_output
The field can output. Is part of generated output selection. (default on)
Definition: field_flag.hh:37
uint
unsigned int uint
Definition: mh_dofhandler.hh:101
Input::Array::begin
Iterator< ValueType > begin() const
Definition: accessors_impl.hh:145
EquationOutput::make_output_type
const Input::Type::Instance & make_output_type(const string &equation_name, const string &aditional_description="")
Definition: equation_output.cc:92
OutputMeshBase::ErrorControlFieldFunc
std::function< void(const Armor::array &, const ElementAccessor< spacedim > &, std::vector< double > &)> ErrorControlFieldFunc
Definition: output_mesh.hh:77
OutputTime::DiscreteSpaceFlags
std::array< bool, 4 > DiscreteSpaceFlags
Definition: output_time.hh:122
FieldCommon::field_output
virtual void field_output(std::shared_ptr< OutputTime > stream, OutputTime::DiscreteSpaceFlags type)=0
FieldSet::field_list
std::vector< FieldCommon * > field_list
List of all fields.
Definition: field_set.hh:383
TimeMarks::begin
TimeMarks::iterator begin(TimeMark::Type mask) const
Iterator for the begin mimics container-like of TimeMarks.
Definition: time_marks.cc:192
Input::Type::Default
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
equation_output.hh
OutputTime::set_discrete_flag
static void set_discrete_flag(DiscreteSpaceFlags &dsf, DiscreteSpace d_space)
Definition: output_time.hh:135
EquationOutput::mesh_
Mesh * mesh_
Definition: equation_output.hh:139
TimeStep::end
double end() const
Definition: time_governor.hh:161
EquationOutput::read_from_input
void read_from_input(Input::Record in_rec, const TimeGovernor &tg)
Definition: equation_output.cc:120
Input::Record
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
Input::Type::Record::allow_auto_conversion
virtual Record & allow_auto_conversion(const string &from_key)
Allows shorter input of the Record providing only value of the from_key given as the parameter.
Definition: type_record.cc:133
accessors.hh
flow_attribute_lib.hh
TimeStep
Representation of one time step..
Definition: time_governor.hh:123
TimeGovernor
Basic time management functionality for unsteady (and steady) solvers (class Equation).
Definition: time_governor.hh:310
Input::Type::Record::root_of_generic_subtree
virtual Record & root_of_generic_subtree()
Definition: type_record.cc:432
EquationOutput::add_output_times
void add_output_times(double begin, double step, double end)
Definition: equation_output.cc:228
OutputTime::empty_discrete_flags
static DiscreteSpaceFlags empty_discrete_flags()
Check if at least one of discrete space flag is set to true.
Definition: output_time.hh:130
Input::Type::Default::obligatory
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:110
EquationOutput::field_output_times_
std::unordered_map< string, FieldOutputConfig > field_output_times_
Time sets of individual fields.
Definition: equation_output.hh:124
FieldCommon
Common abstract parent of all Field<...> classes.
Definition: field_common.hh:74
EquationOutput::equation_type_
TimeMark::Type equation_type_
The time mark type of the equation.
Definition: equation_output.hh:117
EquationOutput::get_input_type
static Input::Type::Record & get_input_type()
Definition: equation_output.cc:22
Input::Record::opt_val
bool opt_val(const string &key, Ret &value) const
Definition: accessors_impl.hh:107
Input::Type::Instance
Helper class that stores data of generic types.
Definition: type_generic.hh:89
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
FieldCommon::is_bc
bool is_bc() const
Definition: field_common.hh:266
output_time_set.hh
Input::Type::Selection
Template for classes storing finite set of named values.
Definition: type_selection.hh:65
Input::Type::Record::close
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
OutputTimeSet::read_from_input
void read_from_input(Input::Array in_array, const TimeGovernor &tg)
Definition: output_time_set.cc:35
Input::Type
Definition: balance.hh:41
Input::Type::Record
Record type proxy class.
Definition: type_record.hh:182
TimeStep::eq
bool eq(double other_time) const
Definition: time_governor.hh:191
EquationOutput::output
void output(TimeStep step)
Definition: equation_output.cc:199
input_type.hh
TimeMarks
This class is a collection of time marks to manage various events occurring during simulation time.
Definition: time_marks.hh:206
EquationOutput::observe_fields_
std::unordered_set< string > observe_fields_
Set of observed fields. The observe points are given within the observe stream.
Definition: equation_output.hh:127
Mesh
Definition: mesh.h:77
OutputTime::NODE_DATA
@ NODE_DATA
Definition: output_time.hh:109
OutputTimeSet::get_input_type
static const Input::Type::Array get_input_type()
Definition: output_time_set.cc:17
Input::Type::Array
Class for declaration of inputs sequences.
Definition: type_base.hh:339
TimeGovernor::marks
static TimeMarks & marks()
Definition: time_governor.hh:331
Field::value_list
virtual void value_list(const Armor::array &point_list, const ElementAccessor< spacedim > &elm, std::vector< typename Value::return_type > &value_list) const
Definition: field.hh:466
Input::Array
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
WarningOut
#define WarningOut()
Macro defining 'warning' record of log.
Definition: logger.hh:270
FieldFlag::equation_input
static constexpr Mask equation_input
The field is data parameter of the owning equation. (default on)
Definition: field_flag.hh:33
OutputTime::CORNER_DATA
@ CORNER_DATA
Definition: output_time.hh:110
EquationOutput::make_output_type_from_record
const Input::Type::Instance & make_output_type_from_record(Input::Type::Record &in_rec, const string &equation_name, const string &aditional_description="")
Definition: equation_output.cc:97
TimeGovernor::equation_mark_type
TimeMark::Type equation_mark_type() const
Definition: time_governor.hh:468
Armor::Array< double >
EquationOutput::make_output_mesh
void make_output_mesh(bool parallel)
Definition: equation_output.cc:234
OutputTime::DiscreteSpace
DiscreteSpace
Definition: output_time.hh:108
EquationOutput::used_interpolations_
std::set< OutputTime::DiscreteSpace > used_interpolations_
Definition: equation_output.hh:134
EquationOutput::common_output_times_
OutputTimeSet common_output_times_
The time set used for the fields without explicit time set.
Definition: equation_output.hh:121
time_marks.hh
FieldCommon::description
FieldCommon & description(const string &description)
Definition: field_common.hh:125
Field
Class template representing a field with values dependent on: point, element, and region.
Definition: field.hh:95
Input::Type::Parameter
Class for representing parametric types in IST.
Definition: type_generic.hh:53
DebugOut
#define DebugOut()
Macro defining 'debug' record of log.
Definition: logger.hh:276
Input::Type::Selection::add_value
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.
Definition: type_selection.cc:50
OutputTimeSet
Definition: output_time_set.hh:28
ASSERT_PTR
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR)
Definition: asserts.hh:336
EquationOutput::stream_
std::shared_ptr< OutputTime > stream_
output stream (may be shared by more equation)
Definition: equation_output.hh:115
EquationOutput::equation_fixed_type_
TimeMark::Type equation_fixed_type_
The fixed time mark type of the equation.
Definition: equation_output.hh:119
Input::Type::Default::optional
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:124
OutputTime::N_DISCRETE_SPACES
static const unsigned int N_DISCRETE_SPACES
Definition: output_time.hh:107
TimeGovernor::init_time
double init_time() const
Definition: time_governor.hh:529
Input::Array::end
IteratorBase end() const
Definition: accessors_impl.hh:157
FieldCommon::time
double time() const
Definition: field_common.hh:285
EquationOutput::output_mesh_
std::shared_ptr< OutputMeshBase > output_mesh_
Output mesh.
Definition: equation_output.hh:142
field.hh
OutputTime::NATIVE_DATA
@ NATIVE_DATA
Definition: output_time.hh:112
FieldSet::field
FieldCommon * field(const std::string &field_name) const
Definition: field_set.cc:147
FieldCommon::name
FieldCommon & name(const string &name)
Definition: field_common.hh:118
FieldValue
Definition: field_values.hh:645