46 using namespace Input::Type;
49 =
Selection(
"Balance_output_format",
"Format of output file for balance.")
55 =
Record(
"Balance",
"Balance of a conservative quantity, boundary fluxes and sources.")
59 "If true, then balance is calculated at each computational time step, which can slow down the program.")
72 : regions_(mesh->region_db()),
76 allocation_done_(false),
77 output_line_counter_(0)
86 std::string default_file_name;
87 switch (output_format_)
90 default_file_name = file_prefix +
"_balance.txt";
93 default_file_name = file_prefix +
"_balance.dat";
96 default_file_name = file_prefix +
"_balance.txt";
104 for (
unsigned int loc_el = 0; loc_el < el_ds->
lsize(); loc_el++)
162 for (
auto name : names)
170 unsigned int max_dofs_per_boundary)
216 for (
unsigned int c=0; c<n_quant; ++c)
218 MatCreateAIJ(PETSC_COMM_WORLD,
223 (
rank_==0)?n_bulk_regs_per_dof:0,
225 (rank_==0)?0:n_bulk_regs_per_dof,
229 MatCreateAIJ(PETSC_COMM_WORLD,
234 max_dofs_per_boundary,
240 MatCreateAIJ(PETSC_COMM_WORLD,
245 (rank_==0)?n_bulk_regs_per_dof:0,
247 (rank_==0)?0:n_bulk_regs_per_dof,
251 MatCreateAIJ(PETSC_COMM_WORLD,
256 (rank_==0)?n_bulk_regs_per_dof:0,
258 (rank_==0)?0:n_bulk_regs_per_dof,
262 VecCreateMPI(PETSC_COMM_WORLD,
267 VecCreateMPI(PETSC_COMM_WORLD,
273 MatCreateAIJ(PETSC_COMM_WORLD,
285 for (
unsigned int loc_el=0; loc_el<
be_regions_.size(); ++loc_el)
297 VecCreateMPI(PETSC_COMM_WORLD,
301 VecGetArray(
ones_, &ones_array);
302 fill_n(ones_array, n_loc_dofs, 1);
303 VecRestoreArray(
ones_, &ones_array);
305 VecCreateMPI(PETSC_COMM_WORLD,
311 VecRestoreArray(
ones_be_, &ones_array);
371 unsigned int region_idx,
375 PetscInt reg_array[1] = { (int)region_idx };
388 unsigned int elem_idx,
392 PetscInt elem_array[1] = { int(
be_offset_+elem_idx) };
405 unsigned int region_idx,
409 PetscInt reg_array[1] = { (int)region_idx };
422 unsigned int elem_idx,
433 unsigned int region_idx,
437 PetscInt reg_array[1] = { (int)region_idx };
459 VecCreateMPIWithArray(PETSC_COMM_WORLD,
467 VecZeroEntries(bulk_vec);
471 VecSum(bulk_vec, &sum_sources);
472 VecDestroy(&bulk_vec);
490 VecCreateMPIWithArray(PETSC_COMM_WORLD,
498 VecZeroEntries(boundary_vec);
506 VecSum(boundary_vec, &sum_fluxes);
507 VecDestroy(&boundary_vec);
522 VecCreateMPIWithArray(PETSC_COMM_WORLD,
530 VecZeroEntries(bulk_vec);
532 VecDestroy(&bulk_vec);
542 VecCreateMPIWithArray(PETSC_COMM_WORLD,
550 VecZeroEntries(bulk_vec);
559 const double *sol_array, *mat_array, *rhs_array;
560 VecGetLocalSize(solution, &lsize);
561 VecDuplicate(solution, &mat_r);
562 VecDuplicate(solution, &rhs_r);
563 VecGetArrayRead(solution, &sol_array);
569 VecGetArrayRead(mat_r, &mat_array);
570 VecGetArrayRead(rhs_r, &rhs_array);
574 for (
int i=0; i<lsize; ++i)
576 double f = mat_array[i]*sol_array[i] + rhs_array[i];
581 VecRestoreArrayRead(mat_r, &mat_array);
582 VecRestoreArrayRead(rhs_r, &rhs_array);
584 VecRestoreArrayRead(solution, &sol_array);
587 VecDestroy(&bulk_vec);
600 VecZeroEntries(boundary_vec);
609 const double *flux_array;
611 VecGetArrayRead(temp, &flux_array);
612 VecGetLocalSize(temp, &lsize);
613 for (
int e=0; e<lsize; ++e)
615 if (flux_array[e] > 0)
618 fluxes_in_[quantity_idx][be_regions_[e]] += flux_array[e];
620 VecRestoreArrayRead(temp, &flux_array);
622 VecDestroy(&boundary_vec);
643 const int buf_size = n_quant*2*n_blk_reg + n_quant*2*n_bdr_reg;
644 double sendbuffer[buf_size], recvbuffer[buf_size];
645 for (
unsigned int qi=0; qi<n_quant; qi++)
647 for (
unsigned int ri=0; ri<n_blk_reg; ri++)
649 sendbuffer[qi*2*n_blk_reg + + ri] =
sources_in_[qi][ri];
650 sendbuffer[qi*2*n_blk_reg + n_blk_reg + ri] =
sources_out_[qi][ri];
652 for (
unsigned int ri=0; ri<n_bdr_reg; ri++)
654 sendbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + + ri] =
fluxes_in_[qi][ri];
655 sendbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + n_bdr_reg + ri] =
fluxes_out_[qi][ri];
665 for (
unsigned int qi=0; qi<n_quant; qi++)
667 for (
unsigned int ri=0; ri<n_blk_reg; ri++)
669 sources_in_[qi][ri] = recvbuffer[qi*2*n_blk_reg + + ri];
670 sources_out_[qi][ri] = recvbuffer[qi*2*n_blk_reg + n_blk_reg + ri];
672 for (
unsigned int ri=0; ri<n_bdr_reg; ri++)
674 fluxes_in_[qi][ri] = recvbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + + ri];
675 fluxes_out_[qi][ri] = recvbuffer[n_quant*2*n_blk_reg + qi*2*n_bdr_reg + n_bdr_reg + ri];
693 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
695 for (
unsigned int qi=0; qi<n_quant; qi++)
705 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
707 for (
unsigned int qi=0; qi<n_quant; qi++)
724 for (
unsigned int qi=0; qi<n_quant; qi++)
729 for (
unsigned int qi=0; qi<n_quant; qi++)
767 if (
rank_ != 0)
return;
774 unsigned int wl = 2*(w-5)+7;
775 string bc_head_format =
"# %-*s%-*s%-*s%-*s%-*s%-*s\n",
776 bc_format =
"%*s%-*d%-*s%-*s%-*g%-*g%-*g\n",
777 bc_total_format =
"# %-*s%-*s%-*g%-*g%-*g\n";
779 output_ <<
"# " << setw((w*c+wl-14)/2) << setfill(
'-') <<
"--"
781 << setw((w*c+wl-14)/2) << setfill(
'-') <<
"" << endl
782 <<
"# Time: " << time <<
"\n\n\n";
785 output_ <<
"# Mass flux through boundary [M/T]:\n# "
786 << setiosflags(ios::left) << setfill(
' ')
787 << setw(w) <<
"[boundary_id]"
788 << setw(wl) <<
"[label]"
789 << setw(w) <<
"[substance]"
790 << setw(w) <<
"[total flux]"
791 << setw(w) <<
"[outward flux]"
792 << setw(w) <<
"[inward flux]"
796 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
800 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg) {
801 for (
unsigned int qi=0; qi<n_quant; qi++) {
803 << setw(w) << (int)reg->id()
804 << setw(wl) << reg->label().c_str()
806 << setw(w) <<
fluxes_[qi][reg->boundary_idx()]
808 << setw(w) <<
fluxes_in_[qi][reg->boundary_idx()]
814 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
817 for (
unsigned int qi=0; qi<n_quant; qi++)
818 output_ <<
"# " << setiosflags(ios::left)
819 << setw(w+wl) <<
"Total mass flux of substance [M/T]"
829 string src_head_format =
"# %-*s%-*s%-*s%-*s%-*s\n",
830 src_format =
"%*s%-*d%-*s%-*s%-*g%-*g\n",
831 src_total_format =
"# %-*s%-*s%-*g%-*g\n";
832 output_ <<
"# Mass [M] and sources [M/T] on regions:\n"
833 <<
"# " << setiosflags(ios::left)
834 << setw(w) <<
"[region_id]"
835 << setw(wl) <<
"[label]"
836 << setw(w) <<
"[substance]"
837 << setw(w) <<
"[total_mass]"
838 << setw(w) <<
"[total_source]"
842 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
846 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
848 for (
unsigned int qi=0; qi<n_quant; qi++)
851 << setw(w) << (int)reg->id()
852 << setw(wl) << reg->label().c_str()
854 << setw(w) <<
masses_[qi][reg->bulk_idx()]
855 << setw(w) <<
sources_[qi][reg->bulk_idx()]
861 output_ <<
"# " << setw(w*c+wl) << setfill(
'-') <<
"" << setfill(
' ') << endl;
864 for (
unsigned int qi=0; qi<n_quant; qi++)
865 output_ <<
"# " << setiosflags(ios::left) << setw(w+wl) <<
"Total mass [M] and sources [M/T]"
874 output_ <<
"\n\n# Cumulative mass balance on time interval ["
876 << setiosflags(ios::left) << time <<
"]\n"
877 <<
"# Initial mass [M] + sources integrated over time [M] - flux integrated over time [M] = current mass [M]\n"
878 <<
"# " << setiosflags(ios::left)
879 << setw(w) <<
"[substance]"
880 << setw(w) <<
"[A=init. mass]"
881 << setw(w) <<
"[B=source]"
882 << setw(w) <<
"[C=flux]"
883 << setw(w) <<
"[A+B-C]"
884 << setw(w) <<
"[D=curr. mass]"
885 << setw(w) <<
"[A+B-C-D=err.]"
886 << setw(w) <<
"[rel. error]"
889 for (
unsigned int qi=0; qi<n_quant; qi++)
892 output_ <<
" " << setiosflags(ios::left)
911 std::stringstream ss;
912 for (
unsigned int i=0; i<cnt; i++) ss <<
format_csv_val(0, delimiter);
917 void Balance::output_csv(
double time,
char delimiter,
const std::string& comment_string,
unsigned int repeat)
920 if (
rank_ != 0)
return;
929 for( RegionSet::const_iterator reg = bulk_set.begin(); reg != bulk_set.end(); ++reg)
931 for (
unsigned int qi=0; qi<n_quant; qi++)
951 for( RegionSet::const_iterator reg = b_set.begin(); reg != b_set.end(); ++reg)
953 for (
unsigned int qi=0; qi<n_quant; qi++) {
970 for (
unsigned int qi=0; qi<n_quant; qi++)
1000 std::stringstream ss;
1001 if (delimiter ==
' ') {
1007 output_ << comment_string << ss.str()
1027 std::stringstream ss;
1028 std::replace( val.begin(), val.end(),
'\"',
'\'');
1030 if (!initial) ss << delimiter;
1031 if (delimiter ==
' ') {
1032 std::stringstream sval;
1033 sval <<
"\"" << val <<
"\"";
1036 ss <<
"\"" << val <<
"\"";
1044 std::stringstream ss;
1046 if (!initial) ss << delimiter;
1047 if (delimiter ==
' ') {
UnitSI units_
Units of conserved quantities.
void calculate_cumulative_sources(unsigned int quantity_idx, const Vec &solution, double dt)
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)
void allocate(unsigned int n_loc_dofs, unsigned int max_dofs_per_boundary)
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
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_
static Input::Type::Record input_type
Main balance input record type.
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_
Balance(const std::string &file_prefix, const Mesh *mesh, const Distribution *el_ds, const int *el_4_loc, const Input::Record &in_rec)
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 of balance and total fluxes over individual regions and region sets...
#define FOR_ELEMENT_SIDES(i, j)
void output_legacy(double time)
Perform output in old format (for compatibility)
bool allocation_done_
true before allocating necessary internal structures (Petsc matrices etc.)
I/O functions with filename storing, able to track current line in opened file. All standard stdio fu...
#define MPI_Reduce(sendbuf, recvbuf, count, datatype, op, root, comm)
const RegionDB & regions_
Database of bulk and boundary regions.
std::vector< double > sum_fluxes_
std::vector< double > increment_sources_
Vec * be_flux_vec_
Vectors for calculation of flux (n_boundary_edges).
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 add_source_rhs_values(unsigned int quantity_idx, unsigned int region_idx, const std::vector< int > &dof_values, const std::vector< double > &values)
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)
void format_csv_output_header(char delimiter, const std::string &comment_string)
Print output header.
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_
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_
SideIter side(const unsigned int loc_index)
void output_csv(double time, char delimiter, const std::string &comment_string, unsigned int repeat=0)
Perform output in csv format.
std::vector< unsigned int > add_quantities(const std::vector< string > &names)
Dedicated class for storing path to input and output files.
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)
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.
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_
unsigned int output_line_counter_
hold count of line printed into output_
void output(double time)
Perform output to file for given time instant.
void add_source_matrix_values(unsigned int quantity_idx, unsigned int region_idx, const std::vector< int > &dof_indices, const std::vector< double > &values)
void start_source_assembly(unsigned int quantity_idx)
static Input::Type::Selection format_selection_input_type
Input selection for file format.
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