41 return Selection(
"Balance_output_format",
"Format of output file for balance.")
49 return Record(
"Balance",
"Balance of a conservative quantity, boundary fluxes and sources.")
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.")
56 "If true, then balance is calculated at each computational time step, which can slow down the program.")
85 : file_prefix_(file_prefix),
89 allocation_done_(false),
91 output_line_counter_(0),
92 output_yaml_header_(false)
180 for (
auto name : names)
187 unsigned int max_dofs_per_boundary)
223 for(
unsigned int si=0; si<elm->
n_sides(); si++)
270 for (
unsigned int c=0; c<n_quant; ++c)
272 chkerr(MatCreateAIJ(PETSC_COMM_WORLD,
277 (
rank_==0)?n_bulk_regs_per_dof:0,
279 (rank_==0)?0:n_bulk_regs_per_dof,
283 chkerr(MatCreateAIJ(PETSC_COMM_WORLD,
288 (rank_==0)?n_bulk_regs_per_dof:0,
290 (rank_==0)?0:n_bulk_regs_per_dof,
294 chkerr(MatCreateAIJ(PETSC_COMM_WORLD,
299 (rank_==0)?n_bulk_regs_per_dof:0,
301 (rank_==0)?0:n_bulk_regs_per_dof,
305 chkerr(MatCreateAIJ(PETSC_COMM_WORLD,
316 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
321 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
326 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
332 chkerr(MatCreateAIJ(PETSC_COMM_WORLD,
344 for (
unsigned int loc_el=0; loc_el<
be_regions_.size(); ++loc_el)
356 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
364 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
375 std::string default_file_name;
484 unsigned int region_idx,
491 PetscInt reg_array[1] = { (int)region_idx };
504 unsigned int boundary_idx,
511 PetscInt elem_array[1] = { int(
be_offset_+boundary_idx) };
523 unsigned int region_idx,
530 PetscInt reg_array[1] = { (int)region_idx };
543 unsigned int region_idx,
554 unsigned int boundary_idx,
568 unsigned int region_idx,
575 PetscInt reg_array[1] = { (int)region_idx };
607 chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD,
615 chkerr(VecZeroEntries(bulk_vec));
620 chkerr(VecSum(bulk_vec, &sum_sources));
621 chkerr(VecDestroy(&bulk_vec));
631 chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD,
639 chkerr(VecZeroEntries(boundary_vec));
645 chkerr(VecScale(temp, -1));
647 chkerr(VecDestroy(&temp));
650 chkerr(VecSum(boundary_vec, &sum_fluxes));
651 chkerr(VecDestroy(&boundary_vec));
668 chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD,
676 chkerr(VecZeroEntries(bulk_vec));
681 chkerr(VecDestroy(&bulk_vec));
693 chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD,
701 chkerr(VecZeroEntries(bulk_vec));
710 const double *sol_array, *mat_array, *rhs_array;
711 chkerr(VecGetLocalSize(solution, &lsize));
712 chkerr(VecDuplicate(solution, &mat_r));
713 chkerr(VecDuplicate(solution, &rhs_r));
714 chkerr(VecGetArrayRead(solution, &sol_array));
720 VecGetArrayRead(mat_r, &mat_array);
721 VecGetArrayRead(rhs_r, &rhs_array);
725 for (
int i=0; i<lsize; ++i)
727 double f = mat_array[i]*sol_array[i] + rhs_array[i];
732 VecRestoreArrayRead(mat_r, &mat_array);
733 VecRestoreArrayRead(rhs_r, &rhs_array);
735 chkerr(VecRestoreArrayRead(solution, &sol_array));
736 chkerr(VecDestroy(&rhs_r));
737 chkerr(VecDestroy(&mat_r));
738 chkerr(VecDestroy(&bulk_vec));
744 chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD, 1,
746 PETSC_DECIDE, &(
fluxes_[quantity_idx][0]), &boundary_vec));
749 chkerr(VecZeroEntries(boundary_vec));
755 chkerr(VecScale(temp, -1));
761 const double *flux_array;
763 chkerr(VecGetArrayRead(temp, &flux_array));
764 chkerr(VecGetLocalSize(temp, &lsize));
765 for (
int e=0; e<lsize; ++e)
767 if (flux_array[e] < 0)
770 fluxes_in_[quantity_idx][be_regions_[e]] += flux_array[e];
772 chkerr(VecRestoreArrayRead(temp, &flux_array));
773 chkerr(VecDestroy(&temp));
774 chkerr(VecDestroy(&boundary_vec));
791 const int buf_size = n_quant*2*n_blk_reg + n_quant*2*n_bdr_reg;
792 double sendbuffer[buf_size], recvbuffer[buf_size];
793 for (
unsigned int qi=0; qi<n_quant; qi++)
795 for (
unsigned int ri=0; ri<n_blk_reg; ri++)
797 sendbuffer[qi*2*n_blk_reg + + ri] =
sources_in_[qi][ri];
798 sendbuffer[qi*2*n_blk_reg + n_blk_reg + ri] =
sources_out_[qi][ri];
800 for (
unsigned int ri=0; ri<n_bdr_reg; ri++)
802 sendbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + + ri] =
fluxes_in_[qi][ri];
803 sendbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + n_bdr_reg + ri] =
fluxes_out_[qi][ri];
813 for (
unsigned int qi=0; qi<n_quant; qi++)
815 for (
unsigned int ri=0; ri<n_blk_reg; ri++)
817 sources_in_[qi][ri] = recvbuffer[qi*2*n_blk_reg + + ri];
818 sources_out_[qi][ri] = recvbuffer[qi*2*n_blk_reg + n_blk_reg + ri];
820 for (
unsigned int ri=0; ri<n_bdr_reg; ri++)
822 fluxes_in_[qi][ri] = recvbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + + ri];
823 fluxes_out_[qi][ri] = recvbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + n_bdr_reg + ri];
843 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
845 for (
unsigned int qi=0; qi<n_quant; qi++)
855 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
857 for (
unsigned int qi=0; qi<n_quant; qi++)
873 for (
unsigned int qi=0; qi<n_quant; qi++)
878 for (
unsigned int qi=0; qi<n_quant; qi++)
918 if (
rank_ != 0)
return;
925 unsigned int wl = 2*(w-5)+7;
926 string bc_head_format =
"# %-*s%-*s%-*s%-*s%-*s%-*s\n",
927 bc_format =
"%*s%-*d%-*s%-*s%-*g%-*g%-*g\n",
928 bc_total_format =
"# %-*s%-*s%-*g%-*g%-*g\n";
930 output_ <<
"# " << setw((w*c+wl-14)/2) << setfill(
'-') <<
"--" 932 << setw((w*c+wl-14)/2) << setfill(
'-') <<
"" << endl
936 output_ <<
"# Mass flux through boundary [M/T]:\n# " 937 << setiosflags(ios::left) << setfill(
' ')
938 << setw(w) <<
"[boundary_id]" 939 << setw(wl) <<
"[label]" 940 << setw(w) <<
"[substance]" 941 << setw(w) <<
"[total flux]" 942 << setw(w) <<
"[outward flux]" 943 << setw(w) <<
"[inward flux]" 947 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
951 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg) {
952 for (
unsigned int qi=0; qi<n_quant; qi++) {
954 << setw(w) << (int)reg->id()
955 << setw(wl) << reg->label().c_str()
957 << setw(w) <<
fluxes_[qi][reg->boundary_idx()]
959 << setw(w) <<
fluxes_in_[qi][reg->boundary_idx()]
965 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
968 for (
unsigned int qi=0; qi<n_quant; qi++)
969 output_ <<
"# " << setiosflags(ios::left)
970 << setw(w+wl) <<
"Total mass flux of substance [M/T]" 980 string src_head_format =
"# %-*s%-*s%-*s%-*s%-*s\n",
981 src_format =
"%*s%-*d%-*s%-*s%-*g%-*g\n",
982 src_total_format =
"# %-*s%-*s%-*g%-*g\n";
983 output_ <<
"# Mass [M] and sources [M/T] on regions:\n" 984 <<
"# " << setiosflags(ios::left)
985 << setw(w) <<
"[region_id]" 986 << setw(wl) <<
"[label]" 987 << setw(w) <<
"[substance]" 988 << setw(w) <<
"[total_mass]" 989 << setw(w) <<
"[total_source]" 993 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
997 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
999 for (
unsigned int qi=0; qi<n_quant; qi++)
1002 << setw(w) << (int)reg->id()
1003 << setw(wl) << reg->label().c_str()
1005 << setw(w) <<
masses_[qi][reg->bulk_idx()]
1006 << setw(w) <<
sources_[qi][reg->bulk_idx()]
1012 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
1015 for (
unsigned int qi=0; qi<n_quant; qi++)
1016 output_ <<
"# " << setiosflags(ios::left) << setw(w+wl) <<
"Total mass [M] and sources [M/T]" 1025 output_ <<
"\n\n# Cumulative mass balance on time interval [" 1027 << setiosflags(ios::left) << time <<
"]\n" 1028 <<
"# Initial mass [M] + sources integrated over time [M] - flux integrated over time [M] = current mass [M]\n" 1029 <<
"# " << setiosflags(ios::left)
1030 << setw(w) <<
"[substance]" 1031 << setw(w) <<
"[A=init. mass]" 1032 << setw(w) <<
"[B=source]" 1033 << setw(w) <<
"[C=flux]" 1034 << setw(w) <<
"[A+B-C]" 1035 << setw(w) <<
"[D=curr. mass]" 1036 << setw(w) <<
"[A+B-C-D=err.]" 1037 << setw(w) <<
"[rel. error]" 1040 for (
unsigned int qi=0; qi<n_quant; qi++)
1043 output_ <<
" " << setiosflags(ios::left)
1062 std::stringstream ss;
1063 for (
unsigned int i=0; i<cnt; i++) ss <<
format_csv_val(0, delimiter);
1071 if (
rank_ != 0)
return;
1080 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
1082 for (
unsigned int qi=0; qi<n_quant; qi++)
1102 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
1104 for (
unsigned int qi=0; qi<n_quant; qi++) {
1121 for (
unsigned int qi=0; qi<n_quant; qi++)
1151 std::stringstream ss;
1152 if (delimiter ==
' ') {
1158 output_ << comment_string << ss.str()
1178 std::stringstream ss;
1179 std::replace( val.begin(), val.end(),
'\"',
'\'');
1181 if (!initial) ss << delimiter;
1182 if (delimiter ==
' ') {
1183 std::stringstream sval;
1184 sval <<
"\"" << val <<
"\"";
1187 ss <<
"\"" << val <<
"\"";
1195 std::stringstream ss;
1197 if (!initial) ss << delimiter;
1198 if (delimiter ==
' ') {
1216 output_yaml_ <<
"column_names: [ flux, flux_in, flux_out, mass, source, source_in, source_out, flux_increment, " 1217 <<
"source_increment, flux_cumulative, source_cumulative, error ]" << endl;
1226 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
1228 for (
unsigned int qi=0; qi<n_quant; qi++)
1231 output_yaml_ << setw(4) <<
"" <<
"region: " << reg->label() << endl;
1233 output_yaml_ << setw(4) <<
"" <<
"data: " <<
"[ 0, 0, 0, " <<
masses_[qi][reg->bulk_idx()] <<
", " 1235 <<
sources_out_[qi][reg->bulk_idx()] <<
", 0, 0, 0, 0, 0 ]" << endl;
1241 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
1243 for (
unsigned int qi=0; qi<n_quant; qi++) {
1245 output_yaml_ << setw(4) <<
"" <<
"region: " << reg->label() << endl;
1247 output_yaml_ << setw(4) <<
"" <<
"data: " <<
"[ " <<
fluxes_[qi][reg->boundary_idx()] <<
", " 1249 <<
", 0, 0, 0, 0, 0, 0, 0, 0, 0 ]" << endl;
1255 for (
unsigned int qi=0; qi<n_quant; qi++)
1259 output_yaml_ << setw(4) <<
"" <<
"region: ALL" << endl;
1267 << error <<
" ]" << endl;
UnitSI units_
Units of conserved quantities.
static const Input::Type::Record & get_input_type()
Main balance input record type.
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
TimeMark::Type output_mark_type_
TimeMark type for output of particular equation.
void allocate(unsigned int n_loc_dofs, unsigned int max_dofs_per_boundary)
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
void add_mass_vec_value(unsigned int quantity_idx, unsigned int region_idx, double value)
bool initial_
true before calculating the mass at initial time, otherwise false
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_
Vec ones_
auxiliary vectors for summation of matrix columns
Mat * region_source_rhs_
Matrices for calculation of signed source (n_dofs x n_bulk_regions).
Input::Record input_record_
Record for current balance.
void add_source_matrix_values(unsigned int quantity_idx, unsigned int region_idx, const std::vector< LongIdx > &dof_indices, const std::vector< double > &values)
ofstream output_
Handle for file for output in given OutputFormat of balance and total fluxes over individual regions ...
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)
void add_mass_matrix_values(unsigned int quantity_idx, unsigned int region_idx, const std::vector< LongIdx > &dof_indices, const std::vector< double > &values)
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).
void add_flux_matrix_values(unsigned int quantity_idx, unsigned int boundary_idx, const std::vector< LongIdx > &dof_indices, const std::vector< double > &values)
static TimeMarks & marks()
#define MPI_Reduce(sendbuf, recvbuf, count, datatype, op, root, comm)
void calculate_instant(unsigned int quantity_idx, const Vec &solution)
void add_flux_vec_value(unsigned int quantity_idx, unsigned int boundary_idx, double value)
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. ...
static constexpr bool value
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_
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< std::vector< double > > sources_
std::vector< double > sum_sources_out_
unsigned int max_dofs_per_boundary_
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 > 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.
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.
void output_yaml(double time)
Perform output in yaml format.
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)
#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_
Number of boundary region for each local boundary edge.
OutputFormat output_format_
Format of output file.
static const Input::Type::Array get_input_type()
void units(const UnitSI &unit)
Setter for units of conserved quantities.
int be_offset_
Offset for local part of vector of boundary edges.
std::vector< std::vector< double > > masses_
void add_source_vec_values(unsigned int quantity_idx, unsigned int region_idx, const std::vector< LongIdx > &dof_values, const std::vector< double > &values)
Vec * region_source_vec_
Vectors for calculation of source (n_bulk_regions).
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.
unsigned int n_loc_dofs_
Allocation parameters. Set by the allocate method used in the lazy_initialize.
LongIdx * get_el_4_loc() const
void undef(bool val=true)
void start_source_assembly(unsigned int quantity_idx)
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