49 using namespace
Input::Type;
53 return Selection(
"DG_variant",
"Type of penalty term.")
54 .
add_value(non_symmetric,
"non-symmetric",
"non-symmetric weighted interior penalty DG method")
55 .
add_value(incomplete,
"incomplete",
"incomplete weighted interior penalty DG method")
56 .
add_value(symmetric,
"symmetric",
"symmetric weighted interior penalty DG method")
79 std::string equation_name = std::string(Model::ModelEqData::name()) +
"_DG";
80 return Model::get_input_type(
"DG",
"Discontinuous Galerkin (DG) solver")
82 "Solver for the linear system.")
85 .make_field_descriptor_type(equation_name)),
87 "Input fields of the equation.")
89 "Variant of the interior penalty discontinuous Galerkin method.")
91 "Polynomial order for the finite element in DG method (order 0 is suitable if there is no diffusion/dispersion).")
93 EqData().output_fields.make_output_type(equation_name,
""),
94 IT::Default(
"{ \"fields\": [ " + Model::ModelEqData::default_output_field() +
"] }"),
95 "Specification of output fields and output times.")
101 Input::register_class< TransportDG<Model>,
Mesh &,
const Input::Record>(std::string(Model::ModelEqData::name()) +
"_DG") +
106 template<
class Model>
110 .
name(
"fracture_sigma")
112 "Coefficient of diffusive transfer through fractures (for each substance).")
120 "Penalty parameter influencing the discontinuity of the solution (for each substance). " 121 "Its default value 1 is sufficient in most cases. Higher value diminishes the inter-element jumps.")
134 .
description(
"Subdomain ids of the domain decomposition.");
145 template<
class Model>
148 double h_max = 0, h_min = numeric_limits<double>::infinity();
149 for (
unsigned int i=0; i<e->
n_nodes(); i++)
150 for (
unsigned int j=i+1; j<e->
n_nodes(); j++)
152 double dist = arma::norm(*e.
node(i) - *e.
node(j));
153 h_max = max(h_max, dist);
154 h_min = min(h_min, dist);
161 template<
class Model>
170 double delta = 0, h = 0;
179 for (
unsigned int i=0; i<side.
n_nodes(); i++)
180 for (
unsigned int j=i+1; j<side.
n_nodes(); j++) {
181 double dist = arma::norm(*side.
node(i) - *side.
node(j));
188 for (
int k=0; k<K_size; k++)
189 delta += dot(K[k]*normal_vector,normal_vector);
197 template<
typename Model>
199 :
Model(init_mesh, in_rec),
209 data_ = make_shared<EqData>();
214 data_->set_mesh(init_mesh);
221 data_->dg_order = in_rec.
val<
unsigned int>(
"dg_order");
223 Model::init_from_input(in_rec);
234 shared_ptr<DiscreteSpace> ds = make_shared<EqualOrderDiscreteSpace>(Model::mesh_, fe);
235 data_->dh_ = make_shared<DOFHandlerMultiDim>(*Model::mesh_);
236 data_->dh_->distribute_dofs(ds);
242 template<
class Model>
245 data_->set_components(Model::substances_.names());
249 data_->gamma.resize(Model::n_substances());
250 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
251 data_->gamma[sbi].resize(Model::mesh_->boundary_.size());
254 int qsize =
data_->mass_assembly_->eval_points()->max_size();
255 int max_edg_sides = max(Model::mesh_->max_edge_sides(1), max(Model::mesh_->max_edge_sides(2), Model::mesh_->max_edge_sides(3)));
258 data_->ad_coef.resize(Model::n_substances());
259 data_->dif_coef.resize(Model::n_substances());
260 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
262 data_->ad_coef[sbi].resize(qsize);
263 data_->dif_coef[sbi].resize(qsize);
265 data_->ad_coef_edg.resize(max_edg_sides);
266 data_->dif_coef_edg.resize(max_edg_sides);
267 for (
int sd=0; sd<max_edg_sides; sd++)
269 data_->ad_coef_edg[sd].resize(Model::n_substances());
270 data_->dif_coef_edg[sd].resize(Model::n_substances());
271 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
273 data_->ad_coef_edg[sd][sbi].resize(qsize);
274 data_->dif_coef_edg[sd][sbi].resize(qsize);
279 data_->output_field.set_components(Model::substances_.names());
280 data_->output_field.set_mesh(*Model::mesh_);
283 data_->output_field.setup_components();
284 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
289 data_->output_field[sbi].set_field(Model::mesh_->region_db().get_region_set(
"ALL"), output_field_ptr, 0);
296 std::string petsc_default_opts;
297 if (
data_->dh_->distr()->np() == 1)
298 petsc_default_opts =
"-ksp_type bcgs -pc_type ilu -pc_factor_levels 2 -ksp_diagonal_scale_fix -pc_factor_fill 6.0";
300 petsc_default_opts =
"-ksp_type bcgs -ksp_diagonal_scale_fix -pc_type asm -pc_asm_overlap 4 -sub_pc_type ilu -sub_pc_factor_levels 3 -sub_pc_factor_fill 6.0";
308 mass_matrix.resize(Model::n_substances(),
nullptr);
309 rhs.resize(Model::n_substances(),
nullptr);
310 mass_vec.resize(Model::n_substances(),
nullptr);
311 data_->ret_vec.resize(Model::n_substances(),
nullptr);
313 for (
unsigned int sbi = 0; sbi < Model::n_substances(); sbi++) {
320 solution_elem_[sbi] =
new double[Model::mesh_->get_el_ds()->lsize()];
322 VecDuplicate(
data_->ls[sbi]->get_solution(), &
data_->ret_vec[sbi]);
327 Model::balance_->allocate(
data_->dh_->distr()->lsize(),
data_->mass_assembly_->eval_points()->max_size());
330 data_->mass_assembly_->multidim_assembly()[1_d]->initialize(*
this);
331 data_->mass_assembly_->multidim_assembly()[2_d]->initialize(*
this);
332 data_->mass_assembly_->multidim_assembly()[3_d]->initialize(*
this);
333 data_->stiffness_assembly_->multidim_assembly()[1_d]->initialize(*
this);
334 data_->stiffness_assembly_->multidim_assembly()[2_d]->initialize(*
this);
335 data_->stiffness_assembly_->multidim_assembly()[3_d]->initialize(*
this);
336 data_->sources_assembly_->multidim_assembly()[1_d]->initialize(*
this);
337 data_->sources_assembly_->multidim_assembly()[2_d]->initialize(*
this);
338 data_->sources_assembly_->multidim_assembly()[3_d]->initialize(*
this);
339 data_->bdr_cond_assembly_->multidim_assembly()[1_d]->initialize(*
this);
340 data_->bdr_cond_assembly_->multidim_assembly()[2_d]->initialize(*
this);
341 data_->bdr_cond_assembly_->multidim_assembly()[3_d]->initialize(*
this);
342 data_->init_cond_assembly_->multidim_assembly()[1_d]->initialize(*
this);
343 data_->init_cond_assembly_->multidim_assembly()[2_d]->initialize(*
this);
344 data_->init_cond_assembly_->multidim_assembly()[3_d]->initialize(*
this);
348 template<
class Model>
353 if (
data_->gamma.size() > 0) {
356 for (
unsigned int i=0; i<Model::n_substances(); i++)
360 delete data_->ls_dt[i];
370 if (
data_->ret_vec[i])
375 delete[]
data_->ls_dt;
382 delete data_->mass_assembly_;
383 delete data_->stiffness_assembly_;
384 delete data_->sources_assembly_;
385 delete data_->bdr_cond_assembly_;
386 delete data_->init_cond_assembly_;
392 template<
class Model>
396 data_->mark_input_times( *(Model::time_) );
398 std::stringstream ss;
406 for (
unsigned int sbi = 0; sbi < Model::n_substances(); sbi++)
413 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
415 Model::balance_->calculate_instant(Model::subst_idx[sbi],
data_->ls[sbi]->get_solution());
425 template<
class Model>
429 for (
unsigned int i=0; i<Model::n_substances(); i++)
432 data_->ls[i]->start_allocation();
437 data_->ls_dt[i]->start_allocation();
439 VecZeroEntries(
data_->ret_vec[i]);
442 data_->stiffness_assembly_->assemble(
data_->dh_);
448 data_->sources_assembly_->assemble(
data_->dh_);
451 data_->bdr_cond_assembly_->assemble(
data_->dh_);
453 for (
unsigned int i=0; i<Model::n_substances(); i++)
455 VecAssemblyBegin(
data_->ret_vec[i]);
456 VecAssemblyEnd(
data_->ret_vec[i]);
464 template<
class Model>
469 Model::time_->next_time();
470 Model::time_->view(
"TDG");
479 for (
unsigned int i=0; i<Model::n_substances(); i++)
481 data_->ls_dt[i]->start_add_assembly();
482 data_->ls_dt[i]->mat_zero_entries();
483 VecZeroEntries(
data_->ret_vec[i]);
488 for (
unsigned int i=0; i<Model::n_substances(); i++)
490 data_->ls_dt[i]->finish_assembly();
491 VecAssemblyBegin(
data_->ret_vec[i]);
492 VecAssemblyEnd(
data_->ret_vec[i]);
498 MatConvert(*(
data_->ls_dt[i]->get_matrix() ), MATSAME, MAT_INITIAL_MATRIX, &
mass_matrix[i]);
501 MatCopy(*(
data_->ls_dt[i]->get_matrix() ),
mass_matrix[i], DIFFERENT_NONZERO_PATTERN);
508 || Model::flux_changed)
512 for (
unsigned int i=0; i<Model::n_substances(); i++)
514 data_->ls[i]->start_add_assembly();
515 data_->ls[i]->mat_zero_entries();
518 data_->stiffness_assembly_->assemble(
data_->dh_);
520 for (
unsigned int i=0; i<Model::n_substances(); i++)
522 data_->ls[i]->finish_assembly();
534 || Model::flux_changed)
536 for (
unsigned int i=0; i<Model::n_substances(); i++)
538 data_->ls[i]->start_add_assembly();
539 data_->ls[i]->rhs_zero_entries();
542 data_->sources_assembly_->assemble(
data_->dh_);
545 data_->bdr_cond_assembly_->assemble(
data_->dh_);
547 for (
unsigned int i=0; i<Model::n_substances(); i++)
549 data_->ls[i]->finish_assembly();
551 if (
rhs[i] ==
nullptr) VecDuplicate(*(
data_->ls[i]->get_rhs() ), &
rhs[i]);
552 VecCopy(*(
data_->ls[i]->get_rhs() ),
rhs[i]);
556 Model::flux_changed =
false;
577 for (
unsigned int i=0; i<Model::n_substances(); i++)
580 MatAXPY(m, 1./Model::time_->dt(),
mass_matrix[i], SUBSET_NONZERO_PATTERN);
581 data_->ls[i]->set_matrix(m, DIFFERENT_NONZERO_PATTERN);
583 VecDuplicate(
rhs[i], &w);
584 VecWAXPY(w, 1./Model::time_->dt(),
mass_vec[i],
rhs[i]);
585 data_->ls[i]->set_rhs(w);
590 data_->ls[i]->solve();
603 template<
class Model>
607 unsigned int i_cell=0;
608 for (
auto cell :
data_->dh_->own_range() )
610 LocDofVec loc_dof_indices = cell.get_loc_dof_indices();
611 unsigned int n_dofs=loc_dof_indices.n_rows;
613 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
617 for (
unsigned int j=0; j<n_dofs; ++j)
629 template<
class Model>
640 data_->output_fields.output(this->
time().step());
642 Model::output_data();
645 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
646 Model::balance_->calculate_instant(Model::subst_idx[sbi],
data_->ls[sbi]->get_solution());
647 Model::balance_->output();
654 template<
class Model>
657 if (Model::balance_->cumulative())
659 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
661 Model::balance_->calculate_cumulative(Model::subst_idx[sbi],
data_->ls[sbi]->get_solution());
675 template<
class Model>
679 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
680 data_->ls[sbi]->start_allocation();
681 data_->init_cond_assembly_->assemble(
data_->dh_);
683 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
684 data_->ls[sbi]->start_add_assembly();
685 data_->init_cond_assembly_->assemble(
data_->dh_);
687 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
689 data_->ls[sbi]->finish_assembly();
690 data_->ls[sbi]->solve();
696 template<
class Model>
699 el_4_loc = Model::mesh_->get_el_4_loc();
700 el_ds = Model::mesh_->get_el_ds();
704 template<
class Model>
707 if (solution_changed)
709 unsigned int i_cell=0;
710 for (
auto cell :
data_->dh_->own_range() )
712 LocDofVec loc_dof_indices = cell.get_loc_dof_indices();
713 unsigned int n_dofs=loc_dof_indices.n_rows;
715 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
717 double old_average = 0;
718 for (
unsigned int j=0; j<n_dofs; ++j)
719 old_average +=
data_->ls[sbi]->get_solution_array()[loc_dof_indices[j]];
720 old_average /= n_dofs;
722 for (
unsigned int j=0; j<n_dofs; ++j)
723 data_->ls[sbi]->get_solution_array()[loc_dof_indices[j]] +=
solution_elem_[sbi][i_cell] - old_average;
729 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
730 MatMult(*(
data_->ls_dt[sbi]->get_matrix()),
data_->ls[sbi]->get_solution(),
mass_vec[sbi]);
733 template<
class Model>
736 return Model::mesh_->get_row_4_el();
Input::Record input_rec
Record with input specification.
static auto subdomain(Mesh &mesh) -> IndexField
void get_par_info(LongIdx *&el_4_loc, Distribution *&el_ds)
unsigned int n_nodes() const
arma::Col< IntIdx > LocDofVec
double elem_anisotropy(ElementAccessor< 3 > e) const
Compute and return anisotropy of given element.
std::vector< std::vector< double > > gamma
Penalty parameters.
static constexpr Mask in_main_matrix
A field is part of main "stiffness matrix" of the equation.
Solver based on the original PETSc solver using MPIAIJ matrix and succesive Schur complement construc...
void calculate_concentration_matrix()
Transport with dispersion implemented using discontinuous Galerkin method.
FieldCommon & flags_add(FieldFlag::Flags::Mask mask)
void set_from_input(const Input::Record in_rec) override
vector< VectorMPI > output_vec
Array for storing the output solution data.
void update_solution() override
Computes the solution in one time instant.
Fields computed from the mesh data.
void set_initial_condition()
Calculates the dispersivity (diffusivity) tensor from the velocity field.
Class FEValues calculates finite element data on the actual cells such as shape function values...
void chkerr(unsigned int ierr)
Replacement of new/delete operator in the spirit of xmalloc.
Discontinuous Galerkin method for equation of transport with dispersion.
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
ElementAccessor< 3 > element() const
Returns iterator to the element of the side.
vector< double > ret_sources_prev
MultiField< 3, FieldValue< 3 >::Scalar > dg_penalty
Penalty enforcing inter-element continuity of solution (for each substance).
NodeAccessor< 3 > node(unsigned int ni) const
EquationOutput output_fields
std::vector< Mat > mass_matrix
The mass matrix.
void calculate_cumulative_balance()
static constexpr bool value
TransportDG(Mesh &init_mesh, const Input::Record in_rec)
Constructor.
void initialize() override
void output_data()
Postprocesses the solution and writes to output file.
MultiField< 3, FieldValue< 3 >::Scalar > fracture_sigma
Transition parameter for diffusive transfer on fractures (for each substance).
unsigned int dim() const
Returns dimension of the side, that is dimension of the element minus one.
static constexpr Mask in_time_term
A field is part of time term of the equation.
FieldCommon & input_default(const string &input_default)
Definitions of basic Lagrangean finite elements with polynomial shape functions.
static constexpr Mask equation_external_output
Match an output field, that can be also copy of other field.
Field< 3, FieldValue< 3 >::Scalar > subdomain
static auto region_id(Mesh &mesh) -> IndexField
#define START_TIMER(tag)
Starts a timer with specified tag.
std::vector< Vec > rhs
Vector of right hand side.
Field< 3, FieldValue< 3 >::Scalar > region_id
static constexpr Mask in_rhs
A field is part of the right hand side of the equation.
void set_DG_parameters_boundary(Side side, const int K_size, const std::vector< arma::mat33 > &K, const double flux, const arma::vec3 &normal_vector, const double alpha, double &gamma)
Sets up parameters of the DG method on a given boundary edge.
NodeAccessor< 3 > node(unsigned int i) const
Returns node for given local index i on the side.
Discontinuous Galerkin method for equation of transport with dispersion.
double ** solution_elem_
Element averages of solution (the array is passed to reactions in operator splitting).
std::vector< Mat > stiffness_matrix
The stiffness matrix.
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
FieldCommon & description(const string &description)
bool allocation_done
Indicates whether matrices have been preallocated.
static const Input::Type::Record & get_input_type()
Declare input record type for the equation TransportDG.
Discontinuous Galerkin method for equation of transport with dispersion.
void update_after_reactions(bool solution_changed)
vector< double > ret_sources
Temporary values of increments due to retardation (e.g. sorption)
Generic class of assemblation.
Definitions of particular quadrature rules on simplices.
#define WarningOut()
Macro defining 'warning' record of log.
FieldCommon & name(const string &name)
#define END_TIMER(tag)
Ends a timer with specified tag.
Discontinuous Galerkin method for equation of transport with dispersion.
static const Input::Type::Record & get_input_type()
std::vector< Vec > mass_vec
Mass from previous time instant (necessary when coefficients of mass matrix change in time)...
FieldCommon & flags(FieldFlag::Flags::Mask mask)
~TransportDG() override
Destructor.
static UnitSI & dimensionless()
Returns dimensionless unit.
static bool print_message_table(ostream &stream, std::string equation_name)
std::shared_ptr< EqData > data_
Field data for model parameters.
Definitions of Raviart-Thomas finite elements.
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
void zero_time_step() override
Initialize solution in the zero time.
unsigned int n_nodes() const
Returns number of nodes of the side.