Flow123d  JS_before_hm-1598-g3b021b4
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", 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();
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  OutputTime::DiscreteSpace interpolation = it->val<OutputTime::DiscreteSpace>("interpolation", OutputTime::UNDEFINED);
152  found_field->output_type(interpolation);
153  Input::Array field_times_array;
154  if (it->opt_val("times", field_times_array)) {
155  OutputTimeSet field_times;
156  field_times.read_from_input(field_times_array, tg);
157  field_output_times_[field_name] = field_times;
158  } else {
160  }
161  // Add init time as the output time for every output field.
162  field_output_times_[field_name].add(tg.init_time(), equation_fixed_type_);
163  }
164  auto observe_fields_array = in_rec.val<Input::Array>("observe_fields");
165  for(auto it = observe_fields_array.begin<Input::FullEnum>(); it != observe_fields_array.end(); ++it) {
166  observe_fields_.insert(string(*it));
167  }
168 
169  // register interpolation type of fields to OutputStream
170  for(FieldCommon * field : this->field_list) {
172  }
173 }
174 
176 {
177  auto &marks = TimeGovernor::marks();
178  auto field_times_it = field_output_times_.find(field.name());
179  if (field_times_it == field_output_times_.end()) return false;
180  ASSERT( step.eq(field.time()) )(step.end())(field.time())(field.name()).error("Field is not set to the output time.");
181  auto current_mark_it = marks.current(step, equation_type_ | marks.type_output() );
182  if (current_mark_it == marks.end(equation_type_ | marks.type_output()) ) return false;
183  return (field_times_it->second.contains(*current_mark_it) );
184 }
185 
186 
188 {
189  ASSERT_PTR(mesh_).error();
190 
191  // automatically call of stream_->write_time_frame if the time in the TimeStep is higher then in output stream
192  if (step.end() > stream_->registered_time()) {
193  stream_->write_time_frame();
194  }
195 
196  // make observe points if not already done
197  auto observe_ptr = stream_->observe(mesh_);
198 
199  this->make_output_mesh( stream_->is_parallel() );
200 
201  for(FieldCommon * field : this->field_list) {
202 
203  if ( field->flags().match( FieldFlag::allow_output) ) {
204  if (is_field_output_time(*field, step)) {
206  }
207  // observe output
208  if (observe_fields_.find(field->name()) != observe_fields_.end()) {
209  field->observe_output( observe_ptr );
210  }
211  }
212  }
213 }
214 
215 
216 void EquationOutput::add_output_times(double begin, double step, double end)
217 {
218  common_output_times_.add(begin,step, end, equation_fixed_type_ );
219 }
220 
221 
223 {
224  // already computed
225  if (stream_->is_output_data_caches_init()) return;
226 
227  // Read optional error control field name
228  bool need_refinment = stream_->get_output_mesh_record();
229 
230  if(need_refinment) {
231  if(stream_->enable_refinement()) {
232  // create output meshes from input record
233  output_mesh_ = std::make_shared<OutputMeshDiscontinuous>(*mesh_, *stream_->get_output_mesh_record());
234 
235  // possibly set error control field for refinement
236  auto ecf = select_error_control_field();
237  output_mesh_->set_error_control_field(ecf);
238 
239  // actually compute refined mesh
240  output_mesh_->create_refined_sub_mesh();
241  output_mesh_->make_serial_master_mesh();
242 
243  stream_->set_output_data_caches(output_mesh_);
244  return;
245  }
246  else
247  {
248  // skip creation of output mesh (use computational one)
249  WarningOut() << "Ignoring output mesh record.\n Output in GMSH format available only on computational mesh!";
250  }
251  }
252 
253  // create output mesh identical with the computational one
254  bool discont = need_refinment | (used_interpolations_.find(OutputTime::CORNER_DATA) != used_interpolations_.end());
255  //discont |= parallel;
256  if (discont) {
257  output_mesh_ = std::make_shared<OutputMeshDiscontinuous>(*mesh_);
258  } else {
259  output_mesh_ = std::make_shared<OutputMesh>(*mesh_);
260  }
261  output_mesh_->create_sub_mesh();
262  if (!parallel) {
263  output_mesh_->make_serial_master_mesh();
264  } else {
265  output_mesh_->make_parallel_master_mesh();
266  }
267  stream_->set_output_data_caches(output_mesh_);
268 }
269 
270 
272 {
273  std::string error_control_field_name = "";
274  // Read optional error control field name
275  auto it = stream_->get_output_mesh_record()->find<std::string>("error_control_field");
276  if(it) error_control_field_name = *it;
277 
278  if(error_control_field_name!="")
279  {
280  FieldCommon* field = this->field(error_control_field_name);
281  // throw input exception if the field is unknown
282  if(field == nullptr){
283  THROW(FieldSet::ExcUnknownField()
284  << FieldCommon::EI_Field(error_control_field_name));
285  }
286 
287  // throw input exception if the field is not scalar
288  if( typeid(*field) == typeid(Field<3,FieldValue<3>::Scalar>) ) {
289 
290  Field<3,FieldValue<3>::Scalar>* error_control_field = static_cast<Field<3,FieldValue<3>::Scalar>*>(field);
291  DebugOut() << "Error control field for output mesh set: " << error_control_field_name << ".";
292  auto lambda_function =
293  [error_control_field](const Armor::array &point_list, const ElementAccessor<OutputMeshBase::spacedim> &elm, std::vector<double> &value_list)->void
294  { error_control_field->value_list(point_list, elm, value_list); };
295 
296  OutputMeshBase::ErrorControlFieldFunc func = lambda_function;
297  return func;
298 
299  }
300  else{
301  THROW(ExcFieldNotScalar()
302  << FieldCommon::EI_Field(error_control_field_name));
303  }
304  }
306 }
virtual void field_output(std::shared_ptr< OutputTime > stream)=0
std::vector< FieldCommon * > field_list
List of all fields.
Definition: field_set.hh:379
void add_output_times(double begin, double step, double end)
Common abstract parent of all Field<...> classes.
Definition: field_common.hh:74
std::unordered_set< string > observe_fields_
Set of observed fields. The observe points are given within the observe stream.
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
double end_time() const
End time.
static constexpr Mask allow_output
The field can output. Is part of generated output selection. (default on)
Definition: field_flag.hh:37
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
Class for declaration of the input of type Bool.
Definition: type_base.hh:452
const Input::Type::Selection & create_output_field_selection(const string &equation_name, const string &additional_description)
OutputTime::DiscreteSpace get_output_type() const
void output(TimeStep step)
const Input::Type::Instance & make_output_type_from_record(Input::Type::Record &in_rec, const string &equation_name, const string &aditional_description="")
Class template representing a field with values dependent on: point, element, and region...
Definition: field.hh:94
const Mesh * mesh() const
Returns pointer to mesh.
Definition: field_set.hh:370
const Instance & close() const
Used for set Instance to TypeRepository.
TimeMarks::iterator begin(TimeMark::Type mask) const
Iterator for the begin mimics container-like of TimeMarks.
Definition: time_marks.cc:192
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:110
virtual std::string get_value_attribute() const =0
Class for representing parametric types in IST.
Definition: type_generic.hh:53
Definition: mesh.h:77
TimeMark::Type equation_fixed_type_
The fixed time mark type of the equation.
Helper class that stores data of generic types.
Definition: type_generic.hh:89
void read_from_input(Input::Array in_array, const TimeGovernor &tg)
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:347
Basic time management functionality for unsteady (and steady) solvers (class Equation).
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
void make_output_mesh(bool parallel)
static TimeMarks & marks()
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
Class for declaration of inputs sequences.
Definition: type_base.hh:339
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:124
double init_time() const
bool opt_val(const string &key, Ret &value) const
void read_from_input(Input::Record in_rec, const TimeGovernor &tg)
double time() const
FieldCommon * field(const std::string &field_name) const
Definition: field_set.cc:148
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
TimeMark::Type equation_fixed_mark_type() const
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
TimeMark::Type equation_mark_type() const
const Ret val(const string &key) const
virtual Record & root_of_generic_subtree()
Definition: type_record.cc:432
OutputMeshBase::ErrorControlFieldFunc select_error_control_field()
Selects the error control field out of output field set according to input record.
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.
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
std::shared_ptr< OutputTime > stream_
output stream (may be shared by more equation)
double end() const
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:465
This class is a collection of time marks to manage various events occurring during simulation time...
Definition: time_marks.hh:206
std::unordered_map< string, OutputTimeSet > field_output_times_
Time sets of individual fields.
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
FieldCommon & description(const string &description)
void initialize(std::shared_ptr< OutputTime > stream, Mesh *mesh, Input::Record in_rec, const TimeGovernor &tg)
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR)
Definition: asserts.hh:336
const Selection & close() const
Close the Selection, no more values can be added.
static Input::Type::Record & get_input_type()
static const Input::Type::Array get_input_type()
TimeMarks::iterator end(TimeMark::Type mask) const
Iterator for the end mimics container-like of TimeMarks.
Definition: time_marks.cc:206
#define WarningOut()
Macro defining &#39;warning&#39; record of log.
Definition: logger.hh:270
FieldCommon & name(const string &name)
virtual void observe_output(std::shared_ptr< Observe > observe)=0
Record type proxy class.
Definition: type_record.hh:182
bool is_field_output_time(const FieldCommon &field, TimeStep step) const
const Input::Type::Instance & make_output_type(const string &equation_name, const string &aditional_description="")
FieldCommon & flags(FieldFlag::Flags::Mask mask)
OutputTimeSet common_output_times_
The time set used for the fields without explicit time set.
static constexpr Mask equation_input
The field is data parameter of the owning equation. (default on)
Definition: field_flag.hh:33
bool is_bc() const
#define DebugOut()
Macro defining &#39;debug&#39; record of log.
Definition: logger.hh:276
TimeMark::Type equation_type_
The time mark type of the equation.
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
Representation of one time step..
std::function< void(const Armor::array &, const ElementAccessor< spacedim > &, std::vector< double > &)> ErrorControlFieldFunc
Definition: output_mesh.hh:77
Template for classes storing finite set of named values.
std::shared_ptr< OutputMeshBase > output_mesh_
Output mesh.
std::set< OutputTime::DiscreteSpace > used_interpolations_
bool eq(double other_time) const
void add(double begin, TimeMark::Type mark_type)