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;
139 xprintf(
PrgErr,
"Unsupported polynomial order %d for finite elements in TransportDG ", fe_order);
159 dh_->distribute_dofs(*fe1_, *fe2_, *fe3_);
205 template<
class Model>
209 .
name(
"fracture_sigma")
211 "Coefficient of diffusive transfer through fractures (for each substance).")
219 "Penalty parameter influencing the discontinuity of the solution (for each substance). " 220 "Its default value 1 is sufficient in most cases. Higher value diminishes the inter-element jumps.")
235 template<
class Model>
237 : Model(init_mesh, in_rec),
251 data_.set_mesh(init_mesh);
259 Model::init_from_input(in_rec);
268 template<
class Model>
271 data_.set_components(Model::substances_.names());
275 gamma.resize(Model::n_substances());
276 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
277 gamma[sbi].resize(Model::mesh_->boundary_.size());
280 int qsize = max(
feo->
q<0>()->size(), max(
feo->
q<1>()->size(), max(
feo->
q<2>()->size(),
feo->
q<3>()->size())));
281 int max_edg_sides = max(Model::mesh_->max_edge_sides(1), max(Model::mesh_->max_edge_sides(2), Model::mesh_->max_edge_sides(3)));
283 ret_coef.resize(Model::n_substances());
285 ad_coef.resize(Model::n_substances());
286 dif_coef.resize(Model::n_substances());
287 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
295 for (
int sd=0; sd<max_edg_sides; sd++)
299 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
311 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
315 VecCreateSeq(PETSC_COMM_SELF, output_vector_size, &
output_vec[sbi]);
317 data_.output_field.set_components(Model::substances_.names());
318 data_.output_field.set_mesh(*Model::mesh_);
321 data_.output_field.setup_components();
322 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
327 data_.output_field[sbi].set_field(Model::mesh_->region_db().get_region_set(
"ALL"), output_field_ptr, 0);
334 ls =
new LinSys*[Model::n_substances()];
337 for (
unsigned int sbi = 0; sbi < Model::n_substances(); sbi++) {
344 solution_elem_[sbi] =
new double[Model::mesh_->get_el_ds()->lsize()];
348 rhs =
new Vec[Model::n_substances()];
349 mass_vec =
new Vec[Model::n_substances()];
353 if (Model::balance_ !=
nullptr)
356 max(
feo->
fe<1>()->n_dofs(), max(
feo->
fe<2>()->n_dofs(),
feo->
fe<3>()->n_dofs())));
362 template<
class Model>
367 if (
gamma.size() > 0) {
370 for (
auto &vec :
output_vec) VecDestroy(&vec);
372 for (
unsigned int i=0; i<Model::n_substances(); i++)
396 template<
class Model>
399 VecScatter output_scatter;
400 VecScatterCreateToZero(
ls[0]->
get_solution(), &output_scatter, PETSC_NULL);
401 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
407 VecScatterDestroy(&(output_scatter));
413 template<
class Model>
417 data_.mark_input_times( *(Model::time_) );
423 for (
unsigned int sbi = 0; sbi < Model::n_substances(); sbi++)
430 if (Model::balance_ !=
nullptr)
432 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
434 Model::balance_->calculate_mass(Model::subst_idx[sbi],
ls[sbi]->
get_solution());
435 Model::balance_->calculate_source(Model::subst_idx[sbi],
ls[sbi]->
get_solution());
436 Model::balance_->calculate_flux(Model::subst_idx[sbi],
ls[sbi]->
get_solution());
441 Model::balance_->calculate_mass(Model::subst_idx[sbi],
ls[sbi]->
get_solution(), masses);
442 for (
auto reg_mass : masses)
453 template<
class Model>
457 for (
unsigned int i=0; i<Model::n_substances(); i++)
478 template<
class Model>
483 Model::time_->next_time();
484 Model::time_->view(
"TDG");
493 for (
unsigned int i=0; i<Model::n_substances(); i++)
499 for (
unsigned int i=0; i<Model::n_substances(); i++)
507 if (Model::balance_ !=
nullptr && Model::balance_->cumulative())
509 double total_mass = 0;
513 MatConvert(*(
ls_dt[i]->get_matrix() ), MATSAME, MAT_INITIAL_MATRIX, &
mass_matrix[i]);
516 MatCopy(*(
ls_dt[i]->get_matrix() ),
mass_matrix[i], DIFFERENT_NONZERO_PATTERN);
523 || Model::flux_changed)
527 for (
unsigned int i=0; i<Model::n_substances(); i++)
533 for (
unsigned int i=0; i<Model::n_substances(); i++)
538 MatConvert(*(
ls[i]->get_matrix() ), MATSAME, MAT_INITIAL_MATRIX, &
stiffness_matrix[i]);
547 || Model::flux_changed)
549 for (
unsigned int i=0; i<Model::n_substances(); i++)
556 for (
unsigned int i=0; i<Model::n_substances(); i++)
560 if (
rhs[i] ==
nullptr) VecDuplicate(*(
ls[i]->get_rhs() ), &
rhs[i]);
561 VecCopy(*(
ls[i]->get_rhs() ),
rhs[i]);
565 Model::flux_changed =
false;
586 for (
unsigned int i=0; i<Model::n_substances(); i++)
589 MatAXPY(m, 1./Model::time_->dt(),
mass_matrix[i], SUBSET_NONZERO_PATTERN);
592 VecDuplicate(
rhs[i], &w);
593 VecWAXPY(w, 1./Model::time_->dt(),
mass_vec[i],
rhs[i]);
612 template<
class Model>
616 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
624 n_dofs =
feo->
fe<1>()->n_dofs();
627 n_dofs =
feo->
fe<2>()->n_dofs();
630 n_dofs =
feo->
fe<3>()->n_dofs();
634 unsigned int dof_indices[n_dofs];
637 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
641 for (
unsigned int j=0; j<n_dofs; ++j)
652 template<
class Model>
666 Model::output_data();
672 template<
class Model>
675 if (Model::balance_ !=
nullptr && Model::balance_->cumulative())
677 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
679 Model::balance_->calculate_cumulative_sources(Model::subst_idx[sbi],
ls[sbi]->
get_solution(), Model::time_->dt());
680 Model::balance_->calculate_cumulative_fluxes(Model::subst_idx[sbi],
ls[sbi]->
get_solution(), Model::time_->dt());
685 Model::balance_->calculate_mass(Model::subst_idx[sbi],
ls[sbi]->
get_solution(), masses);
686 for (
auto reg_mass : masses)
688 double total_mass = 0;
691 Model::balance_->add_cumulative_source(Model::subst_idx[sbi], mass-total_mass-
sorption_sources[sbi]);
698 template<
class Model>
701 if (Model::balance_ !=
nullptr)
703 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
705 Model::balance_->calculate_mass(Model::subst_idx[sbi],
ls[sbi]->
get_solution());
706 Model::balance_->calculate_source(Model::subst_idx[sbi],
ls[sbi]->
get_solution());
707 Model::balance_->calculate_flux(Model::subst_idx[sbi],
ls[sbi]->
get_solution());
713 template<
class Model>
717 if (Model::balance_ !=
nullptr)
718 Model::balance_->start_mass_assembly(Model::subst_idx);
719 assemble_mass_matrix<1>();
720 assemble_mass_matrix<2>();
721 assemble_mass_matrix<3>();
722 if (Model::balance_ !=
nullptr)
723 Model::balance_->finish_mass_assembly(Model::subst_idx);
728 template<
class Model>
template<
unsigned int dim>
732 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim>()->size();
734 PetscScalar local_mass_matrix[ndofs*ndofs];
738 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
741 if (cell->dim() != dim)
continue;
747 Model::compute_mass_matrix_coefficient(fe_values.
point_list(), ele_acc,
mm_coef);
750 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
753 for (
unsigned int i=0; i<ndofs; i++)
755 for (
unsigned int j=0; j<ndofs; j++)
757 local_mass_matrix[i*ndofs+j] = 0;
758 for (
unsigned int k=0; k<qsize; k++)
763 if (Model::balance_ !=
nullptr)
765 for (
unsigned int i=0; i<ndofs; i++)
767 local_mass_balance_vector[i] = 0;
768 for (
unsigned int k=0; k<qsize; k++)
773 Model::balance_->add_mass_matrix_values(Model::subst_idx[sbi], ele_acc.
region().
bulk_idx(), dof_indices, local_mass_balance_vector);
774 ls_dt[sbi]->
mat_set_values(ndofs, &(dof_indices[0]), ndofs, &(dof_indices[0]), local_mass_matrix);
782 template<
class Model>
787 assemble_volume_integrals<1>();
788 assemble_volume_integrals<2>();
789 assemble_volume_integrals<3>();
793 assemble_fluxes_boundary<1>();
794 assemble_fluxes_boundary<2>();
795 assemble_fluxes_boundary<3>();
799 assemble_fluxes_element_element<1>();
800 assemble_fluxes_element_element<2>();
801 assemble_fluxes_element_element<3>();
805 assemble_fluxes_element_side<1>();
806 assemble_fluxes_element_side<2>();
807 assemble_fluxes_element_side<3>();
814 template<
class Model>
815 template<
unsigned int dim>
822 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim>()->size();
823 unsigned int dof_indices[ndofs];
826 PetscScalar local_matrix[ndofs*ndofs];
829 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
832 if (cell->dim() != dim)
continue;
841 Model::compute_sources_sigma(fe_values.
point_list(), ele_acc, sources_sigma);
844 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
846 for (
unsigned int i=0; i<ndofs; i++)
847 for (
unsigned int j=0; j<ndofs; j++)
848 local_matrix[i*ndofs+j] = 0;
850 for (
unsigned int k=0; k<qsize; k++)
852 for (
unsigned int i=0; i<ndofs; i++)
855 double ad_dot_grad_i = arma::dot(ad_coef[sbi][k], fe_values.
shape_grad(i,k));
857 for (
unsigned int j=0; j<ndofs; j++)
858 local_matrix[i*ndofs+j] += (arma::dot(Kt_grad_i, fe_values.
shape_grad(j,k))
863 ls[sbi]->
mat_set_values(ndofs, (
int *)dof_indices, ndofs, (
int *)dof_indices, local_matrix);
869 template<
class Model>
873 if (Model::balance_ !=
nullptr)
874 Model::balance_->start_source_assembly(Model::subst_idx);
878 if (Model::balance_ !=
nullptr)
879 Model::balance_->finish_source_assembly(Model::subst_idx);
883 template<
class Model>
884 template<
unsigned int dim>
889 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim>()->size();
891 sources_density(qsize, arma::vec(Model::n_substances())),
892 sources_sigma(qsize, arma::vec(Model::n_substances()));
894 PetscScalar local_rhs[ndofs];
899 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
902 if (cell->dim() != dim)
continue;
907 Model::compute_source_coefficients(fe_values.
point_list(), cell->element_accessor(), sources_conc, sources_density, sources_sigma);
910 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
912 fill_n(local_rhs, ndofs, 0);
913 local_source_balance_vector.assign(ndofs, 0);
914 local_source_balance_rhs.assign(ndofs, 0);
917 for (
unsigned int k=0; k<qsize; k++)
919 source = (sources_density[k][sbi] + sources_conc[k][sbi]*sources_sigma[k][sbi])*fe_values.
JxW(k);
921 for (
unsigned int i=0; i<ndofs; i++)
926 if (Model::balance_ !=
nullptr)
928 for (
unsigned int i=0; i<ndofs; i++)
930 for (
unsigned int k=0; k<qsize; k++)
931 local_source_balance_vector[i] -= sources_sigma[k][sbi]*fe_values.
shape_value(i,k)*fe_values.
JxW(k);
933 local_source_balance_rhs[i] += local_rhs[i];
935 Model::balance_->add_source_matrix_values(Model::subst_idx[sbi], cell->region().bulk_idx(), dof_indices, local_source_balance_vector);
936 Model::balance_->add_source_vec_values(Model::subst_idx[sbi], cell->region().bulk_idx(), dof_indices, local_source_balance_rhs);
944 template<
class Model>
945 template<
unsigned int dim>
951 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim-1>()->size(),
954 PetscScalar local_matrix[ndofs*ndofs];
957 double gamma_l, omega[2], transport_flux;
959 for (
unsigned int sid=0; sid<n_max_sides; sid++)
961 side_dof_indices.push_back(
new unsigned int[ndofs]);
972 for (
int sid=0; sid<edg->
n_sides; sid++)
977 fe_values[sid]->reinit(cell, edg->
side(sid)->
el_idx());
980 Model::compute_advection_diffusion_coefficients(fe_values[sid]->point_list(), side_velocity[sid], ele_acc,
ad_coef_edg[sid],
dif_coef_edg[sid]);
985 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
988 for (
int sid=0; sid<edg->
n_sides; sid++)
991 for (
unsigned int k=0; k<qsize; k++)
992 fluxes[sid] += arma::dot(
ad_coef_edg[sid][sbi][k], fe_values[sid]->normal_vector(k))*fe_values[sid]->JxW(k);
996 for (
int s1=0; s1<edg->
n_sides; s1++)
998 for (
int s2=s1+1; s2<edg->
n_sides; s2++)
1004 arma::vec3 nv = fe_values[s1]->normal_vector(0);
1007 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);
1013 #define AVERAGE(i,k,side_id) (fe_values[sd[side_id]]->shape_value(i,k)*0.5) 1014 #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]) 1015 #define JUMP(i,k,side_id) ((side_id==0?1:-1)*fe_values[sd[side_id]]->shape_value(i,k)) 1018 for (
int n=0; n<2; n++)
1022 for (
int m=0; m<2; m++)
1024 for (
unsigned int i=0; i<fe_values[sd[n]]->n_dofs(); i++)
1025 for (
unsigned int j=0; j<fe_values[sd[m]]->n_dofs(); j++)
1026 local_matrix[i*fe_values[sd[m]]->n_dofs()+j] = 0;
1028 for (
unsigned int k=0; k<qsize; k++)
1030 double flux_times_JxW = transport_flux*fe_values[0]->JxW(k);
1031 double gamma_times_JxW = gamma_l*fe_values[0]->JxW(k);
1033 for (
unsigned int i=0; i<fe_values[sd[n]]->n_dofs(); i++)
1035 double flux_JxW_jump_i = flux_times_JxW*
JUMP(i,k,n);
1036 double gamma_JxW_jump_i = gamma_times_JxW*
JUMP(i,k,n);
1037 double JxW_jump_i = fe_values[0]->JxW(k)*
JUMP(i,k,n);
1040 for (
unsigned int j=0; j<fe_values[sd[m]]->n_dofs(); j++)
1042 int index = i*fe_values[sd[m]]->n_dofs()+j;
1045 local_matrix[index] += flux_JxW_jump_i*
AVERAGE(j,k,m);
1048 local_matrix[index] += gamma_JxW_jump_i*
JUMP(j,k,m);
1051 local_matrix[index] -=
WAVERAGE(j,k,m)*JxW_jump_i;
1052 local_matrix[index] -=
JUMP(j,k,m)*JxW_var_wavg_i;
1056 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);
1067 for (
unsigned int i=0; i<n_max_sides; i++)
1069 delete fe_values[i];
1070 delete[] side_dof_indices[i];
1075 template<
class Model>
1076 template<
unsigned int dim>
1083 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim-1>()->size();
1084 unsigned int side_dof_indices[ndofs];
1085 PetscScalar local_matrix[ndofs*ndofs];
1089 arma::vec dg_penalty;
1096 if (edg->
n_sides > 1)
continue;
1098 if (edg->
side(0)->
dim() != dim-1)
continue;
1100 if (edg->
side(0)->
cond() == NULL)
continue;
1110 Model::compute_advection_diffusion_coefficients(fe_values_side.
point_list(), side_velocity, ele_acc,
ad_coef,
dif_coef);
1114 data_.cross_section.value_list(fe_values_side.
point_list(), ele_acc, csection);
1116 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1118 for (
unsigned int i=0; i<ndofs; i++)
1119 for (
unsigned int j=0; j<ndofs; j++)
1120 local_matrix[i*ndofs+j] = 0;
1124 double side_flux = 0;
1125 for (
unsigned int k=0; k<qsize; k++)
1126 side_flux += arma::dot(ad_coef[sbi][k], fe_values_side.
normal_vector(k))*fe_values_side.
JxW(k);
1127 double transport_flux = side_flux/side->
measure();
1134 transport_flux += gamma_l;
1138 for (
unsigned int k=0; k<qsize; k++)
1140 double flux_times_JxW;
1144 flux_times_JxW = csection[k]*robin_sigma[k]*fe_values_side.
JxW(k);
1149 flux_times_JxW = (transport_flux + csection[k]*robin_sigma[k])*fe_values_side.
JxW(k);
1154 flux_times_JxW = transport_flux*fe_values_side.
JxW(k);
1156 for (
unsigned int i=0; i<ndofs; i++)
1158 for (
unsigned int j=0; j<ndofs; j++)
1161 local_matrix[i*ndofs+j] += flux_times_JxW*fe_values_side.
shape_value(i,k)*fe_values_side.
shape_value(j,k);
1167 )*fe_values_side.
JxW(k);
1172 ls[sbi]->
mat_set_values(ndofs, (
int *)side_dof_indices, ndofs, (
int *)side_dof_indices, local_matrix);
1178 template<
class Model>
1179 template<
unsigned int dim>
1183 if (dim == 1)
return;
1194 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs();
1195 const unsigned int qsize =
feo->
q<dim-1>()->size();
1196 unsigned int side_dof_indices[2*ndofs], n_dofs[2];
1199 vector<double> csection_lower(qsize), csection_higher(qsize), por_lower(qsize), por_higher(qsize);
1200 PetscScalar local_matrix[4*ndofs*ndofs];
1201 double comm_flux[2][2];
1205 fv_sb[0] = &fe_values_vb;
1206 fv_sb[1] = &fe_values_side;
1217 fe_values_vb.
reinit(cell_sub);
1218 n_dofs[0] = fv_sb[0]->n_dofs();
1223 n_dofs[1] = fv_sb[1]->n_dofs();
1227 element_id[0] = cell_sub.
index();
1228 element_id[1] = cell.
index();
1236 data_.cross_section.value_list(fe_values_vb.
point_list(), cell_sub->element_accessor(), csection_lower);
1237 data_.cross_section.value_list(fe_values_vb.
point_list(), cell->element_accessor(), csection_higher);
1239 data_.porosity.value_list(fe_values_vb.
point_list(), cell_sub->element_accessor(), por_lower);
1240 data_.porosity.value_list(fe_values_vb.
point_list(), cell->element_accessor(), por_higher);
1242 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1244 for (
unsigned int i=0; i<n_dofs[0]+n_dofs[1]; i++)
1245 for (
unsigned int j=0; j<n_dofs[0]+n_dofs[1]; j++)
1246 local_matrix[i*(n_dofs[0]+n_dofs[1])+j] = 0;
1249 for (
unsigned int k=0; k<qsize; k++)
1260 2*csection_higher[k]*csection_higher[k]/(csection_lower[k]*csection_lower[k]);
1263 double por_lower_over_higher = por_lower[k]/por_higher[k];
1265 comm_flux[0][0] = (sigma-min(0.,transport_flux*por_lower_over_higher))*fv_sb[0]->JxW(k);
1266 comm_flux[0][1] = -(sigma-min(0.,transport_flux*por_lower_over_higher))*fv_sb[0]->JxW(k);
1267 comm_flux[1][0] = -(sigma+max(0.,transport_flux))*fv_sb[0]->JxW(k);
1268 comm_flux[1][1] = (sigma+max(0.,transport_flux))*fv_sb[0]->JxW(k);
1270 for (
int n=0; n<2; n++)
1274 for (
unsigned int i=0; i<n_dofs[n]; i++)
1275 for (
int m=0; m<2; m++)
1276 for (
unsigned int j=0; j<n_dofs[m]; j++)
1277 local_matrix[(i+n*n_dofs[0])*(n_dofs[0]+n_dofs[1]) + m*n_dofs[0] + j] +=
1278 comm_flux[m][n]*fv_sb[m]->shape_value(j,k)*fv_sb[n]->shape_value(i,k);
1281 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);
1292 template<
class Model>
1296 if (Model::balance_ !=
nullptr)
1297 Model::balance_->start_flux_assembly(Model::subst_idx);
1298 set_boundary_conditions<1>();
1299 set_boundary_conditions<2>();
1300 set_boundary_conditions<3>();
1301 if (Model::balance_ !=
nullptr)
1302 Model::balance_->finish_flux_assembly(Model::subst_idx);
1307 template<
class Model>
1308 template<
unsigned int dim>
1315 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim-1>()->size();
1317 unsigned int loc_b=0;
1318 double local_rhs[ndofs];
1320 PetscScalar local_flux_balance_rhs;
1324 bc_ref_values(qsize);
1328 for (
unsigned int loc_el = 0; loc_el < Model::mesh_->get_el_ds()->lsize(); loc_el++)
1331 if (elm->boundary_idx_ ==
nullptr)
continue;
1335 Edge *edg = elm->side(si)->edge();
1336 if (edg->
n_sides > 1)
continue;
1338 if (edg->
side(0)->
cond() == NULL)
continue;
1340 if (edg->
side(0)->
dim() != dim-1)
1342 if (edg->
side(0)->
cond() !=
nullptr) ++loc_b;
1351 Model::get_bc_type(ele_acc, bc_type);
1358 data_.cross_section.value_list(fe_values_side.
point_list(), side->
element()->element_accessor(), csection);
1361 data_.bc_dirichlet_value.value_list(fe_values_side.
point_list(), ele_acc, bc_values);
1365 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1367 fill_n(local_rhs, ndofs, 0);
1368 local_flux_balance_vector.assign(ndofs, 0);
1369 local_flux_balance_rhs = 0;
1371 double side_flux = 0;
1372 for (
unsigned int k=0; k<qsize; k++)
1374 double transport_flux = side_flux/side->
measure();
1378 for (
unsigned int k=0; k<qsize; k++)
1380 double bc_term = -transport_flux*bc_values[k][sbi]*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);
1384 if (Model::balance_ !=
nullptr)
1385 for (
unsigned int i=0; i<ndofs; i++)
1386 local_flux_balance_rhs -= local_rhs[i];
1390 for (
unsigned int k=0; k<qsize; k++)
1392 double bc_term =
gamma[sbi][side->
cond_idx()]*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)
1396 + arma::dot(bc_grad,fe_values_side.
shape_grad(i,k));
1398 if (Model::balance_ !=
nullptr)
1400 for (
unsigned int k=0; k<qsize; k++)
1402 for (
unsigned int i=0; i<ndofs; i++)
1409 if (Model::time_->tlevel() > 0)
1410 for (
unsigned int i=0; i<ndofs; i++)
1411 local_flux_balance_rhs -= local_rhs[i];
1416 Model::get_flux_bc_data(sbi, fe_values_side.
point_list(), ele_acc, bc_fluxes, bc_sigma, bc_ref_values);
1417 for (
unsigned int k=0; k<qsize; k++)
1419 double bc_term = csection[k]*(bc_sigma[k]*bc_ref_values[k]+bc_fluxes[k])*fe_values_side.
JxW(k);
1420 for (
unsigned int i=0; i<ndofs; i++)
1421 local_rhs[i] += bc_term*fe_values_side.
shape_value(i,k);
1424 if (Model::balance_ !=
nullptr)
1426 for (
unsigned int i=0; i<ndofs; i++)
1428 for (
unsigned int k=0; k<qsize; k++)
1429 local_flux_balance_vector[i] += csection[k]*bc_sigma[k]*fe_values_side.
JxW(k)*fe_values_side.
shape_value(i,k);
1430 local_flux_balance_rhs -= local_rhs[i];
1436 Model::get_flux_bc_data(sbi, fe_values_side.
point_list(), ele_acc, bc_fluxes, bc_sigma, bc_ref_values);
1437 for (
unsigned int k=0; k<qsize; k++)
1439 double bc_term = csection[k]*(bc_sigma[k]*bc_ref_values[k]+bc_fluxes[k])*fe_values_side.
JxW(k);
1440 for (
unsigned int i=0; i<ndofs; i++)
1441 local_rhs[i] += bc_term*fe_values_side.
shape_value(i,k);
1444 if (Model::balance_ !=
nullptr)
1446 for (
unsigned int i=0; i<ndofs; i++)
1448 for (
unsigned int k=0; k<qsize; k++)
1449 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);
1450 local_flux_balance_rhs -= local_rhs[i];
1456 if (Model::balance_ !=
nullptr)
1458 for (
unsigned int k=0; k<qsize; k++)
1460 for (
unsigned int i=0; i<ndofs; i++)
1467 if (Model::balance_ !=
nullptr)
1469 Model::balance_->add_flux_matrix_values(Model::subst_idx[sbi], loc_b, side_dof_indices, local_flux_balance_vector);
1470 Model::balance_->add_flux_vec_value(Model::subst_idx[sbi], loc_b, local_flux_balance_rhs);
1480 template<
class Model>
1481 template<
unsigned int dim>
1484 OLD_ASSERT(cell->dim() == dim,
"Element dimension mismatch!");
1488 for (
unsigned int k=0; k<fv.
n_points(); k++)
1490 velocity[k].zeros();
1491 for (
unsigned int sid=0; sid<cell->n_sides(); sid++)
1492 velocity[k] += fv.
shape_vector(sid,k) * Model::mh_dh->side_flux( *(cell->side(sid)) );
1500 template<
class Model>
1509 const double alpha1,
1510 const double alpha2,
1513 double &transport_flux)
1517 double local_alpha = 0;
1529 for (
unsigned int i=0; i<s->n_nodes(); i++)
1530 for (
unsigned int j=i+1; j<s->n_nodes(); j++)
1531 h = max(h, s->node(i)->distance(*s->node(j)));
1535 double pflux = 0, nflux = 0;
1536 for (
int i=0; i<edg.
n_sides; i++)
1545 if (fluxes[s2] > 0 && fluxes[s1] < 0 && s1 < s2)
1546 transport_flux = fluxes[s1]*fabs(fluxes[s2]/pflux);
1547 else if (fluxes[s2] < 0 && fluxes[s1] > 0 && s1 < s2)
1548 transport_flux = fluxes[s1]*fabs(fluxes[s2]/nflux);
1550 transport_flux = fluxes[s1];
1554 gamma = 0.5*fabs(transport_flux);
1558 local_alpha = max(alpha1, alpha2);
1566 for (
int k=0; k<K_size; k++)
1567 delta[0] += dot(K1[k]*normal_vector,normal_vector);
1570 gamma += local_alpha/h*(delta[0]);
1576 for (
int k=0; k<K_size; k++)
1578 delta[0] += dot(K1[k]*normal_vector,normal_vector);
1579 delta[1] += dot(K2[k]*normal_vector,normal_vector);
1584 double delta_sum = delta[0] + delta[1];
1588 omega[0] = delta[1]/delta_sum;
1589 omega[1] = delta[0]/delta_sum;
1590 gamma += local_alpha/h*(delta[0]*delta[1]/delta_sum);
1593 for (
int i=0; i<2; i++) omega[i] = 0;
1602 template<
class Model>
1611 double delta = 0, h = 0;
1614 if (side->
dim() == 0)
1620 for (
unsigned int i=0; i<side->
n_nodes(); i++)
1621 for (
unsigned int j=i+1; j<side->
n_nodes(); j++)
1626 for (
int k=0; k<K_size; k++)
1627 delta += dot(K[k]*normal_vector,normal_vector);
1630 gamma = 0.5*fabs(flux) + alpha/h*delta;
1637 template<
class Model>
1641 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1642 ls[sbi]->start_allocation();
1643 prepare_initial_condition<1>();
1644 prepare_initial_condition<2>();
1645 prepare_initial_condition<3>();
1647 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1648 ls[sbi]->start_add_assembly();
1649 prepare_initial_condition<1>();
1650 prepare_initial_condition<2>();
1651 prepare_initial_condition<3>();
1653 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1661 template<
class Model>
1662 template<
unsigned int dim>
1667 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim>()->size();
1668 unsigned int dof_indices[ndofs];
1669 double matrix[ndofs*ndofs],
rhs[ndofs];
1672 for (
unsigned int k=0; k<qsize; k++)
1673 init_values[k].resize(Model::n_substances());
1675 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
1678 if (elem->dim() != dim)
continue;
1684 Model::compute_init_cond(fe_values.
point_list(), ele_acc, init_values);
1686 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1688 for (
unsigned int i=0; i<ndofs; i++)
1691 for (
unsigned int j=0; j<ndofs; j++)
1692 matrix[i*ndofs+j] = 0;
1695 for (
unsigned int k=0; k<qsize; k++)
1697 double rhs_term = init_values[k](sbi)*fe_values.
JxW(k);
1699 for (
unsigned int i=0; i<ndofs; i++)
1701 for (
unsigned int j=0; j<ndofs; j++)
1707 ls[sbi]->
set_values(ndofs, (
int *)dof_indices, ndofs, (
int *)dof_indices, matrix, rhs);
1713 template<
class Model>
1716 el_4_loc = Model::mesh_->get_el_4_loc();
1717 el_ds = Model::mesh_->get_el_ds();
1721 template<
class Model>
1724 if (solution_changed)
1726 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
1730 unsigned int n_dofs;
1731 switch (elem->dim())
1734 n_dofs =
feo->
fe<1>()->n_dofs();
1737 n_dofs =
feo->
fe<2>()->n_dofs();
1740 n_dofs =
feo->
fe<3>()->n_dofs();
1744 unsigned int dof_indices[n_dofs];
1747 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
1749 double old_average = 0;
1750 for (
unsigned int j=0; j<n_dofs; ++j)
1751 old_average +=
ls[sbi]->get_solution_array()[dof_indices[j]-
feo->
dh()->
distr()->
begin()];
1752 old_average /= n_dofs;
1754 for (
unsigned int j=0; j<n_dofs; ++j)
1760 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
1764 template<
class Model>
1767 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.
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.
void initialize(std::shared_ptr< OutputTime > stream, Input::Record in_rec, const TimeGovernor &tg)
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.
unsigned int n_loc_nb() const
Returns number of local neighbours.
Mat * mass_matrix
The mass matrix.
#define AVERAGE(i, k, side_id)
void assemble_stiffness_matrix()
Assembles the stiffness matrix.
int el_index(int loc_el) const
Returns the global index of local element.
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.
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.
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.
vector< double > sorption_sources
Temporary values of source increments.
void initialize() override
vector< vector< vector< arma::vec3 > > > ad_coef_edg
Advection coefficients on edges.
Discontinuous Lagrangean finite element on dim dimensional simplex.
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.
unsigned int begin(int proc) const
get starting local index
int nb_index(int loc_nb) const
Returns the global index of local neighbour.
static auto region_id(Mesh &mesh) -> IndexField
#define START_TIMER(tag)
Starts a timer with specified tag.
Provides the numbering of the finite element degrees of freedom on the computational mesh...
Mat * stiffness_matrix
The stiffness matrix.
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.
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...
FLOW123D_FORCE_LINK_IN_CHILD(concentrationTransportModel)
Vec * rhs
Vector of right hand side.
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...
DOFHandlerMultiDim * dh()
virtual PetscErrorCode rhs_zero_entries()
unsigned int n_loc_edges() const
Returns number of local edges.
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).
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.
virtual MultiFieldValue::return_type value(const Point &p, const ElementAccessor< spacedim > &elm) const
Discontinuous Galerkin method for equation of transport with dispersion.
void get_dof_indices(const CellIterator &cell, unsigned int indices[]) const override
Returns the global indices of dofs associated to the cell.
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.)
Vec * mass_vec
Mass from previous time instant (necessary when coefficients of mass matrix change in time)...
bool set_time(const TimeStep &time, LimitSide limit_side)
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)
vector< Vec > output_vec
Array for storing the output solution data.
#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()
virtual PetscErrorCode set_matrix(Mat &matrix, MatStructure str)
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.
bool el_is_local(int index) const
int edge_index(int loc_edg) const
Returns the global index of local edge.
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...
Distribution * distr() const
Mapping< dim, 3 > * mapping()
static UnitSI & dimensionless()
Returns dimensionless unit.
~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)
Sets up some parameters of the DG method for two sides of an edge.
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.
void get_par_info(int *&el_4_loc, Distribution *&el_ds)
const unsigned int n_global_dofs() const
Getter for the number of all mesh dofs required by the given finite element.
ElementAccessor< 3 > element_accessor()
virtual void value_list(const std::vector< Point > &point_list, const ElementAccessor< spacedim > &elm, std::vector< typename MultiFieldValue::return_type > &value_list) const
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.
unsigned int lsize(int proc) const
get local size