54 return Selection(
"DG_variant",
"Type of penalty term.")
55 .
add_value(non_symmetric,
"non-symmetric",
"non-symmetric weighted interior penalty DG method")
56 .
add_value(incomplete,
"incomplete",
"incomplete weighted interior penalty DG method")
57 .
add_value(symmetric,
"symmetric",
"symmetric weighted interior penalty DG method")
80 std::string equation_name = std::string(Model::ModelEqData::name()) +
"_DG";
81 return Model::get_input_type(
"DG",
"Discontinuous Galerkin (DG) solver")
83 "Solver for the linear system.")
86 .get_user_field(equation_name)),
88 "Input fields of the equation defined by user.")
91 .make_field_descriptor_type(equation_name)),
93 "Input fields of the equation.")
95 "Variant of the interior penalty discontinuous Galerkin method.")
97 "Polynomial order for the finite element in DG method (order 0 is suitable if there is no diffusion/dispersion).")
99 "If true, use DG projection of the initial condition field."
100 "Otherwise, evaluate initial condition field directly (well suited for reading native data).")
102 EqFields().output_fields.make_output_type(equation_name,
""),
103 IT::Default(
"{ \"fields\": [ " + Model::ModelEqData::default_output_field() +
"] }"),
104 "Specification of output fields and output times.")
108 template<
class Model>
110 Input::register_class< TransportDG<Model>,
Mesh &,
const Input::Record>(std::string(Model::ModelEqData::name()) +
"_DG") +
115 template<
class Model>
119 .
name(
"fracture_sigma")
121 "Coefficient of diffusive transfer through fractures (for each substance).")
129 "Penalty parameter influencing the discontinuity of the solution (for each substance). "
130 "Its default value 1 is sufficient in most cases. Higher value diminishes the inter-element jumps.")
143 .
description(
"Subdomain ids of the domain decomposition.");
154 template<
class Model>
157 double h_max = 0, h_min = numeric_limits<double>::infinity();
158 for (
unsigned int i=0; i<e->
n_nodes(); i++)
159 for (
unsigned int j=i+1; j<e->
n_nodes(); j++)
161 double dist = arma::norm(*e.
node(i) - *e.
node(j));
162 h_max = max(h_max, dist);
163 h_min = min(h_min, dist);
170 template<
class Model>
179 double delta = 0, h = 0;
188 for (
unsigned int i=0; i<side.
n_nodes(); i++)
189 for (
unsigned int j=i+1; j<side.
n_nodes(); j++) {
190 double dist = arma::norm(*side.
node(i) - *side.
node(j));
197 for (
int k=0; k<K_size; k++)
198 delta += dot(K[k]*normal_vector,normal_vector);
201 gamma = 0.5*fabs(flux) + alpha/h*delta*elem_anisotropy(side.
element());
206 template<
typename Model>
208 :
Model(init_mesh, in_rec),
223 Model::init_balance(in_rec);
234 eq_data_->dg_order = in_rec.
val<
unsigned int>(
"dg_order");
236 Model::init_from_input(in_rec);
239 shared_ptr<DiscreteSpace> ds = make_shared<EqualOrderDiscreteSpace>(Model::mesh_, fe);
240 eq_data_->dh_ = make_shared<DOFHandlerMultiDim>(*Model::mesh_);
247 template<
class Model>
250 eq_fields_->set_components(eq_data_->substances_.names());
251 eq_fields_->set_input_list( input_rec.val<
Input::Array>(
"input_fields"), *(Model::time_) );
252 eq_data_->set_time_governor(Model::time_);
253 eq_data_->balance_ = this->
balance();
254 eq_fields_->initialize();
257 eq_data_->gamma.resize(eq_data_->n_substances());
258 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
259 eq_data_->gamma[sbi].resize(Model::mesh_->boundary_.size());
262 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)));
263 ret_sources.resize(eq_data_->n_substances());
264 ret_sources_prev.resize(eq_data_->n_substances());
266 eq_data_->output_vec.resize(eq_data_->n_substances());
267 eq_fields_->output_field.set_components(eq_data_->substances_.names());
268 eq_fields_->output_field.set_mesh(*Model::mesh_);
269 eq_fields_->output_fields.set_mesh(*Model::mesh_);
272 eq_fields_->output_field.setup_components();
273 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
276 auto output_field_ptr = create_field_fe< 3, FieldValue<3>::Scalar >(eq_data_->dh_);
277 eq_fields_->output_field[sbi].set(output_field_ptr, 0);
278 eq_data_->output_vec[sbi] = output_field_ptr->vec();
282 eq_fields_->output_fields.initialize(Model::output_stream_, Model::mesh_, input_rec.val<
Input::Record>(
"output"), this->
time());
285 std::string petsc_default_opts;
286 if (eq_data_->dh_->distr()->np() == 1)
287 petsc_default_opts =
"-ksp_type bcgs -pc_type ilu -pc_factor_levels 2 -ksp_diagonal_scale_fix -pc_factor_fill 6.0";
289 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";
292 eq_data_->ls =
new LinSys*[eq_data_->n_substances()];
293 eq_data_->ls_dt =
new LinSys*[eq_data_->n_substances()];
294 eq_data_->conc_fe.resize(eq_data_->n_substances());
297 shared_ptr<DiscreteSpace> ds = make_shared<EqualOrderDiscreteSpace>(Model::mesh_, fe);
298 eq_data_->dh_p0 = make_shared<DOFHandlerMultiDim>(*Model::mesh_);
299 eq_data_->dh_p0->distribute_dofs(ds);
301 stiffness_matrix.resize(eq_data_->n_substances(),
nullptr);
302 mass_matrix.resize(eq_data_->n_substances(),
nullptr);
303 rhs.resize(eq_data_->n_substances(),
nullptr);
304 mass_vec.resize(eq_data_->n_substances(),
nullptr);
305 eq_data_->ret_vec.resize(eq_data_->n_substances(),
nullptr);
307 for (
unsigned int sbi = 0; sbi < eq_data_->n_substances(); sbi++) {
308 eq_data_->ls[sbi] =
new LinSys_PETSC(eq_data_->dh_->distr().get(), petsc_default_opts);
310 eq_data_->ls[sbi]->set_solution(eq_data_->output_vec[sbi].petsc_vec());
312 eq_data_->ls_dt[sbi] =
new LinSys_PETSC(eq_data_->dh_->distr().get(), petsc_default_opts);
315 eq_data_->conc_fe[sbi] = create_field_fe< 3, FieldValue<3>::Scalar >(eq_data_->dh_p0);
317 VecDuplicate(eq_data_->ls[sbi]->get_solution(), &eq_data_->ret_vec[sbi]);
321 init_projection = input_rec.val<
bool>(
"init_projection");
335 Model::balance_->allocate(eq_data_->dh_->distr()->lsize(), mass_assembly_->eval_points()->max_size());
337 int qsize = mass_assembly_->eval_points()->max_size();
338 eq_data_->dif_coef.resize(eq_data_->n_substances());
339 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
341 eq_data_->dif_coef[sbi].resize(qsize);
344 eq_fields_->init_condition.setup_components();
345 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
351 if (input_rec.opt_val(
"user_fields", user_fields_arr)) {
352 eq_fields_->set_user_fields_map(user_fields_arr);
357 template<
class Model>
362 if (eq_data_->gamma.size() > 0) {
365 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
367 if (eq_data_->ls !=
nullptr) {
368 delete eq_data_->ls[i];
369 delete eq_data_->ls_dt[i];
372 if (stiffness_matrix.size() > 0) {
373 if (stiffness_matrix[i])
374 chkerr(MatDestroy(&stiffness_matrix[i]));
376 chkerr(MatDestroy(&mass_matrix[i]));
378 chkerr(VecDestroy(&rhs[i]));
380 chkerr(VecDestroy(&mass_vec[i]));
381 if (eq_data_->ret_vec[i])
382 chkerr(VecDestroy(&eq_data_->ret_vec[i]));
385 if (eq_data_->ls !=
nullptr) {
386 delete[] eq_data_->ls;
387 delete[] eq_data_->ls_dt;
388 eq_data_->ls =
nullptr;
396 if (mass_assembly_ !=
nullptr) {
397 delete mass_assembly_;
398 delete stiffness_assembly_;
399 delete sources_assembly_;
400 delete bdr_cond_assembly_;
401 delete init_assembly_;
408 template<
class Model>
412 eq_fields_->mark_input_times( *(Model::time_) );
414 std::stringstream ss;
421 set_initial_condition();
422 for (
unsigned int sbi = 0; sbi < eq_data_->n_substances(); sbi++)
423 ( (
LinSys_PETSC *)eq_data_->ls[sbi] )->set_initial_guess_nonzero();
426 if (!allocation_done) preallocate();
429 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); ++sbi)
431 Model::balance_->calculate_instant(eq_data_->subst_idx_[sbi], eq_data_->ls[sbi]->get_solution());
434 ret_sources_prev[sbi] = 0;
441 template<
class Model>
445 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
448 eq_data_->ls[i]->start_allocation();
449 stiffness_matrix[i] = NULL;
453 eq_data_->ls_dt[i]->start_allocation();
454 mass_matrix[i] = NULL;
455 VecZeroEntries(eq_data_->ret_vec[i]);
457 stiffness_assembly_->assemble(eq_data_->dh_);
458 mass_assembly_->assemble(eq_data_->dh_);
459 sources_assembly_->assemble(eq_data_->dh_);
460 bdr_cond_assembly_->assemble(eq_data_->dh_);
461 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
463 VecAssemblyBegin(eq_data_->ret_vec[i]);
464 VecAssemblyEnd(eq_data_->ret_vec[i]);
467 allocation_done =
true;
472 template<
class Model>
477 Model::time_->next_time();
478 Model::time_->view(
"TDG");
487 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
489 eq_data_->ls_dt[i]->start_add_assembly();
490 eq_data_->ls_dt[i]->mat_zero_entries();
491 VecZeroEntries(eq_data_->ret_vec[i]);
493 mass_assembly_->assemble(eq_data_->dh_);
494 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
496 eq_data_->ls_dt[i]->finish_assembly();
497 VecAssemblyBegin(eq_data_->ret_vec[i]);
498 VecAssemblyEnd(eq_data_->ret_vec[i]);
500 if (mass_matrix[i] == NULL)
502 VecDuplicate(eq_data_->ls[i]->get_solution(), &mass_vec[i]);
503 MatMult(*(eq_data_->ls_dt[i]->get_matrix()), eq_data_->ls[i]->get_solution(), mass_vec[i]);
504 MatConvert(*( eq_data_->ls_dt[i]->get_matrix() ), MATSAME, MAT_INITIAL_MATRIX, &mass_matrix[i]);
507 MatCopy(*( eq_data_->ls_dt[i]->get_matrix() ), mass_matrix[i], DIFFERENT_NONZERO_PATTERN);
512 if (stiffness_matrix[0] == NULL
514 || eq_fields_->flow_flux.changed())
518 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
520 eq_data_->ls[i]->start_add_assembly();
521 eq_data_->ls[i]->mat_zero_entries();
523 stiffness_assembly_->assemble(eq_data_->dh_);
524 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
526 eq_data_->ls[i]->finish_assembly();
528 if (stiffness_matrix[i] == NULL)
529 MatConvert(*( eq_data_->ls[i]->get_matrix() ), MATSAME, MAT_INITIAL_MATRIX, &stiffness_matrix[i]);
531 MatCopy(*( eq_data_->ls[i]->get_matrix() ), stiffness_matrix[i], DIFFERENT_NONZERO_PATTERN);
538 || eq_fields_->flow_flux.changed())
540 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
542 eq_data_->ls[i]->start_add_assembly();
543 eq_data_->ls[i]->rhs_zero_entries();
545 sources_assembly_->assemble(eq_data_->dh_);
546 bdr_cond_assembly_->assemble(eq_data_->dh_);
547 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
549 eq_data_->ls[i]->finish_assembly();
551 if (rhs[i] ==
nullptr) VecDuplicate(*( eq_data_->ls[i]->get_rhs() ), &rhs[i]);
552 VecCopy(*( eq_data_->ls[i]->get_rhs() ), rhs[i]);
574 for (
unsigned int i=0; i<eq_data_->n_substances(); i++)
576 MatConvert(stiffness_matrix[i], MATSAME, MAT_INITIAL_MATRIX, &m);
577 MatAXPY(m, 1./Model::time_->dt(), mass_matrix[i], SUBSET_NONZERO_PATTERN);
578 eq_data_->ls[i]->set_matrix(m, DIFFERENT_NONZERO_PATTERN);
580 VecDuplicate(rhs[i], &w);
581 VecWAXPY(w, 1./Model::time_->dt(), mass_vec[i], rhs[i]);
582 eq_data_->ls[i]->set_rhs(w);
587 eq_data_->ls[i]->solve();
590 MatMult(*(eq_data_->ls_dt[i]->get_matrix()), eq_data_->ls[i]->get_solution(), mass_vec[i]);
601 calculate_cumulative_balance();
607 template<
class Model>
611 for (
auto cell : eq_data_->dh_->own_range() )
613 LocDofVec loc_dof_indices = cell.get_loc_dof_indices();
614 unsigned int n_dofs=loc_dof_indices.n_rows;
616 DHCellAccessor dh_p0_cell = eq_data_->dh_p0->cell_accessor_from_element(cell.elm_idx());
619 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); ++sbi)
621 eq_data_->conc_fe[sbi]->vec().set(dof_p0, 0);
623 for (
unsigned int j=0; j<n_dofs; ++j)
624 eq_data_->conc_fe[sbi]->vec().add( dof_p0, eq_data_->ls[sbi]->get_solution_array()[loc_dof_indices[j]] );
626 eq_data_->conc_fe[sbi]->vec().set( dof_p0, max(eq_data_->conc_fe[sbi]->vec().get(dof_p0)/n_dofs, 0.) );
634 template<
class Model>
645 eq_fields_->output_fields.output(this->
time().step());
647 Model::output_data();
650 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); ++sbi)
651 Model::balance_->calculate_instant(eq_data_->subst_idx_[sbi], eq_data_->ls[sbi]->get_solution());
652 Model::balance_->output();
659 template<
class Model>
662 if (Model::balance_->cumulative())
664 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); ++sbi)
666 Model::balance_->calculate_cumulative(eq_data_->subst_idx_[sbi], eq_data_->ls[sbi]->get_solution());
669 VecDot(eq_data_->ret_vec[sbi], eq_data_->ls[sbi]->get_solution(), &ret_sources[sbi]);
671 Model::balance_->add_cumulative_source(eq_data_->subst_idx_[sbi], (ret_sources[sbi]-ret_sources_prev[sbi])/Model::time_->dt());
672 ret_sources_prev[sbi] = ret_sources[sbi];
680 template<
class Model>
685 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
686 eq_data_->ls[sbi]->start_allocation();
688 init_assembly_->assemble(eq_data_->dh_);
690 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
691 eq_data_->ls[sbi]->start_add_assembly();
693 init_assembly_->assemble(eq_data_->dh_);
695 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
697 eq_data_->ls[sbi]->finish_assembly();
698 eq_data_->ls[sbi]->solve();
702 init_assembly_->assemble(eq_data_->dh_);
706 template<
class Model>
709 if (solution_changed)
711 for (
auto cell : eq_data_->dh_->own_range() )
713 LocDofVec loc_dof_indices = cell.get_loc_dof_indices();
714 unsigned int n_dofs=loc_dof_indices.n_rows;
716 DHCellAccessor dh_p0_cell = eq_data_->dh_p0->cell_accessor_from_element(cell.elm_idx());
719 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); ++sbi)
721 double old_average = 0;
722 for (
unsigned int j=0; j<n_dofs; ++j)
723 old_average += eq_data_->ls[sbi]->get_solution_array()[loc_dof_indices[j]];
724 old_average /= n_dofs;
726 for (
unsigned int j=0; j<n_dofs; ++j)
727 eq_data_->ls[sbi]->get_solution_array()[loc_dof_indices[j]]
728 += eq_data_->conc_fe[sbi]->vec().get(dof_p0) - old_average;
733 for (
unsigned int sbi=0; sbi<eq_data_->n_substances(); ++sbi)
734 MatMult(*(eq_data_->ls_dt[sbi]->get_matrix()), eq_data_->ls[sbi]->get_solution(), mass_vec[sbi]);