52 return Selection(
"DG_variant",
"Type of penalty term.")
53 .
add_value(non_symmetric,
"non-symmetric",
"non-symmetric weighted interior penalty DG method")
54 .
add_value(incomplete,
"incomplete",
"incomplete weighted interior penalty DG method")
55 .
add_value(symmetric,
"symmetric",
"symmetric weighted interior penalty DG method")
78 std::string equation_name = std::string(Model::ModelEqData::name()) +
"_DG";
79 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 "If true, use DG projection of the initial condition field."
94 "Otherwise, evaluate initial condition field directly (well suited for reading native data).")
96 EqFields().output_fields.make_output_type(equation_name,
""),
97 IT::Default(
"{ \"fields\": [ " + Model::ModelEqData::default_output_field() +
"] }"),
98 "Specification of output fields and output times.")
102 template<
class Model>
104 Input::register_class< TransportDG<Model>,
Mesh &,
const Input::Record>(std::string(Model::ModelEqData::name()) +
"_DG") +
109 template<
class Model>
113 .
name(
"fracture_sigma")
115 "Coefficient of diffusive transfer through fractures (for each substance).")
123 "Penalty parameter influencing the discontinuity of the solution (for each substance). "
124 "Its default value 1 is sufficient in most cases. Higher value diminishes the inter-element jumps.")
137 .
description(
"Subdomain ids of the domain decomposition.");
143 this->add_coords_field();
144 this->set_default_fieldset();
149 template<
typename Model>
151 :
Model(init_mesh, in_rec),
165 Model::init_balance(in_rec);
176 eq_data_->dg_order = in_rec.
val<
unsigned int>(
"dg_order");
178 Model::init_from_input(in_rec);
181 shared_ptr<DiscreteSpace> ds = make_shared<EqualOrderDiscreteSpace>(Model::mesh_, fe);
182 eq_data_->dh_ = make_shared<DOFHandlerMultiDim>(*Model::mesh_);
189 template<
class Model>
192 eq_fields_->set_components(eq_data_->substances_.names());
193 eq_fields_->set_input_list( input_rec.val<
Input::Array>(
"input_fields"), *(Model::time_) );
194 eq_data_->set_time_governor(Model::time_);
195 eq_data_->balance_ = this->balance();
196 eq_fields_->initialize();
199 eq_data_->max_edg_sides = max(Model::mesh_->max_edge_sides(1), max(Model::mesh_->max_edge_sides(2), Model::mesh_->max_edge_sides(3)));
200 ret_sources.resize(eq_data_->n_substances());
201 ret_sources_prev.resize(eq_data_->n_substances());
204 if (input_rec.opt_val(
"user_fields", user_fields_arr)) {
205 this->init_user_fields(user_fields_arr, eq_fields_->output_fields);
208 eq_data_->output_vec.resize(eq_data_->n_substances());
209 eq_fields_->output_field.set_components(eq_data_->substances_.names());
210 eq_fields_->output_field.set_mesh(*Model::mesh_);
211 eq_fields_->output_fields.set_mesh(*Model::mesh_);
214 eq_fields_->output_field.setup_components();
215 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
219 eq_fields_->output_field[sbi].set(output_field_ptr, 0);
220 eq_data_->output_vec[sbi] = output_field_ptr->vec();
224 eq_fields_->output_fields.initialize(Model::output_stream_, Model::mesh_, input_rec.val<
Input::Record>(
"output"), this->time());
227 std::string petsc_default_opts;
228 if (eq_data_->dh_->distr()->np() == 1)
229 petsc_default_opts =
"-ksp_type bcgs -pc_type ilu -pc_factor_levels 2 -ksp_diagonal_scale_fix -pc_factor_fill 6.0";
231 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";
234 eq_data_->ls =
new LinSys*[eq_data_->n_substances()];
235 eq_data_->ls_dt =
new LinSys*[eq_data_->n_substances()];
236 eq_data_->conc_fe.resize(eq_data_->n_substances());
239 shared_ptr<DiscreteSpace> ds = make_shared<EqualOrderDiscreteSpace>(Model::mesh_, fe);
240 eq_data_->dh_p0 = make_shared<DOFHandlerMultiDim>(*Model::mesh_);
241 eq_data_->dh_p0->distribute_dofs(ds);
243 stiffness_matrix.resize(eq_data_->n_substances(),
nullptr);
244 mass_matrix.resize(eq_data_->n_substances(),
nullptr);
245 rhs.resize(eq_data_->n_substances(),
nullptr);
246 mass_vec.resize(eq_data_->n_substances(),
nullptr);
247 eq_data_->ret_vec.resize(eq_data_->n_substances(),
nullptr);
249 for (
unsigned int sbi = 0; sbi < eq_data_->n_substances(); sbi++) {
250 eq_data_->ls[sbi] =
new LinSys_PETSC(eq_data_->dh_->distr().get(), petsc_default_opts);
252 eq_data_->ls[sbi]->set_solution(eq_data_->output_vec[sbi].petsc_vec());
254 eq_data_->ls_dt[sbi] =
new LinSys_PETSC(eq_data_->dh_->distr().get(), petsc_default_opts);
259 VecDuplicate(eq_data_->ls[sbi]->get_solution(), &eq_data_->ret_vec[sbi]);
263 init_projection = input_rec.val<
bool>(
"init_projection");
277 Model::balance_->allocate(eq_data_->dh_->distr()->lsize(), mass_assembly_->eval_points()->max_size());
279 eq_fields_->init_condition.setup_components();
280 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
287 template<
class Model>
292 if (rhs.size() > 0) {
295 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
297 if (eq_data_->ls !=
nullptr) {
298 delete eq_data_->ls[i];
299 delete eq_data_->ls_dt[i];
302 if (stiffness_matrix.size() > 0) {
303 if (stiffness_matrix[i])
304 chkerr(MatDestroy(&stiffness_matrix[i]));
306 chkerr(MatDestroy(&mass_matrix[i]));
308 chkerr(VecDestroy(&rhs[i]));
310 chkerr(VecDestroy(&mass_vec[i]));
311 if (eq_data_->ret_vec[i])
312 chkerr(VecDestroy(&eq_data_->ret_vec[i]));
315 if (eq_data_->ls !=
nullptr) {
316 delete[] eq_data_->ls;
317 delete[] eq_data_->ls_dt;
318 eq_data_->ls =
nullptr;
326 if (mass_assembly_ !=
nullptr) {
327 delete mass_assembly_;
328 delete stiffness_assembly_;
329 delete sources_assembly_;
330 delete bdr_cond_assembly_;
331 delete init_assembly_;
339 template<
class Model>
343 eq_fields_->mark_input_times( *(Model::time_) );
345 std::stringstream ss;
352 set_initial_condition();
353 for (
unsigned int sbi = 0; sbi < eq_data_->n_substances(); sbi++)
354 ( (
LinSys_PETSC *)eq_data_->ls[sbi] )->set_initial_guess_nonzero();
357 if (!allocation_done) preallocate();
360 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); ++sbi)
362 Model::balance_->calculate_instant(eq_data_->subst_idx_[sbi], eq_data_->ls[sbi]->get_solution());
365 ret_sources_prev[sbi] = 0;
372 template<
class Model>
376 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
379 eq_data_->ls[i]->start_allocation();
380 stiffness_matrix[i] = NULL;
384 eq_data_->ls_dt[i]->start_allocation();
385 mass_matrix[i] = NULL;
386 VecZeroEntries(eq_data_->ret_vec[i]);
388 stiffness_assembly_->assemble(eq_data_->dh_);
389 mass_assembly_->assemble(eq_data_->dh_);
390 sources_assembly_->assemble(eq_data_->dh_);
391 bdr_cond_assembly_->assemble(eq_data_->dh_);
392 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
394 VecAssemblyBegin(eq_data_->ret_vec[i]);
395 VecAssemblyEnd(eq_data_->ret_vec[i]);
398 allocation_done =
true;
403 template<
class Model>
408 Model::time_->next_time();
409 Model::time_->view(
"TDG");
418 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
420 eq_data_->ls_dt[i]->start_add_assembly();
421 eq_data_->ls_dt[i]->mat_zero_entries();
422 VecZeroEntries(eq_data_->ret_vec[i]);
424 mass_assembly_->assemble(eq_data_->dh_);
425 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
427 eq_data_->ls_dt[i]->finish_assembly();
428 VecAssemblyBegin(eq_data_->ret_vec[i]);
429 VecAssemblyEnd(eq_data_->ret_vec[i]);
431 if (mass_matrix[i] == NULL)
433 VecDuplicate(eq_data_->ls[i]->get_solution(), &mass_vec[i]);
434 MatMult(*(eq_data_->ls_dt[i]->get_matrix()), eq_data_->ls[i]->get_solution(), mass_vec[i]);
435 MatConvert(*( eq_data_->ls_dt[i]->get_matrix() ), MATSAME, MAT_INITIAL_MATRIX, &mass_matrix[i]);
438 MatCopy(*( eq_data_->ls_dt[i]->get_matrix() ), mass_matrix[i], DIFFERENT_NONZERO_PATTERN);
443 if (stiffness_matrix[0] == NULL
445 || eq_fields_->flow_flux.changed())
449 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
451 eq_data_->ls[i]->start_add_assembly();
452 eq_data_->ls[i]->mat_zero_entries();
454 stiffness_assembly_->assemble(eq_data_->dh_);
455 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
457 eq_data_->ls[i]->finish_assembly();
459 if (stiffness_matrix[i] == NULL)
460 MatConvert(*( eq_data_->ls[i]->get_matrix() ), MATSAME, MAT_INITIAL_MATRIX, &stiffness_matrix[i]);
462 MatCopy(*( eq_data_->ls[i]->get_matrix() ), stiffness_matrix[i], DIFFERENT_NONZERO_PATTERN);
469 || eq_fields_->flow_flux.changed())
471 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
473 eq_data_->ls[i]->start_add_assembly();
474 eq_data_->ls[i]->rhs_zero_entries();
476 sources_assembly_->assemble(eq_data_->dh_);
477 bdr_cond_assembly_->assemble(eq_data_->dh_);
478 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
480 eq_data_->ls[i]->finish_assembly();
482 if (rhs[i] ==
nullptr) VecDuplicate(*( eq_data_->ls[i]->get_rhs() ), &rhs[i]);
483 VecCopy(*( eq_data_->ls[i]->get_rhs() ), rhs[i]);
505 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
507 MatConvert(stiffness_matrix[i], MATSAME, MAT_INITIAL_MATRIX, &m);
508 MatAXPY(m, 1./Model::time_->dt(), mass_matrix[i], SUBSET_NONZERO_PATTERN);
509 eq_data_->ls[i]->set_matrix(m, DIFFERENT_NONZERO_PATTERN);
511 VecDuplicate(rhs[i], &w);
512 VecWAXPY(w, 1./Model::time_->dt(), mass_vec[i], rhs[i]);
513 eq_data_->ls[i]->set_rhs(w);
518 eq_data_->ls[i]->solve();
521 MatMult(*(eq_data_->ls_dt[i]->get_matrix()), eq_data_->ls[i]->get_solution(), mass_vec[i]);
532 calculate_cumulative_balance();
538 template<
class Model>
542 for (
auto cell : eq_data_->dh_->own_range() )
544 LocDofVec loc_dof_indices = cell.get_loc_dof_indices();
545 unsigned int n_dofs=loc_dof_indices.n_rows;
547 DHCellAccessor dh_p0_cell = eq_data_->dh_p0->cell_accessor_from_element(cell.elm_idx());
550 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); ++sbi)
552 eq_data_->conc_fe[sbi]->vec().set(dof_p0, 0);
554 for (
unsigned int j=0; j<n_dofs; ++j)
555 eq_data_->conc_fe[sbi]->vec().add( dof_p0, eq_data_->ls[sbi]->get_solution_array()[loc_dof_indices[j]] );
557 eq_data_->conc_fe[sbi]->vec().set( dof_p0, max(eq_data_->conc_fe[sbi]->vec().get(dof_p0)/n_dofs, 0.) );
565 template<
class Model>
574 eq_fields_->output_fields.set_time( this->time().step(),
LimitSide::left);
576 eq_fields_->output_fields.output(this->time().step());
578 Model::output_data();
581 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); ++sbi)
582 Model::balance_->calculate_instant(eq_data_->subst_idx_[sbi], eq_data_->ls[sbi]->get_solution());
583 Model::balance_->output();
590 template<
class Model>
593 if (Model::balance_->cumulative())
595 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); ++sbi)
597 Model::balance_->calculate_cumulative(eq_data_->subst_idx_[sbi], eq_data_->ls[sbi]->get_solution());
600 VecDot(eq_data_->ret_vec[sbi], eq_data_->ls[sbi]->get_solution(), &ret_sources[sbi]);
602 Model::balance_->add_cumulative_source(eq_data_->subst_idx_[sbi], (ret_sources[sbi]-ret_sources_prev[sbi])/Model::time_->dt());
603 ret_sources_prev[sbi] = ret_sources[sbi];
611 template<
class Model>
616 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
617 eq_data_->ls[sbi]->start_allocation();
619 init_assembly_->assemble(eq_data_->dh_);
621 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
622 eq_data_->ls[sbi]->start_add_assembly();
624 init_assembly_->assemble(eq_data_->dh_);
626 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
628 eq_data_->ls[sbi]->finish_assembly();
629 eq_data_->ls[sbi]->solve();
633 init_assembly_->assemble(eq_data_->dh_);
637 template<
class Model>
640 if (solution_changed)
642 for (
auto cell : eq_data_->dh_->own_range() )
644 LocDofVec loc_dof_indices = cell.get_loc_dof_indices();
645 unsigned int n_dofs=loc_dof_indices.n_rows;
647 DHCellAccessor dh_p0_cell = eq_data_->dh_p0->cell_accessor_from_element(cell.elm_idx());
650 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); ++sbi)
652 double old_average = 0;
653 for (
unsigned int j=0; j<n_dofs; ++j)
654 old_average += eq_data_->ls[sbi]->get_solution_array()[loc_dof_indices[j]];
655 old_average /= n_dofs;
657 for (
unsigned int j=0; j<n_dofs; ++j)
658 eq_data_->ls[sbi]->get_solution_array()[loc_dof_indices[j]]
659 += eq_data_->conc_fe[sbi]->vec().get(dof_p0) - old_average;
664 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); ++sbi)
665 MatMult(*(eq_data_->ls_dt[sbi]->get_matrix()), eq_data_->ls[sbi]->get_solution(), mass_vec[sbi]);
Discontinuous Galerkin method for equation of transport with dispersion.
Cell accessor allow iterate over DOF handler cells.
LocDofVec get_loc_dof_indices() const
Returns the local indices of dofs associated to the cell on the local process.
static Input::Type::Record & user_fields_template(std::string equation_name)
Template Record with common key user_fields for derived equations.
static bool print_message_table(ostream &stream, std::string equation_name)
FieldCommon & description(const string &description)
FieldCommon & flags_add(FieldFlag::Flags::Mask mask)
FieldCommon & flags(FieldFlag::Flags::Mask mask)
FieldCommon & name(const string &name)
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
FieldCommon & input_default(const string &input_default)
static constexpr Mask in_time_term
A field is part of time term of the equation.
static constexpr Mask equation_external_output
Match an output field, that can be also copy of other field.
static constexpr Mask in_rhs
A field is part of the right hand side of the equation.
static constexpr Mask in_main_matrix
A field is part of main "stiffness matrix" of the equation.
Generic class of assemblation.
static auto region_id(Mesh &mesh) -> IndexField
static auto subdomain(Mesh &mesh) -> IndexField
static const Input::Type::Record & get_input_type()
Field< 3, FieldValue< 3 >::Scalar > region_id
MultiField< 3, FieldValue< 3 >::Scalar > dg_penalty
Penalty enforcing inter-element continuity of solution (for each substance).
EquationOutput output_fields
Field< 3, FieldValue< 3 >::Scalar > subdomain
MultiField< 3, FieldValue< 3 >::Scalar > fracture_sigma
Transition parameter for diffusive transfer on fractures (for each substance).
Transport with dispersion implemented using discontinuous Galerkin method.
void update_solution() override
Computes the solution in one time instant.
static const Input::Type::Record & get_input_type()
Declare input record type for the equation TransportDG.
bool allocation_done
Indicates whether matrices have been preallocated.
Input::Record input_rec
Array for storing the output solution data.
void zero_time_step() override
Initialize solution in the zero time.
std::shared_ptr< EqFields > eq_fields_
Fields for model parameters.
void initialize() override
GenericAssembly< MassAssemblyDim > * mass_assembly_
general assembly objects, hold assembly objects of appropriate dimension
static const Input::Type::Selection & get_dg_variant_selection_input_type()
Input type for the DG variant selection.
TransportDG(Mesh &init_mesh, const Input::Record in_rec)
Constructor.
~TransportDG() override
Destructor.
void compute_p0_interpolation()
Compute P0 interpolation of the solution (used in reaction term).
void output_data()
Postprocesses the solution and writes to output file.
void calculate_cumulative_balance()
void set_initial_condition()
Calculates the dispersivity (diffusivity) tensor from the velocity field.
std::shared_ptr< EqData > eq_data_
Data for model parameters.
void update_after_reactions(bool solution_changed)
static UnitSI & dimensionless()
Returns dimensionless unit.
Discontinuous Galerkin method for equation of transport with dispersion.
Definitions of basic Lagrangean finite elements with polynomial shape functions.
Definitions of Raviart-Thomas finite elements.
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Discontinuous Galerkin method for equation of transport with dispersion.
arma::Col< IntIdx > LocDofVec
static constexpr bool value
Solver based on the original PETSc solver using MPIAIJ matrix and succesive Schur complement construc...
#define WarningOut()
Macro defining 'warning' record of log.
Definitions of particular quadrature rules on simplices.
#define END_TIMER(tag)
Ends a timer with specified tag.
#define START_TIMER(tag)
Starts a timer with specified tag.
void chkerr(unsigned int ierr)
Replacement of new/delete operator in the spirit of xmalloc.
Discontinuous Galerkin method for equation of transport with dispersion.