35 return Selection(
"Balance_output_format",
"Format of output file for balance.")
43 return Record(
"Balance",
"Balance of a conservative quantity, boundary fluxes and sources.")
45 .
declare_key(
"add_output_times",
Bool(),
Default(
"true"),
"Add all output times of the balanced equation to the balance output times set. " 46 "Note that this is not the time set of the output stream.")
50 "If true, then balance is calculated at each computational time step, which can slow down the program.")
75 : file_prefix_(file_prefix),
80 allocation_done_(false),
81 output_line_counter_(0),
83 output_yaml_header_(false)
142 std::string default_file_name;
143 switch (output_format_)
186 for (
auto name : names)
193 unsigned int max_dofs_per_boundary)
276 for (
unsigned int c=0; c<n_quant; ++c)
278 chkerr(MatCreateAIJ(PETSC_COMM_WORLD,
283 (
rank_==0)?n_bulk_regs_per_dof:0,
285 (rank_==0)?0:n_bulk_regs_per_dof,
289 chkerr(MatCreateAIJ(PETSC_COMM_WORLD,
294 (rank_==0)?n_bulk_regs_per_dof:0,
296 (rank_==0)?0:n_bulk_regs_per_dof,
300 chkerr(MatCreateAIJ(PETSC_COMM_WORLD,
305 (rank_==0)?n_bulk_regs_per_dof:0,
307 (rank_==0)?0:n_bulk_regs_per_dof,
311 chkerr(MatCreateAIJ(PETSC_COMM_WORLD,
322 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
327 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
332 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
338 chkerr(MatCreateAIJ(PETSC_COMM_WORLD,
350 for (
unsigned int loc_el=0; loc_el<
be_regions_.size(); ++loc_el)
362 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
370 chkerr(VecCreateMPI(PETSC_COMM_WORLD,
468 unsigned int region_idx,
475 PetscInt reg_array[1] = { (int)region_idx };
488 unsigned int elem_idx,
495 PetscInt elem_array[1] = { int(
be_offset_+elem_idx) };
507 unsigned int region_idx,
514 PetscInt reg_array[1] = { (int)region_idx };
527 unsigned int region_idx,
538 unsigned int elem_idx,
552 unsigned int region_idx,
559 PetscInt reg_array[1] = { (int)region_idx };
590 chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD,
598 chkerr(VecZeroEntries(bulk_vec));
603 chkerr(VecSum(bulk_vec, &sum_sources));
604 VecDestroy(&bulk_vec);
621 chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD,
629 chkerr(VecZeroEntries(boundary_vec));
635 chkerr(VecScale(temp, -1));
637 chkerr(VecDestroy(&temp));
640 chkerr(VecSum(boundary_vec, &sum_fluxes));
641 chkerr(VecDestroy(&boundary_vec));
658 chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD,
666 chkerr(VecZeroEntries(bulk_vec));
671 VecDestroy(&bulk_vec);
683 chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD,
691 chkerr(VecZeroEntries(bulk_vec));
700 const double *sol_array, *mat_array, *rhs_array;
701 chkerr(VecGetLocalSize(solution, &lsize));
702 chkerr(VecDuplicate(solution, &mat_r));
703 chkerr(VecDuplicate(solution, &rhs_r));
704 chkerr(VecGetArrayRead(solution, &sol_array));
710 VecGetArrayRead(mat_r, &mat_array);
711 VecGetArrayRead(rhs_r, &rhs_array);
715 for (
int i=0; i<lsize; ++i)
717 double f = mat_array[i]*sol_array[i] + rhs_array[i];
722 VecRestoreArrayRead(mat_r, &mat_array);
723 VecRestoreArrayRead(rhs_r, &rhs_array);
725 chkerr(VecRestoreArrayRead(solution, &sol_array));
728 VecDestroy(&bulk_vec);
740 chkerr(VecCreateMPIWithArray(PETSC_COMM_WORLD, 1,
742 PETSC_DECIDE, &(
fluxes_[quantity_idx][0]), &boundary_vec));
745 chkerr(VecZeroEntries(boundary_vec));
751 chkerr(VecScale(temp, -1));
757 const double *flux_array;
759 chkerr(VecGetArrayRead(temp, &flux_array));
760 chkerr(VecGetLocalSize(temp, &lsize));
761 for (
int e=0; e<lsize; ++e)
763 if (flux_array[e] < 0)
766 fluxes_in_[quantity_idx][be_regions_[e]] += flux_array[e];
768 chkerr(VecRestoreArrayRead(temp, &flux_array));
770 VecDestroy(&boundary_vec);
786 const int buf_size = n_quant*2*n_blk_reg + n_quant*2*n_bdr_reg;
787 double sendbuffer[buf_size], recvbuffer[buf_size];
788 for (
unsigned int qi=0; qi<n_quant; qi++)
790 for (
unsigned int ri=0; ri<n_blk_reg; ri++)
792 sendbuffer[qi*2*n_blk_reg + + ri] =
sources_in_[qi][ri];
793 sendbuffer[qi*2*n_blk_reg + n_blk_reg + ri] =
sources_out_[qi][ri];
795 for (
unsigned int ri=0; ri<n_bdr_reg; ri++)
797 sendbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + + ri] =
fluxes_in_[qi][ri];
798 sendbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + n_bdr_reg + ri] =
fluxes_out_[qi][ri];
808 for (
unsigned int qi=0; qi<n_quant; qi++)
810 for (
unsigned int ri=0; ri<n_blk_reg; ri++)
812 sources_in_[qi][ri] = recvbuffer[qi*2*n_blk_reg + + ri];
813 sources_out_[qi][ri] = recvbuffer[qi*2*n_blk_reg + n_blk_reg + ri];
815 for (
unsigned int ri=0; ri<n_bdr_reg; ri++)
817 fluxes_in_[qi][ri] = recvbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + + ri];
818 fluxes_out_[qi][ri] = recvbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + n_bdr_reg + ri];
838 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
840 for (
unsigned int qi=0; qi<n_quant; qi++)
850 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
852 for (
unsigned int qi=0; qi<n_quant; qi++)
869 for (
unsigned int qi=0; qi<n_quant; qi++)
874 for (
unsigned int qi=0; qi<n_quant; qi++)
914 if (
rank_ != 0)
return;
921 unsigned int wl = 2*(w-5)+7;
922 string bc_head_format =
"# %-*s%-*s%-*s%-*s%-*s%-*s\n",
923 bc_format =
"%*s%-*d%-*s%-*s%-*g%-*g%-*g\n",
924 bc_total_format =
"# %-*s%-*s%-*g%-*g%-*g\n";
926 output_ <<
"# " << setw((w*c+wl-14)/2) << setfill(
'-') <<
"--" 928 << setw((w*c+wl-14)/2) << setfill(
'-') <<
"" << endl
929 <<
"# Time: " << time <<
"\n\n\n";
932 output_ <<
"# Mass flux through boundary [M/T]:\n# " 933 << setiosflags(ios::left) << setfill(
' ')
934 << setw(w) <<
"[boundary_id]" 935 << setw(wl) <<
"[label]" 936 << setw(w) <<
"[substance]" 937 << setw(w) <<
"[total flux]" 938 << setw(w) <<
"[outward flux]" 939 << setw(w) <<
"[inward flux]" 943 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
947 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg) {
948 for (
unsigned int qi=0; qi<n_quant; qi++) {
950 << setw(w) << (int)reg->id()
951 << setw(wl) << reg->label().c_str()
953 << setw(w) <<
fluxes_[qi][reg->boundary_idx()]
955 << setw(w) <<
fluxes_in_[qi][reg->boundary_idx()]
961 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
964 for (
unsigned int qi=0; qi<n_quant; qi++)
965 output_ <<
"# " << setiosflags(ios::left)
966 << setw(w+wl) <<
"Total mass flux of substance [M/T]" 976 string src_head_format =
"# %-*s%-*s%-*s%-*s%-*s\n",
977 src_format =
"%*s%-*d%-*s%-*s%-*g%-*g\n",
978 src_total_format =
"# %-*s%-*s%-*g%-*g\n";
979 output_ <<
"# Mass [M] and sources [M/T] on regions:\n" 980 <<
"# " << setiosflags(ios::left)
981 << setw(w) <<
"[region_id]" 982 << setw(wl) <<
"[label]" 983 << setw(w) <<
"[substance]" 984 << setw(w) <<
"[total_mass]" 985 << setw(w) <<
"[total_source]" 989 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
993 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
995 for (
unsigned int qi=0; qi<n_quant; qi++)
998 << setw(w) << (int)reg->id()
999 << setw(wl) << reg->label().c_str()
1001 << setw(w) <<
masses_[qi][reg->bulk_idx()]
1002 << setw(w) <<
sources_[qi][reg->bulk_idx()]
1008 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
1011 for (
unsigned int qi=0; qi<n_quant; qi++)
1012 output_ <<
"# " << setiosflags(ios::left) << setw(w+wl) <<
"Total mass [M] and sources [M/T]" 1021 output_ <<
"\n\n# Cumulative mass balance on time interval [" 1023 << setiosflags(ios::left) << time <<
"]\n" 1024 <<
"# Initial mass [M] + sources integrated over time [M] - flux integrated over time [M] = current mass [M]\n" 1025 <<
"# " << setiosflags(ios::left)
1026 << setw(w) <<
"[substance]" 1027 << setw(w) <<
"[A=init. mass]" 1028 << setw(w) <<
"[B=source]" 1029 << setw(w) <<
"[C=flux]" 1030 << setw(w) <<
"[A+B-C]" 1031 << setw(w) <<
"[D=curr. mass]" 1032 << setw(w) <<
"[A+B-C-D=err.]" 1033 << setw(w) <<
"[rel. error]" 1036 for (
unsigned int qi=0; qi<n_quant; qi++)
1039 output_ <<
" " << setiosflags(ios::left)
1058 std::stringstream ss;
1059 for (
unsigned int i=0; i<cnt; i++) ss <<
format_csv_val(0, delimiter);
1067 if (
rank_ != 0)
return;
1076 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
1078 for (
unsigned int qi=0; qi<n_quant; qi++)
1098 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
1100 for (
unsigned int qi=0; qi<n_quant; qi++) {
1117 for (
unsigned int qi=0; qi<n_quant; qi++)
1147 std::stringstream ss;
1148 if (delimiter ==
' ') {
1154 output_ << comment_string << ss.str()
1174 std::stringstream ss;
1175 std::replace( val.begin(), val.end(),
'\"',
'\'');
1177 if (!initial) ss << delimiter;
1178 if (delimiter ==
' ') {
1179 std::stringstream sval;
1180 sval <<
"\"" << val <<
"\"";
1183 ss <<
"\"" << val <<
"\"";
1191 std::stringstream ss;
1193 if (!initial) ss << delimiter;
1194 if (delimiter ==
' ') {
1205 if (
rank_ != 0)
return;
1211 output_yaml_ <<
"column_names: [ flux, flux_in, flux_out, mass, source, source_in, source_out, flux_increment, " 1212 <<
"source_increment, flux_cumulative, source_cumulative, error ]" << endl;
1221 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
1223 for (
unsigned int qi=0; qi<n_quant; qi++)
1226 output_yaml_ << setw(4) <<
"" <<
"region: " << reg->label() << endl;
1228 output_yaml_ << setw(4) <<
"" <<
"data: " <<
"[ 0, 0, 0, " <<
masses_[qi][reg->bulk_idx()] <<
", " 1230 <<
sources_out_[qi][reg->bulk_idx()] <<
", 0, 0, 0, 0, 0 ]" << endl;
1236 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
1238 for (
unsigned int qi=0; qi<n_quant; qi++) {
1240 output_yaml_ << setw(4) <<
"" <<
"region: " << reg->label() << endl;
1242 output_yaml_ << setw(4) <<
"" <<
"data: " <<
"[ " <<
fluxes_[qi][reg->boundary_idx()] <<
", " 1244 <<
", 0, 0, 0, 0, 0, 0, 0, 0, 0 ]" << endl;
1250 for (
unsigned int qi=0; qi<n_quant; qi++)
1254 output_yaml_ << setw(4) <<
"" <<
"region: ALL" << endl;
1262 << error <<
" ]" << endl;
UnitSI units_
Units of conserved quantities.
void calculate_cumulative_sources(unsigned int quantity_idx, const Vec &solution, double dt)
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)
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_
double initial_time_
initial time
std::string format_text() const
void calculate_cumulative_fluxes(unsigned int quantity_idx, const Vec &solution, double dt)
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
void add_flux_vec_value(unsigned int quantity_idx, unsigned int elem_idx, double value)
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_
void add_source_vec_values(unsigned int quantity_idx, unsigned int region_idx, const std::vector< int > &dof_values, const std::vector< double > &values)
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).
RegionSet get_region_set(const string &set_name) const
void add_mass_matrix_values(unsigned int quantity_idx, unsigned int region_idx, const std::vector< int > &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)
#define FOR_ELEMENT_SIDES(i, j)
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)
int * get_el_4_loc() const
const RegionDB & region_db() const
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
bool allocation_done_
true before allocating necessary internal structures (Petsc matrices etc.)
Basic time management functionality for unsteady (and steady) solvers (class Equation).
static TimeMarks & marks()
#define MPI_Reduce(sendbuf, recvbuf, count, datatype, op, root, comm)
Basic time management class.
std::vector< double > sum_fluxes_
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 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 calculate_source(unsigned int quantity_idx, const Vec &solution)
void add_flux_matrix_values(unsigned int quantity_idx, unsigned int elem_idx, const std::vector< int > &dof_indices, const std::vector< double > &values)
void finish_mass_assembly(unsigned int quantity_idx)
This method must be called after assembling the matrix for computing mass.
void calculate_flux(unsigned int quantity_idx, const Vec &solution)
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
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)
SideIter side(const unsigned int loc_index)
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
std::vector< unsigned int > add_quantities(const std::vector< string > &names)
Dedicated class for storing path to input and output files.
void output_yaml(double time)
Perform output in yaml format.
std::vector< double > sum_sources_
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
bool is_current(const TimeStep &step)
Returns true if the given time step is marked for the balance output.
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_
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.
void output(double time)
Perform output to file for given time instant.
Class for representation SI units of Fields.
unsigned int n_loc_dofs_
Allocation parameters. Set by the allocate method used in the lazy_initialize.
void add_source_matrix_values(unsigned int quantity_idx, unsigned int region_idx, const std::vector< int > &dof_indices, const std::vector< double > &values)
Representation of one time step..
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.
ElementVector element
Vector of elements of the mesh.
std::vector< double > sum_sources_in_
unsigned int lsize(int proc) const
get local size