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).")
89 EqData().output_fields.make_output_type(equation_name,
""),
90 IT::Default(
"{ \"fields\": [ " + Model::ModelEqData::default_output_field() +
"] }"),
91 "Setting of the field output.")
97 Input::register_class< TransportDG<Model>,
Mesh &,
const Input::Record>(std::string(Model::ModelEqData::name()) +
"_DG") +
105 unsigned int q_order;
107 q_order = 2*fe_order;
125 dh_ = std::make_shared<DOFHandlerMultiDim>(*mesh_);
127 dh_->distribute_dofs(*fe1_, *fe2_, *fe3_);
170 template<
class Model>
174 .
name(
"fracture_sigma")
176 "Coefficient of diffusive transfer through fractures (for each substance).")
184 "Penalty parameter influencing the discontinuity of the solution (for each substance). " 185 "Its default value 1 is sufficient in most cases. Higher value diminishes the inter-element jumps.")
204 template<
class Model>
206 : Model(init_mesh, in_rec),
220 data_.set_mesh(init_mesh);
229 Model::init_from_input(in_rec);
238 template<
class Model>
241 data_.set_components(Model::substances_.names());
245 gamma.resize(Model::n_substances());
246 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
247 gamma[sbi].resize(Model::mesh_->boundary_.size());
250 int qsize = max(
feo->
q<0>()->size(), max(
feo->
q<1>()->size(), max(
feo->
q<2>()->size(),
feo->
q<3>()->size())));
251 int max_edg_sides = max(Model::mesh_->max_edge_sides(1), max(Model::mesh_->max_edge_sides(2), Model::mesh_->max_edge_sides(3)));
253 ret_coef.resize(Model::n_substances());
256 ad_coef.resize(Model::n_substances());
257 dif_coef.resize(Model::n_substances());
258 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
266 for (
int sd=0; sd<max_edg_sides; sd++)
270 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
281 unsigned int output_vector_size= (rank==0)?
feo->
dh()->n_global_dofs():0;
282 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
288 data_.output_field.set_components(Model::substances_.names());
289 data_.output_field.set_mesh(*Model::mesh_);
292 data_.output_field.setup_components();
293 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
298 data_.output_field[sbi].set_field(Model::mesh_->region_db().get_region_set(
"ALL"), output_field_ptr, 0);
305 std::string petsc_default_opts;
306 if (
feo->
dh()->distr()->np() == 1)
307 petsc_default_opts =
"-ksp_type bcgs -pc_type ilu -pc_factor_levels 2 -ksp_diagonal_scale_fix -pc_factor_fill 6.0";
309 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";
312 ls =
new LinSys*[Model::n_substances()];
317 mass_matrix.resize(Model::n_substances(),
nullptr);
318 rhs.resize(Model::n_substances(),
nullptr);
319 mass_vec.resize(Model::n_substances(),
nullptr);
320 ret_vec.resize(Model::n_substances(),
nullptr);
322 for (
unsigned int sbi = 0; sbi < Model::n_substances(); sbi++) {
329 solution_elem_[sbi] =
new double[Model::mesh_->get_el_ds()->lsize()];
336 Model::balance_->allocate(
feo->
dh()->distr()->lsize(),
337 max(
feo->
fe<1>()->n_dofs(), max(
feo->
fe<2>()->n_dofs(),
feo->
fe<3>()->n_dofs())));
342 template<
class Model>
347 if (
gamma.size() > 0) {
350 for (
unsigned int i=0; i<Model::n_substances(); i++)
382 template<
class Model>
385 VecScatter output_scatter;
386 VecScatterCreateToZero(
ls[0]->
get_solution(), &output_scatter, PETSC_NULL);
387 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
390 VecScatterBegin(output_scatter,
ls[sbi]->
get_solution(), (
output_vec[sbi]).get_data_petsc(), INSERT_VALUES, SCATTER_FORWARD);
391 VecScatterEnd(output_scatter,
ls[sbi]->
get_solution(), (
output_vec[sbi]).get_data_petsc(), INSERT_VALUES, SCATTER_FORWARD);
393 VecScatterDestroy(&(output_scatter));
399 template<
class Model>
403 data_.mark_input_times( *(Model::time_) );
405 std::stringstream ss;
413 for (
unsigned int sbi = 0; sbi < Model::n_substances(); sbi++)
420 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
422 Model::balance_->calculate_instant(Model::subst_idx[sbi],
ls[sbi]->
get_solution());
432 template<
class Model>
436 for (
unsigned int i=0; i<Model::n_substances(); i++)
452 for (
unsigned int i=0; i<Model::n_substances(); i++)
463 template<
class Model>
468 Model::time_->next_time();
469 Model::time_->view(
"TDG");
478 for (
unsigned int i=0; i<Model::n_substances(); i++)
485 for (
unsigned int i=0; i<Model::n_substances(); i++)
495 MatConvert(*(
ls_dt[i]->get_matrix() ), MATSAME, MAT_INITIAL_MATRIX, &
mass_matrix[i]);
498 MatCopy(*(
ls_dt[i]->get_matrix() ),
mass_matrix[i], DIFFERENT_NONZERO_PATTERN);
505 || Model::flux_changed)
509 for (
unsigned int i=0; i<Model::n_substances(); i++)
515 for (
unsigned int i=0; i<Model::n_substances(); i++)
520 MatConvert(*(
ls[i]->get_matrix() ), MATSAME, MAT_INITIAL_MATRIX, &
stiffness_matrix[i]);
529 || Model::flux_changed)
531 for (
unsigned int i=0; i<Model::n_substances(); i++)
538 for (
unsigned int i=0; i<Model::n_substances(); i++)
542 if (
rhs[i] ==
nullptr) VecDuplicate(*(
ls[i]->get_rhs() ), &
rhs[i]);
543 VecCopy(*(
ls[i]->get_rhs() ),
rhs[i]);
547 Model::flux_changed =
false;
568 for (
unsigned int i=0; i<Model::n_substances(); i++)
571 MatAXPY(m, 1./Model::time_->dt(),
mass_matrix[i], SUBSET_NONZERO_PATTERN);
574 VecDuplicate(
rhs[i], &w);
575 VecWAXPY(w, 1./Model::time_->dt(),
mass_vec[i],
rhs[i]);
594 template<
class Model>
598 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
606 n_dofs =
feo->
fe<1>()->n_dofs();
609 n_dofs =
feo->
fe<2>()->n_dofs();
612 n_dofs =
feo->
fe<3>()->n_dofs();
617 feo->
dh()->get_dof_indices(elem, dof_indices);
619 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
623 for (
unsigned int j=0; j<n_dofs; ++j)
624 solution_elem_[sbi][i_cell] +=
ls[sbi]->get_solution_array()[dof_indices[j]-
feo->
dh()->distr()->begin()];
634 template<
class Model>
648 Model::output_data();
651 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
652 Model::balance_->calculate_instant(Model::subst_idx[sbi],
ls[sbi]->
get_solution());
653 Model::balance_->output();
660 template<
class Model>
663 if (Model::balance_->cumulative())
665 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
667 Model::balance_->calculate_cumulative(Model::subst_idx[sbi],
ls[sbi]->
get_solution());
679 template<
class Model>
683 Model::balance_->start_mass_assembly(Model::subst_idx);
684 assemble_mass_matrix<1>();
685 assemble_mass_matrix<2>();
686 assemble_mass_matrix<3>();
687 Model::balance_->finish_mass_assembly(Model::subst_idx);
692 template<
class Model>
template<
unsigned int dim>
696 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim>()->size();
698 PetscScalar local_mass_matrix[ndofs*ndofs], local_retardation_balance_vector[ndofs];
702 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
705 if (cell->dim() != dim)
continue;
708 feo->
dh()->get_dof_indices(cell, dof_indices);
711 Model::compute_mass_matrix_coefficient(fe_values.
point_list(), ele_acc,
mm_coef);
714 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
717 for (
unsigned int i=0; i<ndofs; i++)
719 for (
unsigned int j=0; j<ndofs; j++)
721 local_mass_matrix[i*ndofs+j] = 0;
722 for (
unsigned int k=0; k<qsize; k++)
727 for (
unsigned int i=0; i<ndofs; i++)
729 local_mass_balance_vector[i] = 0;
730 local_retardation_balance_vector[i] = 0;
731 for (
unsigned int k=0; k<qsize; k++)
738 Model::balance_->add_mass_matrix_values(Model::subst_idx[sbi], ele_acc.
region().
bulk_idx(), dof_indices, local_mass_balance_vector);
739 ls_dt[sbi]->
mat_set_values(ndofs, &(dof_indices[0]), ndofs, &(dof_indices[0]), local_mass_matrix);
740 VecSetValues(
ret_vec[sbi], ndofs, &(dof_indices[0]), local_retardation_balance_vector, ADD_VALUES);
748 template<
class Model>
753 assemble_volume_integrals<1>();
754 assemble_volume_integrals<2>();
755 assemble_volume_integrals<3>();
759 assemble_fluxes_boundary<1>();
760 assemble_fluxes_boundary<2>();
761 assemble_fluxes_boundary<3>();
765 assemble_fluxes_element_element<1>();
766 assemble_fluxes_element_element<2>();
767 assemble_fluxes_element_element<3>();
771 assemble_fluxes_element_side<1>();
772 assemble_fluxes_element_side<2>();
773 assemble_fluxes_element_side<3>();
780 template<
class Model>
781 template<
unsigned int dim>
788 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim>()->size();
792 PetscScalar local_matrix[ndofs*ndofs];
795 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
798 if (cell->dim() != dim)
continue;
803 feo->
dh()->get_dof_indices(cell, dof_indices);
807 Model::compute_sources_sigma(fe_values.
point_list(), ele_acc, sources_sigma);
810 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
812 for (
unsigned int i=0; i<ndofs; i++)
813 for (
unsigned int j=0; j<ndofs; j++)
814 local_matrix[i*ndofs+j] = 0;
816 for (
unsigned int k=0; k<qsize; k++)
818 for (
unsigned int i=0; i<ndofs; i++)
821 double ad_dot_grad_i = arma::dot(ad_coef[sbi][k], fe_values.
shape_grad(i,k));
823 for (
unsigned int j=0; j<ndofs; j++)
824 local_matrix[i*ndofs+j] += (arma::dot(Kt_grad_i, fe_values.
shape_grad(j,k))
829 ls[sbi]->
mat_set_values(ndofs, &(dof_indices[0]), ndofs, &(dof_indices[0]), local_matrix);
835 template<
class Model>
839 Model::balance_->start_source_assembly(Model::subst_idx);
843 Model::balance_->finish_source_assembly(Model::subst_idx);
847 template<
class Model>
848 template<
unsigned int dim>
853 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim>()->size();
858 PetscScalar local_rhs[ndofs];
863 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
866 if (cell->dim() != dim)
continue;
869 feo->
dh()->get_dof_indices(cell, dof_indices);
871 Model::compute_source_coefficients(fe_values.
point_list(), cell->element_accessor(), sources_conc, sources_density, sources_sigma);
874 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
876 fill_n(local_rhs, ndofs, 0);
877 local_source_balance_vector.assign(ndofs, 0);
878 local_source_balance_rhs.assign(ndofs, 0);
881 for (
unsigned int k=0; k<qsize; k++)
883 source = (sources_density[sbi][k] + sources_conc[sbi][k]*sources_sigma[sbi][k])*fe_values.
JxW(k);
885 for (
unsigned int i=0; i<ndofs; i++)
890 for (
unsigned int i=0; i<ndofs; i++)
892 for (
unsigned int k=0; k<qsize; k++)
893 local_source_balance_vector[i] -= sources_sigma[sbi][k]*fe_values.
shape_value(i,k)*fe_values.
JxW(k);
895 local_source_balance_rhs[i] += local_rhs[i];
897 Model::balance_->add_source_matrix_values(Model::subst_idx[sbi], cell->region().bulk_idx(), dof_indices, local_source_balance_vector);
898 Model::balance_->add_source_vec_values(Model::subst_idx[sbi], cell->region().bulk_idx(), dof_indices, local_source_balance_rhs);
905 template<
class Model>
906 template<
unsigned int dim>
912 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim-1>()->size(),
915 PetscScalar local_matrix[ndofs*ndofs];
918 double gamma_l, omega[2], transport_flux;
920 for (
unsigned int sid=0; sid<n_max_sides; sid++)
928 for (
unsigned int iedg=0; iedg<
feo->
dh()->n_loc_edges(); iedg++)
930 Edge *edg = &Model::mesh_->edges[
feo->
dh()->edge_index(iedg)];
933 for (
int sid=0; sid<edg->
n_sides; sid++)
937 feo->
dh()->get_dof_indices(cell, side_dof_indices[sid]);
938 fe_values[sid]->reinit(cell, edg->
side(sid)->
el_idx());
941 Model::compute_advection_diffusion_coefficients(fe_values[sid]->point_list(), side_velocity[sid], ele_acc,
ad_coef_edg[sid],
dif_coef_edg[sid]);
942 dg_penalty[sid].resize(Model::n_substances());
943 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
944 dg_penalty[sid][sbi] =
data_.
dg_penalty[sbi].value(cell->centre(), ele_acc);
948 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
951 for (
int sid=0; sid<edg->
n_sides; sid++)
954 for (
unsigned int k=0; k<qsize; k++)
955 fluxes[sid] += arma::dot(
ad_coef_edg[sid][sbi][k], fe_values[sid]->normal_vector(k))*fe_values[sid]->JxW(k);
959 for (
int s1=0; s1<edg->
n_sides; s1++)
961 for (
int s2=s1+1; s2<edg->
n_sides; s2++)
967 arma::vec3 nv = fe_values[s1]->normal_vector(0);
970 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);
976 #define AVERAGE(i,k,side_id) (fe_values[sd[side_id]]->shape_value(i,k)*0.5) 977 #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]) 978 #define JUMP(i,k,side_id) ((side_id==0?1:-1)*fe_values[sd[side_id]]->shape_value(i,k)) 981 for (
int n=0; n<2; n++)
985 for (
int m=0; m<2; m++)
987 for (
unsigned int i=0; i<fe_values[sd[n]]->n_dofs(); i++)
988 for (
unsigned int j=0; j<fe_values[sd[m]]->n_dofs(); j++)
989 local_matrix[i*fe_values[sd[m]]->n_dofs()+j] = 0;
991 for (
unsigned int k=0; k<qsize; k++)
993 double flux_times_JxW = transport_flux*fe_values[0]->JxW(k);
994 double gamma_times_JxW = gamma_l*fe_values[0]->JxW(k);
996 for (
unsigned int i=0; i<fe_values[sd[n]]->n_dofs(); i++)
998 double flux_JxW_jump_i = flux_times_JxW*
JUMP(i,k,n);
999 double gamma_JxW_jump_i = gamma_times_JxW*
JUMP(i,k,n);
1000 double JxW_jump_i = fe_values[0]->JxW(k)*
JUMP(i,k,n);
1003 for (
unsigned int j=0; j<fe_values[sd[m]]->n_dofs(); j++)
1005 int index = i*fe_values[sd[m]]->n_dofs()+j;
1008 local_matrix[index] += flux_JxW_jump_i*
AVERAGE(j,k,m);
1011 local_matrix[index] += gamma_JxW_jump_i*
JUMP(j,k,m);
1014 local_matrix[index] -=
WAVERAGE(j,k,m)*JxW_jump_i;
1015 local_matrix[index] -=
JUMP(j,k,m)*JxW_var_wavg_i;
1019 ls[sbi]->
mat_set_values(fe_values[sd[n]]->n_dofs(), &(side_dof_indices[sd[n]][0]), fe_values[sd[m]]->n_dofs(), &(side_dof_indices[sd[m]][0]), local_matrix);
1030 for (
unsigned int i=0; i<n_max_sides; i++)
1032 delete fe_values[i];
1037 template<
class Model>
1038 template<
unsigned int dim>
1045 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim-1>()->size();
1047 PetscScalar local_matrix[ndofs*ndofs];
1054 for (
unsigned int iedg=0; iedg<
feo->
dh()->n_loc_edges(); iedg++)
1056 Edge *edg = &Model::mesh_->edges[
feo->
dh()->edge_index(iedg)];
1057 if (edg->
n_sides > 1)
continue;
1059 if (edg->
side(0)->
dim() != dim-1)
continue;
1061 if (edg->
side(0)->
cond() == NULL)
continue;
1066 feo->
dh()->get_dof_indices(cell, side_dof_indices);
1071 Model::compute_advection_diffusion_coefficients(fe_values_side.
point_list(), side_velocity, ele_acc,
ad_coef,
dif_coef);
1074 data_.cross_section.value_list(fe_values_side.
point_list(), ele_acc, csection);
1076 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1078 for (
unsigned int i=0; i<ndofs; i++)
1079 for (
unsigned int j=0; j<ndofs; j++)
1080 local_matrix[i*ndofs+j] = 0;
1084 double side_flux = 0;
1085 for (
unsigned int k=0; k<qsize; k++)
1086 side_flux += arma::dot(ad_coef[sbi][k], fe_values_side.
normal_vector(k))*fe_values_side.
JxW(k);
1087 double transport_flux = side_flux/side->
measure();
1094 transport_flux += gamma_l;
1098 for (
unsigned int k=0; k<qsize; k++)
1100 double flux_times_JxW;
1104 flux_times_JxW = csection[k]*robin_sigma[k]*fe_values_side.
JxW(k);
1109 flux_times_JxW = (transport_flux + csection[k]*robin_sigma[k])*fe_values_side.
JxW(k);
1114 flux_times_JxW = transport_flux*fe_values_side.
JxW(k);
1116 for (
unsigned int i=0; i<ndofs; i++)
1118 for (
unsigned int j=0; j<ndofs; j++)
1121 local_matrix[i*ndofs+j] += flux_times_JxW*fe_values_side.
shape_value(i,k)*fe_values_side.
shape_value(j,k);
1127 )*fe_values_side.
JxW(k);
1132 ls[sbi]->
mat_set_values(ndofs, &(side_dof_indices[0]), ndofs, &(side_dof_indices[0]), local_matrix);
1138 template<
class Model>
1139 template<
unsigned int dim>
1143 if (dim == 1)
return;
1154 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs();
1155 const unsigned int qsize =
feo->
q<dim-1>()->size();
1156 int side_dof_indices[2*ndofs];
1158 unsigned int n_dofs[2], n_indices;
1162 PetscScalar local_matrix[4*ndofs*ndofs];
1163 double comm_flux[2][2];
1167 fv_sb[0] = &fe_values_vb;
1168 fv_sb[1] = &fe_values_side;
1171 for (
unsigned int inb=0; inb<
feo->
dh()->n_loc_nb(); inb++)
1173 Neighbour *nb = &Model::mesh_->vb_neighbours_[
feo->
dh()->nb_index(inb)];
1178 n_indices =
feo->
dh()->get_dof_indices(cell_sub, indices);
1179 for(
unsigned int i=0; i<n_indices; ++i) {
1180 side_dof_indices[i] = indices[i];
1182 fe_values_vb.
reinit(cell_sub);
1183 n_dofs[0] = fv_sb[0]->n_dofs();
1186 n_indices =
feo->
dh()->get_dof_indices(cell, indices);
1187 for(
unsigned int i=0; i<n_indices; ++i) {
1188 side_dof_indices[i+n_dofs[0]] = indices[i];
1191 n_dofs[1] = fv_sb[1]->n_dofs();
1195 element_id[0] = cell_sub.
index();
1196 element_id[1] = cell.
index();
1204 data_.cross_section.value_list(fe_values_vb.
point_list(), cell_sub->element_accessor(), csection_lower);
1205 data_.cross_section.value_list(fe_values_vb.
point_list(), cell->element_accessor(), csection_higher);
1207 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1209 for (
unsigned int i=0; i<n_dofs[0]+n_dofs[1]; i++)
1210 for (
unsigned int j=0; j<n_dofs[0]+n_dofs[1]; j++)
1211 local_matrix[i*(n_dofs[0]+n_dofs[1])+j] = 0;
1216 for (
unsigned int k=0; k<qsize; k++)
1227 2*csection_higher[k]*csection_higher[k]/(csection_lower[k]*csection_lower[k]);
1231 comm_flux[0][0] = (sigma-min(0.,transport_flux))*fv_sb[0]->JxW(k);
1232 comm_flux[0][1] = -(sigma-min(0.,transport_flux))*fv_sb[0]->JxW(k);
1233 comm_flux[1][0] = -(sigma+max(0.,transport_flux))*fv_sb[0]->JxW(k);
1234 comm_flux[1][1] = (sigma+max(0.,transport_flux))*fv_sb[0]->JxW(k);
1236 for (
int n=0; n<2; n++)
1238 if (!
feo->
dh()->el_is_local(element_id[n]))
continue;
1240 for (
unsigned int i=0; i<n_dofs[n]; i++)
1241 for (
int m=0; m<2; m++)
1242 for (
unsigned int j=0; j<n_dofs[m]; j++)
1243 local_matrix[(i+n*n_dofs[0])*(n_dofs[0]+n_dofs[1]) + m*n_dofs[0] + j] +=
1244 comm_flux[m][n]*fv_sb[m]->shape_value(j,k)*fv_sb[n]->shape_value(i,k);
1247 ls[sbi]->
mat_set_values(n_dofs[0]+n_dofs[1], side_dof_indices, n_dofs[0]+n_dofs[1], side_dof_indices, local_matrix);
1258 template<
class Model>
1262 Model::balance_->start_flux_assembly(Model::subst_idx);
1263 set_boundary_conditions<1>();
1264 set_boundary_conditions<2>();
1265 set_boundary_conditions<3>();
1266 Model::balance_->finish_flux_assembly(Model::subst_idx);
1271 template<
class Model>
1272 template<
unsigned int dim>
1279 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim-1>()->size();
1281 unsigned int loc_b=0;
1282 double local_rhs[ndofs];
1284 PetscScalar local_flux_balance_rhs;
1288 bc_ref_values(qsize);
1292 for (
unsigned int loc_el = 0; loc_el < Model::mesh_->get_el_ds()->lsize(); loc_el++)
1295 if (elm->boundary_idx_ ==
nullptr)
continue;
1299 Edge *edg = elm->side(si)->edge();
1300 if (edg->
n_sides > 1)
continue;
1302 if (edg->
side(0)->
cond() == NULL)
continue;
1304 if (edg->
side(0)->
dim() != dim-1)
1306 if (edg->
side(0)->
cond() !=
nullptr) ++loc_b;
1315 Model::get_bc_type(ele_acc, bc_type);
1322 data_.cross_section.value_list(fe_values_side.
point_list(), side->
element()->element_accessor(), csection);
1324 feo->
dh()->get_dof_indices(cell, side_dof_indices);
1326 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1328 fill_n(local_rhs, ndofs, 0);
1329 local_flux_balance_vector.assign(ndofs, 0);
1330 local_flux_balance_rhs = 0;
1334 data_.bc_dirichlet_value[sbi].value_list(fe_values_side.
point_list(), ele_acc, bc_values);
1336 double side_flux = 0;
1337 for (
unsigned int k=0; k<qsize; k++)
1339 double transport_flux = side_flux/side->
measure();
1343 for (
unsigned int k=0; k<qsize; k++)
1345 double bc_term = -transport_flux*bc_values[k]*fe_values_side.
JxW(k);
1346 for (
unsigned int i=0; i<ndofs; i++)
1347 local_rhs[i] += bc_term*fe_values_side.
shape_value(i,k);
1349 for (
unsigned int i=0; i<ndofs; i++)
1350 local_flux_balance_rhs -= local_rhs[i];
1354 for (
unsigned int k=0; k<qsize; k++)
1356 double bc_term =
gamma[sbi][side->
cond_idx()]*bc_values[k]*fe_values_side.
JxW(k);
1358 for (
unsigned int i=0; i<ndofs; i++)
1359 local_rhs[i] += bc_term*fe_values_side.
shape_value(i,k)
1360 + arma::dot(bc_grad,fe_values_side.
shape_grad(i,k));
1362 for (
unsigned int k=0; k<qsize; k++)
1364 for (
unsigned int i=0; i<ndofs; i++)
1371 if (Model::time_->tlevel() > 0)
1372 for (
unsigned int i=0; i<ndofs; i++)
1373 local_flux_balance_rhs -= local_rhs[i];
1377 Model::get_flux_bc_data(sbi, fe_values_side.
point_list(), ele_acc, bc_fluxes, bc_sigma, bc_ref_values);
1378 for (
unsigned int k=0; k<qsize; k++)
1380 double bc_term = csection[k]*(bc_sigma[k]*bc_ref_values[k]+bc_fluxes[k])*fe_values_side.
JxW(k);
1381 for (
unsigned int i=0; i<ndofs; i++)
1382 local_rhs[i] += bc_term*fe_values_side.
shape_value(i,k);
1385 for (
unsigned int i=0; i<ndofs; i++)
1387 for (
unsigned int k=0; k<qsize; k++)
1388 local_flux_balance_vector[i] += csection[k]*bc_sigma[k]*fe_values_side.
JxW(k)*fe_values_side.
shape_value(i,k);
1389 local_flux_balance_rhs -= local_rhs[i];
1394 Model::get_flux_bc_data(sbi, fe_values_side.
point_list(), ele_acc, bc_fluxes, bc_sigma, bc_ref_values);
1395 for (
unsigned int k=0; k<qsize; k++)
1397 double bc_term = csection[k]*(bc_sigma[k]*bc_ref_values[k]+bc_fluxes[k])*fe_values_side.
JxW(k);
1398 for (
unsigned int i=0; i<ndofs; i++)
1399 local_rhs[i] += bc_term*fe_values_side.
shape_value(i,k);
1402 for (
unsigned int i=0; i<ndofs; i++)
1404 for (
unsigned int k=0; k<qsize; k++)
1405 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);
1406 local_flux_balance_rhs -= local_rhs[i];
1411 for (
unsigned int k=0; k<qsize; k++)
1413 for (
unsigned int i=0; i<ndofs; i++)
1419 Model::balance_->add_flux_matrix_values(Model::subst_idx[sbi], loc_b, side_dof_indices, local_flux_balance_vector);
1420 Model::balance_->add_flux_vec_value(Model::subst_idx[sbi], loc_b, local_flux_balance_rhs);
1429 template<
class Model>
1430 template<
unsigned int dim>
1435 OLD_ASSERT(cell->dim() == dim,
"Element dimension mismatch!");
1439 for (
unsigned int k=0; k<fv.
n_points(); k++)
1441 velocity[k].zeros();
1442 for (
unsigned int sid=0; sid<cell->n_sides(); sid++)
1443 for (
unsigned int c=0; c<3; ++c)
1444 velocity[k][c] += fv.
shape_value_component(sid,k,c) * Model::mh_dh->side_flux( *(cell->side(sid)) );
1452 double h_max = 0, h_min = numeric_limits<double>::infinity();
1453 for (
unsigned int i=0; i<e->n_nodes(); i++)
1454 for (
unsigned int j=i+1; j<e->n_nodes(); j++)
1456 h_max = max(h_max, e->node[i]->distance(*e->node[j]));
1457 h_min = min(h_min, e->node[i]->distance(*e->node[j]));
1464 template<
class Model>
1473 const double alpha1,
1474 const double alpha2,
1477 double &transport_flux)
1481 double local_alpha = 0;
1493 for (
unsigned int i=0; i<s->n_nodes(); i++)
1494 for (
unsigned int j=i+1; j<s->n_nodes(); j++)
1495 h = max(h, s->node(i)->distance(*s->node(j)));
1503 double pflux = 0, nflux = 0;
1504 for (
int i=0; i<edg.
n_sides; i++)
1513 if (fluxes[s2] > 0 && fluxes[s1] < 0 && s1 < s2)
1514 transport_flux = fluxes[s1]*fabs(fluxes[s2]/pflux);
1515 else if (fluxes[s2] < 0 && fluxes[s1] > 0 && s1 < s2)
1516 transport_flux = fluxes[s1]*fabs(fluxes[s2]/nflux);
1518 transport_flux = fluxes[s1];
1522 gamma = 0.5*fabs(transport_flux);
1526 local_alpha = max(alpha1, alpha2);
1534 for (
int k=0; k<K_size; k++)
1535 delta[0] += dot(K1[k]*normal_vector,normal_vector);
1538 gamma += local_alpha/h*aniso1*aniso2*delta[0];
1544 for (
int k=0; k<K_size; k++)
1546 delta[0] += dot(K1[k]*normal_vector,normal_vector);
1547 delta[1] += dot(K2[k]*normal_vector,normal_vector);
1552 double delta_sum = delta[0] + delta[1];
1555 if (fabs(delta_sum) > 0)
1557 omega[0] = delta[1]/delta_sum;
1558 omega[1] = delta[0]/delta_sum;
1559 gamma += local_alpha/h*aniso1*aniso2*(delta[0]*delta[1]/delta_sum);
1562 for (
int i=0; i<2; i++) omega[i] = 0;
1571 template<
class Model>
1580 double delta = 0, h = 0;
1583 if (side->
dim() == 0)
1589 for (
unsigned int i=0; i<side->
n_nodes(); i++)
1590 for (
unsigned int j=i+1; j<side->
n_nodes(); j++)
1595 for (
int k=0; k<K_size; k++)
1596 delta += dot(K[k]*normal_vector,normal_vector);
1606 template<
class Model>
1610 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1611 ls[sbi]->start_allocation();
1612 prepare_initial_condition<1>();
1613 prepare_initial_condition<2>();
1614 prepare_initial_condition<3>();
1616 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1617 ls[sbi]->start_add_assembly();
1618 prepare_initial_condition<1>();
1619 prepare_initial_condition<2>();
1620 prepare_initial_condition<3>();
1622 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1630 template<
class Model>
1631 template<
unsigned int dim>
1636 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim>()->size();
1638 double matrix[ndofs*ndofs],
rhs[ndofs];
1641 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1642 init_values[sbi].resize(qsize);
1644 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
1647 if (elem->dim() != dim)
continue;
1650 feo->
dh()->get_dof_indices(elem, dof_indices);
1653 Model::compute_init_cond(fe_values.
point_list(), ele_acc, init_values);
1655 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1657 for (
unsigned int i=0; i<ndofs; i++)
1660 for (
unsigned int j=0; j<ndofs; j++)
1661 matrix[i*ndofs+j] = 0;
1664 for (
unsigned int k=0; k<qsize; k++)
1666 double rhs_term = init_values[sbi][k]*fe_values.
JxW(k);
1668 for (
unsigned int i=0; i<ndofs; i++)
1670 for (
unsigned int j=0; j<ndofs; j++)
1676 ls[sbi]->
set_values(ndofs, &(dof_indices[0]), ndofs, &(dof_indices[0]), matrix, rhs);
1682 template<
class Model>
1685 el_4_loc = Model::mesh_->get_el_4_loc();
1686 el_ds = Model::mesh_->get_el_ds();
1690 template<
class Model>
1693 if (solution_changed)
1695 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
1699 unsigned int n_dofs;
1700 switch (elem->dim())
1703 n_dofs =
feo->
fe<1>()->n_dofs();
1706 n_dofs =
feo->
fe<2>()->n_dofs();
1709 n_dofs =
feo->
fe<3>()->n_dofs();
1714 feo->
dh()->get_dof_indices(elem, dof_indices);
1716 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
1718 double old_average = 0;
1719 for (
unsigned int j=0; j<n_dofs; ++j)
1720 old_average +=
ls[sbi]->get_solution_array()[dof_indices[j]-
feo->
dh()->distr()->begin()];
1721 old_average /= n_dofs;
1723 for (
unsigned int j=0; j<n_dofs; ++j)
1724 ls[sbi]->get_solution_array()[dof_indices[j]-
feo->
dh()->distr()->begin()] +=
solution_elem_[sbi][i_cell] - old_average;
1729 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
1733 template<
class Model>
1736 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...
int IdxInt
Define integers that are indices into large arrays (elements, nodes, dofs etc.)
static auto subdomain(Mesh &mesh) -> IndexField
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.
vector< VectorSeqDouble > output_vec
Array for storing the output solution data.
FiniteElement< dim, 3 > * fe()
vector< double > mm_coef
Mass matrix coefficients.
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 set_from_input(const Input::Record in_rec) override
virtual void start_add_assembly()
void assemble_mass_matrix()
Assembles the mass matrix.
void output(TimeStep step)
virtual PetscErrorCode mat_zero_entries()
virtual void rhs_set_values(int nrow, int *rows, double *vals)=0
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.
virtual void start_allocation()
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)
virtual void finish_assembly()=0
vector< vector< arma::vec3 > > ad_coef
Advection coefficients.
#define AVERAGE(i, k, side_id)
std::shared_ptr< DOFHandlerMultiDim > dh()
void assemble_stiffness_matrix()
Assembles the stiffness matrix.
vector< vector< vector< arma::mat33 > > > dif_coef_edg
Diffusion coefficients on edges.
Discontinuous Galerkin method for equation of transport with dispersion.
const Vec & get_solution(unsigned int sbi)
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
vector< double > ret_sources_prev
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
std::vector< Mat > mass_matrix
The mass matrix.
void calculate_cumulative_balance()
void assemble_fluxes_boundary()
Assembles the fluxes on the boundary.
static constexpr bool value
Symmetric Gauss-Legendre quadrature formulae on simplices.
#define WAVERAGE(i, k, side_id)
TransportDG(Mesh &init_mesh, const Input::Record in_rec)
Constructor.
vector< vector< double > > ret_coef
Retardation coefficient due to sorption.
arma::vec::fixed< spacedim > normal_vector(unsigned int point_no)
Returns the normal vector to a side at given quadrature point.
void initialize() override
vector< vector< vector< arma::vec3 > > > ad_coef_edg
Advection coefficients on edges.
Transformed quadrature points.
void output_data()
Postprocesses the solution and writes to output file.
virtual PetscErrorCode set_rhs(Vec &rhs)
MultiField< 3, FieldValue< 3 >::Scalar > fracture_sigma
Transition parameter for diffusive transfer on fractures (for each substance).
vector< vector< arma::mat33 > > dif_coef
Diffusion coefficients.
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)
const Vec & get_solution()
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.
std::vector< Vec > rhs
Vector of right hand side.
FiniteElement< dim, 3 > * fe_rt()
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.
Shape function gradients.
FLOW123D_FORCE_LINK_IN_CHILD(concentrationTransportModel)
void set_solution(double *sol_array)
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...
double elem_anisotropy(const ElementFullIter &e)
virtual PetscErrorCode rhs_zero_entries()
void get_par_info(IdxInt *&el_4_loc, Distribution *&el_ds)
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.
FieldCommon & description(const string &description)
void set_values(int nrow, int *rows, int ncol, int *cols, PetscScalar *mat_vals, PetscScalar *rhs_vals)
Set values in the system matrix and values in the right-hand side vector on corresponding rows...
EqData data_
Field data for model parameters.
bool allocation_done
Indicates whether matrices have been preallocated.
unsigned int cond_idx() const
std::vector< std::vector< double > > gamma
Penalty parameters.
static const Input::Type::Record & get_input_type()
Declare input record type for the equation TransportDG.
void initialize(std::shared_ptr< OutputTime > stream, Mesh *mesh, Input::Record in_rec, const TimeGovernor &tg)
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.)
MappingP1< dim, 3 > * mapping()
std::vector< Vec > ret_vec
Auxiliary vectors for calculation of sources in balance due to retardation (e.g. sorption).
double shape_value_component(const unsigned int function_no, const unsigned int point_no, const unsigned int comp) const
Return the value of the function_no-th shape function at the point_no-th quadrature point...
void reinit(ElementFullIter &cell)
Update cell-dependent data (gradients, Jacobians etc.)
vector< double > ret_sources
Temporary values of increments due to retardation (e.g. sorption)
bool set_time(const TimeStep &time, LimitSide limit_side)
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...
unsigned int bulk_idx() const
Returns index of the region in the bulk set.
Definitions of particular quadrature rules on simplices.
#define WarningOut()
Macro defining 'warning' record of log.
FieldCommon & name(const string &name)
virtual SolveInfo solve()=0
#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
virtual PetscErrorCode set_matrix(Mat &matrix, MatStructure str)
std::vector< Vec > mass_vec
Mass from previous time instant (necessary when coefficients of mass matrix change in time)...
void assemble_volume_integrals()
Assembles the volume integrals into the stiffness matrix.
virtual void mat_set_values(int nrow, int *rows, int ncol, int *cols, double *vals)=0
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.
Field< 3, FieldValue< 3 >::Integer > subdomain
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.
static UnitSI & dimensionless()
Returns dimensionless unit.
static bool print_message_table(ostream &stream, std::string equation_name)
~TransportDG()
Destructor.
LinSys ** ls
Linear algebra system for the transport equation.
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)
Calculates the dispersivity (diffusivity) tensor from the velocity field.
SideIter side(const unsigned int i) const
LinSys ** ls_dt
Linear algebra system for the time derivative (actually it is used only for handling the matrix struc...
#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.
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.
Calculates finite element data on a side.