Flow123d  release_3.0.0-903-ge56fc7d
balance.hh
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 balance.hh
15  * @brief
16  */
17 
18 #ifndef BALANCE_HH_
19 #define BALANCE_HH_
20 
21 
22 #include <iosfwd> // for ofstream
23 #include <string> // for string
24 #include <vector> // for vector
25 #include <unordered_map> // for unordered_map
26 #include "mesh/side_impl.hh" // for SideIter
27 #include "tools/unit_si.hh" // for UnitSI
28 #include "input/accessors.hh" // for Record
29 #include "petscmat.h" // for Mat, _p_Mat
30 #include "petscvec.h" // for Vec, _p_Vec
31 #include "system/file_path.hh" // for FilePath
32 #include "tools/time_marks.hh" // for TimeMark, TimeMark::Type
33 #include "mesh/long_idx.hh" // for LongIdx
34 
35 class Mesh;
36 class TimeGovernor;
37 namespace Input {
38  namespace Type {
39  class Record;
40  class Selection;
41  }
42 }
43 
44 
45 
46 
47 
48 /**
49  * Design of balance class - serves as storage and writer.
50  * Equations themselves call methods of Balance that add/modify mass, source and flux
51  * of various quantities and generate output.
52  *
53  * One instance of Balance can handle several conservative quantities of the same type
54  * (e.g. mass of several substances or their phases).
55  *
56  * The mass, flux and source are calculated as follows:
57  *
58  * m(q,r) = ( M'(q) * solution + mv(q) )[r]
59  * f(q,r) = -( R' * ( F(q) * solution + fv(q) ) )[r]
60  * s(q,r) = ( S'(q) * solution + sv(q) )[r]
61  *
62  * where M' stands for matrix transpose,
63  *
64  * m(q,r)...mass of q-th substance in region r
65  * f(q,r)...incoming flux of q-th substance in region r
66  * s(q,r)...source of q-th substance in region r
67  *
68  * and
69  *
70  * M(q)...region_mass_matrix_ n_dofs x n_bulk_regions
71  * F(q)...be_flux_matrix_ n_boundary_edges x n_dofs
72  * S(q)...region_source_matrix_ n_dofs x n_bulk_regions
73  * SV(q)..region_source_rhs_ n_dofs x n_bulk_regions
74  * mv(q)..region_mass_vec_ n_bulk_regions
75  * fv(q)..be_flux_vec_ n_boundary_edges
76  * sv(q)..region_source_vec_ n_bulk_regions
77  * R......region_be_matrix_ n_boundary_edges x n_boundary_regions
78  *
79  * Remark: Matrix F and the vector fv are such that F*solution+fv produces _outcoming_ fluxes per boundary edge.
80  * However we write to output _incoming_ flux due to users' convention and consistently with input interface.
81  *
82  * Note that it holds:
83  *
84  * sv(q) = column sum of SV(q)
85  *
86  * Except for that, we also provide information on positive/negative flux and source:
87  *
88  * fp(q,r) = ( R' * EFP(q) )[r], EFP(q)[e] = max{ 0, ( F(q) * solution + fv(q) )[e] }
89  * fn(q,r) = ( R' * EFN(q) )[r], EFN(q)[e] = min{ 0, ( F(q) * solution + fv(q) )[e] }
90  * sp(q,r) = sum_{i in DOFS } max{ 0, ( S(q)[i,r] * solution[i] + SV(q)[i,r] ) }
91  * sn(q,r) = sum_{i in DOFS } min{ 0, ( S(q)[i,r] * solution[i] + SV(q)[i,r] ) }
92  *
93  * where
94  *
95  * fp(q,r)...positive (inward) flux of q-th quantity in region r
96  * fn(q,r)...negative (outward) flux of q-th quantity in region r
97  * sp(q,r)...positive source (spring) of q-th quantity in region r
98  * sn(q,r)...negative source (sink) of q-th quantity in region r
99  *
100  * Remark: The matrix R is needed only for calculation of signed fluxes.
101  * The reason is that to determine sign, we decompose flux to sum of local contributions
102  * per each boundary element and check its sign. It is not possible to decompose flux
103  * using shape functions, since their normal derivatives may have any sign.
104  *
105  *
106  *
107  * Output values (if not relevant, zero is supplied):
108  *
109  * #time bulk_region quantity 0 0 0 mass source source_in source_out 0 0 0
110  * #time boundary_region quantity flux flux_in flux_out 0 0 0 0 0 0 0
111  * #time ALL quantity flux flux_in flux_out mass source source_in source_out integrated_flux integrated_source error
112  *
113  * error = current_mass - (initial_mass + integrated_source - integrated_flux)
114  *
115  */
116 class Balance {
117 public:
118 
119  /**
120  * Class for storing internal data about conservative quantities handled by the Balance object.
121  * In the future we may store additional data or support definition of derived quantities
122  * (e.g. linear combinations of quantities).
123  */
124  class Quantity {
125  public:
126 
127  Quantity(const unsigned int index, const string &name)
128  : name_(name),
129  index_(index)
130  {}
131 
132  /// Name of quantity (for output).
133  string name_;
134 
135  /// Internal index within list of quantities.
136  const unsigned int index_;
137 
138  };
139 
140  /**
141  * Possible formats of output file.
142  */
144  {
145  legacy,//!< legacy
146  txt, //!< csv
147  gnuplot//!< gnuplot
148  };
149 
150  /// Main balance input record type.
151  static const Input::Type::Record & get_input_type();
152 
153  /// Input selection for file format.
154  static const Input::Type::Selection & get_format_selection_input_type();
155 
156  /// Set global variable to output balance files into YAML format (in addition to the table format).
157  static void set_yaml_output();
158 
159  /**
160  * Constructor.
161  * @param file_prefix Prefix of output file name.
162  * @param mesh Mesh.
163  */
164  Balance(const std::string &file_prefix, const Mesh *mesh);
165 
166  /**
167  * Destructor.
168  */
169  ~Balance();
170 
171 
172  /**
173  * Initialize the balance object according to the input.
174  * The balance output time marks are set according to the already existing output time marks of the same equation.
175  * So, this method must be called after Output::
176  *
177  * @param in_rec Input record of balance.
178  * @param tg TimeGovernor of the equation. We need just equation mark type.
179  *
180  */
181  void init_from_input(const Input::Record &in_rec, TimeGovernor &tg);
182 
183  /// Setter for units of conserved quantities.
184  void units(const UnitSI &unit);
185 
186  /// Getter for cumulative_.
187  inline bool cumulative() const { return cumulative_; }
188 
189 
190  /**
191  * Define a single conservative quantity.
192  * @param name Name of the quantity.
193  * @return Quantity's internal index.
194  */
195  unsigned int add_quantity(const string &name);
196 
197  /**
198  * Define a set of conservative quantities.
199  * @param names List of quantities' names.
200  * @return List of quantities' indices.
201  */
202  std::vector<unsigned int> add_quantities(const std::vector<string> &names);
203 
204  /**
205  * Allocates matrices and vectors for balance.
206  * @param n_loc_dofs Number of solution dofs on the local process.
207  * @param max_dofs_per_boundary Number of dofs contributing to one boundary edge.
208  */
209  void allocate(unsigned int n_loc_dofs,
210  unsigned int max_dofs_per_boundary);
211 
212 
213  /// Returns true if the current time step is marked for the balance output.
214  bool is_current();
215 
216  /**
217  * This method must be called before assembling the matrix for computing mass.
218  * It actually erases the matrix.
219  */
220  void start_mass_assembly(unsigned int quantity_idx);
221 
222  /// Variant of the start_mass_assembly() method for a set of quantities.
224  {
225  for (auto idx : q_idx_vec)
226  start_mass_assembly(idx);
227  }
228 
229  /**
230  * This method must be called before assembling the matrix and vector for fluxes.
231  * It actually erases the matrix and vector.
232  */
233  void start_flux_assembly(unsigned int quantity_idx);
234 
235  /// Variant of the start_flux_assembly() method for a set of quantities.
237  {
238  for (auto idx : q_idx_vec)
239  start_flux_assembly(idx);
240  }
241 
242  /**
243  * This method must be called before assembling the matrix and vectors for sources.
244  * It actually erases the matrix and vectors.
245  */
246  void start_source_assembly(unsigned int quantity_idx);
247 
248  /// Variant of the start_source_assembly() method for a set of quantities.
250  {
251  for (auto idx : q_idx_vec)
252  start_source_assembly(idx);
253  }
254 
255  /**
256  * Adds elements into matrix for computing mass.
257  * @param quantity_idx Index of quantity.
258  * @param region_idx Index of bulk region.
259  * @param dof_indices Dof indices to be added.
260  * @param values Values to be added.
261  */
262  void add_mass_matrix_values(unsigned int quantity_idx,
263  unsigned int region_idx,
264  const std::vector<LongIdx> &dof_indices,
265  const std::vector<double> &values);
266 
267  /**
268  * Adds elements into matrix for computing (outgoing) flux.
269  * @param quantity_idx Index of quantity.
270  * @param side Element side iterator.
271  * @param dof_indices Dof indices (to the solution vector) to be added.
272  * @param values Values to be added.
273  *
274  * TODO: Instead of SideIter and dof_indices, use DHCellSide,
275  * when it is available in all equations.
276  */
277  void add_flux_matrix_values(unsigned int quantity_idx,
278  SideIter side,
279  const std::vector<LongIdx> &dof_indices,
280  const std::vector<double> &values);
281 
282  /**
283  * Adds elements into matrix for computing source.
284  * @param quantity_idx Index of quantity.
285  * @param region_idx Index of bulk region.
286  * @param dof_indices Dof indices to be added.
287  * @param values Values to be added.
288  */
289  void add_source_matrix_values(unsigned int quantity_idx,
290  unsigned int region_idx,
291  const std::vector<LongIdx> &dof_indices,
292  const std::vector<double> &values);
293 
294  /**
295  * Adds element into vector for computing mass.
296  * @param quantity_idx Index of quantity.
297  * @param region_idx Index of bulk region.
298  * @param value Value to be added.
299  */
300  void add_mass_vec_value(unsigned int quantity_idx,
301  unsigned int region_idx,
302  double value);
303 
304  /**
305  * Adds element into vector for computing (outgoing) flux.
306  * @param quantity_idx Index of quantity.
307  * @param side Element side iterator.
308  * @param value Value to be added.
309  *
310  */
311  void add_flux_vec_value(unsigned int quantity_idx,
312  SideIter side,
313  double value);
314 
315  /**
316  * Adds elements into vector for computing source.
317  * @param quantity_idx Index of quantity.
318  * @param region_idx Index of bulk region.
319  * @param dof_indices Dof indices to be added.
320  * @param values Values to be added.
321  */
322  void add_source_vec_values(unsigned int quantity_idx,
323  unsigned int region_idx,
324  const std::vector<LongIdx> &dof_values,
325  const std::vector<double> &values);
326 
327  /// This method must be called after assembling the matrix for computing mass.
328  void finish_mass_assembly(unsigned int quantity_idx);
329 
330  /// Variant of the finish_mass_assembly() method for a set of quantities.
332  {
333  for (auto idx : q_idx_vec)
334  finish_mass_assembly(idx);
335  }
336 
337  /// This method must be called after assembling the matrix and vector for computing flux.
338  void finish_flux_assembly(unsigned int quantity_idx);
339 
340  /// Variant of the finish_flux_assembly() method for a set of quantities.
342  {
343  for (auto idx : q_idx_vec)
344  finish_flux_assembly(idx);
345  }
346 
347  /// This method must be called after assembling the matrix and vectors for computing source.
348  void finish_source_assembly(unsigned int quantity_idx);
349 
350  /// Variant of the finish_source_assembly() method for a set of quantities.
352  {
353  for (auto idx : q_idx_vec)
354  finish_source_assembly(idx);
355  }
356 
357  /**
358  * Updates cumulative quantities for balance.
359  * This method can be called in substeps even if no output is generated.
360  * It calculates the sum of source and sum of (incoming) flux over time interval.
361  * @param quantity_idx Index of quantity.
362  * @param solution Solution vector.
363  */
364  void calculate_cumulative(unsigned int quantity_idx,
365  const Vec &solution);
366 
367  /**
368  * Calculates actual mass and save it to given vector.
369  * @param quantity_idx Index of quantity.
370  * @param solution Solution vector.
371  * @param output_array Vector of output masses per region.
372  */
373  void calculate_mass(unsigned int quantity_idx,
374  const Vec &solution,
375  vector<double> &output_array);
376 
377  /**
378  * Calculates actual mass, incoming flux and source.
379  * @param quantity_idx Index of quantity.
380  * @param solution Solution vector.
381  */
382  void calculate_instant(unsigned int quantity_idx,
383  const Vec &solution);
384 
385  /**
386  * Adds provided values to the cumulative sources.
387  * @param quantity_idx Index of quantity.
388  * @param sources Sources per region.
389  * @param dt Actual time step.
390  */
391  void add_cumulative_source(unsigned int quantity_idx, double source);
392 
393  /// Perform output to file for given time instant.
394  void output();
395 
396 private:
397  /// Size of column in output (used if delimiter is space)
398  static const unsigned int output_column_width = 20;
399  /**
400  * Postponed allocation and initialization to allow calling setters in arbitrary order.
401  * In particular we need to perform adding of output times after the output time marks are set.
402  * On the other hand we need to read the input before we make the allocation.
403  *
404  * The initialization is done during the first call of any start_*_assembly method.
405  */
406  void lazy_initialize();
407 
408  /// Perform output in old format (for compatibility)
409  void output_legacy(double time);
410 
411  /// Perform output in csv format
412  void output_csv(double time, char delimiter, const std::string& comment_string, unsigned int repeat = 0);
413 
414  /// Perform output in yaml format
415  void output_yaml(double time);
416 
417  /// Return part of output represented by zero values. Count of zero values is given by cnt parameter.
418  std::string csv_zero_vals(unsigned int cnt, char delimiter);
419 
420  /// Print output header
421  void format_csv_output_header(char delimiter, const std::string& comment_string);
422 
423  /// Format string value of csv output. Wrap string into quotes and if delimiter is space, align text to column.
424  std::string format_csv_val(std::string val, char delimiter, bool initial = false);
425 
426  /// Format double value of csv output. If delimiter is space, align text to column.
427  std::string format_csv_val(double val, char delimiter, bool initial = false);
428 
429  /** Computes unique id of local boundary edge from local element index and element side index
430  *
431  * @param side is a side of locally owned element
432  */
434  { return 4*side->elem_idx() + side->side_idx();} // 4 is maximum of sides per element
435 
436  //**********************************************
437 
438  static bool do_yaml_output_;
439 
440  /// Allocation parameters. Set by the allocate method used in the lazy_initialize.
441  unsigned int n_loc_dofs_;
443 
444 
445  /// Save prefix passed in in constructor.
446  std::string file_prefix_;
447 
448  /// File path for output_ stream.
450 
451  /// Handle for file for output in given OutputFormat of balance and total fluxes over individual regions and region sets.
452  ofstream output_;
453 
454  // The same as the previous case, but for output in YAML format.
455  ofstream output_yaml_;
456 
457  /// Format of output file.
459 
460  /// Names of conserved quantities.
462 
463  const Mesh *mesh_;
464 
465  /// Units of conserved quantities.
467 
468 
469  /// Matrices for calculation of mass (n_dofs x n_bulk_regions).
471 
472  /// Matrices for calculation of flux (n_boundary_edges x n_dofs).
474 
475  /// Matrices for calculation of source (n_dofs x n_bulk_regions).
477 
478  /// Matrices for calculation of signed source (n_dofs x n_bulk_regions).
480 
481  /// Vectors for calculation of flux (n_boundary_edges).
483 
484  /// Vectors for calculation of mass (n_bulk_regions).
486 
487  /// Vectors for calculation of source (n_bulk_regions).
489 
490  /**
491  * Auxiliary matrix for transfer of quantities between boundary edges and regions
492  * (n_boundary_edges x n_boundary_regions).
493  */
495 
496  /// auxiliary vectors for summation of matrix columns
497  Vec ones_, ones_be_;
498 
499  /** Maps unique identifier of (local bulk element idx, side idx) returned by @p get_boundary_edge_uid(side)
500  * to local boundary edge.
501  * Example usage:
502  * be_id = be_id_map_[get_boundary_edge_uid(side)]
503  */
504  std::unordered_map<LongIdx, unsigned int> be_id_map_;
505 
506  /// Maps local boundary edge to its region boundary index.
508 
509  /// Offset for local part of vector of boundary edges.
511 
512 
513  // Vectors storing mass and balances of fluxes and volumes.
514  // substance, phase, region
522 
523  // Sums of the above vectors over phases and regions
532 
533  // time integrated quantities
538 
539  /// time of last calculated balance
540  double last_time_;
541 
542  /// TimeMark type for balance output of particular equation.
544 
545  /// TimeMark type for output of particular equation.
547 
548  /// true before calculating the mass at initial time, otherwise false
549  bool initial_;
550 
551  /// if true then cumulative balance is computed
553 
554  /// true before allocating necessary internal structures (Petsc matrices etc.)
556 
557  /// If the balance is on. Balance is off in the case of no balance output time marks.
559 
560  /// Add output time marks to balance output time marks.
562 
563 
564  /// MPI rank.
565  int rank_;
566 
567  /// hold count of line printed into output_
568  unsigned int output_line_counter_;
569 
570  /// marks whether YAML output has printed header
572 
573  /// Record for current balance
575 
577 
578 
579 };
580 
581 
582 
583 
584 
585 #endif // BALANCE_HH_
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
Definition: long_idx.hh:22
UnitSI units_
Units of conserved quantities.
Definition: balance.hh:466
std::vector< double > integrated_sources_
Definition: balance.hh:534
std::vector< double > sum_fluxes_out_
Definition: balance.hh:526
LongIdx get_boundary_edge_uid(SideIter side)
Definition: balance.hh:433
TimeMark::Type output_mark_type_
TimeMark type for output of particular equation.
Definition: balance.hh:546
TimeMark::Type balance_output_type_
TimeMark type for balance output of particular equation.
Definition: balance.hh:543
unsigned int side_idx() const
Definition: side_impl.hh:82
bool initial_
true before calculating the mass at initial time, otherwise false
Definition: balance.hh:549
Abstract linear system class.
Definition: balance.hh:37
void start_mass_assembly(std::vector< unsigned int > q_idx_vec)
Variant of the start_mass_assembly() method for a set of quantities.
Definition: balance.hh:223
std::vector< std::vector< double > > sources_in_
Definition: balance.hh:520
void finish_mass_assembly(std::vector< unsigned int > q_idx_vec)
Variant of the finish_mass_assembly() method for a set of quantities.
Definition: balance.hh:331
std::vector< std::vector< double > > fluxes_in_
Definition: balance.hh:516
std::vector< double > sum_fluxes_in_
Definition: balance.hh:525
std::vector< std::vector< double > > fluxes_out_
Definition: balance.hh:517
const TimeGovernor * time_
Definition: balance.hh:576
Mat * region_source_rhs_
Matrices for calculation of signed source (n_dofs x n_bulk_regions).
Definition: balance.hh:479
Definition: mesh.h:80
Input::Record input_record_
Record for current balance.
Definition: balance.hh:574
ofstream output_
Handle for file for output in given OutputFormat of balance and total fluxes over individual regions ...
Definition: balance.hh:452
Vec ones_be_
Definition: balance.hh:497
bool cumulative() const
Getter for cumulative_.
Definition: balance.hh:187
Mat region_be_matrix_
Definition: balance.hh:494
bool allocation_done_
true before allocating necessary internal structures (Petsc matrices etc.)
Definition: balance.hh:555
Basic time management functionality for unsteady (and steady) solvers (class Equation).
std::vector< double > sum_fluxes_
Definition: balance.hh:524
string name_
Name of quantity (for output).
Definition: balance.hh:133
bool balance_on_
If the balance is on. Balance is off in the case of no balance output time marks. ...
Definition: balance.hh:558
static constexpr bool value
Definition: json.hpp:87
std::vector< double > increment_sources_
Definition: balance.hh:537
const unsigned int index_
Internal index within list of quantities.
Definition: balance.hh:136
Vec * be_flux_vec_
Vectors for calculation of flux (n_boundary_edges).
Definition: balance.hh:482
std::vector< double > integrated_fluxes_
Definition: balance.hh:535
std::vector< Quantity > quantities_
Names of conserved quantities.
Definition: balance.hh:461
std::vector< std::vector< double > > sources_out_
Definition: balance.hh:521
Mat * be_flux_matrix_
Matrices for calculation of flux (n_boundary_edges x n_dofs).
Definition: balance.hh:473
double last_time_
time of last calculated balance
Definition: balance.hh:540
std::vector< std::vector< double > > fluxes_
Definition: balance.hh:515
void finish_flux_assembly(std::vector< unsigned int > q_idx_vec)
Variant of the finish_flux_assembly() method for a set of quantities.
Definition: balance.hh:341
int rank_
MPI rank.
Definition: balance.hh:565
Accessor to the data with type Type::Record.
Definition: accessors.hh:292
void start_flux_assembly(std::vector< unsigned int > q_idx_vec)
Variant of the start_flux_assembly() method for a set of quantities.
Definition: balance.hh:236
Mat * region_mass_matrix_
Matrices for calculation of mass (n_dofs x n_bulk_regions).
Definition: balance.hh:470
std::vector< std::vector< double > > sources_
Definition: balance.hh:519
std::vector< double > sum_sources_out_
Definition: balance.hh:530
unsigned int max_dofs_per_boundary_
Definition: balance.hh:442
bool cumulative_
if true then cumulative balance is computed
Definition: balance.hh:552
Mat * region_source_matrix_
Matrices for calculation of source (n_dofs x n_bulk_regions).
Definition: balance.hh:476
std::vector< double > increment_fluxes_
Definition: balance.hh:536
void finish_source_assembly(std::vector< unsigned int > q_idx_vec)
Variant of the finish_source_assembly() method for a set of quantities.
Definition: balance.hh:351
static bool do_yaml_output_
Definition: balance.hh:438
Dedicated class for storing path to input and output files.
Definition: file_path.hh:54
const Mesh * mesh_
Definition: balance.hh:463
std::vector< double > sum_sources_
Definition: balance.hh:528
std::vector< double > initial_mass_
Definition: balance.hh:531
Quantity(const unsigned int index, const string &name)
Definition: balance.hh:127
std::vector< unsigned int > be_regions_
Maps local boundary edge to its region boundary index.
Definition: balance.hh:507
ofstream output_yaml_
Definition: balance.hh:455
OutputFormat output_format_
Format of output file.
Definition: balance.hh:458
std::unordered_map< LongIdx, unsigned int > be_id_map_
Definition: balance.hh:504
int be_offset_
Offset for local part of vector of boundary edges.
Definition: balance.hh:510
std::vector< std::vector< double > > masses_
Definition: balance.hh:518
void start_source_assembly(std::vector< unsigned int > q_idx_vec)
Variant of the start_source_assembly() method for a set of quantities.
Definition: balance.hh:249
Vec * region_source_vec_
Vectors for calculation of source (n_bulk_regions).
Definition: balance.hh:488
unsigned int elem_idx() const
Definition: side_impl.hh:87
Record type proxy class.
Definition: type_record.hh:182
std::vector< double > sum_masses_
Definition: balance.hh:527
Vec * region_mass_vec_
Vectors for calculation of mass (n_bulk_regions).
Definition: balance.hh:485
unsigned int output_line_counter_
hold count of line printed into output_
Definition: balance.hh:568
bool add_output_times_
Add output time marks to balance output time marks.
Definition: balance.hh:561
Class for representation SI units of Fields.
Definition: unit_si.hh:40
unsigned int n_loc_dofs_
Allocation parameters. Set by the allocate method used in the lazy_initialize.
Definition: balance.hh:441
OutputFormat
Definition: balance.hh:143
Template for classes storing finite set of named values.
FilePath balance_output_file_
File path for output_ stream.
Definition: balance.hh:449
std::string file_prefix_
Save prefix passed in in constructor.
Definition: balance.hh:446
bool output_yaml_header_
marks whether YAML output has printed header
Definition: balance.hh:571
std::vector< double > sum_sources_in_
Definition: balance.hh:529