Flow123d  release_3.0.0-1075-gba2c39a
balance.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 balance.cc
15  * @ingroup transport
16  * @brief Mass balance
17  */
18 
19 #include <iostream>
20 #include <iomanip>
21 
22 #include "system/system.hh"
23 #include "system/sys_profiler.hh"
24 
25 #include <petscmat.h>
26 #include "mesh/side_impl.hh"
27 #include "mesh/mesh.h"
28 #include "mesh/long_idx.hh"
29 #include "mesh/accessors.hh"
30 #include "io/output_time_set.hh"
31 #include "coupling/balance.hh"
32 #include "tools/unit_si.hh"
33 #include "tools/time_governor.hh"
34 #include "la/distribution.hh"
35 
36 using namespace Input::Type;
37 
38 bool Balance::do_yaml_output_ = true;
39 
41  return Selection("Balance_output_format", "Format of output file for balance.")
42  .add_value(Balance::legacy, "legacy", "Legacy format used by previous program versions.")
43  .add_value(Balance::txt, "txt", "Excel format with tab delimiter.")
44  .add_value(Balance::gnuplot, "gnuplot", "Format compatible with GnuPlot datafile with fixed column width.")
45  .close();
46 }
47 
49  return Record("Balance", "Balance of a conservative quantity, boundary fluxes and sources.")
50  .declare_key("times", OutputTimeSet::get_input_type(), Default("[]"), "" )
51  .declare_key("add_output_times", Bool(), Default("true"), "Add all output times of the balanced equation to the balance output times set. "
52  "Note that this is not the time set of the output stream.")
53  //.declare_key("balance_on", Bool(), Default("true"), "Balance is computed if the value is true.")
54  .declare_key("format", Balance::get_format_selection_input_type(), Default("\"txt\""), "Format of output file.")
55  .declare_key("cumulative", Bool(), Default("false"), "Compute cumulative balance over time. "
56  "If true, then balance is calculated at each computational time step, which can slow down the program.")
57  .declare_key("file", FileName::output(), Default::read_time("File name generated from the balanced quantity: <quantity_name>_balance.*"), "File name for output of balance.")
58  .close();
59 }
60 
63 }
64 
65 /*
66 std::shared_ptr<Balance> Balance::make_balance(
67  const std::string &file_prefix,
68  const Mesh *mesh,
69  const Input::Record &in_rec,
70  TimeGovernor &tg)
71 {
72  auto ptr = make_shared<Balance>(file_prefix, mesh, in_rec, tg);
73  auto &marks = TimeGovernor::marks();
74  auto balance_output_type = tg.equation_mark_type() | TimeGovernor::marks().type_balance_output();
75  if (marks.begin(balance_output_type) == marks.end(balance_output_type) ) {
76  // no balance output time => force balance off
77  ptr.reset();
78  }
79  return ptr;
80 }*/
81 
82 
83 
84 Balance::Balance(const std::string &file_prefix, const Mesh *mesh)
85  : file_prefix_(file_prefix),
86  mesh_(mesh),
87  last_time_(),
88  initial_(true),
89  allocation_done_(false),
90  balance_on_(true),
91  output_line_counter_(0),
92  output_yaml_header_(false)
93 
94 {
95  MPI_Comm_rank(PETSC_COMM_WORLD, &rank_);
97 }
98 
99 
100 
102 {
103  if (rank_ == 0) {
104  output_.close();
105  if (do_yaml_output_) output_yaml_.close();
106  }
107  if (! allocation_done_) return;
108 
109  for (unsigned int c=0; c<quantities_.size(); ++c)
110  {
111  chkerr(MatDestroy(&(region_mass_matrix_[c])));
112  chkerr(MatDestroy(&(be_flux_matrix_[c])));
113  chkerr(MatDestroy(&(region_source_matrix_[c])));
114  chkerr(MatDestroy(&(region_source_rhs_[c])));
115  chkerr(VecDestroy(&(be_flux_vec_[c])));
116  chkerr(VecDestroy(&(region_mass_vec_[c])));
117  }
118  delete[] region_mass_matrix_;
119  delete[] be_flux_matrix_;
120  delete[] be_flux_vec_;
121  delete[] region_source_matrix_;
122  delete[] region_source_rhs_;
123  delete[] region_mass_vec_;
124 }
125 
126 
128  const Input::Record &in_rec,
129  TimeGovernor &tg)
130 {
132 
133  time_ = &tg;
134 
135  auto &marks = TimeGovernor::marks();
136 
137  output_mark_type_ = tg.equation_mark_type() | marks.type_output(),
138  balance_output_type_ = tg.equation_fixed_mark_type() | marks.type_balance_output();
139 
140  cumulative_ = in_rec.val<bool>("cumulative");
141  output_format_ = in_rec.val<OutputFormat>("format");
142 
143  OutputTimeSet time_set;
144  time_set.read_from_input( in_rec.val<Input::Array>("times"), tg, balance_output_type_);
145  add_output_times_ = in_rec.val<bool>("add_output_times");
146 
147  input_record_ = in_rec;
148 
149 }
150 
151 
152 void Balance::units(const UnitSI &unit)
153 {
155 
156  units_ = unit;
157  units_.undef(false);
158 }
159 
160 unsigned int Balance::add_quantity(const string &name)
161 {
163 
164  Quantity q(quantities_.size(), name);
165  quantities_.push_back(q);
166 
167  return q.index_;
168 }
169 
170 
172 {
173  vector<unsigned int> indices;
174  for (auto name : names)
175  indices.push_back(add_quantity(name));
176  return indices;
177 }
178 
179 
180 void Balance::allocate(unsigned int n_loc_dofs,
181  unsigned int max_dofs_per_boundary)
182 {
184  n_loc_dofs_ = n_loc_dofs;
185  max_dofs_per_boundary_ = max_dofs_per_boundary;
186 }
187 
189 {
190  if (allocation_done_) return;
191 
192  auto &marks = TimeGovernor::marks();
193  if (add_output_times_)
194  marks.add_to_type_all(output_mark_type_, balance_output_type_);
195  // if there are no balance marks turn balance off
196  if (marks.begin(balance_output_type_) == marks.end(balance_output_type_) )
197  {
198  balance_on_ = false;
199  cumulative_ = false;
200  return;
201  }
202 
203  // Max. number of regions to which a single dof can contribute.
204  // TODO: estimate or compute this number directly (from mesh or dof handler).
205  const int n_bulk_regs_per_dof = min(10, (int)mesh_->region_db().bulk_size());
206  const unsigned int n_quant = quantities_.size();
207  const unsigned int n_bdr_reg = mesh_->region_db().boundary_size();
208  const unsigned int n_blk_reg = mesh_->region_db().bulk_size();
209 
210 
211  // construct vector of regions of boundary edges
212  for (unsigned int loc_el = 0; loc_el < mesh_->get_el_ds()->lsize(); loc_el++)
213  {
215  if (elm->boundary_idx_ != nullptr)
216  {
217  for(unsigned int si=0; si<elm->n_sides(); si++)
218  {
219  Boundary *b = elm.side(si)->cond();
220  if (b != nullptr)
221  be_regions_.push_back(b->region().boundary_idx());
222  }
223  }
224  }
225 
226 
227 
228  fluxes_ .resize(n_quant, vector<double>(n_bdr_reg, 0));
229  fluxes_in_ .resize(n_quant, vector<double>(n_bdr_reg, 0));
230  fluxes_out_.resize(n_quant, vector<double>(n_bdr_reg, 0));
231 
232  masses_ .resize(n_quant, vector<double>(n_blk_reg, 0));
233  sources_in_ .resize(n_quant, vector<double>(n_blk_reg, 0));
234  sources_out_.resize(n_quant, vector<double>(n_blk_reg, 0));
235 
236  sum_fluxes_ .resize(n_quant, 0);
237  sum_fluxes_in_ .resize(n_quant, 0);
238  sum_fluxes_out_ .resize(n_quant, 0);
239  sum_masses_ .resize(n_quant, 0);
240  sum_sources_ .resize(n_quant, 0);
241  sum_sources_in_ .resize(n_quant, 0);
242  sum_sources_out_.resize(n_quant, 0);
243 
244  if (cumulative_)
245  {
246  initial_mass_ .resize(n_quant, 0);
247  integrated_fluxes_ .resize(n_quant, 0);
248  integrated_sources_.resize(n_quant, 0);
249  increment_sources_.resize(n_quant, 0);
250  increment_fluxes_.resize(n_quant, 0);
251  }
252 
253 
254 
255  region_mass_matrix_ = new Mat[n_quant];
256  be_flux_matrix_ = new Mat[n_quant];
257  region_source_matrix_ = new Mat[n_quant];
258  region_source_rhs_ = new Mat[n_quant];
259  region_mass_vec_ = new Vec[n_quant];
260  be_flux_vec_ = new Vec[n_quant];
261 
262  for (unsigned int c=0; c<n_quant; ++c)
263  {
264  chkerr(MatCreateAIJ(PETSC_COMM_WORLD,
265  n_loc_dofs_,
266  (rank_==0)?mesh_->region_db().bulk_size():0,
267  PETSC_DECIDE,
268  PETSC_DECIDE,
269  (rank_==0)?n_bulk_regs_per_dof:0,
270  0,
271  (rank_==0)?0:n_bulk_regs_per_dof,
272  0,
273  &(region_mass_matrix_[c])));
274 
275  chkerr(MatCreateSeqAIJ(PETSC_COMM_SELF,
276  n_loc_dofs_,
278  n_bulk_regs_per_dof,
279  NULL,
280  &(region_source_matrix_[c])));
281 
282  chkerr(MatCreateSeqAIJ(PETSC_COMM_SELF,
283  n_loc_dofs_,
285  n_bulk_regs_per_dof,
286  NULL,
287  &(region_source_rhs_[c])));
288 
289  chkerr(MatCreateAIJ(PETSC_COMM_WORLD,
290  be_regions_.size(), // n local rows, number of local boundary edges
291  n_loc_dofs_, // n local cols (local rows of multiplying vector)
292  PETSC_DECIDE, // n global rows
293  PETSC_DECIDE, // n global cols
294  max_dofs_per_boundary_, // allocation, local poriton
295  0,
296  0,
297  0,
298  &(be_flux_matrix_[c])));
299 
300  chkerr(VecCreateMPI(PETSC_COMM_WORLD,
301  (rank_==0)?mesh_->region_db().bulk_size():0,
302  PETSC_DECIDE,
303  &(region_mass_vec_[c])));
304 
305  chkerr(VecCreateMPI(PETSC_COMM_WORLD,
306  be_regions_.size(),
307  PETSC_DECIDE,
308  &(be_flux_vec_[c])));
309  }
310 
311  // set be_offset_, used in add_flux_matrix_values()
312  chkerr(VecGetOwnershipRange(be_flux_vec_[0], &be_offset_, NULL));
313 
314  if (rank_ == 0) {
315  // set default value by output_format_
316  std::string default_file_name;
317  switch (output_format_)
318  {
319  case txt:
320  default_file_name = file_prefix_ + "_balance.txt";
321  break;
322  case gnuplot:
323  default_file_name = file_prefix_ + "_balance.dat";
324  break;
325  case legacy:
326  default_file_name = file_prefix_ + "_balance.txt";
327  break;
328  }
329 
331  try {
333  } INPUT_CATCH(FilePath::ExcFileOpen, FilePath::EI_Address_String, input_record_)
334 
335 
336  // set file name of YAML output
337  if (do_yaml_output_) {
338  string yaml_file_name = file_prefix_ + "_balance.yaml";
340  }
341  }
342 
343  allocation_done_ = true;
344 }
345 
346 
347 
349 {
350  if (! balance_on_) return false;
351 
352  auto &marks = TimeGovernor::marks();
353  bool res = marks.current(time_->step(), balance_output_type_) != marks.end(balance_output_type_);
354 
355  //cout << "flag: " << res << " time: " << step.end() << " type:" << hex << balance_output_type_ << endl;
356  return res;
357 }
358 
359 void Balance::start_mass_assembly(unsigned int quantity_idx)
360 {
361  lazy_initialize();
362  if (! balance_on_) return;
363  chkerr(MatZeroEntries(region_mass_matrix_[quantity_idx]));
364  chkerr(VecZeroEntries(region_mass_vec_[quantity_idx]));
365 }
366 
367 
368 void Balance::start_flux_assembly(unsigned int quantity_idx)
369 {
370  lazy_initialize();
371  if (! balance_on_) return;
372  chkerr(MatZeroEntries(be_flux_matrix_[quantity_idx]));
373  chkerr(VecZeroEntries(be_flux_vec_[quantity_idx]));
374 }
375 
376 
377 void Balance::start_source_assembly(unsigned int quantity_idx)
378 {
379  lazy_initialize();
380  if (! balance_on_) return;
381  chkerr(MatZeroEntries(region_source_matrix_[quantity_idx]));
382  chkerr(MatZeroEntries(region_source_rhs_[quantity_idx]));
383 }
384 
385 
386 void Balance::finish_mass_assembly(unsigned int quantity_idx)
387 {
389  if (! balance_on_) return;
390 
391  chkerr(MatAssemblyBegin(region_mass_matrix_[quantity_idx], MAT_FINAL_ASSEMBLY));
392  chkerr(MatAssemblyEnd(region_mass_matrix_[quantity_idx], MAT_FINAL_ASSEMBLY));
393  chkerr(VecAssemblyBegin(region_mass_vec_[quantity_idx]));
394  chkerr(VecAssemblyEnd(region_mass_vec_[quantity_idx]));
395 }
396 
397 void Balance::finish_flux_assembly(unsigned int quantity_idx)
398 {
400  if (! balance_on_) return;
401 
402  chkerr(MatAssemblyBegin(be_flux_matrix_[quantity_idx], MAT_FINAL_ASSEMBLY));
403  chkerr(MatAssemblyEnd(be_flux_matrix_[quantity_idx], MAT_FINAL_ASSEMBLY));
404  chkerr(VecAssemblyBegin(be_flux_vec_[quantity_idx]));
405  chkerr(VecAssemblyEnd(be_flux_vec_[quantity_idx]));
406 }
407 
408 void Balance::finish_source_assembly(unsigned int quantity_idx)
409 {
411  if (! balance_on_) return;
412 
413  chkerr(MatAssemblyBegin(region_source_matrix_[quantity_idx], MAT_FINAL_ASSEMBLY));
414  chkerr(MatAssemblyEnd(region_source_matrix_[quantity_idx], MAT_FINAL_ASSEMBLY));
415  chkerr(MatAssemblyBegin(region_source_rhs_[quantity_idx], MAT_FINAL_ASSEMBLY));
416  chkerr(MatAssemblyEnd(region_source_rhs_[quantity_idx], MAT_FINAL_ASSEMBLY));
417 }
418 
419 
420 
421 
422 void Balance::add_mass_matrix_values(unsigned int quantity_idx,
423  unsigned int region_idx,
424  const vector<LongIdx> &dof_indices,
425  const vector<double> &values)
426 {
428  if (! balance_on_) return;
429 
430  PetscInt reg_array[1] = { (int)region_idx };
431 
432  chkerr_assert(MatSetValues(region_mass_matrix_[quantity_idx],
433  dof_indices.size(),
434  &(dof_indices[0]),
435  1,
436  reg_array,
437  &(values[0]),
438  ADD_VALUES));
439 }
440 
441 
442 void Balance::add_flux_matrix_values(unsigned int quantity_idx,
443  unsigned int boundary_idx,
444  const vector<LongIdx> &dof_indices,
445  const vector<double> &values)
446 {
448  if (! balance_on_) return;
449 
450  PetscInt elem_array[1] = { int(be_offset_+boundary_idx) };
451  chkerr_assert(MatSetValues(be_flux_matrix_[quantity_idx],
452  1,
453  elem_array,
454  dof_indices.size(),
455  &(dof_indices[0]),
456  &(values[0]),
457  ADD_VALUES));
458 }
459 
460 void Balance::add_source_values(unsigned int quantity_idx,
461  unsigned int region_idx,
462  const vector<LongIdx> &loc_dof_indices,
463  const vector<double> &mat_values,
464  const vector<double> &vec_values)
465 {
467  if (! balance_on_) return;
468 
469  PetscInt reg_array[1] = { (int)region_idx };
470 
471  chkerr_assert(MatSetValues(region_source_matrix_[quantity_idx],
472  loc_dof_indices.size(),
473  &(loc_dof_indices[0]),
474  1,
475  reg_array,
476  &(mat_values[0]),
477  ADD_VALUES));
478 
479  chkerr_assert(MatSetValues(region_source_rhs_[quantity_idx],
480  loc_dof_indices.size(),
481  &(loc_dof_indices[0]),
482  1,
483  reg_array,
484  &(vec_values[0]),
485  ADD_VALUES));
486 }
487 
488 void Balance::add_mass_vec_value(unsigned int quantity_idx,
489  unsigned int region_idx,
490  double value)
491 {
492  chkerr_assert(VecSetValue(region_mass_vec_[quantity_idx],
493  region_idx,
494  value,
495  ADD_VALUES));
496 }
497 
498 
499 void Balance::add_flux_vec_value(unsigned int quantity_idx,
500  unsigned int boundary_idx,
501  double value)
502 {
504  if (! balance_on_) return;
505 
506  chkerr_assert(VecSetValue(be_flux_vec_[quantity_idx],
507  be_offset_+boundary_idx,
508  value,
509  ADD_VALUES));
510 }
511 
512 
513 void Balance::add_cumulative_source(unsigned int quantity_idx, double source)
514 {
516  if (!cumulative_) return;
517 
518  if (rank_ == 0)
519  increment_sources_[quantity_idx] += source;
520 }
521 
522 
523 void Balance::calculate_cumulative(unsigned int quantity_idx,
524  const Vec &solution)
525 {
527  if (!cumulative_) return;
528  if (time_->tlevel() <= 0) return;
529 
530  // sources
531  double temp_source = 0;
532  int lsize, n_cols_mat, n_cols_rhs;
533  //const int *cols;
534  const double *vals_mat, *vals_rhs, *sol_array;
535  chkerr(VecGetLocalSize(solution, &lsize));
536  chkerr(VecGetArrayRead(solution, &sol_array));
537 
538  // computes transpose multiplication and sums region_source_rhs_ over dofs
539  // resulting in a vector of sources for each region
540  // transpose(region_source_matrix_) * solution + region_source_rhs_*ones(n_blk_reg)
541  // the region vector is then summed up to temp_source
542  for (int i=0; i<lsize; ++i){
543  chkerr(MatGetRow(region_source_matrix_[quantity_idx], i, &n_cols_mat, NULL, &vals_mat));
544  chkerr(MatGetRow(region_source_rhs_[quantity_idx], i, &n_cols_rhs, NULL, &vals_rhs));
545 
546  ASSERT_DBG(n_cols_mat == n_cols_rhs);
547 
548  for (int j=0; j<n_cols_mat; ++j)
549  temp_source += vals_mat[j]*sol_array[i] + vals_rhs[j];
550 
551  chkerr(MatRestoreRow(region_source_matrix_[quantity_idx], i, &n_cols_mat, NULL, &vals_mat));
552  chkerr(MatRestoreRow(region_source_rhs_[quantity_idx], i, &n_cols_rhs, NULL, &vals_rhs));
553  }
554  chkerr(VecRestoreArrayRead(solution, &sol_array));
555 
556  increment_sources_[quantity_idx] += temp_source*time_->dt();
557 
558 
559  // fluxes
560  Vec temp;
561  chkerr(VecCreateMPI(PETSC_COMM_WORLD,
562  be_regions_.size(),
563  PETSC_DECIDE,
564  &temp));
565 
566  chkerr(MatMultAdd(be_flux_matrix_[quantity_idx], solution, be_flux_vec_[quantity_idx], temp));
567 
568  double sum_fluxes;
569  chkerr(VecSum(temp, &sum_fluxes));
570  chkerr(VecDestroy(&temp));
571 
572  if (rank_ == 0)
573  // sum fluxes in one step
574  // Since internally we keep outgoing fluxes, we change sign
575  // to write to output _incoming_ fluxes.
576  increment_fluxes_[quantity_idx] += -1.0 * sum_fluxes*time_->dt();
577 }
578 
579 
580 void Balance::calculate_mass(unsigned int quantity_idx,
581  const Vec &solution,
582  vector<double> &output_array)
583 {
585  if (! balance_on_) return;
586 
587  Vec bulk_vec;
588 
589  chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD,
590  1,
591  (rank_==0)?mesh_->region_db().bulk_size():0,
592  PETSC_DECIDE,
593  &(output_array[0]),
594  &bulk_vec));
595 
596  // compute mass on regions: M'.u
597  chkerr(VecZeroEntries(bulk_vec));
598  chkerr(MatMultTransposeAdd(region_mass_matrix_[quantity_idx],
599  solution,
600  region_mass_vec_[quantity_idx],
601  bulk_vec));
602  chkerr(VecDestroy(&bulk_vec));
603 }
604 
605 void Balance::calculate_instant(unsigned int quantity_idx, const Vec& solution)
606 {
607  if ( !is_current() ) return;
608 
609  calculate_mass(quantity_idx, solution, masses_[quantity_idx]);
610 
611  // compute positive/negative sources
612  for (unsigned int r=0; r<mesh_->region_db().bulk_size(); ++r)
613  {
614  sources_in_[quantity_idx][r] = 0;
615  sources_out_[quantity_idx][r] = 0;
616  }
617 
618  int lsize, n_cols_mat, n_cols_rhs;
619  const int *cols; // the columns must be same - matrices created and filled in the same way
620  const double *vals_mat, *vals_rhs, *sol_array;
621  chkerr(VecGetLocalSize(solution, &lsize));
622  chkerr(VecGetArrayRead(solution, &sol_array));
623 
624  // computes transpose multiplication and sums region_source_rhs_ over dofs
625  // resulting in a vector of sources for each region, one positive, one negative
626  // transpose(region_source_matrix_) * solution + region_source_rhs_*ones(n_blk_reg)
627  for (int i=0; i<lsize; ++i)
628  {
629  int row = i;
630  chkerr(MatGetRow(region_source_matrix_[quantity_idx], row, &n_cols_mat, &cols, &vals_mat));
631  chkerr(MatGetRow(region_source_rhs_[quantity_idx], row, &n_cols_rhs, NULL, &vals_rhs));
632 
633  ASSERT_DBG(n_cols_mat == n_cols_rhs);
634 
635  for (int j=0; j<n_cols_mat; ++j)
636  {
637  int col = cols[j];
638 
639  double f = vals_mat[j]*sol_array[i] + vals_rhs[j];
640  if (f > 0) sources_in_[quantity_idx][col] += f;
641  else sources_out_[quantity_idx][col] += f;
642  }
643  }
644  chkerr(VecRestoreArrayRead(solution, &sol_array));
645 
646  // calculate flux
647  Vec temp;
648  chkerr(VecCreateMPI(PETSC_COMM_WORLD,
649  be_regions_.size(),
650  PETSC_DECIDE,
651  &temp));
652 
653  chkerr(MatMultAdd(be_flux_matrix_[quantity_idx], solution, be_flux_vec_[quantity_idx], temp));
654  // Since internally we keep outgoing fluxes, we change sign
655  // to write to output _incoming_ fluxes.
656  chkerr(VecScale(temp, -1));
657 
658  // compute positive/negative fluxes
659  fluxes_in_[quantity_idx].assign(mesh_->region_db().boundary_size(), 0);
660  fluxes_out_[quantity_idx].assign(mesh_->region_db().boundary_size(), 0);
661  const double *flux_array;
662 // int lsize;
663  chkerr(VecGetArrayRead(temp, &flux_array));
664  chkerr(VecGetLocalSize(temp, &lsize));
665  for (int e=0; e<lsize; ++e)
666  {
667  if (flux_array[e] < 0)
668  fluxes_out_[quantity_idx][be_regions_[e]] += flux_array[e];
669  else
670  fluxes_in_[quantity_idx][be_regions_[e]] += flux_array[e];
671  }
672  chkerr(VecRestoreArrayRead(temp, &flux_array));
673  chkerr(VecDestroy(&temp));
674 }
675 
676 
677 
678 
679 
681 {
683  if (! balance_on_) return;
684  if (! is_current() ) return;
685 
686  // gather results from processes and sum them up
687  const unsigned int n_quant = quantities_.size();
688  const unsigned int n_blk_reg = mesh_->region_db().bulk_size();
689  const unsigned int n_bdr_reg = mesh_->region_db().boundary_size();
690  const int buf_size = n_quant*2*n_blk_reg + n_quant*2*n_bdr_reg + n_quant;
691  double sendbuffer[buf_size], recvbuffer[buf_size];
692  for (unsigned int qi=0; qi<n_quant; qi++)
693  {
694  for (unsigned int ri=0; ri<n_blk_reg; ri++)
695  {
696  sendbuffer[qi*2*n_blk_reg + + ri] = sources_in_[qi][ri];
697  sendbuffer[qi*2*n_blk_reg + n_blk_reg + ri] = sources_out_[qi][ri];
698  }
699  for (unsigned int ri=0; ri<n_bdr_reg; ri++)
700  {
701  sendbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + + ri] = fluxes_in_[qi][ri];
702  sendbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + n_bdr_reg + ri] = fluxes_out_[qi][ri];
703  }
704  if (cumulative_)
705  {
706  sendbuffer[n_quant*2*n_blk_reg + n_quant*2*n_bdr_reg + qi] = increment_sources_[qi];
707  }
708  }
709 
710  MPI_Reduce(&sendbuffer,recvbuffer,buf_size,MPI_DOUBLE,MPI_SUM,0,PETSC_COMM_WORLD);
711  // for other than 0th process update last_time and finish,
712  // on process #0 sum balances over all regions and calculate
713  // cumulative balance over time.
714  if (rank_ == 0)
715  {
716  // update balance vectors
717  for (unsigned int qi=0; qi<n_quant; qi++)
718  {
719  for (unsigned int ri=0; ri<n_blk_reg; ri++)
720  {
721  sources_in_[qi][ri] = recvbuffer[qi*2*n_blk_reg + + ri];
722  sources_out_[qi][ri] = recvbuffer[qi*2*n_blk_reg + n_blk_reg + ri];
723  }
724  for (unsigned int ri=0; ri<n_bdr_reg; ri++)
725  {
726  fluxes_in_[qi][ri] = recvbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + + ri];
727  fluxes_out_[qi][ri] = recvbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + n_bdr_reg + ri];
728  }
729  if (cumulative_)
730  {
731  increment_sources_[qi] = recvbuffer[n_quant*2*n_blk_reg + n_quant*2*n_bdr_reg + qi];
732  }
733  }
734  }
735 
736 
737  // The convention for input/output of fluxes is that positive means inward.
738  // Therefore in the following code we switch sign of fluxes.
739  if (rank_ == 0)
740  {
741  sum_fluxes_.assign(n_quant, 0);
742  sum_fluxes_in_.assign(n_quant, 0);
743  sum_fluxes_out_.assign(n_quant, 0);
744  sum_masses_.assign(n_quant, 0);
745  sum_sources_.assign(n_quant, 0);
746  sum_sources_in_.assign(n_quant, 0);
747  sum_sources_out_.assign(n_quant, 0);
748 
749  // sum all boundary fluxes
750  const RegionSet & b_set = mesh_->region_db().get_region_set(".BOUNDARY");
751  for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
752  {
753  for (unsigned int qi=0; qi<n_quant; qi++)
754  {
755  sum_fluxes_[qi] += fluxes_in_ [qi][reg->boundary_idx()] + fluxes_out_[qi][reg->boundary_idx()];
756  sum_fluxes_in_[qi] += fluxes_in_ [qi][reg->boundary_idx()];
757  sum_fluxes_out_[qi] += fluxes_out_[qi][reg->boundary_idx()];
758  }
759  }
760 
761  // sum all volume sources
762  const RegionSet & bulk_set = mesh_->region_db().get_region_set("BULK");
763  for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
764  {
765  for (unsigned int qi=0; qi<n_quant; qi++)
766  {
767  sum_masses_[qi] += masses_[qi][reg->bulk_idx()];
768  sum_sources_[qi] += sources_in_[qi][reg->bulk_idx()] + sources_out_[qi][reg->bulk_idx()];
769  sum_sources_in_[qi] += sources_in_[qi][reg->bulk_idx()];
770  sum_sources_out_[qi] += sources_out_[qi][reg->bulk_idx()];
771  }
772  }
773 
774  // cumulative balance over time
775  if (cumulative_)
776  {
777  // save initial time and mass
778  if (initial_)
779  {
781  for (unsigned int qi=0; qi<n_quant; qi++)
782  initial_mass_[qi] = sum_masses_[qi];
783  initial_ = false;
784  }
785 
786  for (unsigned int qi=0; qi<n_quant; qi++)
787  {
790  }
791  }
792  }
793 
794  last_time_ = time_->t();
795 
796 
797  // perform actual output
798  switch (output_format_)
799  {
800  case txt:
801  output_csv(time_->t(), '\t', "");
802  break;
803  case gnuplot:
804  output_csv(time_->t(), ' ', "#", 30);
805  break;
806  case legacy:
807  output_legacy(time_->t());
808  break;
809  }
810  // output in YAML format
811  output_yaml(time_->t());
812 
813  if (rank_ == 0)
814  {
815  sum_fluxes_.assign(n_quant, 0);
816  sum_sources_.assign(n_quant, 0);
817  increment_fluxes_.assign(n_quant, 0);
818  }
819  increment_sources_.assign(n_quant, 0);
820 }
821 
822 
823 void Balance::output_legacy(double time)
824 {
825  // write output only on process #0
826  if (rank_ != 0) return;
827 
828  const unsigned int n_quant = quantities_.size();
829 
830  // print the head of mass balance file
831  unsigned int c = 6; //column number without label
832  unsigned int w = 14; //column width
833  unsigned int wl = 2*(w-5)+7; //label column width
834  string bc_head_format = "# %-*s%-*s%-*s%-*s%-*s%-*s\n",
835  bc_format = "%*s%-*d%-*s%-*s%-*g%-*g%-*g\n",
836  bc_total_format = "# %-*s%-*s%-*g%-*g%-*g\n";
837 
838  output_ << "# " << setw((w*c+wl-14)/2) << setfill('-') << "--"
839  << " MASS BALANCE "
840  << setw((w*c+wl-14)/2) << setfill('-') << "" << endl
841  << "# Time: " << (time / time_->get_coef()) << "[" << time_->get_unit_string() << "]\n\n\n";
842 
843  // header for table of boundary fluxes
844  output_ << "# Mass flux through boundary [M/T]:\n# "
845  << setiosflags(ios::left) << setfill(' ')
846  << setw(w) << "[boundary_id]"
847  << setw(wl) << "[label]"
848  << setw(w) << "[substance]"
849  << setw(w) << "[total flux]"
850  << setw(w) << "[outward flux]"
851  << setw(w) << "[inward flux]"
852  << endl;
853 
854  // draw long line
855  output_ << "# " << setw(w*c+wl) << setfill('-') << "" << setfill(' ') << endl;
856 
857  // print mass fluxes over boundaries
858  const RegionSet & b_set = mesh_->region_db().get_region_set(".BOUNDARY");
859  for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg) {
860  for (unsigned int qi=0; qi<n_quant; qi++) {
861  output_ << setw(2) << ""
862  << setw(w) << (int)reg->id()
863  << setw(wl) << reg->label().c_str()
864  << setw(w) << quantities_[qi].name_.c_str()
865  << setw(w) << fluxes_in_[qi][reg->boundary_idx()] + fluxes_out_[qi][reg->boundary_idx()]
866  << setw(w) << fluxes_out_[qi][reg->boundary_idx()]
867  << setw(w) << fluxes_in_[qi][reg->boundary_idx()]
868  << endl;
869  }
870  }
871 
872  // draw long line
873  output_ << "# " << setw(w*c+wl) << setfill('-') << "" << setfill(' ') << endl;
874 
875  // total boundary balance
876  for (unsigned int qi=0; qi<n_quant; qi++)
877  output_ << "# " << setiosflags(ios::left)
878  << setw(w+wl) << "Total mass flux of substance [M/T]"
879  << setw(w) << quantities_[qi].name_.c_str()
880  << setw(w) << sum_fluxes_[qi]
881  << setw(w) << sum_fluxes_out_[qi]
882  << setw(w) << sum_fluxes_in_[qi]
883  << endl;
884  output_ << "\n\n";
885 
886 
887  // header for table of volume sources and masses
888  string src_head_format = "# %-*s%-*s%-*s%-*s%-*s\n",
889  src_format = "%*s%-*d%-*s%-*s%-*g%-*g\n",
890  src_total_format = "# %-*s%-*s%-*g%-*g\n";
891  output_ << "# Mass [M] and sources [M/T] on regions:\n"
892  << "# " << setiosflags(ios::left)
893  << setw(w) << "[region_id]"
894  << setw(wl) << "[label]"
895  << setw(w) << "[substance]"
896  << setw(w) << "[total_mass]"
897  << setw(w) << "[total_source]"
898  << endl;
899 
900  // draw long line
901  output_ << "# " << setw(w*c+wl) << setfill('-') << "" << setfill(' ') << endl;
902 
903  // print balance of volume sources and masses
904  const RegionSet & bulk_set = mesh_->region_db().get_region_set("BULK");
905  for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
906  {
907  for (unsigned int qi=0; qi<n_quant; qi++)
908  {
909  output_ << setw(2) << ""
910  << setw(w) << (int)reg->id()
911  << setw(wl) << reg->label().c_str()
912  << setw(w) << quantities_[qi].name_.c_str()
913  << setw(w) << masses_[qi][reg->bulk_idx()]
914  << setw(w) << sources_in_[qi][reg->bulk_idx()] + sources_out_[qi][reg->bulk_idx()]
915  << endl;
916  }
917  }
918 
919  // draw long line
920  output_ << "# " << setw(w*c+wl) << setfill('-') << "" << setfill(' ') << endl;
921 
922  // total sources balance
923  for (unsigned int qi=0; qi<n_quant; qi++)
924  output_ << "# " << setiosflags(ios::left) << setw(w+wl) << "Total mass [M] and sources [M/T]"
925  << setw(w) << quantities_[qi].name_.c_str()
926  << setw(w) << sum_masses_[qi]
927  << setw(w) << sum_sources_[qi]
928  << endl;
929 
930  if (cumulative_)
931  {
932  // Print cumulative sources
933  output_ << "\n\n# Cumulative mass balance on time interval ["
934  << setiosflags(ios::left) << time_->init_time() << ","
935  << setiosflags(ios::left) << time << "]\n"
936  << "# Initial mass [M] + sources integrated over time [M] - flux integrated over time [M] = current mass [M]\n"
937  << "# " << setiosflags(ios::left)
938  << setw(w) << "[substance]"
939  << setw(w) << "[A=init. mass]"
940  << setw(w) << "[B=source]"
941  << setw(w) << "[C=flux]"
942  << setw(w) << "[A+B-C]"
943  << setw(w) << "[D=curr. mass]"
944  << setw(w) << "[A+B-C-D=err.]"
945  << setw(w) << "[rel. error]"
946  << endl;
947 
948  for (unsigned int qi=0; qi<n_quant; qi++)
949  {
950  double denominator = max(fabs(initial_mass_[qi]+integrated_sources_[qi]-integrated_fluxes_[qi]),fabs(sum_masses_[qi]));
951  output_ << " " << setiosflags(ios::left)
952  << setw(w) << quantities_[qi].name_.c_str()
953  << setw(w) << initial_mass_[qi]
954  << setw(w) << integrated_sources_[qi]
955  << setw(w) << integrated_fluxes_[qi]
956  << setw(w) << initial_mass_[qi]+integrated_sources_[qi]-integrated_fluxes_[qi]
957  << setw(w) << sum_masses_[qi]
959  << setw(w) << fabs(initial_mass_[qi]+integrated_sources_[qi]+integrated_fluxes_[qi]-sum_masses_[qi])/(denominator==0?1:denominator)
960  << endl;
961  }
962  }
963 
964  output_ << endl << endl;
965 }
966 
967 
968 std::string Balance::csv_zero_vals(unsigned int cnt, char delimiter)
969 {
970  std::stringstream ss;
971  for (unsigned int i=0; i<cnt; i++) ss << format_csv_val(0, delimiter);
972  return ss.str();
973 }
974 
975 
976 void Balance::output_csv(double time, char delimiter, const std::string& comment_string, unsigned int repeat)
977 {
978  // write output only on process #0
979  if (rank_ != 0) return;
980 
981  const unsigned int n_quant = quantities_.size();
982 
983  // print data header only on first line
984  if (repeat==0 && output_line_counter_==0) format_csv_output_header(delimiter, comment_string);
985 
986  // print sources and masses over bulk regions
987  const RegionSet & bulk_set = mesh_->region_db().get_region_set("BULK");
988  for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
989  {
990  for (unsigned int qi=0; qi<n_quant; qi++)
991  {
992  // print data header (repeat header after every "repeat" lines)
993  if (repeat && (output_line_counter_%repeat == 0)) format_csv_output_header(delimiter, comment_string);
994 
995  output_ << format_csv_val(time / time_->get_coef(), delimiter, true)
996  << format_csv_val(reg->label(), delimiter)
997  << format_csv_val(quantities_[qi].name_, delimiter)
998  << csv_zero_vals(3, delimiter)
999  << format_csv_val(masses_[qi][reg->bulk_idx()], delimiter)
1000  << format_csv_val(sources_in_[qi][reg->bulk_idx()] + sources_out_[qi][reg->bulk_idx()], delimiter)
1001  << format_csv_val(sources_in_[qi][reg->bulk_idx()], delimiter)
1002  << format_csv_val(sources_out_[qi][reg->bulk_idx()], delimiter)
1003  << csv_zero_vals(5, delimiter) << endl;
1005  }
1006  }
1007 
1008  // print mass fluxes over boundaries
1009  const RegionSet & b_set = mesh_->region_db().get_region_set(".BOUNDARY");
1010  for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
1011  {
1012  for (unsigned int qi=0; qi<n_quant; qi++) {
1013  // print data header (repeat header after every "repeat" lines)
1014  if (repeat && (output_line_counter_%repeat == 0)) format_csv_output_header(delimiter, comment_string);
1015 
1016  output_ << format_csv_val(time / time_->get_coef(), delimiter, true)
1017  << format_csv_val(reg->label(), delimiter)
1018  << format_csv_val(quantities_[qi].name_, delimiter)
1019  << format_csv_val(fluxes_in_[qi][reg->boundary_idx()] + fluxes_out_[qi][reg->boundary_idx()], delimiter)
1020  << format_csv_val(fluxes_in_[qi][reg->boundary_idx()], delimiter)
1021  << format_csv_val(fluxes_out_[qi][reg->boundary_idx()], delimiter)
1022  << csv_zero_vals(9, delimiter) << endl;
1024  }
1025  }
1026 
1027  if (cumulative_)
1028  {
1029  for (unsigned int qi=0; qi<n_quant; qi++)
1030  {
1031  // print data header (repeat header after every "repeat" lines)
1032  if (repeat && (output_line_counter_%repeat == 0)) format_csv_output_header(delimiter, comment_string);
1033 
1034  double error = sum_masses_[qi] - (initial_mass_[qi] + integrated_sources_[qi] + integrated_fluxes_[qi]);
1035  output_ << format_csv_val(time / time_->get_coef(), delimiter, true)
1036  << format_csv_val("ALL", delimiter)
1037  << format_csv_val(quantities_[qi].name_, delimiter)
1038  << format_csv_val(sum_fluxes_[qi], delimiter)
1039  << format_csv_val(sum_fluxes_in_[qi], delimiter)
1040  << format_csv_val(sum_fluxes_out_[qi], delimiter)
1041  << format_csv_val(sum_masses_[qi], delimiter)
1042  << format_csv_val(sum_sources_[qi], delimiter)
1043  << format_csv_val(sum_sources_in_[qi], delimiter)
1044  << format_csv_val(sum_sources_out_[qi], delimiter)
1045  << format_csv_val(increment_fluxes_[qi], delimiter)
1046  << format_csv_val(increment_sources_[qi], delimiter)
1047  << format_csv_val(integrated_fluxes_[qi], delimiter)
1048  << format_csv_val(integrated_sources_[qi], delimiter)
1049  << format_csv_val(error, delimiter) << endl;
1051  }
1052  }
1053 
1054 }
1055 
1056 
1057 void Balance::format_csv_output_header(char delimiter, const std::string& comment_string)
1058 {
1059  std::stringstream ss;
1060  if (delimiter == ' ') {
1061  ss << setw(output_column_width-comment_string.size()) << "\"time [" << time_->get_unit_string() << "]\"";
1062  } else {
1063  ss << "\"time [" << time_->get_unit_string() << "]\"";
1064  }
1065 
1066  output_ << comment_string << ss.str()
1067  << format_csv_val("region", delimiter)
1068  << format_csv_val("quantity [" + units_.format_text() + "]", delimiter)
1069  << format_csv_val("flux", delimiter)
1070  << format_csv_val("flux_in", delimiter)
1071  << format_csv_val("flux_out", delimiter)
1072  << format_csv_val("mass", delimiter)
1073  << format_csv_val("source", delimiter)
1074  << format_csv_val("source_in", delimiter)
1075  << format_csv_val("source_out", delimiter)
1076  << format_csv_val("flux_increment", delimiter)
1077  << format_csv_val("source_increment", delimiter)
1078  << format_csv_val("flux_cumulative", delimiter)
1079  << format_csv_val("source_cumulative", delimiter)
1080  << format_csv_val("error", delimiter)
1081  << endl;
1082 }
1083 
1084 std::string Balance::format_csv_val(std::string val, char delimiter, bool initial)
1085 {
1086  std::stringstream ss;
1087  std::replace( val.begin(), val.end(), '\"', '\'');
1088 
1089  if (!initial) ss << delimiter;
1090  if (delimiter == ' ') {
1091  std::stringstream sval;
1092  sval << "\"" << val << "\"";
1093  ss << " " << setw(output_column_width-1) << sval.str();
1094  } else {
1095  ss << "\"" << val << "\"";
1096  }
1097 
1098  return ss.str();
1099 }
1100 
1101 std::string Balance::format_csv_val(double val, char delimiter, bool initial)
1102 {
1103  std::stringstream ss;
1104 
1105  if (!initial) ss << delimiter;
1106  if (delimiter == ' ') {
1107  ss << " " << setw(output_column_width-1) << val;
1108  } else {
1109  ss << val;
1110  }
1111  return ss.str();
1112 }
1113 
1114 void Balance::output_yaml(double time)
1115 {
1116 
1117  // write output only on process #0
1118  if (!do_yaml_output_ || rank_ != 0) return;
1119 
1120  const unsigned int n_quant = quantities_.size();
1121 
1122  // print data header only once
1123  if (!output_yaml_header_) {
1124  output_yaml_ << "column_names: [ flux, flux_in, flux_out, mass, source, source_in, source_out, flux_increment, "
1125  << "source_increment, flux_cumulative, source_cumulative, error ]" << endl;
1126  output_yaml_ << "data:" << endl;
1127  output_yaml_header_ = true;
1128  }
1129 
1130  output_yaml_ << setfill(' ');
1131 
1132  // print sources and masses over bulk regions
1133  const RegionSet & bulk_set = mesh_->region_db().get_region_set("BULK");
1134  for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
1135  {
1136  for (unsigned int qi=0; qi<n_quant; qi++)
1137  {
1138  output_yaml_ << " - time: " << (time / time_->get_coef()) << endl;
1139  output_yaml_ << setw(4) << "" << "region: " << reg->label() << endl;
1140  output_yaml_ << setw(4) << "" << "quantity: " << quantities_[qi].name_ << endl;
1141  output_yaml_ << setw(4) << "" << "data: " << "[ 0, 0, 0, " << masses_[qi][reg->bulk_idx()] << ", "
1142  << sources_in_[qi][reg->bulk_idx()] + sources_out_[qi][reg->bulk_idx()] << ", "
1143  << sources_in_[qi][reg->bulk_idx()] << ", " << sources_out_[qi][reg->bulk_idx()]
1144  << ", 0, 0, 0, 0, 0 ]" << endl;
1145  }
1146  }
1147 
1148  // print mass fluxes over boundaries
1149  const RegionSet & b_set = mesh_->region_db().get_region_set(".BOUNDARY");
1150  for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
1151  {
1152  for (unsigned int qi=0; qi<n_quant; qi++) {
1153  output_yaml_ << " - time: " << (time / time_->get_coef()) << endl;
1154  output_yaml_ << setw(4) << "" << "region: " << reg->label() << endl;
1155  output_yaml_ << setw(4) << "" << "quantity: " << quantities_[qi].name_ << endl;
1156  output_yaml_ << setw(4) << "" << "data: " << "[ "
1157  << fluxes_in_[qi][reg->boundary_idx()] + fluxes_out_[qi][reg->boundary_idx()] << ", "
1158  << fluxes_in_[qi][reg->boundary_idx()] << ", " << fluxes_out_[qi][reg->boundary_idx()]
1159  << ", 0, 0, 0, 0, 0, 0, 0, 0, 0 ]" << endl;
1160  }
1161  }
1162 
1163  if (cumulative_)
1164  {
1165  for (unsigned int qi=0; qi<n_quant; qi++)
1166  {
1167  double error = sum_masses_[qi] - (initial_mass_[qi] + integrated_sources_[qi] + integrated_fluxes_[qi]);
1168  output_yaml_ << " - time: " << (time / time_->get_coef()) << endl;
1169  output_yaml_ << setw(4) << "" << "region: ALL" << endl;
1170  output_yaml_ << setw(4) << "" << "quantity: " << quantities_[qi].name_ << endl;
1171  output_yaml_ << setw(4) << "" << "data: " << "[ " << sum_fluxes_[qi] << ", "
1172  << sum_fluxes_in_[qi] << ", " << sum_fluxes_out_[qi] << ", "
1173  << sum_masses_[qi] << ", " << sum_sources_[qi] << ", "
1174  << sum_sources_in_[qi] << ", " << sum_sources_out_[qi] << ", "
1175  << increment_fluxes_[qi] << ", " << increment_sources_[qi] << ", "
1176  << integrated_fluxes_[qi] << ", " << integrated_sources_[qi] << ", "
1177  << error << " ]" << endl;
1178  }
1179  }
1180 }
1181 
1182 
1183 
1184 
1185 
1186 
UnitSI units_
Units of conserved quantities.
Definition: balance.hh:453
void lazy_initialize()
Definition: balance.cc:188
static const Input::Type::Record & get_input_type()
Main balance input record type.
Definition: balance.cc:48
std::vector< double > integrated_sources_
Definition: balance.hh:501
unsigned int add_quantity(const string &name)
Definition: balance.cc:160
std::vector< double > sum_fluxes_out_
Definition: balance.hh:493
void calculate_mass(unsigned int quantity_idx, const Vec &solution, vector< double > &output_array)
Definition: balance.cc:580
RegionSet get_region_set(const std::string &set_name) const
Definition: region.cc:329
TimeMark::Type output_mark_type_
TimeMark type for output of particular equation.
Definition: balance.hh:513
Accessor to input data conforming to declared Array.
Definition: accessors.hh:567
void allocate(unsigned int n_loc_dofs, unsigned int max_dofs_per_boundary)
Definition: balance.cc:180
TimeMark::Type balance_output_type_
TimeMark type for balance output of particular equation.
Definition: balance.hh:510
unsigned int * boundary_idx_
Definition: elements.h:83
std::string format_text() const
Definition: unit_si.cc:127
int tlevel() const
void finish_source_assembly(unsigned int quantity_idx)
This method must be called after assembling the matrix and vectors for computing source.
Definition: balance.cc:408
unsigned int bulk_size() const
Definition: region.cc:269
void add_mass_vec_value(unsigned int quantity_idx, unsigned int region_idx, double value)
Definition: balance.cc:488
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:459
gnuplot
Definition: balance.hh:145
bool initial_
true before calculating the mass at initial time, otherwise false
Definition: balance.hh:516
Boundary * cond() const
Definition: side_impl.hh:71
std::vector< std::vector< double > > sources_in_
Definition: balance.hh:487
void add_cumulative_source(unsigned int quantity_idx, double source)
Definition: balance.cc:513
std::vector< std::vector< double > > fluxes_in_
Definition: balance.hh:484
std::vector< double > sum_fluxes_in_
Definition: balance.hh:492
std::vector< std::vector< double > > fluxes_out_
Definition: balance.hh:485
#define INPUT_CATCH(ExceptionType, AddressEITag, input_accessor)
Definition: accessors.hh:64
const TimeGovernor * time_
Definition: balance.hh:543
#define MPI_SUM
Definition: mpi.h:196
Mat * region_source_rhs_
Matrices for calculation of signed source (n_dofs x n_bulk_regions).
Definition: balance.hh:466
Definition: mesh.h:76
Input::Record input_record_
Record for current balance.
Definition: balance.hh:541
ofstream output_
Handle for file for output in given OutputFormat of balance and total fluxes over individual regions ...
Definition: balance.hh:439
void read_from_input(Input::Array in_array, const TimeGovernor &tg)
void chkerr(unsigned int ierr)
Replacement of new/delete operator in the spirit of xmalloc.
Definition: system.hh:147
void output_legacy(double time)
Perform output in old format (for compatibility)
Definition: balance.cc:823
SideIter side(const unsigned int loc_index)
Definition: accessors.hh:137
void add_mass_matrix_values(unsigned int quantity_idx, unsigned int region_idx, const std::vector< LongIdx > &dof_indices, const std::vector< double > &values)
Definition: balance.cc:422
const RegionDB & region_db() const
Definition: mesh.h:143
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:346
Region region()
Definition: boundaries.cc:35
const TimeStep & step(int index=-1) const
bool allocation_done_
true before allocating necessary internal structures (Petsc matrices etc.)
Definition: balance.hh:522
double t() const
void calculate_cumulative(unsigned int quantity_idx, const Vec &solution)
Definition: balance.cc:523
Basic time management functionality for unsteady (and steady) solvers (class Equation).
void add_flux_matrix_values(unsigned int quantity_idx, unsigned int boundary_idx, const std::vector< LongIdx > &dof_indices, const std::vector< double > &values)
Definition: balance.cc:442
static TimeMarks & marks()
#define MPI_Reduce(sendbuf, recvbuf, count, datatype, op, root, comm)
Definition: mpi.h:608
void calculate_instant(unsigned int quantity_idx, const Vec &solution)
Definition: balance.cc:605
void add_flux_vec_value(unsigned int quantity_idx, unsigned int boundary_idx, double value)
Definition: balance.cc:499
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:303
Basic time management class.
std::vector< double > sum_fluxes_
Definition: balance.hh:491
virtual ElementAccessor< 3 > element_accessor(unsigned int idx) const
Create and return ElementAccessor to element of given idx.
Definition: mesh.cc:726
bool balance_on_
If the balance is on. Balance is off in the case of no balance output time marks. ...
Definition: balance.hh:525
static constexpr bool value
Definition: json.hpp:87
std::vector< double > increment_sources_
Definition: balance.hh:504
Vec * be_flux_vec_
Vectors for calculation of flux (n_boundary_edges).
Definition: balance.hh:469
static void set_yaml_output()
Set global variable to output balance files into YAML format (in addition to the table format)...
Definition: balance.cc:61
static const Input::Type::Selection & get_format_selection_input_type()
Input selection for file format.
Definition: balance.cc:40
std::vector< double > integrated_fluxes_
Definition: balance.hh:502
unsigned int boundary_idx() const
Returns index of the region in the boundary set.
Definition: region.hh:86
std::vector< Quantity > quantities_
Names of conserved quantities.
Definition: balance.hh:448
std::string csv_zero_vals(unsigned int cnt, char delimiter)
Return part of output represented by zero values. Count of zero values is given by cnt parameter...
Definition: balance.cc:968
std::vector< std::vector< double > > sources_out_
Definition: balance.hh:488
Mat * be_flux_matrix_
Matrices for calculation of flux (n_boundary_edges x n_dofs).
Definition: balance.hh:460
double last_time_
time of last calculated balance
Definition: balance.hh:507
void open_stream(Stream &stream) const
Definition: file_path.cc:211
double init_time() const
std::vector< std::vector< double > > fluxes_
Definition: balance.hh:483
void finish_mass_assembly(unsigned int quantity_idx)
This method must be called after assembling the matrix for computing mass.
Definition: balance.cc:386
TimeMark::Type equation_fixed_mark_type() const
void format_csv_output_header(char delimiter, const std::string &comment_string)
Print output header.
Definition: balance.cc:1057
int rank_
MPI rank.
Definition: balance.hh:532
Accessor to the data with type Type::Record.
Definition: accessors.hh:292
TimeMark::Type equation_mark_type() const
const Ret val(const string &key) const
unsigned int n_sides() const
Definition: elements.h:135
void init_from_input(const Input::Record &in_rec, TimeGovernor &tg)
Definition: balance.cc:127
Mat * region_mass_matrix_
Matrices for calculation of mass (n_dofs x n_bulk_regions).
Definition: balance.hh:457
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.
std::vector< double > sum_sources_out_
Definition: balance.hh:497
unsigned int max_dofs_per_boundary_
Definition: balance.hh:429
bool cumulative_
if true then cumulative balance is computed
Definition: balance.hh:519
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:501
Mat * region_source_matrix_
Matrices for calculation of source (n_dofs x n_bulk_regions).
Definition: balance.hh:463
std::vector< double > increment_fluxes_
Definition: balance.hh:503
void chkerr_assert(unsigned int ierr)
Definition: system.hh:158
bool is_current()
Returns true if the current time step is marked for the balance output.
Definition: balance.cc:348
Balance(const std::string &file_prefix, const Mesh *mesh)
Definition: balance.cc:84
void output_csv(double time, char delimiter, const std::string &comment_string, unsigned int repeat=0)
Perform output in csv format.
Definition: balance.cc:976
Distribution * get_el_ds() const
Definition: mesh.h:164
~Balance()
Definition: balance.cc:101
static bool do_yaml_output_
Definition: balance.hh:425
#define MPI_DOUBLE
Definition: mpi.h:156
#define MPI_Comm_rank
Definition: mpi.h:236
std::vector< unsigned int > add_quantities(const std::vector< string > &names)
Definition: balance.cc:171
Dedicated class for storing path to input and output files.
Definition: file_path.hh:54
const Mesh * mesh_
Definition: balance.hh:450
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
Support classes for parallel programing.
void output_yaml(double time)
Perform output in yaml format.
Definition: balance.cc:1114
void output()
Perform output to file for given time instant.
Definition: balance.cc:680
std::vector< double > sum_sources_
Definition: balance.hh:495
std::string get_unit_string() const
void start_flux_assembly(unsigned int quantity_idx)
Definition: balance.cc:368
std::vector< double > initial_mass_
Definition: balance.hh:498
static const unsigned int output_column_width
Size of column in output (used if delimiter is space)
Definition: balance.hh:391
void add_source_values(unsigned int quantity_idx, unsigned int region_idx, const std::vector< LongIdx > &loc_dof_indices, const std::vector< double > &mat_values, const std::vector< double > &vec_values)
Definition: balance.cc:460
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR)
Definition: asserts.hh:335
const Selection & close() const
Close the Selection, no more values can be added.
unsigned int boundary_size() const
Definition: region.cc:262
double dt() const
void finish_flux_assembly(unsigned int quantity_idx)
This method must be called after assembling the matrix and vector for computing flux.
Definition: balance.cc:397
std::vector< unsigned int > be_regions_
Number of boundary region for each local boundary edge.
Definition: balance.hh:475
ofstream output_yaml_
Definition: balance.hh:442
OutputFormat output_format_
Format of output file.
Definition: balance.hh:445
#define ASSERT_DBG(expr)
Definition: asserts.hh:349
static const Input::Type::Array get_input_type()
void units(const UnitSI &unit)
Setter for units of conserved quantities.
Definition: balance.cc:152
int be_offset_
Offset for local part of vector of boundary edges.
Definition: balance.hh:478
std::vector< std::vector< double > > masses_
Definition: balance.hh:486
void start_mass_assembly(unsigned int quantity_idx)
Definition: balance.cc:359
Record type proxy class.
Definition: type_record.hh:182
std::vector< double > sum_masses_
Definition: balance.hh:494
Vec * region_mass_vec_
Vectors for calculation of mass (n_bulk_regions).
Definition: balance.hh:472
unsigned int output_line_counter_
hold count of line printed into output_
Definition: balance.hh:535
bool add_output_times_
Add output time marks to balance output time marks.
Definition: balance.hh:528
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:428
double get_coef() const
static FileName output()
The factory function for declaring type FileName for input files.
Definition: type_base.cc:533
OutputFormat
Definition: balance.hh:141
LongIdx * get_el_4_loc() const
Definition: mesh.h:170
void undef(bool val=true)
Definition: unit_si.cc:197
void start_source_assembly(unsigned int quantity_idx)
Definition: balance.cc:377
Template for classes storing finite set of named values.
FilePath balance_output_file_
File path for output_ stream.
Definition: balance.hh:436
std::string file_prefix_
Save prefix passed in in constructor.
Definition: balance.hh:433
bool output_yaml_header_
marks whether YAML output has printed header
Definition: balance.hh:538
std::string format_csv_val(std::string val, char delimiter, bool initial=false)
Format string value of csv output. Wrap string into quotes and if delimiter is space, align text to column.
Definition: balance.cc:1084
std::vector< double > sum_sources_in_
Definition: balance.hh:496
unsigned int lsize(int proc) const
get local size