21 #include <unordered_map>
46 return Selection(
"Balance_output_format",
"Format of output file for balance.")
54 return Record(
"Balance",
"Balance of a conservative quantity, boundary fluxes and sources.")
56 .
declare_key(
"add_output_times",
Bool(),
Default(
"true"),
"Add all output times of the balanced equation to the balance output times set. "
57 "Note that this is not the time set of the output stream.")
61 "If true, then balance is calculated at each computational time step, which can slow down the program.")
90 : file_prefix_(file_prefix),
94 allocation_done_(false),
96 output_line_counter_(0),
97 output_yaml_header_(false)
179 for (
auto name : names)
186 unsigned int max_dofs_per_boundary)
195 unsigned int max_dofs_per_boundary)
235 unsigned int be_id = 0;
236 for (
unsigned int loc_el = 0; loc_el <
mesh_->
get_el_ds()->lsize(); loc_el++)
241 for(
unsigned int si=0; si<elm->
n_sides(); si++)
290 for (
unsigned int c=0; c<n_quant; ++c)
292 chkerr(MatCreateAIJ(PETSC_COMM_WORLD,
297 (
rank_==0)?n_bulk_regs_per_dof:0,
299 (
rank_==0)?0:n_bulk_regs_per_dof,
303 chkerr(MatCreateSeqAIJ(PETSC_COMM_SELF,
310 chkerr(MatCreateSeqAIJ(PETSC_COMM_SELF,
317 chkerr(MatCreateAIJ(PETSC_COMM_WORLD,
328 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
333 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
344 std::string default_file_name;
458 uint m = mat_values.size();
460 for (
uint i=0; i<m; i++)
491 uint m = mat_values.size();
493 for (
uint i=0; i<m; i++)
514 unsigned int region_idx,
522 PetscInt reg_array[1] = { (int)region_idx };
525 loc_dof_indices.size(),
526 loc_dof_indices.memptr(),
529 &(mult_mat_values[0]),
533 loc_dof_indices.size(),
534 loc_dof_indices.memptr(),
537 &(add_mat_values[0]),
560 double temp_source = 0;
561 int lsize, n_cols_mat, n_cols_rhs;
563 const double *vals_mat, *vals_rhs, *sol_array;
567 chkerr(VecGetArrayRead(solution, &sol_array));
573 for (
int i=0; i<lsize; ++i){
577 ASSERT(n_cols_mat == n_cols_rhs);
579 for (
int j=0; j<n_cols_mat; ++j)
580 temp_source += vals_mat[j]*sol_array[i] + vals_rhs[j];
585 chkerr(VecRestoreArrayRead(solution, &sol_array));
592 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
600 chkerr(VecSum(temp, &sum_fluxes));
601 chkerr(VecDestroy(&temp));
620 chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD,
628 chkerr(VecZeroEntries(bulk_vec));
633 chkerr(VecDestroy(&bulk_vec));
649 int lsize, n_cols_mat, n_cols_rhs;
651 const double *vals_mat, *vals_rhs, *sol_array;
655 chkerr(VecGetArrayRead(solution, &sol_array));
660 for (
int i=0; i<lsize; ++i)
666 ASSERT(n_cols_mat == n_cols_rhs);
668 for (
int j=0; j<n_cols_mat; ++j)
672 double f = vals_mat[j]*sol_array[i] + vals_rhs[j];
677 chkerr(VecRestoreArrayRead(solution, &sol_array));
681 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
689 chkerr(VecScale(temp, -1));
694 const double *flux_array;
696 chkerr(VecGetArrayRead(temp, &flux_array));
697 chkerr(VecGetLocalSize(temp, &lsize));
698 for (
int e=0; e<lsize; ++e)
700 if (flux_array[e] < 0)
705 chkerr(VecRestoreArrayRead(temp, &flux_array));
706 chkerr(VecDestroy(&temp));
723 const int buf_size = n_quant*2*n_blk_reg + n_quant*2*n_bdr_reg + n_quant;
724 double sendbuffer[buf_size], recvbuffer[buf_size];
725 for (
unsigned int qi=0; qi<n_quant; qi++)
727 for (
unsigned int ri=0; ri<n_blk_reg; ri++)
729 sendbuffer[qi*2*n_blk_reg + + ri] =
sources_in_[qi][ri];
730 sendbuffer[qi*2*n_blk_reg + n_blk_reg + ri] =
sources_out_[qi][ri];
732 for (
unsigned int ri=0; ri<n_bdr_reg; ri++)
734 sendbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + + ri] =
fluxes_in_[qi][ri];
735 sendbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + n_bdr_reg + ri] =
fluxes_out_[qi][ri];
750 for (
unsigned int qi=0; qi<n_quant; qi++)
752 for (
unsigned int ri=0; ri<n_blk_reg; ri++)
754 sources_in_[qi][ri] = recvbuffer[qi*2*n_blk_reg + + ri];
755 sources_out_[qi][ri] = recvbuffer[qi*2*n_blk_reg + n_blk_reg + ri];
757 for (
unsigned int ri=0; ri<n_bdr_reg; ri++)
759 fluxes_in_[qi][ri] = recvbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + + ri];
760 fluxes_out_[qi][ri] = recvbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + n_bdr_reg + ri];
784 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
786 for (
unsigned int qi=0; qi<n_quant; qi++)
796 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
798 for (
unsigned int qi=0; qi<n_quant; qi++)
814 for (
unsigned int qi=0; qi<n_quant; qi++)
819 for (
unsigned int qi=0; qi<n_quant; qi++)
859 if (
rank_ != 0)
return;
866 unsigned int wl = 2*(w-5)+7;
867 string bc_head_format =
"# %-*s%-*s%-*s%-*s%-*s%-*s\n",
868 bc_format =
"%*s%-*d%-*s%-*s%-*g%-*g%-*g\n",
869 bc_total_format =
"# %-*s%-*s%-*g%-*g%-*g\n";
871 output_ <<
"# " << setw((w*c+wl-14)/2) << setfill(
'-') <<
"--"
873 << setw((w*c+wl-14)/2) << setfill(
'-') <<
"" << endl
878 output_ <<
"# Mass flux through boundary [M/T]:\n# "
879 << setiosflags(ios::left) << setfill(
' ')
880 << setw(w) <<
"[boundary_id]"
881 << setw(wl) <<
"[label]"
882 << setw(w) <<
"[substance]"
883 << setw(w) <<
"[total flux]"
884 << setw(w) <<
"[outward flux]"
885 << setw(w) <<
"[inward flux]"
889 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
893 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg) {
894 for (
unsigned int qi=0; qi<n_quant; qi++) {
896 << setw(w) << (int)reg->id()
897 << setw(wl) << reg->label().c_str()
901 << setw(w) <<
fluxes_in_[qi][reg->boundary_idx()]
907 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
910 for (
unsigned int qi=0; qi<n_quant; qi++)
911 output_ <<
"# " << setiosflags(ios::left)
912 << setw(w+wl) <<
"Total mass flux of substance [M/T]"
922 string src_head_format =
"# %-*s%-*s%-*s%-*s%-*s\n",
923 src_format =
"%*s%-*d%-*s%-*s%-*g%-*g\n",
924 src_total_format =
"# %-*s%-*s%-*g%-*g\n";
925 output_ <<
"# Mass [M] and sources [M/T] on regions:\n"
926 <<
"# " << setiosflags(ios::left)
927 << setw(w) <<
"[region_id]"
928 << setw(wl) <<
"[label]"
929 << setw(w) <<
"[substance]"
930 << setw(w) <<
"[total_mass]"
931 << setw(w) <<
"[total_source]"
935 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
939 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
941 for (
unsigned int qi=0; qi<n_quant; qi++)
944 << setw(w) << (int)reg->id()
945 << setw(wl) << reg->label().c_str()
947 << setw(w) <<
masses_[qi][reg->bulk_idx()]
954 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
957 for (
unsigned int qi=0; qi<n_quant; qi++)
958 output_ <<
"# " << setiosflags(ios::left) << setw(w+wl) <<
"Total mass [M] and sources [M/T]"
967 output_ <<
"\n\n# Cumulative mass balance on time interval ["
969 << setiosflags(ios::left) << time <<
"]\n"
970 <<
"# Initial mass [M] + sources integrated over time [M] - flux integrated over time [M] = current mass [M]\n"
971 <<
"# " << setiosflags(ios::left)
972 << setw(w) <<
"[substance]"
973 << setw(w) <<
"[A=init. mass]"
974 << setw(w) <<
"[B=source]"
975 << setw(w) <<
"[C=flux]"
976 << setw(w) <<
"[A+B-C]"
977 << setw(w) <<
"[D=curr. mass]"
978 << setw(w) <<
"[A+B-C-D=err.]"
979 << setw(w) <<
"[rel. error]"
982 for (
unsigned int qi=0; qi<n_quant; qi++)
985 output_ <<
" " << setiosflags(ios::left)
1004 std::stringstream ss;
1005 for (
unsigned int i=0; i<cnt; i++) ss <<
format_csv_val(0, delimiter);
1013 if (
rank_ != 0)
return;
1022 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
1024 for (
unsigned int qi=0; qi<n_quant; qi++)
1044 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
1046 for (
unsigned int qi=0; qi<n_quant; qi++) {
1063 for (
unsigned int qi=0; qi<n_quant; qi++)
1098 std::stringstream ss;
1099 if (delimiter ==
' ') {
1106 output_ << comment_string << ss.str()
1126 std::stringstream ss;
1127 std::replace( val.begin(), val.end(),
'\"',
'\'');
1129 if (!initial) ss << delimiter;
1130 if (delimiter ==
' ') {
1131 std::stringstream sval;
1132 sval <<
"\"" << val <<
"\"";
1135 ss <<
"\"" << val <<
"\"";
1143 std::stringstream ss;
1145 if (!initial) ss << delimiter;
1146 if (delimiter ==
' ') {
1164 output_yaml_ <<
"column_names: [ flux, flux_in, flux_out, mass, source, source_in, source_out, flux_increment, "
1165 <<
"source_increment, flux_cumulative, source_cumulative, error ]" << endl;
1174 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
1176 for (
unsigned int qi=0; qi<n_quant; qi++)
1179 output_yaml_ << setw(4) <<
"" <<
"region: " << reg->label() << endl;
1181 output_yaml_ << setw(4) <<
"" <<
"data: " <<
"[ 0, 0, 0, " <<
masses_[qi][reg->bulk_idx()] <<
", "
1184 <<
", 0, 0, 0, 0, 0 ]" << endl;
1190 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
1192 for (
unsigned int qi=0; qi<n_quant; qi++) {
1194 output_yaml_ << setw(4) <<
"" <<
"region: " << reg->label() << endl;
1199 <<
", 0, 0, 0, 0, 0, 0, 0, 0, 0 ]" << endl;
1205 for (
unsigned int qi=0; qi<n_quant; qi++)
1209 output_yaml_ << setw(4) <<
"" <<
"region: ALL" << endl;
1217 << error <<
" ]" << endl;
#define ASSERT_PERMANENT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR)
#define ASSERT_PERMANENT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
const unsigned int index_
Internal index within list of quantities.
std::vector< double > sum_fluxes_in_
OutputFormat output_format_
Format of output file.
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.
void allocate(const std::shared_ptr< DOFHandlerMultiDim > &dh, unsigned int max_dofs_per_boundary)
void calculate_instant(unsigned int quantity_idx, const Vec &solution)
bool balance_on_
If the balance is on. Balance is off in the case of no balance output time marks.
unsigned int n_loc_dofs_seq_
double last_time_
time of last calculated balance
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)
TimeMark::Type balance_output_type_
TimeMark type for balance output of particular equation.
bool is_current()
Returns true if the current time step is marked for the balance output.
void output_yaml(double time)
Perform output in yaml format.
unsigned int n_loc_dofs_par_
Allocation parameters. Set by the allocate method used in the lazy_initialize.
Mat * be_flux_matrix_
Matrices for calculation of flux (n_boundary_edges x n_dofs).
std::vector< double > integrated_sources_
std::vector< unsigned int > be_regions_
Maps local boundary edge to its region boundary index.
unsigned int max_dofs_per_boundary_
Mat * region_source_rhs_
Matrices for calculation of signed source (n_dofs x n_bulk_regions).
void calculate_cumulative(unsigned int quantity_idx, const Vec &solution)
void start_source_assembly(unsigned int quantity_idx)
std::string file_prefix_
Save prefix passed in in constructor.
static const Input::Type::Record & get_input_type()
Main balance input record type.
std::vector< double > integrated_fluxes_
std::unordered_map< LongIdx, unsigned int > be_id_map_
void start_mass_assembly(unsigned int quantity_idx)
std::ofstream output_
Handle for file for output in given OutputFormat of balance and total fluxes over individual regions ...
std::vector< double > sum_fluxes_
static const Input::Type::Selection & get_format_selection_input_type()
Input selection for file format.
std::vector< double > sum_sources_
std::vector< std::vector< double > > masses_
void output()
Perform output to file for given time instant.
void units(const UnitSI &unit)
Setter for units of conserved quantities.
static bool do_yaml_output_
void calculate_mass(unsigned int quantity_idx, const Vec &solution, vector< double > &output_array)
TimeMark::Type output_mark_type_
TimeMark type for output of particular equation.
std::vector< std::vector< double > > fluxes_in_
void format_csv_output_header(char delimiter, const std::string &comment_string)
Print output header.
Balance(const std::string &file_prefix, const Mesh *mesh)
bool initial_
true before calculating the mass at initial time, otherwise false
std::vector< std::vector< double > > fluxes_out_
Vec * region_mass_vec_
Vectors for calculation of mass (n_bulk_regions).
void init_from_input(const Input::Record &in_rec, TimeGovernor &tg)
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,...
Input::Record input_record_
Record for current balance.
std::vector< std::vector< double > > fluxes_
void finish_source_assembly(unsigned int quantity_idx)
This method must be called after assembling the matrix and vectors for computing source.
const TimeGovernor * time_
Vec * be_flux_vec_
Vectors for calculation of flux (n_boundary_edges).
std::vector< std::vector< double > > sources_out_
std::ofstream output_yaml_
FilePath balance_output_file_
File path for output_ stream.
bool allocation_done_
true before allocating necessary internal structures (Petsc matrices etc.)
std::vector< std::vector< double > > sources_in_
void add_cumulative_source(unsigned int quantity_idx, double source)
void output_csv(double time, char delimiter, const std::string &comment_string, unsigned int repeat=0)
Perform output in csv format.
unsigned int output_line_counter_
hold count of line printed into output_
Mat * region_mass_matrix_
Matrices for calculation of mass (n_dofs x n_bulk_regions).
std::vector< Quantity > quantities_
Names of conserved quantities.
void output_legacy(double time)
Perform output in old format (for compatibility)
void finish_mass_assembly(unsigned int quantity_idx)
This method must be called after assembling the matrix for computing mass.
bool output_yaml_header_
marks whether YAML output has printed header
bool add_output_times_
Add output time marks to balance output time marks.
UnitSI units_
Units of conserved quantities.
std::vector< double > increment_sources_
bool cumulative_
if true then cumulative balance is computed
Mat * region_source_matrix_
Matrices for calculation of source (n_dofs x n_bulk_regions).
std::vector< double > sum_fluxes_out_
static void set_yaml_output()
Set global variable to output balance files into YAML format (in addition to the table format).
void start_flux_assembly(unsigned int quantity_idx)
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)
void finish_flux_assembly(unsigned int quantity_idx)
This method must be called after assembling the matrix and vector for computing flux.
std::vector< double > sum_masses_
int be_offset_
Offset for local part of vector of boundary edges.
std::vector< double > initial_mass_
std::vector< double > sum_sources_in_
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)
std::vector< double > increment_fluxes_
std::vector< unsigned int > add_quantities(const std::vector< string > &names)
std::vector< double > sum_sources_out_
static const unsigned int output_column_width
Size of column in output (used if delimiter is space)
unsigned int add_quantity(const string &name)
LongIdx get_boundary_edge_uid(SideIter side)
Cell accessor allow iterate over DOF handler cells.
const ElementAccessor< 3 > elm() const
Return ElementAccessor to element of loc_ele_idx_.
const DOFHandlerMultiDim * dh() const
Return DOF handler.
Side accessor allows to iterate over sides of DOF handler cell.
Side side() const
Return Side of given cell and side_idx.
const DHCellAccessor & cell() const
Return DHCellAccessor appropriate to the side.
const std::vector< LongIdx > & get_local_to_global_map() const
Get the map between local dof indices and the global ones.
SideIter side(const unsigned int loc_index)
RegionIdx region_idx() const
unsigned int * boundary_idx_
unsigned int n_sides() const
Dedicated class for storing path to input and output files.
void open_stream(Stream &stream) const
LongIdx * get_el_4_loc() const
const RegionDB & region_db() const
Distribution * get_el_ds() const
ElementAccessor< 3 > element_accessor(unsigned int idx) const
Create and return ElementAccessor to element of given idx.
static const Input::Type::Array get_input_type()
void read_from_input(Input::Array in_array, const TimeGovernor &tg)
unsigned int boundary_size() const
RegionSet get_region_set(const std::string &set_name) const
unsigned int bulk_size() const
unsigned int boundary_idx() const
Returns index of the region in the boundary set.
unsigned int bulk_idx() const
Returns index of the region in the bulk set.
bool is_boundary() const
Returns true for side on the boundary.
Basic time management functionality for unsteady (and steady) solvers (class Equation).
TimeMark::Type equation_fixed_mark_type() const
std::shared_ptr< TimeUnitConversion > get_unit_conversion() const
Getter for time unit conversion object.
TimeMark::Type equation_mark_type() const
const TimeStep & step(int index=-1) const
static TimeMarks & marks()
Class used for marking specified times at which some events occur.
Class for representation SI units of Fields.
std::string format_text() const
void undef(bool val=true)
Support classes for parallel programing.
Declaration of class which handles the ordering of degrees of freedom (dof) and mappings between loca...
arma::Col< IntIdx > LocDofVec
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
#define MPI_Reduce(sendbuf, recvbuf, count, datatype, op, root, comm)
void chkerr(unsigned int ierr)
Replacement of new/delete operator in the spirit of xmalloc.
void chkerr_assert(unsigned int ierr)
Basic time management class.