45 using namespace Input::Type;
49 return Selection(
"DG_variant",
"Type of penalty term.")
50 .
add_value(non_symmetric,
"non-symmetric",
"non-symmetric weighted interior penalty DG method")
51 .
add_value(incomplete,
"incomplete",
"incomplete weighted interior penalty DG method")
52 .
add_value(symmetric,
"symmetric",
"symmetric weighted interior penalty DG method")
75 std::string equation_name = std::string(Model::ModelEqData::name()) +
"_DG";
76 return Model::get_input_type(
"DG",
"DG solver")
78 "Linear solver for MH problem.")
81 .make_field_descriptor_type(equation_name)),
83 "Input fields of the equation.")
85 "Variant of interior penalty discontinuous Galerkin method.")
87 "Polynomial order for finite element in DG method (order 0 is suitable if there is no diffusion/dispersion).")
102 EqData().output_fields.make_output_type(equation_name,
""),
103 IT::Default(
"{ \"fields\": [ " + Model::ModelEqData::default_output_field() +
"] }"),
104 "Setting of the field output.")
108 template<
class Model>
110 Input::register_class< TransportDG<Model>,
Mesh &,
const Input::Record>(std::string(Model::ModelEqData::name()) +
"_DG") +
118 unsigned int q_order;
152 xprintf(
PrgErr,
"Unsupported polynomial order %d for finite elements in TransportDG ", fe_order);
172 dh_->distribute_dofs(*fe1_, *fe2_, *fe3_);
218 template<
class Model>
222 .
name(
"fracture_sigma")
224 "Coefficient of diffusive transfer through fractures (for each substance).")
232 "Penalty parameter influencing the discontinuity of the solution (for each substance). "
233 "Its default value 1 is sufficient in most cases. Higher value diminishes the inter-element jumps.")
248 template<
class Model>
250 : Model(init_mesh, in_rec),
258 static_assert(std::is_base_of<AdvectionDiffusionModel, Model>::value,
"");
264 data_.set_mesh(init_mesh);
272 Model::init_from_input(in_rec);
281 template<
class Model>
284 data_.set_components(Model::substances_.names());
285 data_.set_input_list( input_rec.val<
Input::Array>(
"input_fields") );
288 gamma.resize(Model::n_substances());
289 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
290 gamma[sbi].resize(Model::mesh_->boundary_.size());
293 int qsize = max(feo->q<0>()->size(), max(feo->q<1>()->size(), max(feo->q<2>()->size(), feo->q<3>()->size())));
294 int max_edg_sides = max(Model::mesh_->max_edge_sides(1), max(Model::mesh_->max_edge_sides(2), Model::mesh_->max_edge_sides(3)));
295 mm_coef.resize(qsize);
296 ret_coef.resize(Model::n_substances());
297 sorption_sources.resize(Model::n_substances());
298 ad_coef.resize(Model::n_substances());
299 dif_coef.resize(Model::n_substances());
300 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
302 ret_coef[sbi].resize(qsize);
303 ad_coef[sbi].resize(qsize);
304 dif_coef[sbi].resize(qsize);
306 ad_coef_edg.resize(max_edg_sides);
307 dif_coef_edg.resize(max_edg_sides);
308 for (
int sd=0; sd<max_edg_sides; sd++)
310 ad_coef_edg[sd].resize(Model::n_substances());
311 dif_coef_edg[sd].resize(Model::n_substances());
312 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
314 ad_coef_edg[sd][sbi].resize(qsize);
315 dif_coef_edg[sd][sbi].resize(qsize);
319 output_vec.resize(Model::n_substances());
323 unsigned int output_vector_size= (rank==0)?feo->dh()->n_global_dofs():0;
324 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
328 VecCreateSeq(PETSC_COMM_SELF, output_vector_size, &output_vec[sbi]);
330 data_.output_field.set_components(Model::substances_.names());
331 data_.output_field.set_mesh(*Model::mesh_);
334 data_.output_field.setup_components();
335 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
339 output_field_ptr->set_fe_data(feo->dh(), feo->mapping<1>(), feo->mapping<2>(), feo->mapping<3>(), &output_vec[sbi]);
340 data_.output_field[sbi].set_field(Model::mesh_->region_db().get_region_set(
"ALL"), output_field_ptr, 0);
344 data_.output_fields.initialize(Model::output_stream_, input_rec.val<
Input::Record>(
"output"), this->time());
347 ls =
new LinSys*[Model::n_substances()];
348 ls_dt =
new LinSys*[Model::n_substances()];
349 solution_elem_ =
new double*[Model::n_substances()];
350 for (
unsigned int sbi = 0; sbi < Model::n_substances(); sbi++) {
353 ls[sbi]->set_solution(NULL);
357 solution_elem_[sbi] =
new double[Model::mesh_->get_el_ds()->lsize()];
359 stiffness_matrix =
new Mat[Model::n_substances()];
360 mass_matrix =
new Mat[Model::n_substances()];
361 rhs =
new Vec[Model::n_substances()];
362 mass_vec =
new Vec[Model::n_substances()];
366 if (Model::balance_ !=
nullptr)
368 Model::balance_->allocate(feo->dh()->distr()->lsize(),
369 max(feo->fe<1>()->n_dofs(), max(feo->fe<2>()->n_dofs(), feo->fe<3>()->n_dofs())));
375 template<
class Model>
380 if (gamma.size() > 0) {
383 for (
auto &vec : output_vec) VecDestroy(&vec);
385 for (
unsigned int i=0; i<Model::n_substances(); i++)
388 delete[] solution_elem_[i];
390 MatDestroy(&stiffness_matrix[i]);
391 MatDestroy(&mass_matrix[i]);
393 VecDestroy(&mass_vec[i]);
396 delete[] solution_elem_;
398 delete[] stiffness_matrix;
399 delete[] mass_matrix;
409 template<
class Model>
412 VecScatter output_scatter;
413 VecScatterCreateToZero(ls[0]->get_solution(), &output_scatter, PETSC_NULL);
414 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
417 VecScatterBegin(output_scatter, ls[sbi]->get_solution(), output_vec[sbi], INSERT_VALUES, SCATTER_FORWARD);
418 VecScatterEnd(output_scatter, ls[sbi]->get_solution(), output_vec[sbi], INSERT_VALUES, SCATTER_FORWARD);
420 VecScatterDestroy(&(output_scatter));
426 template<
class Model>
430 data_.mark_input_times( *(Model::time_) );
435 set_initial_condition();
436 for (
unsigned int sbi = 0; sbi < Model::n_substances(); sbi++)
437 ( (
LinSys_PETSC *)ls[sbi] )->set_initial_guess_nonzero();
440 if (!allocation_done) preallocate();
443 if (Model::balance_ !=
nullptr)
445 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
447 Model::balance_->calculate_mass(Model::subst_idx[sbi], ls[sbi]->get_solution());
448 Model::balance_->calculate_source(Model::subst_idx[sbi], ls[sbi]->get_solution());
449 Model::balance_->calculate_flux(Model::subst_idx[sbi], ls[sbi]->get_solution());
454 Model::balance_->calculate_mass(Model::subst_idx[sbi], ls[sbi]->get_solution(), masses);
455 for (
auto reg_mass : masses)
458 sorption_sources[sbi] = mass;
466 template<
class Model>
470 for (
unsigned int i=0; i<Model::n_substances(); i++)
473 ls[i]->start_allocation();
474 stiffness_matrix[i] = NULL;
478 ls_dt[i]->start_allocation();
479 mass_matrix[i] = NULL;
481 assemble_stiffness_matrix();
482 assemble_mass_matrix();
484 set_boundary_conditions();
486 allocation_done =
true;
491 template<
class Model>
496 Model::time_->next_time();
497 Model::time_->view(
"TDG");
506 for (
unsigned int i=0; i<Model::n_substances(); i++)
508 ls_dt[i]->start_add_assembly();
509 ls_dt[i]->mat_zero_entries();
511 assemble_mass_matrix();
512 for (
unsigned int i=0; i<Model::n_substances(); i++)
514 ls_dt[i]->finish_assembly();
516 if (mass_matrix[i] == NULL)
518 VecDuplicate(ls[i]->get_solution(), &mass_vec[i]);
519 MatMult(*(ls_dt[i]->get_matrix()), ls[i]->get_solution(), mass_vec[i]);
520 if (Model::balance_ !=
nullptr && Model::balance_->cumulative())
522 double total_mass = 0;
523 VecSum(mass_vec[i], &total_mass);
524 sorption_sources[i] -= total_mass;
526 MatConvert(*( ls_dt[i]->get_matrix() ), MATSAME, MAT_INITIAL_MATRIX, &mass_matrix[i]);
529 MatCopy(*( ls_dt[i]->get_matrix() ), mass_matrix[i], DIFFERENT_NONZERO_PATTERN);
534 if (stiffness_matrix[0] == NULL
536 || Model::flux_changed)
540 for (
unsigned int i=0; i<Model::n_substances(); i++)
542 ls[i]->start_add_assembly();
543 ls[i]->mat_zero_entries();
545 assemble_stiffness_matrix();
546 for (
unsigned int i=0; i<Model::n_substances(); i++)
548 ls[i]->finish_assembly();
550 if (stiffness_matrix[i] == NULL)
551 MatConvert(*( ls[i]->get_matrix() ), MATSAME, MAT_INITIAL_MATRIX, &stiffness_matrix[i]);
553 MatCopy(*( ls[i]->get_matrix() ), stiffness_matrix[i], DIFFERENT_NONZERO_PATTERN);
560 || Model::flux_changed)
562 for (
unsigned int i=0; i<Model::n_substances(); i++)
564 ls[i]->start_add_assembly();
565 ls[i]->rhs_zero_entries();
568 set_boundary_conditions();
569 for (
unsigned int i=0; i<Model::n_substances(); i++)
571 ls[i]->finish_assembly();
573 if (rhs[i] ==
nullptr) VecDuplicate(*( ls[i]->get_rhs() ), &rhs[i]);
574 VecCopy(*( ls[i]->get_rhs() ), rhs[i]);
578 Model::flux_changed =
false;
599 for (
unsigned int i=0; i<Model::n_substances(); i++)
601 MatConvert(stiffness_matrix[i], MATSAME, MAT_INITIAL_MATRIX, &m);
602 MatAXPY(m, 1./Model::time_->dt(), mass_matrix[i], SUBSET_NONZERO_PATTERN);
603 ls[i]->set_matrix(m, DIFFERENT_NONZERO_PATTERN);
605 VecDuplicate(rhs[i], &w);
606 VecWAXPY(w, 1./Model::time_->dt(), mass_vec[i], rhs[i]);
615 MatMult(*(ls_dt[i]->get_matrix()), ls[i]->get_solution(), mass_vec[i]);
619 calculate_cumulative_balance();
625 template<
class Model>
629 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
637 n_dofs = feo->fe<1>()->n_dofs();
640 n_dofs = feo->fe<2>()->n_dofs();
643 n_dofs = feo->fe<3>()->n_dofs();
647 unsigned int dof_indices[n_dofs];
648 feo->dh()->get_dof_indices(elem, dof_indices);
650 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
652 solution_elem_[sbi][i_cell] = 0;
654 for (
unsigned int j=0; j<n_dofs; ++j)
655 solution_elem_[sbi][i_cell] += ls[sbi]->get_solution_array()[dof_indices[j]-feo->dh()->distr()->begin()];
657 solution_elem_[sbi][i_cell] = max(solution_elem_[sbi][i_cell]/n_dofs, 0.);
665 template<
class Model>
676 output_vector_gather();
677 data_.output_fields.output(this->
time().step());
679 Model::output_data();
685 template<
class Model>
688 if (Model::balance_ !=
nullptr && Model::balance_->cumulative())
690 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
692 Model::balance_->calculate_cumulative_sources(Model::subst_idx[sbi], ls[sbi]->get_solution(), Model::time_->dt());
693 Model::balance_->calculate_cumulative_fluxes(Model::subst_idx[sbi], ls[sbi]->get_solution(), Model::time_->dt());
698 Model::balance_->calculate_mass(Model::subst_idx[sbi], ls[sbi]->get_solution(), masses);
699 for (
auto reg_mass : masses)
701 double total_mass = 0;
702 VecSum(mass_vec[sbi], &total_mass);
704 Model::balance_->add_cumulative_source(Model::subst_idx[sbi], mass-total_mass-sorption_sources[sbi]);
705 sorption_sources[sbi] = mass - total_mass;
711 template<
class Model>
714 if (Model::balance_ !=
nullptr)
716 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
718 Model::balance_->calculate_mass(Model::subst_idx[sbi], ls[sbi]->get_solution());
719 Model::balance_->calculate_source(Model::subst_idx[sbi], ls[sbi]->get_solution());
720 Model::balance_->calculate_flux(Model::subst_idx[sbi], ls[sbi]->get_solution());
726 template<
class Model>
730 if (Model::balance_ !=
nullptr)
731 Model::balance_->start_mass_assembly(Model::subst_idx);
732 assemble_mass_matrix<1>();
733 assemble_mass_matrix<2>();
734 assemble_mass_matrix<3>();
735 if (Model::balance_ !=
nullptr)
736 Model::balance_->finish_mass_assembly(Model::subst_idx);
741 template<
class Model>
template<
unsigned int dim>
745 const unsigned int ndofs = feo->fe<dim>()->n_dofs(), qsize = feo->q<dim>()->size();
747 PetscScalar local_mass_matrix[ndofs*ndofs];
751 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
754 if (cell->dim() != dim)
continue;
756 fe_values.reinit(cell);
757 feo->dh()->get_dof_indices(cell, (
unsigned int*)&(dof_indices[0]));
760 Model::compute_mass_matrix_coefficient(fe_values.point_list(), ele_acc, mm_coef);
761 Model::compute_retardation_coefficient(fe_values.point_list(), ele_acc, ret_coef);
763 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
766 for (
unsigned int i=0; i<ndofs; i++)
768 for (
unsigned int j=0; j<ndofs; j++)
770 local_mass_matrix[i*ndofs+j] = 0;
771 for (
unsigned int k=0; k<qsize; k++)
772 local_mass_matrix[i*ndofs+j] += (mm_coef[k]+ret_coef[sbi][k])*fe_values.shape_value(j,k)*fe_values.shape_value(i,k)*fe_values.JxW(k);
776 if (Model::balance_ !=
nullptr)
778 for (
unsigned int i=0; i<ndofs; i++)
780 local_mass_balance_vector[i] = 0;
781 for (
unsigned int k=0; k<qsize; k++)
782 local_mass_balance_vector[i] += mm_coef[k]*fe_values.shape_value(i,k)*fe_values.JxW(k);
786 Model::balance_->add_mass_matrix_values(Model::subst_idx[sbi], ele_acc.
region().
bulk_idx(), dof_indices, local_mass_balance_vector);
787 ls_dt[sbi]->mat_set_values(ndofs, &(dof_indices[0]), ndofs, &(dof_indices[0]), local_mass_matrix);
795 template<
class Model>
800 assemble_volume_integrals<1>();
801 assemble_volume_integrals<2>();
802 assemble_volume_integrals<3>();
806 assemble_fluxes_boundary<1>();
807 assemble_fluxes_boundary<2>();
808 assemble_fluxes_boundary<3>();
812 assemble_fluxes_element_element<1>();
813 assemble_fluxes_element_element<2>();
814 assemble_fluxes_element_element<3>();
818 assemble_fluxes_element_side<1>();
819 assemble_fluxes_element_side<2>();
820 assemble_fluxes_element_side<3>();
827 template<
class Model>
828 template<
unsigned int dim>
831 FEValues<dim,3> fv_rt(*feo->mapping<dim>(), *feo->q<dim>(), *feo->fe_rt<dim>(),
833 FEValues<dim,3> fe_values(*feo->mapping<dim>(), *feo->q<dim>(), *feo->fe<dim>(),
835 const unsigned int ndofs = feo->fe<dim>()->n_dofs(), qsize = feo->q<dim>()->size();
836 unsigned int dof_indices[ndofs];
839 PetscScalar local_matrix[ndofs*ndofs];
842 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
845 if (cell->dim() != dim)
continue;
850 feo->dh()->get_dof_indices(cell, dof_indices);
852 calculate_velocity(cell, velocity, fv_rt);
853 Model::compute_advection_diffusion_coefficients(fe_values.
point_list(), velocity, ele_acc, ad_coef, dif_coef);
854 Model::compute_sources_sigma(fe_values.
point_list(), ele_acc, sources_sigma);
857 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
859 for (
unsigned int i=0; i<ndofs; i++)
860 for (
unsigned int j=0; j<ndofs; j++)
861 local_matrix[i*ndofs+j] = 0;
863 for (
unsigned int k=0; k<qsize; k++)
865 for (
unsigned int i=0; i<ndofs; i++)
868 double ad_dot_grad_i = arma::dot(ad_coef[sbi][k], fe_values.
shape_grad(i,k));
870 for (
unsigned int j=0; j<ndofs; j++)
871 local_matrix[i*ndofs+j] += (arma::dot(Kt_grad_i, fe_values.
shape_grad(j,k))
876 ls[sbi]->mat_set_values(ndofs, (
int *)dof_indices, ndofs, (
int *)dof_indices, local_matrix);
882 template<
class Model>
886 if (Model::balance_ !=
nullptr)
887 Model::balance_->start_source_assembly(Model::subst_idx);
891 if (Model::balance_ !=
nullptr)
892 Model::balance_->finish_source_assembly(Model::subst_idx);
896 template<
class Model>
897 template<
unsigned int dim>
900 FEValues<dim,3> fe_values(*feo->mapping<dim>(), *feo->q<dim>(), *feo->fe<dim>(),
902 const unsigned int ndofs = feo->fe<dim>()->n_dofs(), qsize = feo->q<dim>()->size();
904 sources_density(qsize, arma::vec(Model::n_substances())),
905 sources_sigma(qsize, arma::vec(Model::n_substances()));
907 PetscScalar local_rhs[ndofs];
912 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
915 if (cell->dim() != dim)
continue;
917 fe_values.reinit(cell);
918 feo->dh()->get_dof_indices(cell, (
unsigned int *)&(dof_indices[0]));
920 Model::compute_source_coefficients(fe_values.point_list(), cell->element_accessor(), sources_conc, sources_density, sources_sigma);
923 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
925 fill_n(local_rhs, ndofs, 0);
926 local_source_balance_vector.assign(ndofs, 0);
927 local_source_balance_rhs.assign(ndofs, 0);
930 for (
unsigned int k=0; k<qsize; k++)
932 source = (sources_density[k][sbi] + sources_conc[k][sbi]*sources_sigma[k][sbi])*fe_values.JxW(k);
934 for (
unsigned int i=0; i<ndofs; i++)
935 local_rhs[i] += source*fe_values.shape_value(i,k);
937 ls[sbi]->rhs_set_values(ndofs, &(dof_indices[0]), local_rhs);
939 if (Model::balance_ !=
nullptr)
941 for (
unsigned int i=0; i<ndofs; i++)
943 for (
unsigned int k=0; k<qsize; k++)
944 local_source_balance_vector[i] -= sources_sigma[k][sbi]*fe_values.shape_value(i,k)*fe_values.JxW(k);
946 local_source_balance_rhs[i] += local_rhs[i];
948 Model::balance_->add_source_matrix_values(Model::subst_idx[sbi], cell->region().bulk_idx(), dof_indices, local_source_balance_vector);
949 Model::balance_->add_source_vec_values(Model::subst_idx[sbi], cell->region().bulk_idx(), dof_indices, local_source_balance_rhs);
957 template<
class Model>
958 template<
unsigned int dim>
964 const unsigned int ndofs = feo->fe<dim>()->n_dofs(), qsize = feo->q<dim-1>()->size(),
965 n_max_sides = ad_coef_edg.size();
967 PetscScalar local_matrix[ndofs*ndofs];
970 double gamma_l, omega[2], transport_flux;
972 for (
unsigned int sid=0; sid<n_max_sides; sid++)
974 side_dof_indices.push_back(
new unsigned int[ndofs]);
975 fe_values.push_back(
new FESideValues<dim,3>(*feo->mapping<dim>(), *feo->q<dim-1>(), *feo->fe<dim>(),
980 for (
unsigned int iedg=0; iedg<feo->dh()->n_loc_edges(); iedg++)
982 Edge *edg = &Model::mesh_->edges[feo->dh()->edge_index(iedg)];
985 for (
int sid=0; sid<edg->
n_sides; sid++)
989 feo->dh()->get_dof_indices(cell, side_dof_indices[sid]);
990 fe_values[sid]->reinit(cell, edg->
side(sid)->
el_idx());
992 calculate_velocity(cell, side_velocity[sid], fsv_rt);
993 Model::compute_advection_diffusion_coefficients(fe_values[sid]->point_list(), side_velocity[sid], ele_acc, ad_coef_edg[sid], dif_coef_edg[sid]);
994 dg_penalty[sid] = data_.dg_penalty.value(cell->centre(), ele_acc);
998 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1001 for (
int sid=0; sid<edg->
n_sides; sid++)
1004 for (
unsigned int k=0; k<qsize; k++)
1005 fluxes[sid] += arma::dot(ad_coef_edg[sid][sbi][k], fe_values[sid]->normal_vector(k))*fe_values[sid]->JxW(k);
1009 for (
int s1=0; s1<edg->
n_sides; s1++)
1011 for (
int s2=s1+1; s2<edg->
n_sides; s2++)
1017 arma::vec3 nv = fe_values[s1]->normal_vector(0);
1020 set_DG_parameters_edge(*edg, s1, s2, qsize, dif_coef_edg[s1][sbi], dif_coef_edg[s2][sbi], fluxes, fe_values[0]->normal_vector(0), dg_penalty[s1][sbi], dg_penalty[s2][sbi], gamma_l, omega, transport_flux);
1026 #define AVERAGE(i,k,side_id) (fe_values[sd[side_id]]->shape_value(i,k)*0.5)
1027 #define WAVERAGE(i,k,side_id) (arma::dot(dif_coef_edg[sd[side_id]][sbi][k]*fe_values[sd[side_id]]->shape_grad(i,k),nv)*omega[side_id])
1028 #define JUMP(i,k,side_id) ((side_id==0?1:-1)*fe_values[sd[side_id]]->shape_value(i,k))
1031 for (
int n=0; n<2; n++)
1033 if (!feo->dh()->el_is_local(edg->
side(sd[n])->
element().
index()))
continue;
1035 for (
int m=0; m<2; m++)
1037 for (
unsigned int i=0; i<fe_values[sd[n]]->n_dofs(); i++)
1038 for (
unsigned int j=0; j<fe_values[sd[m]]->n_dofs(); j++)
1039 local_matrix[i*fe_values[sd[m]]->n_dofs()+j] = 0;
1041 for (
unsigned int k=0; k<qsize; k++)
1043 double flux_times_JxW = transport_flux*fe_values[0]->JxW(k);
1044 double gamma_times_JxW = gamma_l*fe_values[0]->JxW(k);
1046 for (
unsigned int i=0; i<fe_values[sd[n]]->n_dofs(); i++)
1048 double flux_JxW_jump_i = flux_times_JxW*
JUMP(i,k,n);
1049 double gamma_JxW_jump_i = gamma_times_JxW*
JUMP(i,k,n);
1050 double JxW_jump_i = fe_values[0]->JxW(k)*
JUMP(i,k,n);
1051 double JxW_var_wavg_i = fe_values[0]->JxW(k)*
WAVERAGE(i,k,n)*dg_variant;
1053 for (
unsigned int j=0; j<fe_values[sd[m]]->n_dofs(); j++)
1055 int index = i*fe_values[sd[m]]->n_dofs()+j;
1058 local_matrix[index] += flux_JxW_jump_i*
AVERAGE(j,k,m);
1061 local_matrix[index] += gamma_JxW_jump_i*
JUMP(j,k,m);
1064 local_matrix[index] -=
WAVERAGE(j,k,m)*JxW_jump_i;
1065 local_matrix[index] -=
JUMP(j,k,m)*JxW_var_wavg_i;
1069 ls[sbi]->mat_set_values(fe_values[sd[n]]->n_dofs(), (
int *)side_dof_indices[sd[n]], fe_values[sd[m]]->n_dofs(), (
int *)side_dof_indices[sd[m]], local_matrix);
1080 for (
unsigned int i=0; i<n_max_sides; i++)
1082 delete fe_values[i];
1083 delete[] side_dof_indices[i];
1088 template<
class Model>
1089 template<
unsigned int dim>
1092 FESideValues<dim,3> fe_values_side(*feo->mapping<dim>(), *feo->q<dim-1>(), *feo->fe<dim>(),
1096 const unsigned int ndofs = feo->fe<dim>()->n_dofs(), qsize = feo->q<dim-1>()->size();
1097 unsigned int side_dof_indices[ndofs];
1098 PetscScalar local_matrix[ndofs*ndofs];
1102 arma::vec dg_penalty;
1106 for (
unsigned int iedg=0; iedg<feo->dh()->n_loc_edges(); iedg++)
1108 Edge *edg = &Model::mesh_->edges[feo->dh()->edge_index(iedg)];
1109 if (edg->
n_sides > 1)
continue;
1111 if (edg->
side(0)->
dim() != dim-1)
continue;
1113 if (edg->
side(0)->
cond() == NULL)
continue;
1118 feo->dh()->get_dof_indices(cell, side_dof_indices);
1122 calculate_velocity(cell, side_velocity, fsv_rt);
1123 Model::compute_advection_diffusion_coefficients(fe_values_side.
point_list(), side_velocity, ele_acc, ad_coef, dif_coef);
1124 dg_penalty = data_.dg_penalty.value(cell->centre(), ele_acc);
1127 data_.cross_section.value_list(fe_values_side.
point_list(), ele_acc, csection);
1129 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1131 for (
unsigned int i=0; i<ndofs; i++)
1132 for (
unsigned int j=0; j<ndofs; j++)
1133 local_matrix[i*ndofs+j] = 0;
1137 double side_flux = 0;
1138 for (
unsigned int k=0; k<qsize; k++)
1139 side_flux += arma::dot(ad_coef[sbi][k], fe_values_side.
normal_vector(k))*fe_values_side.
JxW(k);
1140 double transport_flux = side_flux/side->
measure();
1145 set_DG_parameters_boundary(side, qsize, dif_coef[sbi], transport_flux, fe_values_side.
normal_vector(0), dg_penalty[sbi], gamma_l);
1146 gamma[sbi][side->
cond_idx()] = gamma_l;
1147 transport_flux += gamma_l;
1151 for (
unsigned int k=0; k<qsize; k++)
1153 double flux_times_JxW;
1157 flux_times_JxW = csection[k]*robin_sigma[k]*fe_values_side.
JxW(k);
1162 flux_times_JxW = (transport_flux + csection[k]*robin_sigma[k])*fe_values_side.
JxW(k);
1167 flux_times_JxW = transport_flux*fe_values_side.
JxW(k);
1169 for (
unsigned int i=0; i<ndofs; i++)
1171 for (
unsigned int j=0; j<ndofs; j++)
1174 local_matrix[i*ndofs+j] += flux_times_JxW*fe_values_side.
shape_value(i,k)*fe_values_side.
shape_value(j,k);
1180 )*fe_values_side.
JxW(k);
1185 ls[sbi]->mat_set_values(ndofs, (
int *)side_dof_indices, ndofs, (
int *)side_dof_indices, local_matrix);
1191 template<
class Model>
1192 template<
unsigned int dim>
1196 if (dim == 1)
return;
1197 FEValues<dim-1,3> fe_values_vb(*feo->mapping<dim-1>(), *feo->q<dim-1>(), *feo->
fe<dim-1>(),
1203 FEValues<dim-1,3> fv_rt(*feo->mapping<dim-1>(), *feo->q<dim-1>(), *feo->fe_rt<dim-1>(),
1207 const unsigned int ndofs = feo->fe<dim>()->n_dofs();
1208 const unsigned int qsize = feo->q<dim-1>()->size();
1209 unsigned int side_dof_indices[2*ndofs], n_dofs[2];
1212 vector<double> csection_lower(qsize), csection_higher(qsize), por_lower(qsize), por_higher(qsize);
1213 PetscScalar local_matrix[4*ndofs*ndofs];
1214 double comm_flux[2][2];
1218 fv_sb[0] = &fe_values_vb;
1219 fv_sb[1] = &fe_values_side;
1222 for (
unsigned int inb=0; inb<feo->dh()->n_loc_nb(); inb++)
1224 Neighbour *nb = &Model::mesh_->vb_neighbours_[feo->dh()->nb_index(inb)];
1229 feo->dh()->get_dof_indices(cell_sub, side_dof_indices);
1230 fe_values_vb.
reinit(cell_sub);
1231 n_dofs[0] = fv_sb[0]->n_dofs();
1234 feo->dh()->get_dof_indices(cell, side_dof_indices+n_dofs[0]);
1236 n_dofs[1] = fv_sb[1]->n_dofs();
1240 element_id[0] = cell_sub.
index();
1241 element_id[1] = cell.
index();
1245 calculate_velocity(cell, velocity_higher, fsv_rt);
1246 calculate_velocity(cell_sub, velocity_lower, fv_rt);
1247 Model::compute_advection_diffusion_coefficients(fe_values_vb.
point_list(), velocity_lower, cell_sub->element_accessor(), ad_coef_edg[0], dif_coef_edg[0]);
1248 Model::compute_advection_diffusion_coefficients(fe_values_vb.
point_list(), velocity_higher, cell->element_accessor(), ad_coef_edg[1], dif_coef_edg[1]);
1249 data_.cross_section.value_list(fe_values_vb.
point_list(), cell_sub->element_accessor(), csection_lower);
1250 data_.cross_section.value_list(fe_values_vb.
point_list(), cell->element_accessor(), csection_higher);
1251 data_.fracture_sigma.value_list(fe_values_vb.
point_list(), cell_sub->element_accessor(), frac_sigma);
1252 data_.porosity.value_list(fe_values_vb.
point_list(), cell_sub->element_accessor(), por_lower);
1253 data_.porosity.value_list(fe_values_vb.
point_list(), cell->element_accessor(), por_higher);
1255 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1257 for (
unsigned int i=0; i<n_dofs[0]+n_dofs[1]; i++)
1258 for (
unsigned int j=0; j<n_dofs[0]+n_dofs[1]; j++)
1259 local_matrix[i*(n_dofs[0]+n_dofs[1])+j] = 0;
1262 for (
unsigned int k=0; k<qsize; k++)
1272 double sigma = frac_sigma[k][sbi]*arma::dot(dif_coef_edg[0][sbi][k]*fe_values_side.
normal_vector(k),fe_values_side.
normal_vector(k))*
1273 2*csection_higher[k]*csection_higher[k]/(csection_lower[k]*csection_lower[k]);
1275 double transport_flux = arma::dot(ad_coef_edg[1][sbi][k], fe_values_side.
normal_vector(k));
1276 double por_lower_over_higher = por_lower[k]/por_higher[k];
1278 comm_flux[0][0] = (sigma-min(0.,transport_flux*por_lower_over_higher))*fv_sb[0]->JxW(k);
1279 comm_flux[0][1] = -(sigma-min(0.,transport_flux*por_lower_over_higher))*fv_sb[0]->JxW(k);
1280 comm_flux[1][0] = -(sigma+max(0.,transport_flux))*fv_sb[0]->JxW(k);
1281 comm_flux[1][1] = (sigma+max(0.,transport_flux))*fv_sb[0]->JxW(k);
1283 for (
int n=0; n<2; n++)
1285 if (!feo->dh()->el_is_local(element_id[n]))
continue;
1287 for (
unsigned int i=0; i<n_dofs[n]; i++)
1288 for (
int m=0; m<2; m++)
1289 for (
unsigned int j=0; j<n_dofs[m]; j++)
1290 local_matrix[(i+n*n_dofs[0])*(n_dofs[0]+n_dofs[1]) + m*n_dofs[0] + j] +=
1291 comm_flux[m][n]*fv_sb[m]->shape_value(j,k)*fv_sb[n]->shape_value(i,k);
1294 ls[sbi]->mat_set_values(n_dofs[0]+n_dofs[1], (
int *)side_dof_indices, n_dofs[0]+n_dofs[1], (
int *)side_dof_indices, local_matrix);
1305 template<
class Model>
1309 if (Model::balance_ !=
nullptr)
1310 Model::balance_->start_flux_assembly(Model::subst_idx);
1311 set_boundary_conditions<1>();
1312 set_boundary_conditions<2>();
1313 set_boundary_conditions<3>();
1314 if (Model::balance_ !=
nullptr)
1315 Model::balance_->finish_flux_assembly(Model::subst_idx);
1320 template<
class Model>
1321 template<
unsigned int dim>
1324 FESideValues<dim,3> fe_values_side(*feo->mapping<dim>(), *feo->q<dim-1>(), *feo->fe<dim>(),
1328 const unsigned int ndofs = feo->fe<dim>()->n_dofs(), qsize = feo->q<dim-1>()->size();
1330 unsigned int loc_b=0;
1331 double local_rhs[ndofs];
1333 PetscScalar local_flux_balance_rhs;
1337 bc_ref_values(qsize);
1341 for (
unsigned int loc_el = 0; loc_el < Model::mesh_->get_el_ds()->lsize(); loc_el++)
1343 ElementFullIter elm = Model::mesh_->element(feo->dh()->el_index(loc_el));
1344 if (elm->boundary_idx_ ==
nullptr)
continue;
1348 Edge *edg = elm->side(si)->edge();
1349 if (edg->
n_sides > 1)
continue;
1351 if (edg->
side(0)->
cond() == NULL)
continue;
1353 if (edg->
side(0)->
dim() != dim-1)
1355 if (edg->
side(0)->
cond() !=
nullptr) ++loc_b;
1364 Model::get_bc_type(ele_acc, bc_type);
1366 fe_values_side.reinit(cell, side->
el_idx());
1367 fsv_rt.reinit(cell, side->
el_idx());
1368 calculate_velocity(cell, velocity, fsv_rt);
1370 Model::compute_advection_diffusion_coefficients(fe_values_side.point_list(), velocity, side->
element()->element_accessor(), ad_coef, dif_coef);
1371 data_.cross_section.value_list(fe_values_side.point_list(), side->
element()->element_accessor(), csection);
1374 data_.bc_dirichlet_value.value_list(fe_values_side.point_list(), ele_acc, bc_values);
1376 feo->dh()->get_dof_indices(cell, (
unsigned int *)&(side_dof_indices[0]));
1378 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1380 fill_n(local_rhs, ndofs, 0);
1381 local_flux_balance_vector.assign(ndofs, 0);
1382 local_flux_balance_rhs = 0;
1384 double side_flux = 0;
1385 for (
unsigned int k=0; k<qsize; k++)
1386 side_flux += arma::dot(ad_coef[sbi][k], fe_values_side.normal_vector(k))*fe_values_side.JxW(k);
1387 double transport_flux = side_flux/side->
measure();
1391 for (
unsigned int k=0; k<qsize; k++)
1393 double bc_term = -transport_flux*bc_values[k][sbi]*fe_values_side.JxW(k);
1394 for (
unsigned int i=0; i<ndofs; i++)
1395 local_rhs[i] += bc_term*fe_values_side.shape_value(i,k);
1397 if (Model::balance_ !=
nullptr)
1398 for (
unsigned int i=0; i<ndofs; i++)
1399 local_flux_balance_rhs -= local_rhs[i];
1403 for (
unsigned int k=0; k<qsize; k++)
1405 double bc_term = gamma[sbi][side->
cond_idx()]*bc_values[k][sbi]*fe_values_side.JxW(k);
1406 arma::vec3 bc_grad = -bc_values[k][sbi]*fe_values_side.JxW(k)*dg_variant*(arma::trans(dif_coef[sbi][k])*fe_values_side.normal_vector(k));
1407 for (
unsigned int i=0; i<ndofs; i++)
1408 local_rhs[i] += bc_term*fe_values_side.shape_value(i,k)
1409 + arma::dot(bc_grad,fe_values_side.shape_grad(i,k));
1411 if (Model::balance_ !=
nullptr)
1413 for (
unsigned int k=0; k<qsize; k++)
1415 for (
unsigned int i=0; i<ndofs; i++)
1417 local_flux_balance_vector[i] += (arma::dot(ad_coef[sbi][k], fe_values_side.normal_vector(k))*fe_values_side.shape_value(i,k)
1418 - arma::dot(dif_coef[sbi][k]*fe_values_side.shape_grad(i,k),fe_values_side.normal_vector(k))
1419 + gamma[sbi][side->
cond_idx()]*fe_values_side.shape_value(i,k))*fe_values_side.JxW(k);
1422 if (Model::time_->tlevel() > 0)
1423 for (
unsigned int i=0; i<ndofs; i++)
1424 local_flux_balance_rhs -= local_rhs[i];
1429 Model::get_flux_bc_data(sbi, fe_values_side.point_list(), ele_acc, bc_fluxes, bc_sigma, bc_ref_values);
1430 for (
unsigned int k=0; k<qsize; k++)
1432 double bc_term = csection[k]*(bc_sigma[k]*bc_ref_values[k]+bc_fluxes[k])*fe_values_side.JxW(k);
1433 for (
unsigned int i=0; i<ndofs; i++)
1434 local_rhs[i] += bc_term*fe_values_side.shape_value(i,k);
1437 if (Model::balance_ !=
nullptr)
1439 for (
unsigned int i=0; i<ndofs; i++)
1441 for (
unsigned int k=0; k<qsize; k++)
1442 local_flux_balance_vector[i] += csection[k]*bc_sigma[k]*fe_values_side.JxW(k)*fe_values_side.shape_value(i,k);
1443 local_flux_balance_rhs -= local_rhs[i];
1449 Model::get_flux_bc_data(sbi, fe_values_side.point_list(), ele_acc, bc_fluxes, bc_sigma, bc_ref_values);
1450 for (
unsigned int k=0; k<qsize; k++)
1452 double bc_term = csection[k]*(bc_sigma[k]*bc_ref_values[k]+bc_fluxes[k])*fe_values_side.JxW(k);
1453 for (
unsigned int i=0; i<ndofs; i++)
1454 local_rhs[i] += bc_term*fe_values_side.shape_value(i,k);
1457 if (Model::balance_ !=
nullptr)
1459 for (
unsigned int i=0; i<ndofs; i++)
1461 for (
unsigned int k=0; k<qsize; k++)
1462 local_flux_balance_vector[i] += csection[k]*(arma::dot(ad_coef[sbi][k], fe_values_side.normal_vector(k)) + bc_sigma[k])*fe_values_side.JxW(k)*fe_values_side.shape_value(i,k);
1463 local_flux_balance_rhs -= local_rhs[i];
1469 if (Model::balance_ !=
nullptr)
1471 for (
unsigned int k=0; k<qsize; k++)
1473 for (
unsigned int i=0; i<ndofs; i++)
1474 local_flux_balance_vector[i] += arma::dot(ad_coef[sbi][k], fe_values_side.normal_vector(k))*fe_values_side.JxW(k)*fe_values_side.shape_value(i,k);
1478 ls[sbi]->rhs_set_values(ndofs, &(side_dof_indices[0]), local_rhs);
1480 if (Model::balance_ !=
nullptr)
1482 Model::balance_->add_flux_matrix_values(Model::subst_idx[sbi], loc_b, side_dof_indices, local_flux_balance_vector);
1483 Model::balance_->add_flux_vec_value(Model::subst_idx[sbi], loc_b, local_flux_balance_rhs);
1493 template<
class Model>
1494 template<
unsigned int dim>
1497 OLD_ASSERT(cell->dim() == dim,
"Element dimension mismatch!");
1501 for (
unsigned int k=0; k<fv.
n_points(); k++)
1503 velocity[k].zeros();
1504 for (
unsigned int sid=0; sid<cell->n_sides(); sid++)
1505 velocity[k] += fv.
shape_vector(sid,k) * Model::mh_dh->side_flux( *(cell->side(sid)) );
1513 template<
class Model>
1522 const double alpha1,
1523 const double alpha2,
1526 double &transport_flux)
1530 double local_alpha = 0;
1542 for (
unsigned int i=0; i<s->n_nodes(); i++)
1543 for (
unsigned int j=i+1; j<s->n_nodes(); j++)
1544 h = max(h, s->node(i)->distance(*s->node(j)));
1548 double pflux = 0, nflux = 0;
1549 for (
int i=0; i<edg.
n_sides; i++)
1558 if (fluxes[s2] > 0 && fluxes[s1] < 0 && s1 < s2)
1559 transport_flux = fluxes[s1]*fabs(fluxes[s2]/pflux);
1560 else if (fluxes[s2] < 0 && fluxes[s1] > 0 && s1 < s2)
1561 transport_flux = fluxes[s1]*fabs(fluxes[s2]/nflux);
1563 transport_flux = fluxes[s1];
1567 gamma = 0.5*fabs(transport_flux);
1571 local_alpha = max(alpha1, alpha2);
1579 for (
int k=0; k<K_size; k++)
1580 delta[0] += dot(K1[k]*normal_vector,normal_vector);
1583 gamma += local_alpha/h*(delta[0]);
1589 for (
int k=0; k<K_size; k++)
1591 delta[0] += dot(K1[k]*normal_vector,normal_vector);
1592 delta[1] += dot(K2[k]*normal_vector,normal_vector);
1597 double delta_sum = delta[0] + delta[1];
1601 omega[0] = delta[1]/delta_sum;
1602 omega[1] = delta[0]/delta_sum;
1603 gamma += local_alpha/h*(delta[0]*delta[1]/delta_sum);
1606 for (
int i=0; i<2; i++) omega[i] = 0;
1615 template<
class Model>
1624 double delta = 0, h = 0;
1627 if (side->
dim() == 0)
1633 for (
unsigned int i=0; i<side->
n_nodes(); i++)
1634 for (
unsigned int j=i+1; j<side->
n_nodes(); j++)
1639 for (
int k=0; k<K_size; k++)
1640 delta += dot(K[k]*normal_vector,normal_vector);
1643 gamma = 0.5*fabs(flux) + alpha/h*delta;
1650 template<
class Model>
1654 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1655 ls[sbi]->start_allocation();
1656 prepare_initial_condition<1>();
1657 prepare_initial_condition<2>();
1658 prepare_initial_condition<3>();
1660 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1661 ls[sbi]->start_add_assembly();
1662 prepare_initial_condition<1>();
1663 prepare_initial_condition<2>();
1664 prepare_initial_condition<3>();
1666 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1668 ls[sbi]->finish_assembly();
1674 template<
class Model>
1675 template<
unsigned int dim>
1678 FEValues<dim,3> fe_values(*feo->mapping<dim>(), *feo->q<dim>(), *feo->fe<dim>(),
1680 const unsigned int ndofs = feo->fe<dim>()->n_dofs(), qsize = feo->q<dim>()->size();
1681 unsigned int dof_indices[ndofs];
1682 double matrix[ndofs*ndofs], rhs[ndofs];
1685 for (
unsigned int k=0; k<qsize; k++)
1686 init_values[k].resize(Model::n_substances());
1688 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
1691 if (elem->dim() != dim)
continue;
1694 feo->dh()->get_dof_indices(elem, dof_indices);
1697 Model::compute_init_cond(fe_values.
point_list(), ele_acc, init_values);
1699 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1701 for (
unsigned int i=0; i<ndofs; i++)
1704 for (
unsigned int j=0; j<ndofs; j++)
1705 matrix[i*ndofs+j] = 0;
1708 for (
unsigned int k=0; k<qsize; k++)
1710 double rhs_term = init_values[k](sbi)*fe_values.
JxW(k);
1712 for (
unsigned int i=0; i<ndofs; i++)
1714 for (
unsigned int j=0; j<ndofs; j++)
1720 ls[sbi]->set_values(ndofs, (
int *)dof_indices, ndofs, (
int *)dof_indices, matrix, rhs);
1726 template<
class Model>
1729 el_4_loc = Model::mesh_->get_el_4_loc();
1730 el_ds = Model::mesh_->get_el_ds();
1734 template<
class Model>
1737 if (solution_changed)
1739 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
1743 unsigned int n_dofs;
1744 switch (elem->dim())
1747 n_dofs = feo->fe<1>()->n_dofs();
1750 n_dofs = feo->fe<2>()->n_dofs();
1753 n_dofs = feo->fe<3>()->n_dofs();
1757 unsigned int dof_indices[n_dofs];
1758 feo->dh()->get_dof_indices(elem, dof_indices);
1760 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
1762 double old_average = 0;
1763 for (
unsigned int j=0; j<n_dofs; ++j)
1764 old_average += ls[sbi]->get_solution_array()[dof_indices[j]-feo->dh()->distr()->begin()];
1765 old_average /= n_dofs;
1767 for (
unsigned int j=0; j<n_dofs; ++j)
1768 ls[sbi]->get_solution_array()[dof_indices[j]-feo->dh()->distr()->begin()] += solution_elem_[sbi][i_cell] - old_average;
1773 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
1774 MatMult(*(ls_dt[sbi]->get_matrix()), ls[sbi]->get_solution(), mass_vec[sbi]);
1777 template<
class Model>
1780 return Model::mesh_->get_row_4_el();
Input::Record input_rec
Record with input specification.
Class MappingP1 implements the affine transformation of the unit cell onto the actual cell...
double JxW(const unsigned int point_no)
Return the product of Jacobian determinant and the quadrature weight at given quadrature point...
void assemble_fluxes_element_element()
Assembles the fluxes between elements of the same dimension.
void set_sources()
Assembles the right hand side due to volume sources.
void set_boundary_conditions()
Assembles the r.h.s. components corresponding to the Dirichlet boundary conditions.
Transformed quadrature weight for cell sides.
void assemble_fluxes_element_side()
Assembles the fluxes between elements of different dimensions.
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.
Field< 3, FieldValue< 3 >::Integer > region_id
FieldCommon & flags_add(FieldFlag::Flags::Mask mask)
double distance(const Node &n2) const
void assemble_mass_matrix()
Assembles the mass matrix.
void update_solution() override
Computes the solution in one time instant.
int dg_variant
DG variant ((non-)symmetric/incomplete.
void prepare_initial_condition()
Assembles the auxiliary linear system to calculate the initial solution as L^2-projection of the pres...
Fields computed from the mesh data.
void set_initial_condition()
Sets the initial condition.
Class FEValues calculates finite element data on the actual cells such as shape function values...
#define FOR_ELEMENT_SIDES(i, j)
void set_from_input(const Input::Record in_rec)
#define AVERAGE(i, k, side_id)
void assemble_stiffness_matrix()
Assembles the stiffness matrix.
Discontinuous Galerkin method for equation of transport with dispersion.
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
MultiField< 3, FieldValue< 3 >::Scalar > dg_penalty
Penalty enforcing inter-element continuity of solution (for each substance).
static const Input::Type::Selection & get_dg_variant_selection_input_type()
Input type for the DG variant selection.
unsigned int n_points()
Returns the number of quadrature points.
EquationOutput output_fields
void calculate_cumulative_balance()
void assemble_fluxes_boundary()
Assembles the fluxes on the boundary.
Symmetric Gauss-Legendre quadrature formulae on simplices.
#define WAVERAGE(i, k, side_id)
TransportDG(Mesh &init_mesh, const Input::Record in_rec)
Constructor.
arma::vec::fixed< spacedim > normal_vector(unsigned int point_no)
Returns the normal vector to a side at given quadrature point.
void initialize() override
Discontinuous Lagrangean finite element on dim dimensional simplex.
Transformed quadrature points.
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).
FEObjects * feo
Finite element objects.
static constexpr Mask in_time_term
A field is part of time term of the equation.
FieldCommon & input_default(const string &input_default)
Raviart-Thomas element of order 0.
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.
static auto region_id(Mesh &mesh) -> IndexField
#define START_TIMER(tag)
Starts a timer with specified tag.
FiniteElement< dim, spacedim > * fe
The used finite element.
Provides the numbering of the finite element degrees of freedom on the computational mesh...
unsigned int dg_order
Polynomial order of finite elements.
void output_vector_gather()
static constexpr Mask in_rhs
A field is part of the right hand side of the equation.
Affine mapping between reference and actual cell.
Shape function gradients.
arma::vec::fixed< spacedim > shape_vector(const unsigned int function_no, const unsigned int point_no)
Return the value of the function_no-th shape function at the point_no-th quadrature point...
double shape_value(const unsigned int function_no, const unsigned int point_no)
Return the value of the function_no-th shape function at the point_no-th quadrature point...
DOFHandlerMultiDim * dh()
Discontinuous Galerkin method for equation of transport with dispersion.
void output_data() override
Write computed fields.
FieldCommon & description(const string &description)
EqData data_
Field data for model parameters.
bool allocation_done
Indicates whether matrices have been preallocated.
unsigned int cond_idx() const
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.
ElementFullIter element() const
void update_after_reactions(bool solution_changed)
void reinit(ElementFullIter &cell, unsigned int sid)
Update cell-dependent data (gradients, Jacobians etc.)
void reinit(ElementFullIter &cell)
Update cell-dependent data (gradients, Jacobians etc.)
unsigned int bulk_idx() const
Returns index of the region in the bulk set.
Abstract linear system class.
Definitions of particular quadrature rules on simplices.
FieldCommon & name(const string &name)
#define END_TIMER(tag)
Ends a timer with specified tag.
Discontinuous Galerkin method for equation of transport with dispersion.
vector< arma::vec::fixed< spacedim > > & point_list()
Return coordinates of all quadrature points in the actual cell system.
static const Input::Type::Record & get_input_type()
unsigned int el_idx() const
void calculate_instant_balance()
void assemble_volume_integrals()
Assembles the volume integrals into the stiffness matrix.
FieldCommon & flags(FieldFlag::Flags::Mask mask)
Abstract class for the description of a general finite element on a reference simplex in dim dimensio...
Base class for FEValues and FESideValues.
const Node * node(unsigned int i) const
void calculate_velocity(const ElementFullIter &cell, std::vector< arma::vec3 > &velocity, FEValuesBase< dim, 3 > &fv)
Calculates the velocity field on a given dim dimensional cell.
arma::vec::fixed< spacedim > shape_grad(const unsigned int function_no, const unsigned int point_no)
Return the gradient of the function_no-th shape function at the point_no-th quadrature point...
static UnitSI & dimensionless()
Returns dimensionless unit.
~TransportDG()
Destructor.
void set_DG_parameters_edge(const Edge &edg, const int s1, const int s2, const int K_size, const std::vector< arma::mat33 > &K1, const std::vector< arma::mat33 > &K2, const std::vector< double > &fluxes, const arma::vec3 &normal_vector, const double alpha1, const double alpha2, double &gamma, double *omega, double &transport_flux)
Sets up some parameters of the DG method for two sides of an edge.
SideIter side(const unsigned int i) const
#define JUMP(i, k, side_id)
void set_DG_parameters_boundary(const SideIter 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.
Definitions of Raviart-Thomas finite elements.
void get_par_info(int *&el_4_loc, Distribution *&el_ds)
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
ElementAccessor< 3 > element_accessor()
void zero_time_step() override
Initialize solution in the zero time.
FEObjects(Mesh *mesh_, unsigned int fe_order)
unsigned int n_nodes() const
Transformed quadrature weights.