46 return Selection(
"DG_variant",
"Type of penalty term.")
47 .
add_value(non_symmetric,
"non-symmetric",
"non-symmetric weighted interior penalty DG method")
48 .
add_value(incomplete,
"incomplete",
"incomplete weighted interior penalty DG method")
49 .
add_value(symmetric,
"symmetric",
"symmetric weighted interior penalty DG method")
72 return Model::get_input_type(
"DG",
"DG solver")
74 "Linear solver for MH problem.")
77 .make_field_descriptor_type(std::string(Model::ModelEqData::name()) +
"_DG")),
79 "Input fields of the equation.")
81 "Variant of interior penalty discontinuous Galerkin method.")
83 "Polynomial order for finite element in DG method (order 0 is suitable if there is no diffusion/dispersion).")
88 Model::ModelEqData::get_output_selection()
91 EqData().make_output_field_selection(
"DG_output_fields",
"Auxiliary Selection")
94 Default(Model::ModelEqData::default_output_field()),
95 "List of fields to write to output file.")
101 Input::register_class< TransportDG<Model>,
Mesh &,
const Input::Record>(std::string(Model::ModelEqData::name()) +
"_DG") +
109 unsigned int q_order;
143 xprintf(
PrgErr,
"Unsupported polynomial order %d for finite elements in TransportDG ", fe_order);
163 dh_->distribute_dofs(*fe1_, *fe2_, *fe3_);
209 template<
class Model>
213 .
name(
"fracture_sigma")
215 "Coefficient of diffusive transfer through fractures (for each substance).")
223 "Penalty parameter influencing the discontinuity of the solution (for each substance). " 224 "Its default value 1 is sufficient in most cases. Higher value diminishes the inter-element jumps.")
237 template<
class Model>
239 : Model(init_mesh, in_rec),
248 static_assert(std::is_base_of<AdvectionDiffusionModel, Model>::value,
"");
254 data_.set_mesh(init_mesh);
264 DBGMSG(
"TDG: solution size %d\n", feo->dh()->n_global_dofs());
269 template<
class Model>
272 data_.set_components(Model::substances_.names());
276 gamma.resize(Model::n_substances());
277 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
278 gamma[sbi].resize(Model::mesh_->boundary_.size());
281 int qsize = max(
feo->
q<0>()->size(), max(
feo->
q<1>()->size(), max(
feo->
q<2>()->size(),
feo->
q<3>()->size())));
282 int max_edg_sides = max(Model::mesh_->max_edge_sides(1), max(Model::mesh_->max_edge_sides(2), Model::mesh_->max_edge_sides(3)));
284 ad_coef.resize(Model::n_substances());
285 dif_coef.resize(Model::n_substances());
286 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
293 for (
int sd=0; sd<max_edg_sides; sd++)
297 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
309 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
313 VecCreateSeq(PETSC_COMM_SELF, output_vector_size, &
output_vec[sbi]);
315 data_.output_field.set_components(Model::substances_.names());
316 data_.output_field.set_mesh(*Model::mesh_);
319 data_.output_field.setup_components();
320 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
325 data_.output_field[sbi].set_field(Model::mesh_->region_db().get_region_set(
"ALL"), output_field_ptr, 0);
330 Model::output_stream_->mark_output_times(*Model::time_);
334 ls =
new LinSys*[Model::n_substances()];
338 for (
unsigned int sbi = 0; sbi < Model::n_substances(); sbi++) {
342 solution_elem_[sbi] =
new double[Model::mesh_->get_el_ds()->lsize()];
345 rhs =
new Vec[Model::n_substances()];
346 mass_vec =
new Vec[Model::n_substances()];
350 if (Model::balance_ !=
nullptr)
353 max(
feo->
fe<1>()->n_dofs(), max(
feo->
fe<2>()->n_dofs(),
feo->
fe<3>()->n_dofs())));
359 template<
class Model>
365 if (Model::mesh_->get_el_ds()->myp() == 0)
367 for (
unsigned int i=0; i<Model::n_substances(); i++)
374 for (
unsigned int i=0; i<Model::n_substances(); i++)
393 template<
class Model>
397 VecScatter output_scatter;
399 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
404 VecScatterCreateToZero(
ls[sbi]->
get_solution(), &output_scatter, PETSC_NULL);
407 VecScatterDestroy(&(output_scatter));
414 template<
class Model>
418 data_.mark_input_times( *(Model::time_) );
424 for (
unsigned int sbi = 0; sbi < Model::n_substances(); sbi++)
431 if (Model::balance_ !=
nullptr)
433 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
435 Model::balance_->calculate_mass(Model::subst_idx[sbi],
ls[sbi]->
get_solution());
436 Model::balance_->calculate_source(Model::subst_idx[sbi],
ls[sbi]->
get_solution());
437 Model::balance_->calculate_flux(Model::subst_idx[sbi],
ls[sbi]->
get_solution());
445 template<
class Model>
454 for (
unsigned int i=0; i<Model::n_substances(); i++)
469 template<
class Model>
474 Model::time_->next_time();
475 Model::time_->view(
"TDG");
492 for (
unsigned int i=0; i<Model::n_substances(); i++)
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, 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();
616 unsigned int dof_indices[n_dofs];
619 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
623 for (
unsigned int j=0; j<n_dofs; ++j)
634 template<
class Model>
637 if (!Model::time_->is_current( Model::time_->marks().type_output() ))
return;
644 data_.output(Model::output_stream_);
646 Model::output_data();
652 template<
class Model>
655 if (Model::balance_ !=
nullptr && Model::balance_->cumulative())
657 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
659 Model::balance_->calculate_cumulative_sources(Model::subst_idx[sbi],
ls[sbi]->
get_solution(), Model::time_->dt());
660 Model::balance_->calculate_cumulative_fluxes(Model::subst_idx[sbi],
ls[sbi]->
get_solution(), Model::time_->dt());
666 template<
class Model>
669 if (Model::balance_ !=
nullptr)
671 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
673 Model::balance_->calculate_mass(Model::subst_idx[sbi],
ls[sbi]->
get_solution());
674 Model::balance_->calculate_source(Model::subst_idx[sbi],
ls[sbi]->
get_solution());
675 Model::balance_->calculate_flux(Model::subst_idx[sbi],
ls[sbi]->
get_solution());
681 template<
class Model>
685 if (Model::balance_ !=
nullptr)
686 Model::balance_->start_mass_assembly(Model::subst_idx);
687 assemble_mass_matrix<1>();
688 assemble_mass_matrix<2>();
689 assemble_mass_matrix<3>();
690 if (Model::balance_ !=
nullptr)
691 Model::balance_->finish_mass_assembly(Model::subst_idx);
696 template<
class Model>
template<
unsigned int dim>
700 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim>()->size();
702 PetscScalar local_mass_matrix[ndofs*ndofs];
706 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
709 if (cell->dim() != dim)
continue;
715 Model::compute_mass_matrix_coefficient(fe_values.
point_list(), ele_acc,
mm_coef);
718 for (
unsigned int i=0; i<ndofs; i++)
720 for (
unsigned int j=0; j<ndofs; j++)
722 local_mass_matrix[i*ndofs+j] = 0;
723 for (
unsigned int k=0; k<qsize; k++)
728 if (Model::balance_ !=
nullptr)
730 for (
unsigned int i=0; i<ndofs; i++)
732 local_mass_balance_vector[i] = 0;
733 for (
unsigned int k=0; k<qsize; k++)
737 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
738 Model::balance_->add_mass_matrix_values(Model::subst_idx[sbi], ele_acc.
region().
bulk_idx(), dof_indices, local_mass_balance_vector);
741 ls_dt->
mat_set_values(ndofs, &(dof_indices[0]), ndofs, &(dof_indices[0]), local_mass_matrix);
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();
789 unsigned int dof_indices[ndofs];
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;
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, (
int *)dof_indices, ndofs, (
int *)dof_indices, local_matrix);
835 template<
class Model>
839 if (Model::balance_ !=
nullptr)
840 Model::balance_->start_source_assembly(Model::subst_idx);
844 if (Model::balance_ !=
nullptr)
845 Model::balance_->finish_source_assembly(Model::subst_idx);
849 template<
class Model>
850 template<
unsigned int dim>
855 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim>()->size();
857 sources_density(qsize, arma::vec(Model::n_substances())),
858 sources_sigma(qsize, arma::vec(Model::n_substances()));
860 PetscScalar local_rhs[ndofs];
865 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
868 if (cell->dim() != dim)
continue;
873 Model::compute_source_coefficients(fe_values.
point_list(), cell->element_accessor(), sources_conc, sources_density, sources_sigma);
876 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
878 fill_n(local_rhs, ndofs, 0);
879 local_source_balance_vector.assign(ndofs, 0);
880 local_source_balance_rhs.assign(ndofs, 0);
883 for (
unsigned int k=0; k<qsize; k++)
885 source = (sources_density[k][sbi] + sources_conc[k][sbi]*sources_sigma[k][sbi])*fe_values.
JxW(k);
887 for (
unsigned int i=0; i<ndofs; i++)
892 if (Model::balance_ !=
nullptr)
894 for (
unsigned int i=0; i<ndofs; i++)
896 for (
unsigned int k=0; k<qsize; k++)
897 local_source_balance_vector[i] -= sources_sigma[k][sbi]*fe_values.
shape_value(i,k)*fe_values.
JxW(k);
899 local_source_balance_rhs[i] += local_rhs[i];
901 Model::balance_->add_source_matrix_values(Model::subst_idx[sbi], cell->region().bulk_idx(), dof_indices, local_source_balance_vector);
902 Model::balance_->add_source_rhs_values(Model::subst_idx[sbi], cell->region().bulk_idx(), dof_indices, local_source_balance_rhs);
910 template<
class Model>
911 template<
unsigned int dim>
917 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim-1>()->size(),
920 PetscScalar local_matrix[ndofs*ndofs];
923 double gamma_l, omega[2], transport_flux;
925 for (
unsigned int sid=0; sid<n_max_sides; sid++)
927 side_dof_indices.push_back(
new unsigned int[ndofs]);
938 for (
int sid=0; sid<edg->
n_sides; sid++)
943 fe_values[sid]->reinit(cell, edg->
side(sid)->
el_idx());
946 Model::compute_advection_diffusion_coefficients(fe_values[sid]->point_list(), side_velocity[sid], ele_acc,
ad_coef_edg[sid],
dif_coef_edg[sid]);
951 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
954 for (
int sid=0; sid<edg->
n_sides; sid++)
957 for (
unsigned int k=0; k<qsize; k++)
958 fluxes[sid] += arma::dot(
ad_coef_edg[sid][sbi][k], fe_values[sid]->normal_vector(k))*fe_values[sid]->JxW(k);
962 for (
int s1=0; s1<edg->
n_sides; s1++)
964 for (
int s2=s1+1; s2<edg->
n_sides; s2++)
970 arma::vec3 nv = fe_values[s1]->normal_vector(0);
973 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);
979 #define AVERAGE(i,k,side_id) (fe_values[sd[side_id]]->shape_value(i,k)*0.5) 980 #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]) 981 #define JUMP(i,k,side_id) ((side_id==0?1:-1)*fe_values[sd[side_id]]->shape_value(i,k)) 984 for (
int n=0; n<2; n++)
988 for (
int m=0; m<2; m++)
990 for (
unsigned int i=0; i<fe_values[sd[n]]->n_dofs(); i++)
991 for (
unsigned int j=0; j<fe_values[sd[m]]->n_dofs(); j++)
992 local_matrix[i*fe_values[sd[m]]->n_dofs()+j] = 0;
994 for (
unsigned int k=0; k<qsize; k++)
996 double flux_times_JxW = transport_flux*fe_values[0]->JxW(k);
997 double gamma_times_JxW = gamma_l*fe_values[0]->JxW(k);
999 for (
unsigned int i=0; i<fe_values[sd[n]]->n_dofs(); i++)
1001 double flux_JxW_jump_i = flux_times_JxW*
JUMP(i,k,n);
1002 double gamma_JxW_jump_i = gamma_times_JxW*
JUMP(i,k,n);
1003 double JxW_jump_i = fe_values[0]->JxW(k)*
JUMP(i,k,n);
1006 for (
unsigned int j=0; j<fe_values[sd[m]]->n_dofs(); j++)
1008 int index = i*fe_values[sd[m]]->n_dofs()+j;
1011 local_matrix[index] += flux_JxW_jump_i*
AVERAGE(j,k,m);
1014 local_matrix[index] += gamma_JxW_jump_i*
JUMP(j,k,m);
1017 local_matrix[index] -=
WAVERAGE(j,k,m)*JxW_jump_i;
1018 local_matrix[index] -=
JUMP(j,k,m)*JxW_var_wavg_i;
1022 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);
1033 for (
unsigned int i=0; i<n_max_sides; i++)
1035 delete fe_values[i];
1036 delete[] side_dof_indices[i];
1041 template<
class Model>
1042 template<
unsigned int dim>
1049 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim-1>()->size();
1050 unsigned int side_dof_indices[ndofs];
1051 PetscScalar local_matrix[ndofs*ndofs];
1055 arma::vec dg_penalty;
1062 if (edg->
n_sides > 1)
continue;
1064 if (edg->
side(0)->
dim() != dim-1)
continue;
1066 if (edg->
side(0)->
cond() == NULL)
continue;
1076 Model::compute_advection_diffusion_coefficients(fe_values_side.
point_list(), side_velocity, ele_acc,
ad_coef,
dif_coef);
1080 data_.cross_section.value_list(fe_values_side.
point_list(), ele_acc, csection);
1082 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1084 for (
unsigned int i=0; i<ndofs; i++)
1085 for (
unsigned int j=0; j<ndofs; j++)
1086 local_matrix[i*ndofs+j] = 0;
1090 double side_flux = 0;
1091 for (
unsigned int k=0; k<qsize; k++)
1092 side_flux += arma::dot(ad_coef[sbi][k], fe_values_side.
normal_vector(k))*fe_values_side.
JxW(k);
1093 double transport_flux = side_flux/side->
measure();
1100 transport_flux += gamma_l;
1104 for (
unsigned int k=0; k<qsize; k++)
1106 double flux_times_JxW;
1110 flux_times_JxW = csection[k]*robin_sigma[k]*fe_values_side.
JxW(k);
1115 flux_times_JxW = (transport_flux + csection[k]*robin_sigma[k])*fe_values_side.
JxW(k);
1120 flux_times_JxW = transport_flux*fe_values_side.
JxW(k);
1122 for (
unsigned int i=0; i<ndofs; i++)
1124 for (
unsigned int j=0; j<ndofs; j++)
1127 local_matrix[i*ndofs+j] += flux_times_JxW*fe_values_side.
shape_value(i,k)*fe_values_side.
shape_value(j,k);
1133 )*fe_values_side.
JxW(k);
1138 ls[sbi]->
mat_set_values(ndofs, (
int *)side_dof_indices, ndofs, (
int *)side_dof_indices, local_matrix);
1144 template<
class Model>
1145 template<
unsigned int dim>
1149 if (dim == 1)
return;
1160 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs();
1161 const unsigned int qsize =
feo->
q<dim-1>()->size();
1162 unsigned int side_dof_indices[2*ndofs], n_dofs[2];
1165 vector<double> csection_lower(qsize), csection_higher(qsize), mm_coef_lower(qsize), mm_coef_higher(qsize);
1166 PetscScalar local_matrix[4*ndofs*ndofs];
1167 double comm_flux[2][2];
1171 fv_sb[0] = &fe_values_vb;
1172 fv_sb[1] = &fe_values_side;
1183 fe_values_vb.
reinit(cell_sub);
1184 n_dofs[0] = fv_sb[0]->n_dofs();
1189 n_dofs[1] = fv_sb[1]->n_dofs();
1193 element_id[0] = cell_sub.
index();
1194 element_id[1] = cell.
index();
1202 Model::compute_mass_matrix_coefficient(fe_values_vb.
point_list(), cell_sub->element_accessor(), mm_coef_lower);
1203 Model::compute_mass_matrix_coefficient(fe_values_vb.
point_list(), cell->element_accessor(), mm_coef_higher);
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);
1208 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1210 for (
unsigned int i=0; i<n_dofs[0]+n_dofs[1]; i++)
1211 for (
unsigned int j=0; j<n_dofs[0]+n_dofs[1]; j++)
1212 local_matrix[i*(n_dofs[0]+n_dofs[1])+j] = 0;
1215 for (
unsigned int k=0; k<qsize; k++)
1226 2*csection_higher[k]*csection_higher[k]/(csection_lower[k]*csection_lower[k]);
1230 double por_lower_over_higher = mm_coef_lower[k]*csection_higher[k]/(mm_coef_higher[k]*csection_lower[k]);
1232 comm_flux[0][0] = (sigma-min(0.,transport_flux*por_lower_over_higher))*fv_sb[0]->JxW(k);
1233 comm_flux[0][1] = -(sigma-min(0.,transport_flux*por_lower_over_higher))*fv_sb[0]->JxW(k);
1234 comm_flux[1][0] = -(sigma+max(0.,transport_flux))*fv_sb[0]->JxW(k);
1235 comm_flux[1][1] = (sigma+max(0.,transport_flux))*fv_sb[0]->JxW(k);
1237 for (
int n=0; n<2; n++)
1241 for (
unsigned int i=0; i<n_dofs[n]; i++)
1242 for (
int m=0; m<2; m++)
1243 for (
unsigned int j=0; j<n_dofs[m]; j++)
1244 local_matrix[(i+n*n_dofs[0])*(n_dofs[0]+n_dofs[1]) + m*n_dofs[0] + j] +=
1245 comm_flux[m][n]*fv_sb[m]->shape_value(j,k)*fv_sb[n]->shape_value(i,k);
1248 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);
1259 template<
class Model>
1263 if (Model::balance_ !=
nullptr)
1264 Model::balance_->start_flux_assembly(Model::subst_idx);
1265 set_boundary_conditions<1>();
1266 set_boundary_conditions<2>();
1267 set_boundary_conditions<3>();
1268 if (Model::balance_ !=
nullptr)
1269 Model::balance_->finish_flux_assembly(Model::subst_idx);
1274 template<
class Model>
1275 template<
unsigned int dim>
1282 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim-1>()->size();
1284 unsigned int loc_b=0;
1285 double local_rhs[ndofs];
1287 PetscScalar local_flux_balance_rhs;
1291 bc_ref_values(qsize);
1295 for (
unsigned int loc_el = 0; loc_el < Model::mesh_->get_el_ds()->lsize(); loc_el++)
1298 if (elm->boundary_idx_ ==
nullptr)
continue;
1302 Edge *edg = elm->side(si)->edge();
1303 if (edg->
n_sides > 1)
continue;
1305 if (edg->
side(0)->
cond() == NULL)
continue;
1307 if (edg->
side(0)->
dim() != dim-1)
1309 if (edg->
side(0)->
cond() !=
nullptr) ++loc_b;
1318 Model::get_bc_type(ele_acc, bc_type);
1325 data_.cross_section.value_list(fe_values_side.
point_list(), side->
element()->element_accessor(), csection);
1328 data_.bc_dirichlet_value.value_list(fe_values_side.
point_list(), ele_acc, bc_values);
1332 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1334 fill_n(local_rhs, ndofs, 0);
1335 local_flux_balance_vector.assign(ndofs, 0);
1336 local_flux_balance_rhs = 0;
1338 double side_flux = 0;
1339 for (
unsigned int k=0; k<qsize; k++)
1341 double transport_flux = side_flux/side->
measure();
1345 for (
unsigned int k=0; k<qsize; k++)
1347 double bc_term = -transport_flux*bc_values[k][sbi]*fe_values_side.
JxW(k);
1348 for (
unsigned int i=0; i<ndofs; i++)
1349 local_rhs[i] += bc_term*fe_values_side.
shape_value(i,k);
1351 if (Model::balance_ !=
nullptr)
1352 for (
unsigned int i=0; i<ndofs; i++)
1353 local_flux_balance_rhs -= local_rhs[i];
1357 for (
unsigned int k=0; k<qsize; k++)
1359 double bc_term =
gamma[sbi][side->
cond_idx()]*bc_values[k][sbi]*fe_values_side.
JxW(k);
1361 for (
unsigned int i=0; i<ndofs; i++)
1362 local_rhs[i] += bc_term*fe_values_side.
shape_value(i,k)
1363 + arma::dot(bc_grad,fe_values_side.
shape_grad(i,k));
1365 if (Model::balance_ !=
nullptr)
1367 for (
unsigned int k=0; k<qsize; k++)
1369 for (
unsigned int i=0; i<ndofs; i++)
1376 if (Model::time_->tlevel() > 0)
1377 for (
unsigned int i=0; i<ndofs; i++)
1378 local_flux_balance_rhs -= local_rhs[i];
1383 Model::get_flux_bc_data(sbi, fe_values_side.
point_list(), ele_acc, bc_fluxes, bc_sigma, bc_ref_values);
1384 for (
unsigned int k=0; k<qsize; k++)
1386 double bc_term = csection[k]*(bc_sigma[k]*bc_ref_values[k]+bc_fluxes[k])*fe_values_side.
JxW(k);
1387 for (
unsigned int i=0; i<ndofs; i++)
1388 local_rhs[i] += bc_term*fe_values_side.
shape_value(i,k);
1391 if (Model::balance_ !=
nullptr)
1393 for (
unsigned int i=0; i<ndofs; i++)
1395 for (
unsigned int k=0; k<qsize; k++)
1396 local_flux_balance_vector[i] += csection[k]*bc_sigma[k]*fe_values_side.
JxW(k)*fe_values_side.
shape_value(i,k);
1397 local_flux_balance_rhs -= local_rhs[i];
1403 Model::get_flux_bc_data(sbi, fe_values_side.
point_list(), ele_acc, bc_fluxes, bc_sigma, bc_ref_values);
1404 for (
unsigned int k=0; k<qsize; k++)
1406 double bc_term = csection[k]*(bc_sigma[k]*bc_ref_values[k]+bc_fluxes[k])*fe_values_side.
JxW(k);
1407 for (
unsigned int i=0; i<ndofs; i++)
1408 local_rhs[i] += bc_term*fe_values_side.
shape_value(i,k);
1411 if (Model::balance_ !=
nullptr)
1413 for (
unsigned int i=0; i<ndofs; i++)
1415 for (
unsigned int k=0; k<qsize; k++)
1416 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);
1417 local_flux_balance_rhs -= local_rhs[i];
1423 if (Model::balance_ !=
nullptr)
1425 for (
unsigned int k=0; k<qsize; k++)
1427 for (
unsigned int i=0; i<ndofs; i++)
1434 if (Model::balance_ !=
nullptr)
1436 Model::balance_->add_flux_matrix_values(Model::subst_idx[sbi], loc_b, side_dof_indices, local_flux_balance_vector);
1437 Model::balance_->add_flux_vec_value(Model::subst_idx[sbi], loc_b, local_flux_balance_rhs);
1447 template<
class Model>
1448 template<
unsigned int dim>
1451 OLD_ASSERT(cell->dim() == dim,
"Element dimension mismatch!");
1455 for (
unsigned int k=0; k<fv.
n_points(); k++)
1457 velocity[k].zeros();
1458 for (
unsigned int sid=0; sid<cell->n_sides(); sid++)
1459 velocity[k] += fv.
shape_vector(sid,k) * Model::mh_dh->side_flux( *(cell->side(sid)) );
1467 template<
class Model>
1476 const double alpha1,
1477 const double alpha2,
1480 double &transport_flux)
1484 double local_alpha = 0;
1496 for (
unsigned int i=0; i<s->n_nodes(); i++)
1497 for (
unsigned int j=i+1; j<s->n_nodes(); j++)
1498 h = max(h, s->node(i)->distance(*s->node(j)));
1502 double pflux = 0, nflux = 0;
1503 for (
int i=0; i<edg.
n_sides; i++)
1512 if (fluxes[s2] > 0 && fluxes[s1] < 0 && s1 < s2)
1513 transport_flux = fluxes[s1]*fabs(fluxes[s2]/pflux);
1514 else if (fluxes[s2] < 0 && fluxes[s1] > 0 && s1 < s2)
1515 transport_flux = fluxes[s1]*fabs(fluxes[s2]/nflux);
1517 transport_flux = fluxes[s1];
1521 gamma = 0.5*fabs(transport_flux);
1525 local_alpha = max(alpha1, alpha2);
1533 for (
int k=0; k<K_size; k++)
1534 delta[0] += dot(K1[k]*normal_vector,normal_vector);
1537 gamma += local_alpha/h*(delta[0]);
1543 for (
int k=0; k<K_size; k++)
1545 delta[0] += dot(K1[k]*normal_vector,normal_vector);
1546 delta[1] += dot(K2[k]*normal_vector,normal_vector);
1551 double delta_sum = delta[0] + delta[1];
1555 omega[0] = delta[1]/delta_sum;
1556 omega[1] = delta[0]/delta_sum;
1557 gamma += local_alpha/h*(delta[0]*delta[1]/delta_sum);
1560 for (
int i=0; i<2; i++) omega[i] = 0;
1569 template<
class Model>
1578 double delta = 0, h = 0;
1581 if (side->
dim() == 0)
1587 for (
unsigned int i=0; i<side->
n_nodes(); i++)
1588 for (
unsigned int j=i+1; j<side->
n_nodes(); j++)
1593 for (
int k=0; k<K_size; k++)
1594 delta += dot(K[k]*normal_vector,normal_vector);
1597 gamma = 0.5*fabs(flux) + alpha/h*delta;
1604 template<
class Model>
1608 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1609 ls[sbi]->start_allocation();
1610 prepare_initial_condition<1>();
1611 prepare_initial_condition<2>();
1612 prepare_initial_condition<3>();
1614 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1615 ls[sbi]->start_add_assembly();
1616 prepare_initial_condition<1>();
1617 prepare_initial_condition<2>();
1618 prepare_initial_condition<3>();
1620 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1628 template<
class Model>
1629 template<
unsigned int dim>
1634 const unsigned int ndofs =
feo->
fe<dim>()->n_dofs(), qsize =
feo->
q<dim>()->size();
1635 unsigned int dof_indices[ndofs];
1636 double matrix[ndofs*ndofs],
rhs[ndofs];
1639 for (
unsigned int k=0; k<qsize; k++)
1640 init_values[k].resize(Model::n_substances());
1642 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
1645 if (elem->dim() != dim)
continue;
1651 Model::compute_init_cond(fe_values.
point_list(), ele_acc, init_values);
1653 for (
unsigned int sbi=0; sbi<Model::n_substances(); sbi++)
1655 for (
unsigned int i=0; i<ndofs; i++)
1658 for (
unsigned int j=0; j<ndofs; j++)
1659 matrix[i*ndofs+j] = 0;
1662 for (
unsigned int k=0; k<qsize; k++)
1664 double rhs_term = init_values[k](sbi)*fe_values.
JxW(k);
1666 for (
unsigned int i=0; i<ndofs; i++)
1668 for (
unsigned int j=0; j<ndofs; j++)
1674 ls[sbi]->
set_values(ndofs, (
int *)dof_indices, ndofs, (
int *)dof_indices, matrix, rhs);
1680 template<
class Model>
1683 el_4_loc = Model::mesh_->get_el_4_loc();
1684 el_ds = Model::mesh_->get_el_ds();
1688 template<
class Model>
1691 if (solution_changed)
1693 for (
unsigned int i_cell=0; i_cell<Model::mesh_->get_el_ds()->lsize(); i_cell++)
1697 unsigned int n_dofs;
1698 switch (elem->dim())
1701 n_dofs =
feo->
fe<1>()->n_dofs();
1704 n_dofs =
feo->
fe<2>()->n_dofs();
1707 n_dofs =
feo->
fe<3>()->n_dofs();
1711 unsigned int dof_indices[n_dofs];
1714 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
1716 double old_average = 0;
1717 for (
unsigned int j=0; j<n_dofs; ++j)
1718 old_average +=
ls[sbi]->get_solution_array()[dof_indices[j]-
feo->
dh()->
distr()->
begin()];
1719 old_average /= n_dofs;
1721 for (
unsigned int j=0; j<n_dofs; ++j)
1727 for (
unsigned int sbi=0; sbi<Model::n_substances(); ++sbi)
1731 template<
class Model>
1734 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.
void get_dof_indices(const CellIterator &cell, unsigned int indices[]) const override
Returns the global indices of dofs associated to the cell.
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...
static constexpr Mask allow_output
The field can output. Is part of generated output selection. (default on)
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
virtual void start_add_assembly()
void assemble_mass_matrix()
Assembles the mass matrix.
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.
unsigned int n_loc_nb() const
Returns number of local neighbours.
void set_from_input(const Input::Record in_rec)
#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.
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
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)
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
Mat mass_matrix
The mass matrix.
#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()
LinSys * ls_dt
Linear algebra system for the time derivative (actually it is used only for handling the matrix struc...
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.
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)...
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.
virtual const Mat * get_matrix()
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.
#define JUMP(i, k, side_id)
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
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