Flow123d  JS_before_hm-979-g397e552
assembly_dg_old.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file assembly_dg.hh
15  * @brief
16  */
17 
18 #ifndef ASSEMBLY_DG_HH_
19 #define ASSEMBLY_DG_HH_
20 
22 #include "fem/mapping_p1.hh"
23 #include "fem/fe_p.hh"
24 #include "fem/fe_rt.hh"
25 #include "fem/fe_values.hh"
27 #include "coupling/balance.hh"
28 
29 
30 /**
31  * Base (non-templated) class of container for Finite element and related objects.
32  */
34 {
35 public:
36  virtual ~AssemblyDGBase() {}
37 
38  virtual void initialize() = 0;
39 
40  virtual void assemble_mass_matrix(DHCellAccessor cell) = 0;
41 
42  virtual void assemble_volume_integrals(DHCellAccessor cell) = 0;
43 
44  virtual void assemble_fluxes_boundary(DHCellAccessor cell) = 0;
45 
46  virtual void assemble_fluxes_element_element(DHCellAccessor cell) = 0;
47 
48  virtual void assemble_fluxes_element_side(DHCellAccessor cell_lower_dim) = 0;
49 
50  virtual void set_sources(DHCellAccessor cell) = 0;
51 
52  virtual void set_boundary_conditions(DHCellAccessor cell) = 0;
53 
54  virtual void prepare_initial_condition(DHCellAccessor cell) = 0;
55 };
56 
57 
58 /**
59  * Auxiliary container class for Finite element and related objects of given dimension.
60  */
61 template <unsigned int dim, class Model>
62 class AssemblyDG : public AssemblyDGBase
63 {
64 public:
66 
67  /// Constructor.
68  AssemblyDG(std::shared_ptr<EqDataDG> data, TransportDG<Model> &model)
69  : fe_(make_shared< FE_P_disc<dim> >(data->dg_order)), fe_low_(make_shared< FE_P_disc<dim-1> >(data->dg_order)),
70  fe_rt_(new FE_RT0<dim>), fe_rt_low_(new FE_RT0<dim-1>),
71  quad_(new QGauss(dim, 2*data->dg_order)),
72  quad_low_(new QGauss(dim-1, 2*data->dg_order)),
73  model_(model), data_(data), fv_rt_(*quad_, *fe_rt_, update_values | update_gradients | update_quadrature_points),
75  fv_rt_vb_(nullptr), fe_values_vb_(nullptr),
77  fsv_rt_(*quad_low_, *fe_rt_, update_values | update_quadrature_points) {
78 
79  if (dim>1) {
80  fv_rt_vb_ = new FEValues<dim-1,3>(*quad_low_, *fe_rt_low_, update_values | update_quadrature_points);
81  fe_values_vb_ = new FEValues<dim-1,3>(*quad_low_, *fe_low_,
83  }
84  ndofs_ = fe_->n_dofs();
85  qsize_ = quad_->size();
86  qsize_lower_dim_ = quad_low_->size();
87  dof_indices_.resize(ndofs_);
88  loc_dof_indices_.resize(ndofs_);
89  side_dof_indices_vb_.resize(2*ndofs_);
90  }
91 
92  /// Destructor.
94  delete fe_rt_;
95  delete fe_rt_low_;
96  delete quad_;
97  delete quad_low_;
98  if (fv_rt_vb_!=nullptr) delete fv_rt_vb_;
99  if (fe_values_vb_!=nullptr) delete fe_values_vb_;
100 
101  for (unsigned int i=0; i<data_->ad_coef_edg.size(); i++)
102  {
103  delete fe_values_vec_[i];
104  }
105  }
106 
107  /// Initialize auxiliary vectors and other data members
108  void initialize() override {
109  local_matrix_.resize(4*ndofs_*ndofs_);
110  local_retardation_balance_vector_.resize(ndofs_);
111  local_mass_balance_vector_.resize(ndofs_);
112  local_rhs_.resize(ndofs_);
113  local_source_balance_vector_.resize(ndofs_);
114  local_source_balance_rhs_.resize(ndofs_);
115  local_flux_balance_vector_.resize(ndofs_);
116  velocity_.resize(qsize_);
117  side_velocity_vec_.resize(data_->ad_coef_edg.size());
118  sources_conc_.resize(model_.n_substances(), std::vector<double>(qsize_));
119  sources_density_.resize(model_.n_substances(), std::vector<double>(qsize_));
120  sources_sigma_.resize(model_.n_substances(), std::vector<double>(qsize_));
121  sigma_.resize(qsize_lower_dim_);
122  csection_.resize(qsize_lower_dim_);
123  csection_higher_.resize(qsize_lower_dim_);
124  dg_penalty_.resize(data_->ad_coef_edg.size());
125  bc_values_.resize(qsize_lower_dim_);
126  bc_fluxes_.resize(qsize_lower_dim_);
127  bc_ref_values_.resize(qsize_lower_dim_);
128  init_values_.resize(model_.n_substances(), std::vector<double>(qsize_));
129 
130  mm_coef_.resize(qsize_);
131  ret_coef_.resize(model_.n_substances());
132  for (unsigned int sbi=0; sbi<model_.n_substances(); sbi++)
133  {
134  ret_coef_[sbi].resize(qsize_);
135  }
136 
137  for (unsigned int sid=0; sid<data_->ad_coef_edg.size(); sid++)
138  {
139  side_dof_indices_.push_back( vector<LongIdx>(ndofs_) );
140  fe_values_vec_.push_back(new FESideValues<dim,3>(*quad_low_, *fe_,
142  }
143 
144  // index 0 = element with lower dimension,
145  // index 1 = side of element with higher dimension
146  fv_sb_.resize(2);
147  fv_sb_[0] = fe_values_vb_;
148  fv_sb_[1] = &fe_values_side_;
149  }
150 
151  /// Assemble integral over element
153  {
154  ASSERT_EQ_DBG(cell.dim(), dim).error("Dimension of element mismatch!");
155  ElementAccessor<3> elm = cell.elm();
156 
157  fe_values_.reinit(elm);
158  cell.get_dof_indices(dof_indices_);
159 
160  model_.compute_mass_matrix_coefficient(fe_values_.point_list(), elm, mm_coef_);
161  model_.compute_retardation_coefficient(fe_values_.point_list(), elm, ret_coef_);
162 
163  for (unsigned int sbi=0; sbi<model_.n_substances(); ++sbi)
164  {
165  // assemble the local mass matrix
166  for (unsigned int i=0; i<ndofs_; i++)
167  {
168  for (unsigned int j=0; j<ndofs_; j++)
169  {
170  local_matrix_[i*ndofs_+j] = 0;
171  for (unsigned int k=0; k<qsize_; k++)
172  local_matrix_[i*ndofs_+j] += (mm_coef_[k]+ret_coef_[sbi][k])*fe_values_.shape_value(j,k)*fe_values_.shape_value(i,k)*fe_values_.JxW(k);
173  }
174  }
175 
176  for (unsigned int i=0; i<ndofs_; i++)
177  {
178  local_mass_balance_vector_[i] = 0;
179  local_retardation_balance_vector_[i] = 0;
180  for (unsigned int k=0; k<qsize_; k++)
181  {
182  local_mass_balance_vector_[i] += mm_coef_[k]*fe_values_.shape_value(i,k)*fe_values_.JxW(k);
183  local_retardation_balance_vector_[i] -= ret_coef_[sbi][k]*fe_values_.shape_value(i,k)*fe_values_.JxW(k);
184  }
185  }
186 
187  model_.balance()->add_mass_matrix_values(model_.get_subst_idx()[sbi], elm.region().bulk_idx(), dof_indices_, local_mass_balance_vector_);
188  data_->ls_dt[sbi]->mat_set_values(ndofs_, &(dof_indices_[0]), ndofs_, &(dof_indices_[0]), &(local_matrix_[0]));
189  VecSetValues(data_->ret_vec[sbi], ndofs_, &(dof_indices_[0]), &(local_retardation_balance_vector_[0]), ADD_VALUES);
190  }
191  }
192 
193  /// Assembles the volume integrals into the stiffness matrix.
195  {
196  ASSERT_EQ_DBG(cell.dim(), dim).error("Dimension of element mismatch!");
197  if (!cell.is_own()) return;
198 
199  ElementAccessor<3> elm = cell.elm();
200 
201  fe_values_.reinit(elm);
202  fv_rt_.reinit(elm);
203  cell.get_dof_indices(dof_indices_);
204 
205  calculate_velocity(elm, velocity_, fv_rt_.point_list());
206  model_.compute_advection_diffusion_coefficients(fe_values_.point_list(), velocity_, elm, data_->ad_coef, data_->dif_coef);
207  model_.compute_sources_sigma(fe_values_.point_list(), elm, sources_sigma_);
208 
209  // assemble the local stiffness matrix
210  for (unsigned int sbi=0; sbi<model_.n_substances(); sbi++)
211  {
212  for (unsigned int i=0; i<ndofs_; i++)
213  for (unsigned int j=0; j<ndofs_; j++)
214  local_matrix_[i*ndofs_+j] = 0;
215 
216  for (unsigned int k=0; k<qsize_; k++)
217  {
218  for (unsigned int i=0; i<ndofs_; i++)
219  {
220  arma::vec3 Kt_grad_i = data_->dif_coef[sbi][k].t()*fe_values_.shape_grad(i,k);
221  double ad_dot_grad_i = arma::dot(data_->ad_coef[sbi][k], fe_values_.shape_grad(i,k));
222 
223  for (unsigned int j=0; j<ndofs_; j++)
224  local_matrix_[i*ndofs_+j] += (arma::dot(Kt_grad_i, fe_values_.shape_grad(j,k))
225  -fe_values_.shape_value(j,k)*ad_dot_grad_i
226  +sources_sigma_[sbi][k]*fe_values_.shape_value(j,k)*fe_values_.shape_value(i,k))*fe_values_.JxW(k);
227  }
228  }
229  data_->ls[sbi]->mat_set_values(ndofs_, &(dof_indices_[0]), ndofs_, &(dof_indices_[0]), &(local_matrix_[0]));
230  }
231  }
232 
233  /// Assembles the fluxes on the boundary.
235  {
236  ASSERT_EQ_DBG(cell.dim(), dim).error("Dimension of element mismatch!");
237  if (!cell.is_own()) return;
238 
239  for( DHCellSide cell_side : cell.side_range() )
240  {
241  Side side = cell_side.side();
242  if (side.edge()->n_sides > 1) continue;
243  // check spatial dimension
244  if (side.dim() != dim-1) continue;
245  // skip edges lying not on the boundary
246  if (side.cond() == NULL) continue;
247 
248  ElementAccessor<3> elm_acc = cell.elm();
249  cell.get_dof_indices(dof_indices_);
250  fe_values_side_.reinit(elm_acc, side.side_idx());
251  fsv_rt_.reinit(elm_acc, side.side_idx());
252 
253  calculate_velocity(elm_acc, velocity_, fsv_rt_.point_list());
254  model_.compute_advection_diffusion_coefficients(fe_values_side_.point_list(), velocity_, elm_acc, data_->ad_coef, data_->dif_coef);
255  arma::uvec bc_type;
256  model_.get_bc_type(side.cond()->element_accessor(), bc_type);
257  data_->cross_section.value_list(fe_values_side_.point_list(), elm_acc, csection_);
258 
259  for (unsigned int sbi=0; sbi<model_.n_substances(); sbi++)
260  {
261  std::fill(local_matrix_.begin(), local_matrix_.end(), 0);
262 
263  // On Neumann boundaries we have only term from integrating by parts the advective term,
264  // on Dirichlet boundaries we additionally apply the penalty which enforces the prescribed value.
265  double side_flux = 0;
266  for (unsigned int k=0; k<qsize_lower_dim_; k++)
267  side_flux += arma::dot(data_->ad_coef[sbi][k], fe_values_side_.normal_vector(k))*fe_values_side_.JxW(k);
268  double transport_flux = side_flux/side.measure();
269 
270  if (bc_type[sbi] == AdvectionDiffusionModel::abc_dirichlet)
271  {
272  // set up the parameters for DG method
273  double gamma_l;
274  data_->set_DG_parameters_boundary(side, qsize_lower_dim_, data_->dif_coef[sbi], transport_flux, fe_values_side_.normal_vector(0), data_->dg_penalty[sbi].value(elm_acc.centre(), elm_acc), gamma_l);
275  data_->gamma[sbi][side.cond_idx()] = gamma_l;
276  transport_flux += gamma_l;
277  }
278 
279  // fluxes and penalty
280  for (unsigned int k=0; k<qsize_lower_dim_; k++)
281  {
282  double flux_times_JxW;
283  if (bc_type[sbi] == AdvectionDiffusionModel::abc_total_flux)
284  {
285  //sigma_ corresponds to robin_sigma
286  model_.get_flux_bc_sigma(sbi, fe_values_side_.point_list(), side.cond()->element_accessor(), sigma_);
287  flux_times_JxW = csection_[k]*sigma_[k]*fe_values_side_.JxW(k);
288  }
289  else if (bc_type[sbi] == AdvectionDiffusionModel::abc_diffusive_flux)
290  {
291  model_.get_flux_bc_sigma(sbi, fe_values_side_.point_list(), side.cond()->element_accessor(), sigma_);
292  flux_times_JxW = (transport_flux + csection_[k]*sigma_[k])*fe_values_side_.JxW(k);
293  }
294  else if (bc_type[sbi] == AdvectionDiffusionModel::abc_inflow && side_flux < 0)
295  flux_times_JxW = 0;
296  else
297  flux_times_JxW = transport_flux*fe_values_side_.JxW(k);
298 
299  for (unsigned int i=0; i<ndofs_; i++)
300  {
301  for (unsigned int j=0; j<ndofs_; j++)
302  {
303  // flux due to advection and penalty
304  local_matrix_[i*ndofs_+j] += flux_times_JxW*fe_values_side_.shape_value(i,k)*fe_values_side_.shape_value(j,k);
305 
306  // flux due to diffusion (only on dirichlet and inflow boundary)
307  if (bc_type[sbi] == AdvectionDiffusionModel::abc_dirichlet)
308  local_matrix_[i*ndofs_+j] -= (arma::dot(data_->dif_coef[sbi][k]*fe_values_side_.shape_grad(j,k),fe_values_side_.normal_vector(k))*fe_values_side_.shape_value(i,k)
309  + arma::dot(data_->dif_coef[sbi][k]*fe_values_side_.shape_grad(i,k),fe_values_side_.normal_vector(k))*fe_values_side_.shape_value(j,k)*data_->dg_variant
310  )*fe_values_side_.JxW(k);
311  }
312  }
313  }
314 
315  data_->ls[sbi]->mat_set_values(ndofs_, &(dof_indices_[0]), ndofs_, &(dof_indices_[0]), &(local_matrix_[0]));
316  }
317  }
318  }
319 
320 
321  /// Assembles the fluxes between elements of the same dimension.
323  {
324  ASSERT_EQ_DBG(cell.dim(), dim).error("Dimension of element mismatch!");
325 
326  // assemble integral over sides
327  for( DHCellSide cell_side : cell.side_range() )
328  {
329  if (cell_side.n_edge_sides() < 2) continue;
330  bool unique_edge = (cell_side.edge_sides().begin()->element().idx() != cell.elm_idx());
331  if ( unique_edge ) continue;
332  sid=0;
333  for( DHCellSide edge_side : cell_side.edge_sides() )
334  {
335  auto dh_edge_cell = data_->dh_->cell_accessor_from_element( edge_side.elem_idx() );
336  ElementAccessor<3> edg_elm = dh_edge_cell.elm();
337  dh_edge_cell.get_dof_indices(side_dof_indices_[sid]);
338  fe_values_vec_[sid]->reinit(edg_elm, edge_side.side_idx());
339  fsv_rt_.reinit(edg_elm, edge_side.side_idx());
340  calculate_velocity(edg_elm, side_velocity_vec_[sid], fsv_rt_.point_list());
341  model_.compute_advection_diffusion_coefficients(fe_values_vec_[sid]->point_list(), side_velocity_vec_[sid], edg_elm, data_->ad_coef_edg[sid], data_->dif_coef_edg[sid]);
342  dg_penalty_[sid].resize(model_.n_substances());
343  for (unsigned int sbi=0; sbi<model_.n_substances(); sbi++)
344  dg_penalty_[sid][sbi] = data_->dg_penalty[sbi].value(edg_elm.centre(), edg_elm);
345  ++sid;
346  }
347  arma::vec3 normal_vector = fe_values_vec_[0]->normal_vector(0);
348 
349  // fluxes and penalty
350  for (unsigned int sbi=0; sbi<model_.n_substances(); sbi++)
351  {
352  vector<double> fluxes(cell_side.n_edge_sides());
353  double pflux = 0, nflux = 0; // calculate the total in- and out-flux through the edge
354  sid=0;
355  for( DHCellSide edge_side : cell_side.edge_sides() )
356  {
357  fluxes[sid] = 0;
358  for (unsigned int k=0; k<qsize_lower_dim_; k++)
359  fluxes[sid] += arma::dot(data_->ad_coef_edg[sid][sbi][k], fe_values_vec_[sid]->normal_vector(k))*fe_values_vec_[sid]->JxW(k);
360  fluxes[sid] /= edge_side.measure();
361  if (fluxes[sid] > 0)
362  pflux += fluxes[sid];
363  else
364  nflux += fluxes[sid];
365  ++sid;
366  }
367 
368  s1=0;
369  for( DHCellSide edge_side1 : cell_side.edge_sides() )
370  {
371  s2=-1; // need increment at begin of loop (see conditionally 'continue' directions)
372  for( DHCellSide edge_side2 : cell_side.edge_sides() )
373  {
374  s2++;
375  if (s2<=s1) continue;
376  ASSERT(edge_side1.is_valid()).error("Invalid side of edge.");
377 
378  arma::vec3 nv = fe_values_vec_[s1]->normal_vector(0);
379 
380  // set up the parameters for DG method
381  // calculate the flux from edge_side1 to edge_side2
382  if (fluxes[s2] > 0 && fluxes[s1] < 0)
383  transport_flux = fluxes[s1]*fabs(fluxes[s2]/pflux);
384  else if (fluxes[s2] < 0 && fluxes[s1] > 0)
385  transport_flux = fluxes[s1]*fabs(fluxes[s2]/nflux);
386  else
387  transport_flux = 0;
388 
389  gamma_l = 0.5*fabs(transport_flux);
390 
391  delta[0] = 0;
392  delta[1] = 0;
393  for (unsigned int k=0; k<qsize_lower_dim_; k++)
394  {
395  delta[0] += dot(data_->dif_coef_edg[s1][sbi][k]*normal_vector,normal_vector);
396  delta[1] += dot(data_->dif_coef_edg[s2][sbi][k]*normal_vector,normal_vector);
397  }
398  delta[0] /= qsize_lower_dim_;
399  delta[1] /= qsize_lower_dim_;
400 
401  delta_sum = delta[0] + delta[1];
402 
403 // if (delta_sum > numeric_limits<double>::epsilon())
404  if (fabs(delta_sum) > 0)
405  {
406  omega[0] = delta[1]/delta_sum;
407  omega[1] = delta[0]/delta_sum;
408  double local_alpha = max(dg_penalty_[s1][sbi], dg_penalty_[s2][sbi]);
409  double h = edge_side1.diameter();
410  aniso1 = data_->elem_anisotropy(edge_side1.element());
411  aniso2 = data_->elem_anisotropy(edge_side2.element());
412  gamma_l += local_alpha/h*aniso1*aniso2*(delta[0]*delta[1]/delta_sum);
413  }
414  else
415  for (int i=0; i<2; i++) omega[i] = 0;
416  // end of set up the parameters for DG method
417 
418  int sd[2]; bool is_side_own[2];
419  sd[0] = s1; is_side_own[0] = edge_side1.cell().is_own();
420  sd[1] = s2; is_side_own[1] = edge_side2.cell().is_own();
421 
422 #define AVERAGE(i,k,side_id) (fe_values_vec_[sd[side_id]]->shape_value(i,k)*0.5)
423 #define WAVERAGE(i,k,side_id) (arma::dot(data_->dif_coef_edg[sd[side_id]][sbi][k]*fe_values_vec_[sd[side_id]]->shape_grad(i,k),nv)*omega[side_id])
424 #define JUMP(i,k,side_id) ((side_id==0?1:-1)*fe_values_vec_[sd[side_id]]->shape_value(i,k))
425 
426  // For selected pair of elements:
427  for (int n=0; n<2; n++)
428  {
429  if (!is_side_own[n]) continue;
430 
431  for (int m=0; m<2; m++)
432  {
433  for (unsigned int i=0; i<fe_values_vec_[sd[n]]->n_dofs(); i++)
434  for (unsigned int j=0; j<fe_values_vec_[sd[m]]->n_dofs(); j++)
435  local_matrix_[i*fe_values_vec_[sd[m]]->n_dofs()+j] = 0;
436 
437  for (unsigned int k=0; k<qsize_lower_dim_; k++)
438  {
439  double flux_times_JxW = transport_flux*fe_values_vec_[0]->JxW(k);
440  double gamma_times_JxW = gamma_l*fe_values_vec_[0]->JxW(k);
441 
442  for (unsigned int i=0; i<fe_values_vec_[sd[n]]->n_dofs(); i++)
443  {
444  double flux_JxW_jump_i = flux_times_JxW*JUMP(i,k,n);
445  double gamma_JxW_jump_i = gamma_times_JxW*JUMP(i,k,n);
446  double JxW_jump_i = fe_values_vec_[0]->JxW(k)*JUMP(i,k,n);
447  double JxW_var_wavg_i = fe_values_vec_[0]->JxW(k)*WAVERAGE(i,k,n)*data_->dg_variant;
448 
449  for (unsigned int j=0; j<fe_values_vec_[sd[m]]->n_dofs(); j++)
450  {
451  int index = i*fe_values_vec_[sd[m]]->n_dofs()+j;
452 
453  // flux due to transport (applied on interior edges) (average times jump)
454  local_matrix_[index] += flux_JxW_jump_i*AVERAGE(j,k,m);
455 
456  // penalty enforcing continuity across edges (applied on interior and Dirichlet edges) (jump times jump)
457  local_matrix_[index] += gamma_JxW_jump_i*JUMP(j,k,m);
458 
459  // terms due to diffusion
460  local_matrix_[index] -= WAVERAGE(j,k,m)*JxW_jump_i;
461  local_matrix_[index] -= JUMP(j,k,m)*JxW_var_wavg_i;
462  }
463  }
464  }
465  data_->ls[sbi]->mat_set_values(fe_values_vec_[sd[n]]->n_dofs(), &(side_dof_indices_[sd[n]][0]), fe_values_vec_[sd[m]]->n_dofs(), &(side_dof_indices_[sd[m]][0]), &(local_matrix_[0]));
466  }
467  }
468 #undef AVERAGE
469 #undef WAVERAGE
470 #undef JUMP
471  }
472  s1++;
473  }
474  }
475  }
476 
477  }
478 
479 
480  /// Assembles the fluxes between elements of different dimensions.
481  void assemble_fluxes_element_side(DHCellAccessor cell_lower_dim) override
482  {
483  if (dim == 1) return;
484  ASSERT_EQ_DBG(cell_lower_dim.dim(), dim-1).error("Dimension of element mismatch!");
485 
486  // Note: use data members csection_ and velocity_ for appropriate quantities of lower dim element
487 
488  for( DHCellSide neighb_side : cell_lower_dim.neighb_sides() )
489  {
490  // skip neighbours of different dimension
491  if (cell_lower_dim.dim() != dim-1) continue;
492 
493  ElementAccessor<3> elm_lower_dim = cell_lower_dim.elm();
494  n_indices = cell_lower_dim.get_dof_indices(dof_indices_);
495  for(unsigned int i=0; i<n_indices; ++i) {
496  side_dof_indices_vb_[i] = dof_indices_[i];
497  }
498  fe_values_vb_->reinit(elm_lower_dim);
499  n_dofs[0] = fv_sb_[0]->n_dofs();
500 
501  DHCellAccessor cell_higher_dim = data_->dh_->cell_accessor_from_element( neighb_side.element().idx() );
502  ElementAccessor<3> elm_higher_dim = cell_higher_dim.elm();
503  n_indices = cell_higher_dim.get_dof_indices(dof_indices_);
504  for(unsigned int i=0; i<n_indices; ++i) {
505  side_dof_indices_vb_[i+n_dofs[0]] = dof_indices_[i];
506  }
507  fe_values_side_.reinit(elm_higher_dim, neighb_side.side_idx());
508  n_dofs[1] = fv_sb_[1]->n_dofs();
509 
510  // Testing element if they belong to local partition.
511  bool own_element_id[2];
512  own_element_id[0] = cell_lower_dim.is_own();
513  own_element_id[1] = cell_higher_dim.is_own();
514 
515  fsv_rt_.reinit(elm_higher_dim, neighb_side.side_idx());
516  fv_rt_vb_->reinit(elm_lower_dim);
517  calculate_velocity(elm_higher_dim, velocity_higher_, fsv_rt_.point_list());
518  calculate_velocity(elm_lower_dim, velocity_, fv_rt_vb_->point_list());
519  model_.compute_advection_diffusion_coefficients(fe_values_vb_->point_list(), velocity_, elm_lower_dim, data_->ad_coef_edg[0], data_->dif_coef_edg[0]);
520  model_.compute_advection_diffusion_coefficients(fe_values_vb_->point_list(), velocity_higher_, elm_higher_dim, data_->ad_coef_edg[1], data_->dif_coef_edg[1]);
521  data_->cross_section.value_list(fe_values_vb_->point_list(), elm_lower_dim, csection_);
522  data_->cross_section.value_list(fe_values_vb_->point_list(), elm_higher_dim, csection_higher_);
523 
524  for (unsigned int sbi=0; sbi<model_.n_substances(); sbi++) // Optimize: SWAP LOOPS
525  {
526  for (unsigned int i=0; i<n_dofs[0]+n_dofs[1]; i++)
527  for (unsigned int j=0; j<n_dofs[0]+n_dofs[1]; j++)
528  local_matrix_[i*(n_dofs[0]+n_dofs[1])+j] = 0;
529 
530  // sigma_ corresponds to frac_sigma
531  data_->fracture_sigma[sbi].value_list(fe_values_vb_->point_list(), elm_lower_dim, sigma_);
532 
533  // set transmission conditions
534  for (unsigned int k=0; k<qsize_lower_dim_; k++)
535  {
536  // The communication flux has two parts:
537  // - "diffusive" term containing sigma
538  // - "advective" term representing usual upwind
539  //
540  // The calculation differs from the reference manual, since ad_coef and dif_coef have different meaning
541  // than b and A in the manual.
542  // In calculation of sigma there appears one more csection_lower in the denominator.
543  double sigma = sigma_[k]*arma::dot(data_->dif_coef_edg[0][sbi][k]*fe_values_side_.normal_vector(k),fe_values_side_.normal_vector(k))*
544  2*csection_higher_[k]*csection_higher_[k]/(csection_[k]*csection_[k]);
545 
546  double transport_flux = arma::dot(data_->ad_coef_edg[1][sbi][k], fe_values_side_.normal_vector(k));
547 
548  comm_flux[0][0] = (sigma-min(0.,transport_flux))*fv_sb_[0]->JxW(k);
549  comm_flux[0][1] = -(sigma-min(0.,transport_flux))*fv_sb_[0]->JxW(k);
550  comm_flux[1][0] = -(sigma+max(0.,transport_flux))*fv_sb_[0]->JxW(k);
551  comm_flux[1][1] = (sigma+max(0.,transport_flux))*fv_sb_[0]->JxW(k);
552 
553  for (int n=0; n<2; n++)
554  {
555  if (!own_element_id[n]) continue;
556 
557  for (unsigned int i=0; i<n_dofs[n]; i++)
558  for (int m=0; m<2; m++)
559  for (unsigned int j=0; j<n_dofs[m]; j++)
560  local_matrix_[(i+n*n_dofs[0])*(n_dofs[0]+n_dofs[1]) + m*n_dofs[0] + j] +=
561  comm_flux[m][n]*fv_sb_[m]->shape_value(j,k)*fv_sb_[n]->shape_value(i,k);
562  }
563  }
564  data_->ls[sbi]->mat_set_values(n_dofs[0]+n_dofs[1], &(side_dof_indices_vb_[0]), n_dofs[0]+n_dofs[1], &(side_dof_indices_vb_[0]), &(local_matrix_[0]));
565  }
566  }
567 
568  }
569 
570 
571  /// Assembles the right hand side vector due to volume sources.
572  void set_sources(DHCellAccessor cell) override
573  {
574  ASSERT_EQ_DBG(cell.dim(), dim).error("Dimension of element mismatch!");
575 
576  ElementAccessor<3> elm = cell.elm();
577 
578  fe_values_.reinit(elm);
579  cell.get_dof_indices(dof_indices_);
580 
581  model_.compute_source_coefficients(fe_values_.point_list(), elm, sources_conc_, sources_density_, sources_sigma_);
582 
583  // assemble the local stiffness matrix
584  for (unsigned int sbi=0; sbi<model_.n_substances(); sbi++)
585  {
586  fill_n( &(local_rhs_[0]), ndofs_, 0 );
587  local_source_balance_vector_.assign(ndofs_, 0);
588  local_source_balance_rhs_.assign(ndofs_, 0);
589 
590  // compute sources
591  for (unsigned int k=0; k<qsize_; k++)
592  {
593  source = (sources_density_[sbi][k] + sources_conc_[sbi][k]*sources_sigma_[sbi][k])*fe_values_.JxW(k);
594 
595  for (unsigned int i=0; i<ndofs_; i++)
596  local_rhs_[i] += source*fe_values_.shape_value(i,k);
597  }
598  data_->ls[sbi]->rhs_set_values(ndofs_, &(dof_indices_[0]), &(local_rhs_[0]));
599 
600  for (unsigned int i=0; i<ndofs_; i++)
601  {
602  for (unsigned int k=0; k<qsize_; k++)
603  local_source_balance_vector_[i] -= sources_sigma_[sbi][k]*fe_values_.shape_value(i,k)*fe_values_.JxW(k);
604 
605  local_source_balance_rhs_[i] += local_rhs_[i];
606  // temporary, TODO: replace with LocDofVec in balance
607  loc_dof_indices_[i] = cell.get_loc_dof_indices()[i];
608  }
609  model_.balance()->add_source_values(model_.get_subst_idx()[sbi], elm.region().bulk_idx(), loc_dof_indices_,
610  local_source_balance_vector_, local_source_balance_rhs_);
611  }
612  }
613 
614 
616  {
617  if (cell.elm()->boundary_idx_ == nullptr) return;
618 
619  for (unsigned int si=0; si<cell.elm()->n_sides(); si++)
620  {
621  const Edge *edg = cell.elm().side(si)->edge();
622  if (edg->n_sides > 1) continue;
623  // skip edges lying not on the boundary
624  if (edg->side(0)->cond() == NULL) continue;
625 
626 
627  Side side = *(edg->side(0));
628  ElementAccessor<3> elm = model_.mesh().element_accessor( side.element().idx() );
629  ElementAccessor<3> ele_acc = side.cond()->element_accessor();
630 
631  arma::uvec bc_type;
632  model_.get_bc_type(ele_acc, bc_type);
633 
634  fe_values_side_.reinit(elm, side.side_idx());
635  fsv_rt_.reinit(elm, side.side_idx());
636  calculate_velocity(elm, velocity_, fsv_rt_.point_list());
637 
638  model_.compute_advection_diffusion_coefficients(fe_values_side_.point_list(), velocity_, side.element(), data_->ad_coef, data_->dif_coef);
639  data_->cross_section.value_list(fe_values_side_.point_list(), side.element(), csection_);
640 
641  DHCellAccessor dh_side_cell = data_->dh_->cell_accessor_from_element( side.element().idx() );
642  dh_side_cell.get_dof_indices(dof_indices_);
643 
644  for (unsigned int sbi=0; sbi<model_.n_substances(); sbi++)
645  {
646  fill_n(&(local_rhs_[0]), ndofs_, 0);
647  local_flux_balance_vector_.assign(ndofs_, 0);
648  local_flux_balance_rhs_ = 0;
649 
650  // The b.c. data are fetched for all possible b.c. types since we allow
651  // different bc_type for each substance.
652  data_->bc_dirichlet_value[sbi].value_list(fe_values_side_.point_list(), ele_acc, bc_values_);
653 
654  double side_flux = 0;
655  for (unsigned int k=0; k<qsize_lower_dim_; k++)
656  side_flux += arma::dot(data_->ad_coef[sbi][k], fe_values_side_.normal_vector(k))*fe_values_side_.JxW(k);
657  double transport_flux = side_flux/side.measure();
658 
659  if (bc_type[sbi] == AdvectionDiffusionModel::abc_inflow && side_flux < 0)
660  {
661  for (unsigned int k=0; k<qsize_lower_dim_; k++)
662  {
663  double bc_term = -transport_flux*bc_values_[k]*fe_values_side_.JxW(k);
664  for (unsigned int i=0; i<ndofs_; i++)
665  local_rhs_[i] += bc_term*fe_values_side_.shape_value(i,k);
666  }
667  for (unsigned int i=0; i<ndofs_; i++)
668  local_flux_balance_rhs_ -= local_rhs_[i];
669  }
670  else if (bc_type[sbi] == AdvectionDiffusionModel::abc_dirichlet)
671  {
672  for (unsigned int k=0; k<qsize_lower_dim_; k++)
673  {
674  double bc_term = data_->gamma[sbi][side.cond_idx()]*bc_values_[k]*fe_values_side_.JxW(k);
675  arma::vec3 bc_grad = -bc_values_[k]*fe_values_side_.JxW(k)*data_->dg_variant*(arma::trans(data_->dif_coef[sbi][k])*fe_values_side_.normal_vector(k));
676  for (unsigned int i=0; i<ndofs_; i++)
677  local_rhs_[i] += bc_term*fe_values_side_.shape_value(i,k)
678  + arma::dot(bc_grad,fe_values_side_.shape_grad(i,k));
679  }
680  for (unsigned int k=0; k<qsize_lower_dim_; k++)
681  {
682  for (unsigned int i=0; i<ndofs_; i++)
683  {
684  local_flux_balance_vector_[i] += (arma::dot(data_->ad_coef[sbi][k], fe_values_side_.normal_vector(k))*fe_values_side_.shape_value(i,k)
685  - arma::dot(data_->dif_coef[sbi][k]*fe_values_side_.shape_grad(i,k),fe_values_side_.normal_vector(k))
686  + data_->gamma[sbi][side.cond_idx()]*fe_values_side_.shape_value(i,k))*fe_values_side_.JxW(k);
687  }
688  }
689  if (model_.time().tlevel() > 0)
690  for (unsigned int i=0; i<ndofs_; i++)
691  local_flux_balance_rhs_ -= local_rhs_[i];
692  }
693  else if (bc_type[sbi] == AdvectionDiffusionModel::abc_total_flux)
694  {
695  model_.get_flux_bc_data(sbi, fe_values_side_.point_list(), ele_acc, bc_fluxes_, sigma_, bc_ref_values_);
696  for (unsigned int k=0; k<qsize_lower_dim_; k++)
697  {
698  double bc_term = csection_[k]*(sigma_[k]*bc_ref_values_[k]+bc_fluxes_[k])*fe_values_side_.JxW(k);
699  for (unsigned int i=0; i<ndofs_; i++)
700  local_rhs_[i] += bc_term*fe_values_side_.shape_value(i,k);
701  }
702 
703  for (unsigned int i=0; i<ndofs_; i++)
704  {
705  for (unsigned int k=0; k<qsize_lower_dim_; k++)
706  local_flux_balance_vector_[i] += csection_[k]*sigma_[k]*fe_values_side_.JxW(k)*fe_values_side_.shape_value(i,k);
707  local_flux_balance_rhs_ -= local_rhs_[i];
708  }
709  }
710  else if (bc_type[sbi] == AdvectionDiffusionModel::abc_diffusive_flux)
711  {
712  model_.get_flux_bc_data(sbi, fe_values_side_.point_list(), ele_acc, bc_fluxes_, sigma_, bc_ref_values_);
713  for (unsigned int k=0; k<qsize_lower_dim_; k++)
714  {
715  double bc_term = csection_[k]*(sigma_[k]*bc_ref_values_[k]+bc_fluxes_[k])*fe_values_side_.JxW(k);
716  for (unsigned int i=0; i<ndofs_; i++)
717  local_rhs_[i] += bc_term*fe_values_side_.shape_value(i,k);
718  }
719 
720  for (unsigned int i=0; i<ndofs_; i++)
721  {
722  for (unsigned int k=0; k<qsize_lower_dim_; k++)
723  local_flux_balance_vector_[i] += csection_[k]*(arma::dot(data_->ad_coef[sbi][k], fe_values_side_.normal_vector(k)) + sigma_[k])*fe_values_side_.JxW(k)*fe_values_side_.shape_value(i,k);
724  local_flux_balance_rhs_ -= local_rhs_[i];
725  }
726  }
727  else if (bc_type[sbi] == AdvectionDiffusionModel::abc_inflow && side_flux >= 0)
728  {
729  for (unsigned int k=0; k<qsize_lower_dim_; k++)
730  {
731  for (unsigned int i=0; i<ndofs_; i++)
732  local_flux_balance_vector_[i] += arma::dot(data_->ad_coef[sbi][k], fe_values_side_.normal_vector(k))*fe_values_side_.JxW(k)*fe_values_side_.shape_value(i,k);
733  }
734  }
735  data_->ls[sbi]->rhs_set_values(ndofs_, &(dof_indices_[0]), &(local_rhs_[0]));
736 
737  model_.balance()->add_flux_matrix_values(model_.get_subst_idx()[sbi], side, dof_indices_, local_flux_balance_vector_);
738  model_.balance()->add_flux_vec_value(model_.get_subst_idx()[sbi], side, local_flux_balance_rhs_);
739  }
740  }
741  }
742 
743 
744  /**
745  * @brief Assembles the auxiliary linear system to calculate the initial solution
746  * as L^2-projection of the prescribed initial condition.
747  */
749  {
750  ASSERT_EQ_DBG(cell.dim(), dim).error("Dimension of element mismatch!");
751 
752  ElementAccessor<3> elem = cell.elm();
753  cell.get_dof_indices(dof_indices_);
754  fe_values_.reinit(elem);
755  model_.compute_init_cond(fe_values_.point_list(), elem, init_values_);
756 
757  for (unsigned int sbi=0; sbi<model_.n_substances(); sbi++)
758  {
759  for (unsigned int i=0; i<ndofs_; i++)
760  {
761  local_rhs_[i] = 0;
762  for (unsigned int j=0; j<ndofs_; j++)
763  local_matrix_[i*ndofs_+j] = 0;
764  }
765 
766  for (unsigned int k=0; k<qsize_; k++)
767  {
768  double rhs_term = init_values_[sbi][k]*fe_values_.JxW(k);
769 
770  for (unsigned int i=0; i<ndofs_; i++)
771  {
772  for (unsigned int j=0; j<ndofs_; j++)
773  local_matrix_[i*ndofs_+j] += fe_values_.shape_value(i,k)*fe_values_.shape_value(j,k)*fe_values_.JxW(k);
774 
775  local_rhs_[i] += fe_values_.shape_value(i,k)*rhs_term;
776  }
777  }
778  data_->ls[sbi]->set_values(ndofs_, &(dof_indices_[0]), ndofs_, &(dof_indices_[0]), &(local_matrix_[0]), &(local_rhs_[0]));
779  }
780  }
781 
782 
783 private:
784  /**
785  * @brief Calculates the velocity field on a given cell.
786  *
787  * @param cell The cell.
788  * @param velocity The computed velocity field (at quadrature points).
789  * @param point_list The quadrature points.
790  */
792  const std::vector<arma::vec::fixed<3>> &point_list)
793  {
794  velocity.resize(point_list.size());
795  model_.velocity_field_ptr()->value_list(point_list, cell, velocity);
796  }
797 
798 
799  shared_ptr<FiniteElement<dim>> fe_; ///< Finite element for the solution of the advection-diffusion equation.
800  shared_ptr<FiniteElement<dim-1>> fe_low_; ///< Finite element for the solution of the advection-diffusion equation (dim-1).
801  FiniteElement<dim> *fe_rt_; ///< Finite element for the water velocity field.
802  FiniteElement<dim-1> *fe_rt_low_; ///< Finite element for the water velocity field (dim-1).
803  Quadrature *quad_; ///< Quadrature used in assembling methods.
804  Quadrature *quad_low_; ///< Quadrature used in assembling methods (dim-1).
805 
806  /// Reference to model (we must use common ancestor of concentration and heat model)
808 
809  /// Data object shared with TransportDG
810  std::shared_ptr<EqDataDG> data_;
811 
812  unsigned int ndofs_; ///< Number of dofs
813  unsigned int qsize_; ///< Size of quadrature of actual dim
814  unsigned int qsize_lower_dim_; ///< Size of quadrature of dim-1
815  FEValues<dim,3> fv_rt_; ///< FEValues of object (of RT0 finite element type)
816  FEValues<dim,3> fe_values_; ///< FEValues of object (of P disc finite element type)
817  FEValues<dim-1,3> *fv_rt_vb_; ///< FEValues of dim-1 object (of RT0 finite element type)
818  FEValues<dim-1,3> *fe_values_vb_; ///< FEValues of dim-1 object (of P disc finite element type)
819  FESideValues<dim,3> fe_values_side_; ///< FESideValues of object (of P disc finite element type)
820  FESideValues<dim,3> fsv_rt_; ///< FESideValues of object (of RT0 finite element type)
821  vector<FESideValues<dim,3>*> fe_values_vec_; ///< Vector of FESideValues of object (of P disc finite element types)
822  vector<FEValuesSpaceBase<3>*> fv_sb_; ///< Auxiliary vector, holds FEValues objects for assemble element-side
823 
824  vector<LongIdx> dof_indices_; ///< Vector of global DOF indices
825  vector<LongIdx> loc_dof_indices_; ///< Vector of local DOF indices
826  vector< vector<LongIdx> > side_dof_indices_; ///< Vector of vectors of side DOF indices
827  vector<LongIdx> side_dof_indices_vb_; ///< Vector of side DOF indices (assemble element-side fluxex)
828  vector<PetscScalar> local_matrix_; ///< Auxiliary vector for assemble methods
829  vector<PetscScalar> local_retardation_balance_vector_; ///< Auxiliary vector for assemble mass matrix.
831  vector<PetscScalar> local_rhs_; ///< Auxiliary vector for set_sources method.
832  vector<PetscScalar> local_source_balance_vector_; ///< Auxiliary vector for set_sources method.
833  vector<PetscScalar> local_source_balance_rhs_; ///< Auxiliary vector for set_sources method.
834  vector<PetscScalar> local_flux_balance_vector_; ///< Auxiliary vector for set_boundary_conditions method.
835  PetscScalar local_flux_balance_rhs_; ///< Auxiliary variable for set_boundary_conditions method.
836  vector<arma::vec3> velocity_; ///< Auxiliary results.
837  vector<arma::vec3> velocity_higher_; ///< Velocity results of higher dim element (element-side computation).
838  vector<vector<arma::vec3> > side_velocity_vec_; ///< Vector of velocities results.
839  vector<vector<double> > sources_conc_; ///< Auxiliary vectors for set_sources method.
840  vector<vector<double> > sources_density_; ///< Auxiliary vectors for set_sources method.
841  vector<vector<double> > sources_sigma_; ///< Auxiliary vectors for assemble volume integrals and set_sources method.
842  vector<double> sigma_; ///< Auxiliary vector for assemble boundary fluxes (robin sigma), element-side fluxes (frac sigma) and set boundary conditions method
843  vector<double> csection_; ///< Auxiliary vector for assemble boundary fluxes, element-side fluxes and set boundary conditions
844  vector<double> csection_higher_; ///< Auxiliary vector for assemble element-side fluxes
845  vector<vector<double> > dg_penalty_; ///< Auxiliary vectors for assemble element-element fluxes
846  vector<double> bc_values_; ///< Auxiliary vector for set boundary conditions method
847  vector<double> bc_fluxes_; ///< Same as previous
848  vector<double> bc_ref_values_; ///< Same as previous
849  std::vector<std::vector<double> > init_values_; ///< Auxiliary vectors for prepare initial condition
850 
851  /// Mass matrix coefficients.
853  /// Retardation coefficient due to sorption.
855 
856  /// @name Auxiliary variables used during element-element assembly
857  // @{
858 
859  double gamma_l, omega[2], transport_flux, delta[2], delta_sum;
860  double aniso1, aniso2;
861  int sid, s1, s2;
862 
863  // @}
864 
865  /// @name Auxiliary variables used during element-side assembly
866  // @{
867 
868  unsigned int n_dofs[2], n_indices;
869  double comm_flux[2][2];
870 
871  // @}
872 
873  /// @name Auxiliary variables used during set sources
874  // @{
875 
876  double source;
877 
878  // @}
879 
880  friend class TransportDG<Model>;
881 
882 };
883 
884 
885 
886 #endif /* FE_VALUE_HANDLER_HH_ */
vector< vector< double > > ret_coef_
Retardation coefficient due to sorption.
Class MappingP1 implements the affine transformation of the unit cell onto the actual cell...
Shape function values.
Definition: update_flags.hh:87
void set_boundary_conditions(DHCellAccessor cell) override
unsigned int n_sides() const
Returns number of sides aligned with the edge.
Definition: accessors.hh:300
Range< DHCellSide > side_range() const
Returns range of cell sides.
Transformed quadrature weight for cell sides.
#define ASSERT_EQ_DBG(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:332
unsigned int elm_idx() const
Return serial idx to element of loc_ele_idx_.
shared_ptr< FiniteElement< dim-1 > > fe_low_
Finite element for the solution of the advection-diffusion equation (dim-1).
unsigned int * boundary_idx_
Definition: elements.h:80
unsigned int side_idx() const
Returns local index of the side on the element.
Definition: accessors.hh:415
Transport with dispersion implemented using discontinuous Galerkin method.
FESideValues< dim, 3 > fsv_rt_
FESideValues of object (of RT0 finite element type)
unsigned int ndofs_
Number of dofs.
vector< vector< double > > sources_sigma_
Auxiliary vectors for assemble volume integrals and set_sources method.
unsigned int get_dof_indices(std::vector< LongIdx > &indices) const
Fill vector of the global indices of dofs associated to the cell.
PetscScalar local_flux_balance_rhs_
Auxiliary variable for set_boundary_conditions method.
Edge edge() const
Returns pointer to the edge connected to the side.
#define WAVERAGE(i, k, side_id)
vector< LongIdx > dof_indices_
Vector of global DOF indices.
vector< vector< arma::vec3 > > side_velocity_vec_
Vector of velocities results.
vector< LongIdx > loc_dof_indices_
Vector of local DOF indices.
unsigned int dim() const
Return dimension of element appropriate to cell.
vector< PetscScalar > local_retardation_balance_vector_
Auxiliary vector for assemble mass matrix.
unsigned int n_dofs() const
Returns the number of shape functions.
Definition: fe_values.hh:279
#define AVERAGE(i, k, side_id)
Cell accessor allow iterate over DOF handler cells.
Class FEValues calculates finite element data on the actual cells such as shape function values...
vector< double > bc_fluxes_
Same as previous.
vector< PetscScalar > local_source_balance_vector_
Auxiliary vector for set_sources method.
LocDofVec get_loc_dof_indices() const
Returns the local indices of dofs associated to the cell on the local process.
SideIter side(const unsigned int loc_index)
virtual void assemble_volume_integrals(DHCellAccessor cell)=0
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:347
virtual void assemble_fluxes_element_element(DHCellAccessor cell)=0
vector< LongIdx > side_dof_indices_vb_
Vector of side DOF indices (assemble element-side fluxex)
bool is_own() const
Return true if accessor represents own element (false for ghost element)
ElementAccessor< 3 > element() const
Returns iterator to the element of the side.
FEValues< dim, 3 > fv_rt_
FEValues of object (of RT0 finite element type)
virtual void set_boundary_conditions(DHCellAccessor cell)=0
virtual void assemble_fluxes_element_side(DHCellAccessor cell_lower_dim)=0
virtual void prepare_initial_condition(DHCellAccessor cell)=0
unsigned int n_indices
vector< double > bc_ref_values_
Same as previous.
Base class for quadrature rules on simplices in arbitrary dimensions.
Definition: quadrature.hh:48
void initialize() override
Initialize auxiliary vectors and other data members.
Symmetric Gauss-Legendre quadrature formulae on simplices.
void set_sources(DHCellAccessor cell) override
Assembles the right hand side vector due to volume sources.
arma::vec::fixed< spacedim > centre() const
Computes the barycenter.
Discontinuous Lagrangean finite element on dim dimensional simplex.
Definition: fe_p.hh:108
Transformed quadrature points.
const ElementAccessor< 3 > elm() const
Return ElementAccessor to element of loc_ele_idx_.
FiniteElement< dim-1 > * fe_rt_low_
Finite element for the water velocity field (dim-1).
vector< FEValuesSpaceBase< 3 > * > fv_sb_
Auxiliary vector, holds FEValues objects for assemble element-side.
double transport_flux
unsigned int dim() const
Returns dimension of the side, that is dimension of the element minus one.
vector< PetscScalar > local_flux_balance_vector_
Auxiliary vector for set_boundary_conditions method.
vector< vector< LongIdx > > side_dof_indices_
Vector of vectors of side DOF indices.
virtual void assemble_fluxes_boundary(DHCellAccessor cell)=0
vector< vector< double > > sources_density_
Auxiliary vectors for set_sources method.
RangeConvert< DHEdgeSide, DHCellSide > edge_sides() const
Returns range of all sides looped over common Edge.
void prepare_initial_condition(DHCellAccessor cell) override
Assembles the auxiliary linear system to calculate the initial solution as L^2-projection of the pres...
vector< vector< double > > dg_penalty_
Auxiliary vectors for assemble element-element fluxes.
Raviart-Thomas element of order 0.
Definition: fe_rt.hh:60
Definitions of basic Lagrangean finite elements with polynomial shape functions.
unsigned int n_sides() const
Definition: elements.h:132
RangeConvert< DHNeighbSide, DHCellSide > neighb_sides() const
Returns range of neighbour cell of lower dimension corresponding to cell of higher dimension...
virtual void initialize()=0
vector< PetscScalar > local_mass_balance_vector_
Same as previous.
FiniteElement< dim > * fe_rt_
Finite element for the water velocity field.
void assemble_fluxes_element_element(DHCellAccessor cell) override
Assembles the fluxes between elements of the same dimension.
Quadrature * quad_low_
Quadrature used in assembling methods (dim-1).
vector< double > csection_higher_
Auxiliary vector for assemble element-side fluxes.
Shape function gradients.
Definition: update_flags.hh:95
unsigned int qsize_
Size of quadrature of actual dim.
TransportDG< Model > & model_
Reference to model (we must use common ancestor of concentration and heat model)
vector< arma::vec3 > velocity_higher_
Velocity results of higher dim element (element-side computation).
void assemble_volume_integrals(DHCellAccessor cell) override
Assembles the volume integrals into the stiffness matrix.
double measure() const
Calculate metrics of the side.
Definition: accessors.cc:27
std::vector< std::vector< double > > init_values_
Auxiliary vectors for prepare initial condition.
FEValues< dim-1, 3 > * fv_rt_vb_
FEValues of dim-1 object (of RT0 finite element type)
Quadrature * quad_
Quadrature used in assembling methods.
Region region() const
Definition: accessors.hh:165
Normal vectors.
Discontinuous Galerkin method for equation of transport with dispersion.
vector< double > csection_
Auxiliary vector for assemble boundary fluxes, element-side fluxes and set boundary conditions...
#define JUMP(i, k, side_id)
~AssemblyDG()
Destructor.
vector< double > mm_coef_
Mass matrix coefficients.
vector< PetscScalar > local_matrix_
Auxiliary vector for assemble methods.
unsigned int cond_idx() const
Returns global index of the prescribed boundary condition.
shared_ptr< FiniteElement< dim > > fe_
Finite element for the solution of the advection-diffusion equation.
unsigned int qsize_lower_dim_
Size of quadrature of dim-1.
FEValues< dim-1, 3 > * fe_values_vb_
FEValues of dim-1 object (of P disc finite element type)
FEValues< dim, 3 > fe_values_
FEValues of object (of P disc finite element type)
virtual ~AssemblyDGBase()
vector< arma::vec3 > velocity_
Auxiliary results.
unsigned int bulk_idx() const
Returns index of the region in the bulk set.
Definition: region.hh:91
Definitions of particular quadrature rules on simplices.
Calculates finite element data on the actual cell.
Definition: fe_values.hh:59
FESideValues< dim, 3 > fe_values_side_
FESideValues of object (of P disc finite element type)
AssemblyDG(std::shared_ptr< EqDataDG > data, TransportDG< Model > &model)
Constructor.
vector< FESideValues< dim, 3 > * > fe_values_vec_
Vector of FESideValues of object (of P disc finite element types)
TransportDG< Model >::EqData EqDataDG
vector< vector< double > > sources_conc_
Auxiliary vectors for set_sources method.
Abstract class for the description of a general finite element on a reference simplex in dim dimensio...
Boundary cond() const
void assemble_fluxes_element_side(DHCellAccessor cell_lower_dim) override
Assembles the fluxes between elements of different dimensions.
std::shared_ptr< EqDataDG > data_
Data object shared with TransportDG.
void assemble_fluxes_boundary(DHCellAccessor cell) override
Assembles the fluxes on the boundary.
vector< double > bc_values_
Auxiliary vector for set boundary conditions method.
virtual void set_sources(DHCellAccessor cell)=0
unsigned int idx() const
Return local idx of element in boundary / bulk part of element vector.
Definition: accessors.hh:181
void calculate_velocity(const ElementAccessor< 3 > &cell, vector< arma::vec3 > &velocity, const std::vector< arma::vec::fixed< 3 >> &point_list)
Calculates the velocity field on a given cell.
SideIter side(const unsigned int i) const
Gets side iterator of the i -th side.
vector< PetscScalar > local_rhs_
Auxiliary vector for set_sources method.
Definitions of Raviart-Thomas finite elements.
vector< double > sigma_
Auxiliary vector for assemble boundary fluxes (robin sigma), element-side fluxes (frac sigma) and set...
Side accessor allows to iterate over sides of DOF handler cell.
vector< PetscScalar > local_source_balance_rhs_
Auxiliary vector for set_sources method.
ElementAccessor< 3 > element_accessor()
virtual void assemble_mass_matrix(DHCellAccessor cell)=0
void assemble_mass_matrix(DHCellAccessor cell) override
Assemble integral over element.
Transformed quadrature weights.