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++)
287 auto output_field_ptr = create_field_fe< 3, FieldValue<3>::Scalar >(
data_->dh_);
288 data_->output_field[sbi].set_field(Model::mesh_->region_db().get_region_set(
"ALL"), output_field_ptr, 0);
289 output_vec[sbi] = output_field_ptr->get_data_vec();
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 ||
data_->flow_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 ||
data_->flow_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]);
575 for (
unsigned int i=0; i<Model::n_substances(); i++)
578 MatAXPY(m, 1./Model::time_->dt(),
mass_matrix[i], SUBSET_NONZERO_PATTERN);
579 data_->ls[i]->set_matrix(m, DIFFERENT_NONZERO_PATTERN);
581 VecDuplicate(
rhs[i], &w);
582 VecWAXPY(w, 1./Model::time_->dt(),
mass_vec[i],
rhs[i]);
583 data_->ls[i]->set_rhs(w);
588 data_->ls[i]->solve();
601 template<
class Model>
605 unsigned int i_cell=0;
606 for (
auto cell :
data_->dh_->own_range() )
608 LocDofVec loc_dof_indices = cell.get_loc_dof_indices();
609 unsigned int n_dofs=loc_dof_indices.n_rows;
611 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
615 for (
unsigned int j=0; j<n_dofs; ++j)
627 template<
class Model>
638 data_->output_fields.output(this->
time().step());
640 Model::output_data();
643 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
644 Model::balance_->calculate_instant(Model::subst_idx[sbi],
data_->ls[sbi]->get_solution());
645 Model::balance_->output();
652 template<
class Model>
655 if (Model::balance_->cumulative())
657 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
659 Model::balance_->calculate_cumulative(Model::subst_idx[sbi],
data_->ls[sbi]->get_solution());
673 template<
class Model>
677 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
678 data_->ls[sbi]->start_allocation();
679 data_->init_cond_assembly_->assemble(
data_->dh_);
681 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
682 data_->ls[sbi]->start_add_assembly();
683 data_->init_cond_assembly_->assemble(
data_->dh_);
685 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
687 data_->ls[sbi]->finish_assembly();
688 data_->ls[sbi]->solve();
694 template<
class Model>
697 el_4_loc = Model::mesh_->get_el_4_loc();
698 el_ds = Model::mesh_->get_el_ds();
702 template<
class Model>
705 if (solution_changed)
707 unsigned int i_cell=0;
708 for (
auto cell :
data_->dh_->own_range() )
710 LocDofVec loc_dof_indices = cell.get_loc_dof_indices();
711 unsigned int n_dofs=loc_dof_indices.n_rows;
713 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
715 double old_average = 0;
716 for (
unsigned int j=0; j<n_dofs; ++j)
717 old_average +=
data_->ls[sbi]->get_solution_array()[loc_dof_indices[j]];
718 old_average /= n_dofs;
720 for (
unsigned int j=0; j<n_dofs; ++j)
721 data_->ls[sbi]->get_solution_array()[loc_dof_indices[j]] +=
solution_elem_[sbi][i_cell] - old_average;
727 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
728 MatMult(*(
data_->ls_dt[sbi]->get_matrix()),
data_->ls[sbi]->get_solution(),
mass_vec[sbi]);
731 template<
class Model>
734 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.