21 #include <unordered_map> 43 return Selection(
"Balance_output_format",
"Format of output file for balance.")
51 return Record(
"Balance",
"Balance of a conservative quantity, boundary fluxes and sources.")
53 .
declare_key(
"add_output_times",
Bool(),
Default(
"true"),
"Add all output times of the balanced equation to the balance output times set. " 54 "Note that this is not the time set of the output stream.")
58 "If true, then balance is calculated at each computational time step, which can slow down the program.")
87 : file_prefix_(file_prefix),
91 allocation_done_(false),
93 output_line_counter_(0),
94 output_yaml_header_(false)
176 for (
auto name : names)
183 unsigned int max_dofs_per_boundary)
192 unsigned int max_dofs_per_boundary)
228 unsigned int be_id = 0;
234 for(
unsigned int si=0; si<elm->
n_sides(); si++)
283 for (
unsigned int c=0; c<n_quant; ++c)
285 chkerr(MatCreateAIJ(PETSC_COMM_WORLD,
290 (
rank_==0)?n_bulk_regs_per_dof:0,
292 (rank_==0)?0:n_bulk_regs_per_dof,
296 chkerr(MatCreateSeqAIJ(PETSC_COMM_SELF,
303 chkerr(MatCreateSeqAIJ(PETSC_COMM_SELF,
310 chkerr(MatCreateAIJ(PETSC_COMM_WORLD,
321 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
326 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
337 std::string default_file_name;
451 uint m = mat_values.size();
453 for (
uint i=0; i<m; i++)
484 uint m = mat_values.size();
486 for (
uint i=0; i<m; i++)
507 unsigned int region_idx,
515 PetscInt reg_array[1] = { (int)region_idx };
518 loc_dof_indices.size(),
519 loc_dof_indices.memptr(),
522 &(mult_mat_values[0]),
526 loc_dof_indices.size(),
527 loc_dof_indices.memptr(),
530 &(add_mat_values[0]),
553 double temp_source = 0;
554 int lsize, n_cols_mat, n_cols_rhs;
556 const double *vals_mat, *vals_rhs, *sol_array;
560 chkerr(VecGetArrayRead(solution, &sol_array));
566 for (
int i=0; i<lsize; ++i){
572 for (
int j=0; j<n_cols_mat; ++j)
573 temp_source += vals_mat[j]*sol_array[i] + vals_rhs[j];
578 chkerr(VecRestoreArrayRead(solution, &sol_array));
585 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
593 chkerr(VecSum(temp, &sum_fluxes));
594 chkerr(VecDestroy(&temp));
613 chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD,
621 chkerr(VecZeroEntries(bulk_vec));
626 chkerr(VecDestroy(&bulk_vec));
642 int lsize, n_cols_mat, n_cols_rhs;
644 const double *vals_mat, *vals_rhs, *sol_array;
648 chkerr(VecGetArrayRead(solution, &sol_array));
653 for (
int i=0; i<lsize; ++i)
661 for (
int j=0; j<n_cols_mat; ++j)
665 double f = vals_mat[j]*sol_array[i] + vals_rhs[j];
670 chkerr(VecRestoreArrayRead(solution, &sol_array));
674 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
682 chkerr(VecScale(temp, -1));
687 const double *flux_array;
689 chkerr(VecGetArrayRead(temp, &flux_array));
690 chkerr(VecGetLocalSize(temp, &lsize));
691 for (
int e=0; e<lsize; ++e)
693 if (flux_array[e] < 0)
696 fluxes_in_[quantity_idx][be_regions_[e]] += flux_array[e];
698 chkerr(VecRestoreArrayRead(temp, &flux_array));
699 chkerr(VecDestroy(&temp));
716 const int buf_size = n_quant*2*n_blk_reg + n_quant*2*n_bdr_reg + n_quant;
717 double sendbuffer[buf_size], recvbuffer[buf_size];
718 for (
unsigned int qi=0; qi<n_quant; qi++)
720 for (
unsigned int ri=0; ri<n_blk_reg; ri++)
722 sendbuffer[qi*2*n_blk_reg + + ri] =
sources_in_[qi][ri];
723 sendbuffer[qi*2*n_blk_reg + n_blk_reg + ri] =
sources_out_[qi][ri];
725 for (
unsigned int ri=0; ri<n_bdr_reg; ri++)
727 sendbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + + ri] =
fluxes_in_[qi][ri];
728 sendbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + n_bdr_reg + ri] =
fluxes_out_[qi][ri];
743 for (
unsigned int qi=0; qi<n_quant; qi++)
745 for (
unsigned int ri=0; ri<n_blk_reg; ri++)
747 sources_in_[qi][ri] = recvbuffer[qi*2*n_blk_reg + + ri];
748 sources_out_[qi][ri] = recvbuffer[qi*2*n_blk_reg + n_blk_reg + ri];
750 for (
unsigned int ri=0; ri<n_bdr_reg; ri++)
752 fluxes_in_[qi][ri] = recvbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + + ri];
753 fluxes_out_[qi][ri] = recvbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + n_bdr_reg + ri];
777 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
779 for (
unsigned int qi=0; qi<n_quant; qi++)
789 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
791 for (
unsigned int qi=0; qi<n_quant; qi++)
807 for (
unsigned int qi=0; qi<n_quant; qi++)
812 for (
unsigned int qi=0; qi<n_quant; qi++)
852 if (
rank_ != 0)
return;
859 unsigned int wl = 2*(w-5)+7;
860 string bc_head_format =
"# %-*s%-*s%-*s%-*s%-*s%-*s\n",
861 bc_format =
"%*s%-*d%-*s%-*s%-*g%-*g%-*g\n",
862 bc_total_format =
"# %-*s%-*s%-*g%-*g%-*g\n";
864 output_ <<
"# " << setw((w*c+wl-14)/2) << setfill(
'-') <<
"--" 866 << setw((w*c+wl-14)/2) << setfill(
'-') <<
"" << endl
870 output_ <<
"# Mass flux through boundary [M/T]:\n# " 871 << setiosflags(ios::left) << setfill(
' ')
872 << setw(w) <<
"[boundary_id]" 873 << setw(wl) <<
"[label]" 874 << setw(w) <<
"[substance]" 875 << setw(w) <<
"[total flux]" 876 << setw(w) <<
"[outward flux]" 877 << setw(w) <<
"[inward flux]" 881 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
885 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg) {
886 for (
unsigned int qi=0; qi<n_quant; qi++) {
888 << setw(w) << (int)reg->id()
889 << setw(wl) << reg->label().c_str()
893 << setw(w) <<
fluxes_in_[qi][reg->boundary_idx()]
899 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
902 for (
unsigned int qi=0; qi<n_quant; qi++)
903 output_ <<
"# " << setiosflags(ios::left)
904 << setw(w+wl) <<
"Total mass flux of substance [M/T]" 914 string src_head_format =
"# %-*s%-*s%-*s%-*s%-*s\n",
915 src_format =
"%*s%-*d%-*s%-*s%-*g%-*g\n",
916 src_total_format =
"# %-*s%-*s%-*g%-*g\n";
917 output_ <<
"# Mass [M] and sources [M/T] on regions:\n" 918 <<
"# " << setiosflags(ios::left)
919 << setw(w) <<
"[region_id]" 920 << setw(wl) <<
"[label]" 921 << setw(w) <<
"[substance]" 922 << setw(w) <<
"[total_mass]" 923 << setw(w) <<
"[total_source]" 927 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
931 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
933 for (
unsigned int qi=0; qi<n_quant; qi++)
936 << setw(w) << (int)reg->id()
937 << setw(wl) << reg->label().c_str()
939 << setw(w) <<
masses_[qi][reg->bulk_idx()]
946 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
949 for (
unsigned int qi=0; qi<n_quant; qi++)
950 output_ <<
"# " << setiosflags(ios::left) << setw(w+wl) <<
"Total mass [M] and sources [M/T]" 959 output_ <<
"\n\n# Cumulative mass balance on time interval [" 961 << setiosflags(ios::left) << time <<
"]\n" 962 <<
"# Initial mass [M] + sources integrated over time [M] - flux integrated over time [M] = current mass [M]\n" 963 <<
"# " << setiosflags(ios::left)
964 << setw(w) <<
"[substance]" 965 << setw(w) <<
"[A=init. mass]" 966 << setw(w) <<
"[B=source]" 967 << setw(w) <<
"[C=flux]" 968 << setw(w) <<
"[A+B-C]" 969 << setw(w) <<
"[D=curr. mass]" 970 << setw(w) <<
"[A+B-C-D=err.]" 971 << setw(w) <<
"[rel. error]" 974 for (
unsigned int qi=0; qi<n_quant; qi++)
977 output_ <<
" " << setiosflags(ios::left)
996 std::stringstream ss;
997 for (
unsigned int i=0; i<cnt; i++) ss <<
format_csv_val(0, delimiter);
1005 if (
rank_ != 0)
return;
1014 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
1016 for (
unsigned int qi=0; qi<n_quant; qi++)
1036 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
1038 for (
unsigned int qi=0; qi<n_quant; qi++) {
1055 for (
unsigned int qi=0; qi<n_quant; qi++)
1085 std::stringstream ss;
1086 if (delimiter ==
' ') {
1092 output_ << comment_string << ss.str()
1112 std::stringstream ss;
1113 std::replace( val.begin(), val.end(),
'\"',
'\'');
1115 if (!initial) ss << delimiter;
1116 if (delimiter ==
' ') {
1117 std::stringstream sval;
1118 sval <<
"\"" << val <<
"\"";
1121 ss <<
"\"" << val <<
"\"";
1129 std::stringstream ss;
1131 if (!initial) ss << delimiter;
1132 if (delimiter ==
' ') {
1150 output_yaml_ <<
"column_names: [ flux, flux_in, flux_out, mass, source, source_in, source_out, flux_increment, " 1151 <<
"source_increment, flux_cumulative, source_cumulative, error ]" << endl;
1160 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
1162 for (
unsigned int qi=0; qi<n_quant; qi++)
1165 output_yaml_ << setw(4) <<
"" <<
"region: " << reg->label() << endl;
1167 output_yaml_ << setw(4) <<
"" <<
"data: " <<
"[ 0, 0, 0, " <<
masses_[qi][reg->bulk_idx()] <<
", " 1170 <<
", 0, 0, 0, 0, 0 ]" << endl;
1176 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
1178 for (
unsigned int qi=0; qi<n_quant; qi++) {
1180 output_yaml_ << setw(4) <<
"" <<
"region: " << reg->label() << endl;
1185 <<
", 0, 0, 0, 0, 0, 0, 0, 0, 0 ]" << endl;
1191 for (
unsigned int qi=0; qi<n_quant; qi++)
1195 output_yaml_ << setw(4) <<
"" <<
"region: ALL" << endl;
1203 << error <<
" ]" << endl;
void add_source_values(unsigned int quantity_idx, unsigned int region_idx, const LocDofVec &loc_dof_indices, const std::vector< double > &mult_mat_values, const std::vector< double > &add_mat_values)
UnitSI units_
Units of conserved quantities.
static const Input::Type::Record & get_input_type()
Main balance input record type.
unsigned int n_loc_dofs_par_
Allocation parameters. Set by the allocate method used in the lazy_initialize.
Declaration of class which handles the ordering of degrees of freedom (dof) and mappings between loca...
std::vector< double > integrated_sources_
unsigned int add_quantity(const string &name)
std::vector< double > sum_fluxes_out_
void calculate_mass(unsigned int quantity_idx, const Vec &solution, vector< double > &output_array)
RegionSet get_region_set(const std::string &set_name) const
LongIdx get_boundary_edge_uid(SideIter side)
TimeMark::Type output_mark_type_
TimeMark type for output of particular equation.
TimeMark::Type balance_output_type_
TimeMark type for balance output of particular equation.
unsigned int * boundary_idx_
std::string format_text() const
void finish_source_assembly(unsigned int quantity_idx)
This method must be called after assembling the matrix and vectors for computing source.
unsigned int bulk_size() const
bool initial_
true before calculating the mass at initial time, otherwise false
void allocate(const std::shared_ptr< DOFHandlerMultiDim > &dh, unsigned int max_dofs_per_boundary)
std::vector< std::vector< double > > sources_in_
void add_cumulative_source(unsigned int quantity_idx, double source)
std::vector< std::vector< double > > fluxes_in_
std::vector< double > sum_fluxes_in_
std::vector< std::vector< double > > fluxes_out_
const TimeGovernor * time_
Mat * region_source_rhs_
Matrices for calculation of signed source (n_dofs x n_bulk_regions).
Input::Record input_record_
Record for current balance.
Cell accessor allow iterate over DOF handler cells.
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.
void output_legacy(double time)
Perform output in old format (for compatibility)
SideIter side(const unsigned int loc_index)
const RegionDB & region_db() const
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
const TimeStep & step(int index=-1) const
bool allocation_done_
true before allocating necessary internal structures (Petsc matrices etc.)
void calculate_cumulative(unsigned int quantity_idx, const Vec &solution)
Basic time management functionality for unsteady (and steady) solvers (class Equation).
Side side() const
Return Side of given cell and side_idx.
static TimeMarks & marks()
#define MPI_Reduce(sendbuf, recvbuf, count, datatype, op, root, comm)
void calculate_instant(unsigned int quantity_idx, const Vec &solution)
Basic time management class.
std::vector< double > sum_fluxes_
virtual ElementAccessor< 3 > element_accessor(unsigned int idx) const
Create and return ElementAccessor to element of given idx.
bool balance_on_
If the balance is on. Balance is off in the case of no balance output time marks. ...
std::vector< double > increment_sources_
Vec * be_flux_vec_
Vectors for calculation of flux (n_boundary_edges).
static void set_yaml_output()
Set global variable to output balance files into YAML format (in addition to the table format)...
static const Input::Type::Selection & get_format_selection_input_type()
Input selection for file format.
std::vector< double > integrated_fluxes_
unsigned int boundary_idx() const
Returns index of the region in the boundary set.
std::vector< Quantity > quantities_
Names of conserved quantities.
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...
std::vector< std::vector< double > > sources_out_
Mat * be_flux_matrix_
Matrices for calculation of flux (n_boundary_edges x n_dofs).
double last_time_
time of last calculated balance
void open_stream(Stream &stream) const
std::vector< std::vector< double > > fluxes_
const ElementAccessor< 3 > elm() const
Return ElementAccessor to element of loc_ele_idx_.
bool is_boundary() const
Returns true for side on the boundary.
std::ofstream output_
Handle for file for output in given OutputFormat of balance and total fluxes over individual regions ...
void finish_mass_assembly(unsigned int quantity_idx)
This method must be called after assembling the matrix for computing mass.
TimeMark::Type equation_fixed_mark_type() const
void format_csv_output_header(char delimiter, const std::string &comment_string)
Print output header.
TimeMark::Type equation_mark_type() const
unsigned int n_sides() const
void init_from_input(const Input::Record &in_rec, TimeGovernor &tg)
Mat * region_mass_matrix_
Matrices for calculation of mass (n_dofs x n_bulk_regions).
std::vector< double > sum_sources_out_
unsigned int max_dofs_per_boundary_
bool cumulative_
if true then cumulative balance is computed
unsigned int n_loc_dofs_seq_
Mat * region_source_matrix_
Matrices for calculation of source (n_dofs x n_bulk_regions).
std::vector< double > increment_fluxes_
void chkerr_assert(unsigned int ierr)
bool is_current()
Returns true if the current time step is marked for the balance output.
Balance(const std::string &file_prefix, const Mesh *mesh)
void output_csv(double time, char delimiter, const std::string &comment_string, unsigned int repeat=0)
Perform output in csv format.
const DOFHandlerMultiDim * dh() const
Return DOF handler.
Distribution * get_el_ds() const
static bool do_yaml_output_
std::vector< unsigned int > add_quantities(const std::vector< string > &names)
Dedicated class for storing path to input and output files.
Support classes for parallel programing.
const DHCellAccessor & cell() const
Return DHCellAccessor appropriate to the side.
void output_yaml(double time)
Perform output in yaml format.
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
void output()
Perform output to file for given time instant.
std::vector< double > sum_sources_
std::string get_unit_string() const
void start_flux_assembly(unsigned int quantity_idx)
std::vector< double > initial_mass_
static const unsigned int output_column_width
Size of column in output (used if delimiter is space)
std::ofstream output_yaml_
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR)
unsigned int boundary_size() const
void finish_flux_assembly(unsigned int quantity_idx)
This method must be called after assembling the matrix and vector for computing flux.
std::vector< unsigned int > be_regions_
Maps local boundary edge to its region boundary index.
RegionIdx region_idx() const
OutputFormat output_format_
Format of output file.
std::unordered_map< LongIdx, unsigned int > be_id_map_
static const Input::Type::Array get_input_type()
unsigned int bulk_idx() const
Returns index of the region in the bulk set.
void units(const UnitSI &unit)
Setter for units of conserved quantities.
int be_offset_
Offset for local part of vector of boundary edges.
void add_flux_values(unsigned int quantity_idx, const DHCellSide &side, const LocDofVec &loc_dof_indices, const std::vector< double > &mat_values, double vec_value)
std::vector< std::vector< double > > masses_
const std::vector< LongIdx > & get_local_to_global_map() const
Get the map between local dof indices and the global ones.
void add_mass_values(unsigned int quantity_idx, const DHCellAccessor &dh_cell, const LocDofVec &loc_dof_indices, const std::vector< double > &mat_values, double vec_value)
void start_mass_assembly(unsigned int quantity_idx)
std::vector< double > sum_masses_
Vec * region_mass_vec_
Vectors for calculation of mass (n_bulk_regions).
unsigned int output_line_counter_
hold count of line printed into output_
bool add_output_times_
Add output time marks to balance output time marks.
Class for representation SI units of Fields.
arma::Col< Idx > LocDofVec
LongIdx * get_el_4_loc() const
void undef(bool val=true)
void start_source_assembly(unsigned int quantity_idx)
Side accessor allows to iterate over sides of DOF handler cell.
FilePath balance_output_file_
File path for output_ stream.
std::string file_prefix_
Save prefix passed in in constructor.
bool output_yaml_header_
marks whether YAML output has printed header
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.
std::vector< double > sum_sources_in_
unsigned int lsize(int proc) const
get local size