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