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);
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";
305 data_->conc_fe.resize(Model::n_substances());
308 shared_ptr<DiscreteSpace> ds = make_shared<EqualOrderDiscreteSpace>(Model::mesh_, fe);
309 data_->dh_p0 = make_shared<DOFHandlerMultiDim>(*Model::mesh_);
310 data_->dh_p0->distribute_dofs(ds);
314 mass_matrix.resize(Model::n_substances(),
nullptr);
315 rhs.resize(Model::n_substances(),
nullptr);
316 mass_vec.resize(Model::n_substances(),
nullptr);
317 data_->ret_vec.resize(Model::n_substances(),
nullptr);
319 for (
unsigned int sbi = 0; sbi < Model::n_substances(); sbi++) {
327 data_->conc_fe[sbi] = create_field_fe< 3, FieldValue<3>::Scalar >(
data_->dh_p0);
329 VecDuplicate(
data_->ls[sbi]->get_solution(), &
data_->ret_vec[sbi]);
334 Model::balance_->allocate(
data_->dh_->distr()->lsize(),
data_->mass_assembly_->eval_points()->max_size());
337 data_->mass_assembly_->multidim_assembly()[1_d]->initialize(*
this);
338 data_->mass_assembly_->multidim_assembly()[2_d]->initialize(*
this);
339 data_->mass_assembly_->multidim_assembly()[3_d]->initialize(*
this);
340 data_->stiffness_assembly_->multidim_assembly()[1_d]->initialize(*
this);
341 data_->stiffness_assembly_->multidim_assembly()[2_d]->initialize(*
this);
342 data_->stiffness_assembly_->multidim_assembly()[3_d]->initialize(*
this);
343 data_->sources_assembly_->multidim_assembly()[1_d]->initialize(*
this);
344 data_->sources_assembly_->multidim_assembly()[2_d]->initialize(*
this);
345 data_->sources_assembly_->multidim_assembly()[3_d]->initialize(*
this);
346 data_->bdr_cond_assembly_->multidim_assembly()[1_d]->initialize(*
this);
347 data_->bdr_cond_assembly_->multidim_assembly()[2_d]->initialize(*
this);
348 data_->bdr_cond_assembly_->multidim_assembly()[3_d]->initialize(*
this);
349 data_->init_cond_assembly_->multidim_assembly()[1_d]->initialize(*
this);
350 data_->init_cond_assembly_->multidim_assembly()[2_d]->initialize(*
this);
351 data_->init_cond_assembly_->multidim_assembly()[3_d]->initialize(*
this);
355 template<
class Model>
360 if (
data_->gamma.size() > 0) {
363 for (
unsigned int i=0; i<Model::n_substances(); i++)
366 delete data_->ls_dt[i];
376 if (
data_->ret_vec[i])
380 delete[]
data_->ls_dt;
387 delete data_->mass_assembly_;
388 delete data_->stiffness_assembly_;
389 delete data_->sources_assembly_;
390 delete data_->bdr_cond_assembly_;
391 delete data_->init_cond_assembly_;
397 template<
class Model>
401 data_->mark_input_times( *(Model::time_) );
403 std::stringstream ss;
411 for (
unsigned int sbi = 0; sbi < Model::n_substances(); sbi++)
418 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
420 Model::balance_->calculate_instant(Model::subst_idx[sbi],
data_->ls[sbi]->get_solution());
430 template<
class Model>
434 for (
unsigned int i=0; i<Model::n_substances(); i++)
437 data_->ls[i]->start_allocation();
442 data_->ls_dt[i]->start_allocation();
444 VecZeroEntries(
data_->ret_vec[i]);
447 data_->stiffness_assembly_->assemble(
data_->dh_);
453 data_->sources_assembly_->assemble(
data_->dh_);
456 data_->bdr_cond_assembly_->assemble(
data_->dh_);
458 for (
unsigned int i=0; i<Model::n_substances(); i++)
460 VecAssemblyBegin(
data_->ret_vec[i]);
461 VecAssemblyEnd(
data_->ret_vec[i]);
469 template<
class Model>
474 Model::time_->next_time();
475 Model::time_->view(
"TDG");
484 for (
unsigned int i=0; i<Model::n_substances(); i++)
486 data_->ls_dt[i]->start_add_assembly();
487 data_->ls_dt[i]->mat_zero_entries();
488 VecZeroEntries(
data_->ret_vec[i]);
493 for (
unsigned int i=0; i<Model::n_substances(); i++)
495 data_->ls_dt[i]->finish_assembly();
496 VecAssemblyBegin(
data_->ret_vec[i]);
497 VecAssemblyEnd(
data_->ret_vec[i]);
503 MatConvert(*(
data_->ls_dt[i]->get_matrix() ), MATSAME, MAT_INITIAL_MATRIX, &
mass_matrix[i]);
506 MatCopy(*(
data_->ls_dt[i]->get_matrix() ),
mass_matrix[i], DIFFERENT_NONZERO_PATTERN);
513 ||
data_->flow_flux.changed())
517 for (
unsigned int i=0; i<Model::n_substances(); i++)
519 data_->ls[i]->start_add_assembly();
520 data_->ls[i]->mat_zero_entries();
523 data_->stiffness_assembly_->assemble(
data_->dh_);
525 for (
unsigned int i=0; i<Model::n_substances(); i++)
527 data_->ls[i]->finish_assembly();
539 ||
data_->flow_flux.changed())
541 for (
unsigned int i=0; i<Model::n_substances(); i++)
543 data_->ls[i]->start_add_assembly();
544 data_->ls[i]->rhs_zero_entries();
547 data_->sources_assembly_->assemble(
data_->dh_);
550 data_->bdr_cond_assembly_->assemble(
data_->dh_);
552 for (
unsigned int i=0; i<Model::n_substances(); i++)
554 data_->ls[i]->finish_assembly();
556 if (
rhs[i] ==
nullptr) VecDuplicate(*(
data_->ls[i]->get_rhs() ), &
rhs[i]);
557 VecCopy(*(
data_->ls[i]->get_rhs() ),
rhs[i]);
580 for (
unsigned int i=0; i<Model::n_substances(); i++)
583 MatAXPY(m, 1./Model::time_->dt(),
mass_matrix[i], SUBSET_NONZERO_PATTERN);
584 data_->ls[i]->set_matrix(m, DIFFERENT_NONZERO_PATTERN);
586 VecDuplicate(
rhs[i], &w);
587 VecWAXPY(w, 1./Model::time_->dt(),
mass_vec[i],
rhs[i]);
588 data_->ls[i]->set_rhs(w);
593 data_->ls[i]->solve();
606 template<
class Model>
610 for (
auto cell :
data_->dh_->own_range() )
612 LocDofVec loc_dof_indices = cell.get_loc_dof_indices();
613 unsigned int n_dofs=loc_dof_indices.n_rows;
618 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
620 data_->conc_fe[sbi]->vec()[dof_p0] = 0;
622 for (
unsigned int j=0; j<n_dofs; ++j)
623 data_->conc_fe[sbi]->vec()[dof_p0] +=
data_->ls[sbi]->get_solution_array()[loc_dof_indices[j]];
625 data_->conc_fe[sbi]->vec()[dof_p0] = max(
data_->conc_fe[sbi]->vec()[dof_p0]/n_dofs, 0.);
633 template<
class Model>
644 data_->output_fields.output(this->
time().step());
646 Model::output_data();
649 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
650 Model::balance_->calculate_instant(Model::subst_idx[sbi],
data_->ls[sbi]->get_solution());
651 Model::balance_->output();
658 template<
class Model>
661 if (Model::balance_->cumulative())
663 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
665 Model::balance_->calculate_cumulative(Model::subst_idx[sbi],
data_->ls[sbi]->get_solution());
679 template<
class Model>
683 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
684 data_->ls[sbi]->start_allocation();
685 data_->init_cond_assembly_->assemble(
data_->dh_);
687 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
688 data_->ls[sbi]->start_add_assembly();
689 data_->init_cond_assembly_->assemble(
data_->dh_);
691 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
693 data_->ls[sbi]->finish_assembly();
694 data_->ls[sbi]->solve();
700 template<
class Model>
703 el_4_loc = Model::mesh_->get_el_4_loc();
704 el_ds = Model::mesh_->get_el_ds();
708 template<
class Model>
711 if (solution_changed)
713 for (
auto cell :
data_->dh_->own_range() )
715 LocDofVec loc_dof_indices = cell.get_loc_dof_indices();
716 unsigned int n_dofs=loc_dof_indices.n_rows;
721 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
723 double old_average = 0;
724 for (
unsigned int j=0; j<n_dofs; ++j)
725 old_average +=
data_->ls[sbi]->get_solution_array()[loc_dof_indices[j]];
726 old_average /= n_dofs;
728 for (
unsigned int j=0; j<n_dofs; ++j)
729 data_->ls[sbi]->get_solution_array()[loc_dof_indices[j]]
730 +=
data_->conc_fe[sbi]->vec()[dof_p0] - old_average;
735 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
736 MatMult(*(
data_->ls_dt[sbi]->get_matrix()),
data_->ls[sbi]->get_solution(),
mass_vec[sbi]);
739 template<
class Model>
742 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...
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.
Cell accessor allow iterate over DOF handler cells.
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.
LocDofVec get_loc_dof_indices() const
Returns the local indices of dofs associated to the cell on the local process.
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.
void compute_p0_interpolation()
Compute P0 interpolation of the solution (used in reaction term).
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.
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.