Flow123d  master-aa98e5e
assembly_dg.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 
24 #include "fem/fe_p.hh"
25 #include "fem/fe_values.hh"
27 #include "coupling/balance.hh"
29 
30 
31 
32 /**
33  * Auxiliary container class for Finite element and related objects of given dimension.
34  */
35 template <unsigned int dim, class Model>
36 class MassAssemblyDG : public AssemblyBase<dim>
37 {
38 public:
41 
42  static constexpr const char * name() { return "MassAssemblyDG"; }
43 
44  /// Constructor.
45  MassAssemblyDG(EqFields *eq_fields, EqData *eq_data)
46  : AssemblyBase<dim>(eq_data->dg_order), eq_fields_(eq_fields), eq_data_(eq_data) {
48  this->used_fields_ += eq_fields_->mass_matrix_coef;
49  this->used_fields_ += eq_fields_->retardation_coef;
50  }
51 
52  /// Destructor.
54 
55  /// Initialize auxiliary vectors and other data members
56  void initialize(ElementCacheMap *element_cache_map) {
57  this->element_cache_map_ = element_cache_map;
58 
59  fe_ = std::make_shared< FE_P_disc<dim> >(eq_data_->dg_order);
61  fe_values_.initialize(*this->quad_, *fe_, u);
62  if (dim==1) // print to log only one time
63  DebugOut() << "List of MassAssembly FEValues updates flags: " << this->print_update_flags(u);
64  ndofs_ = fe_->n_dofs();
65  dof_indices_.resize(ndofs_);
66  local_matrix_.resize(4*ndofs_*ndofs_);
69 
70  }
71 
72 
73  /// Assemble integral over element
74  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
75  {
76  ASSERT_EQ(cell.dim(), dim).error("Dimension of element mismatch!");
77 
78  ElementAccessor<3> elm = cell.elm();
79  unsigned int k;
80 
81  fe_values_.reinit(elm);
83 
84  for (unsigned int sbi=0; sbi<eq_data_->n_substances(); ++sbi)
85  {
86  // assemble the local mass matrix
87  for (unsigned int i=0; i<ndofs_; i++)
88  {
89  for (unsigned int j=0; j<ndofs_; j++)
90  {
91  local_matrix_[i*ndofs_+j] = 0;
92  k=0;
93  for (auto p : this->bulk_points(element_patch_idx) )
94  {
95  local_matrix_[i*ndofs_+j] += (eq_fields_->mass_matrix_coef(p)+eq_fields_->retardation_coef[sbi](p)) *
97  k++;
98  }
99  }
100  }
101 
102  for (unsigned int i=0; i<ndofs_; i++)
103  {
106  k=0;
107  for (auto p : this->bulk_points(element_patch_idx) )
108  {
109  local_mass_balance_vector_[i] += eq_fields_->mass_matrix_coef(p)*fe_values_.shape_value(i,k)*fe_values_.JxW(k);
110  local_retardation_balance_vector_[i] -= eq_fields_->retardation_coef[sbi](p)*fe_values_.shape_value(i,k)*fe_values_.JxW(k);
111  k++;
112  }
113  }
114 
115  eq_data_->balance_->add_mass_values(eq_data_->subst_idx()[sbi], cell, cell.get_loc_dof_indices(),
117 
119  VecSetValues(eq_data_->ret_vec[sbi], ndofs_, &(dof_indices_[0]), &(local_retardation_balance_vector_[0]), ADD_VALUES);
120  }
121  }
122 
123  /// Implements @p AssemblyBase::begin.
124  void begin() override
125  {
126  eq_data_->balance_->start_mass_assembly( eq_data_->subst_idx() );
127  }
128 
129  /// Implements @p AssemblyBase::end.
130  void end() override
131  {
132  eq_data_->balance_->finish_mass_assembly( eq_data_->subst_idx() );
133  }
134 
135  private:
136  shared_ptr<FiniteElement<dim>> fe_; ///< Finite element for the solution of the advection-diffusion equation.
137 
138  /// Data objects shared with TransportDG
141 
142  /// Sub field set contains fields used in calculation.
144 
145  unsigned int ndofs_; ///< Number of dofs
146  FEValues<3> fe_values_; ///< FEValues of object (of P disc finite element type)
147 
148  vector<LongIdx> dof_indices_; ///< Vector of global DOF indices
149  vector<PetscScalar> local_matrix_; ///< Auxiliary vector for assemble methods
150  vector<PetscScalar> local_retardation_balance_vector_; ///< Auxiliary vector for assemble mass matrix.
152 
153  template < template<IntDim...> class DimAssembly>
154  friend class GenericAssembly;
155 
156 };
157 
158 
159 // return the ratio of longest and shortest edge
161 {
162  double h_max = 0, h_min = numeric_limits<double>::infinity();
163  for (unsigned int i=0; i<e->n_nodes(); i++)
164  for (unsigned int j=i+1; j<e->n_nodes(); j++)
165  {
166  double dist = arma::norm(*e.node(i) - *e.node(j));
167  h_max = max(h_max, dist);
168  h_min = min(h_min, dist);
169  }
170  return h_max/h_min;
171 }
172 
173 /**
174  * @brief Computes average normal diffusivity over a set of points
175  *
176  * @param diff_coef Diffusion tensor.
177  * @param pts Points.
178  * @param nv Normal vector.
179  * @return double
180  */
182 {
183  double delta = 0;
184  unsigned int n = 0;
185  for (auto p : pts )
186  {
187  delta += dot(diff_coef(p)*nv, nv);
188  n++;
189  }
190  return n == 0 ? 0 : (delta/n);
191 }
192 
193 
194 /**
195  * @brief Computes the penalty parameter of the DG method on a given boundary edge.
196  *
197  * Assumption is that the edge consists of only 1 side.
198  * @param side The boundary side.
199  * @param diff_delta Average normal dispersivity K*n.n computed by diffusion_delta()
200  * @param ad_vector Advection vector.
201  * @param alpha Penalty parameter that influences the continuity
202  * of the solution (large value=more continuity).
203  */
205  const double &diff_delta,
206  const double flux,
207  const double alpha)
208 {
209  return 0.5*fabs(flux) + alpha/side.diameter()*diff_delta*elem_anisotropy(side.element());
210 }
211 
212 
213 /**
214  * @brief Computes advective flux.
215  *
216  * @param advection_coef Advection vector.
217  * @param pts Quadrature points.
218  * @param fv FE values object.
219  * @return double
220  */
221 template <class PointType>
223 {
224  double side_flux = 0;
225  unsigned int k=0;
226  for (auto p : pts) {
227  side_flux += arma::dot(advection_coef(p), fv.normal_vector(k))*fv.JxW(k);
228  k++;
229  }
230  return side_flux;
231 }
232 
233 
234 /**
235  * Auxiliary container class for Finite element and related objects of given dimension.
236  */
237 template <unsigned int dim, class Model>
239 {
240 public:
243 
244  static constexpr const char * name() { return "StiffnessAssemblyDG"; }
245 
246  /// Constructor.
247  StiffnessAssemblyDG(EqFields *eq_fields, EqData *eq_data)
248  : AssemblyBase<dim>(eq_data->dg_order), eq_fields_(eq_fields), eq_data_(eq_data) {
250  this->used_fields_ += eq_fields_->advection_coef;
251  this->used_fields_ += eq_fields_->diffusion_coef;
252  this->used_fields_ += eq_fields_->cross_section;
254  this->used_fields_ += eq_fields_->sources_sigma_out;
256  this->used_fields_ += eq_fields_->bc_type;
257  this->used_fields_ += eq_fields_->bc_robin_sigma;
258  }
259 
260  /// Destructor.
262  for (auto a : averages) if (a != nullptr) delete[] a;
263  for (auto a : waverages) if (a != nullptr) delete[] a;
264  for (auto a : jumps) if (a != nullptr) delete[] a;
265  }
266 
267  /// Initialize auxiliary vectors and other data members
268  void initialize(ElementCacheMap *element_cache_map) {
269  this->element_cache_map_ = element_cache_map;
270 
271  fe_ = std::make_shared< FE_P_disc<dim> >(eq_data_->dg_order);
272  fe_low_ = std::make_shared< FE_P_disc<dim-1> >(eq_data_->dg_order);
275  fe_values_.initialize(*this->quad_, *fe_, u);
276  if (dim>1) {
277  fe_values_vb_.initialize(*this->quad_low_, *fe_low_, u);
278  }
279  fe_values_side_.initialize(*this->quad_low_, *fe_, u_side);
280  if (dim==1) { // print to log only one time
281  DebugOut() << "List of StiffnessAssemblyDG FEValues (cell) updates flags: " << this->print_update_flags(u);
282  DebugOut() << "List of StiffnessAssemblyDG FEValues (side) updates flags: " << this->print_update_flags(u_side);
283  }
284  ndofs_ = fe_->n_dofs();
285  qsize_lower_dim_ = this->quad_low_->size();
286  dof_indices_.resize(ndofs_);
287  side_dof_indices_vb_.resize(2*ndofs_);
288  local_matrix_.resize(4*ndofs_*ndofs_);
289 
291  for (unsigned int sid=0; sid<eq_data_->max_edg_sides; sid++)
292  {
294  fe_values_vec_[sid].initialize(*this->quad_low_, *fe_,
296  }
297 
298  // index 0 = element with lower dimension,
299  // index 1 = side of element with higher dimension
300  fv_sb_.resize(2);
301  fv_sb_[0] = &fe_values_vb_;
302  fv_sb_[1] = &fe_values_side_;
303 
305  for (unsigned int s=0; s<eq_data_->max_edg_sides; s++)
306  averages[s] = new double[qsize_lower_dim_*fe_->n_dofs()];
307  waverages.resize(2);
308  jumps.resize(2);
309  for (unsigned int s=0; s<2; s++)
310  {
311  waverages[s] = new double[qsize_lower_dim_*fe_->n_dofs()];
312  jumps[s] = new double[qsize_lower_dim_*fe_->n_dofs()];
313  }
314  }
315 
316 
317  /// Assembles the cell (volume) integral into the stiffness matrix.
318  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
319  {
320  ASSERT_EQ(cell.dim(), dim).error("Dimension of element mismatch!");
321  if (!cell.is_own()) return;
322 
323  ElementAccessor<3> elm = cell.elm();
324 
325  fe_values_.reinit(elm);
327  unsigned int k;
328 
329  // assemble the local stiffness matrix
330  for (unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
331  {
332  for (unsigned int i=0; i<ndofs_; i++)
333  for (unsigned int j=0; j<ndofs_; j++)
334  local_matrix_[i*ndofs_+j] = 0;
335 
336  k=0;
337  for (auto p : this->bulk_points(element_patch_idx) )
338  {
339  for (unsigned int i=0; i<ndofs_; i++)
340  {
341  arma::vec3 Kt_grad_i = eq_fields_->diffusion_coef[sbi](p).t()*fe_values_.shape_grad(i,k);
342  double ad_dot_grad_i = arma::dot(eq_fields_->advection_coef[sbi](p), fe_values_.shape_grad(i,k));
343 
344  for (unsigned int j=0; j<ndofs_; j++)
345  local_matrix_[i*ndofs_+j] += (arma::dot(Kt_grad_i, fe_values_.shape_grad(j,k))
346  -fe_values_.shape_value(j,k)*ad_dot_grad_i
347  +eq_fields_->sources_sigma_out[sbi](p)*fe_values_.shape_value(j,k)*fe_values_.shape_value(i,k))*fe_values_.JxW(k);
348  }
349  k++;
350  }
352  }
353  }
354 
355 
356  /// Assembles the fluxes on the boundary.
357  inline void boundary_side_integral(DHCellSide cell_side)
358  {
359  ASSERT_EQ(cell_side.dim(), dim).error("Dimension of element mismatch!");
360  if (!cell_side.cell().is_own()) return;
361 
362  Side side = cell_side.side();
363  const DHCellAccessor &cell = cell_side.cell();
364 
366  fe_values_side_.reinit(side);
367  unsigned int k;
368  double gamma_l;
369 
370  for (unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
371  {
372  std::fill(local_matrix_.begin(), local_matrix_.end(), 0);
373 
374  double side_flux = advective_flux(eq_fields_->advection_coef[sbi], this->boundary_points(cell_side), fe_values_side_);
375  double transport_flux = side_flux/side.measure();
376 
377  // On Neumann boundaries we have only term from integrating by parts the advective term,
378  // on Dirichlet boundaries we additionally apply the penalty which enforces the prescribed value.
379  auto p_side = *( this->boundary_points(cell_side).begin() );
380  auto p_bdr = p_side.point_bdr( side.cond().element_accessor() );
381  unsigned int bc_type = eq_fields_->bc_type[sbi](p_bdr);
383  {
384  // set up the parameters for DG method
385  gamma_l = DG_penalty_boundary(side,
386  diffusion_delta(eq_fields_->diffusion_coef[sbi], this->boundary_points(cell_side), fe_values_side_.normal_vector(0)),
387  transport_flux,
388  eq_fields_->dg_penalty[sbi](p_side));
389  transport_flux += gamma_l;
390  }
391 
392  // fluxes and penalty
393  k=0;
394  for (auto p : this->boundary_points(cell_side) )
395  {
396  double flux_times_JxW;
398  {
399  //sigma_ corresponds to robin_sigma
400  auto p_bdr = p.point_bdr(side.cond().element_accessor());
401  flux_times_JxW = eq_fields_->cross_section(p)*eq_fields_->bc_robin_sigma[sbi](p_bdr)*fe_values_side_.JxW(k);
402  }
404  {
405  auto p_bdr = p.point_bdr(side.cond().element_accessor());
406  flux_times_JxW = (transport_flux + eq_fields_->cross_section(p)*eq_fields_->bc_robin_sigma[sbi](p_bdr))*fe_values_side_.JxW(k);
407  }
408  else if (bc_type == AdvectionDiffusionModel::abc_inflow && side_flux < 0)
409  flux_times_JxW = 0;
410  else
411  flux_times_JxW = transport_flux*fe_values_side_.JxW(k);
412 
413  for (unsigned int i=0; i<ndofs_; i++)
414  {
415  for (unsigned int j=0; j<ndofs_; j++)
416  {
417  // flux due to advection and penalty
419 
420  // flux due to diffusion (only on dirichlet and inflow boundary)
422  local_matrix_[i*ndofs_+j] -= (arma::dot(eq_fields_->diffusion_coef[sbi](p)*fe_values_side_.shape_grad(j,k),fe_values_side_.normal_vector(k))*fe_values_side_.shape_value(i,k)
424  )*fe_values_side_.JxW(k);
425  }
426  }
427  k++;
428  }
429 
431  }
432  }
433 
434 
435  /// Assembles the fluxes between sides of elements of the same dimension.
437  ASSERT_EQ(edge_side_range.begin()->element().dim(), dim).error("Dimension of element mismatch!");
438 
439  unsigned int k;
440  double gamma_l, omega[2], transport_flux, delta[2], delta_sum;
441  double aniso1, aniso2;
442  double local_alpha=0.0;
443  int sid=0, s1, s2;
444  for( DHCellSide edge_side : edge_side_range )
445  {
446  auto dh_edge_cell = eq_data_->dh_->cell_accessor_from_element( edge_side.elem_idx() );
447  dh_edge_cell.get_dof_indices(side_dof_indices_[sid]);
448  fe_values_vec_[sid].reinit(edge_side.side());
449  ++sid;
450  }
451  arma::vec3 normal_vector = fe_values_vec_[0].normal_vector(0);
452 
453  // fluxes and penalty
454  for (unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
455  {
456  vector<double> fluxes(edge_side_range.begin()->n_edge_sides());
457  double pflux = 0, nflux = 0; // calculate the total in- and out-flux through the edge
458  sid=0;
459  for( DHCellSide edge_side : edge_side_range )
460  {
461  fluxes[sid] = advective_flux(eq_fields_->advection_coef[sbi], this->edge_points(edge_side), fe_values_vec_[sid]) / edge_side.measure();
462  if (fluxes[sid] > 0)
463  pflux += fluxes[sid];
464  else
465  nflux += fluxes[sid];
466  ++sid;
467  }
468 
469  // precompute averages of shape functions over pairs of sides
470  s1=0;
471  for (DHCellSide edge_side : edge_side_range)
472  {
473  (void)edge_side;
474  for (unsigned int k=0; k<qsize_lower_dim_; k++)
475  {
476  for (unsigned int i=0; i<fe_->n_dofs(); i++)
477  averages[s1][k*fe_->n_dofs()+i] = fe_values_vec_[s1].shape_value(i,k)*0.5;
478  }
479  s1++;
480  }
481 
482 
483 
484  s1=0;
485  for( DHCellSide edge_side1 : edge_side_range )
486  {
487  s2=-1; // need increment at begin of loop (see conditionally 'continue' directions)
488  for( DHCellSide edge_side2 : edge_side_range )
489  {
490  s2++;
491  if (s2<=s1) continue;
492  ASSERT(edge_side1.is_valid()).error("Invalid side of edge.");
493 
494  arma::vec3 nv = fe_values_vec_[s1].normal_vector(0);
495 
496  // set up the parameters for DG method
497  // calculate the flux from edge_side1 to edge_side2
498  if (fluxes[s2] > 0 && fluxes[s1] < 0)
499  transport_flux = fluxes[s1]*fabs(fluxes[s2]/pflux);
500  else if (fluxes[s2] < 0 && fluxes[s1] > 0)
501  transport_flux = fluxes[s1]*fabs(fluxes[s2]/nflux);
502  else
503  transport_flux = 0;
504 
505  gamma_l = 0.5*fabs(transport_flux);
506 
507  delta[0] = 0;
508  delta[1] = 0;
509  for (auto p1 : this->edge_points(edge_side1) )
510  {
511  auto p2 = p1.point_on(edge_side2);
512  delta[0] += dot(eq_fields_->diffusion_coef[sbi](p1)*normal_vector,normal_vector);
513  delta[1] += dot(eq_fields_->diffusion_coef[sbi](p2)*normal_vector,normal_vector);
514  local_alpha = max(eq_fields_->dg_penalty[sbi](p1), eq_fields_->dg_penalty[sbi](p2));
515  }
516  delta[0] /= qsize_lower_dim_;
517  delta[1] /= qsize_lower_dim_;
518 
519  delta_sum = delta[0] + delta[1];
520 
521 // if (delta_sum > numeric_limits<double>::epsilon())
522  if (fabs(delta_sum) > 0)
523  {
524  omega[0] = delta[1]/delta_sum;
525  omega[1] = delta[0]/delta_sum;
526  double h = edge_side1.diameter();
527  aniso1 = elem_anisotropy(edge_side1.element());
528  aniso2 = elem_anisotropy(edge_side2.element());
529  gamma_l += local_alpha/h*aniso1*aniso2*(delta[0]*delta[1]/delta_sum);
530  }
531  else
532  for (int i=0; i<2; i++) omega[i] = 0;
533  // end of set up the parameters for DG method
534 
535  int sd[2]; bool is_side_own[2];
536  sd[0] = s1; is_side_own[0] = edge_side1.cell().is_own();
537  sd[1] = s2; is_side_own[1] = edge_side2.cell().is_own();
538 
539  // precompute jumps and weighted averages of shape functions over the pair of sides (s1,s2)
540  k=0;
541  for (auto p1 : this->edge_points(edge_side1) )
542  {
543  auto p2 = p1.point_on(edge_side2);
544  for (unsigned int i=0; i<fe_->n_dofs(); i++)
545  {
546  for (int n=0; n<2; n++)
547  {
548  jumps[n][k*fe_->n_dofs()+i] = (n==0)*fe_values_vec_[s1].shape_value(i,k) - (n==1)*fe_values_vec_[s2].shape_value(i,k);
549  waverages[n][k*fe_->n_dofs()+i] = arma::dot(eq_fields_->diffusion_coef[sbi]( (n==0 ? p1 : p2) )*fe_values_vec_[sd[n]].shape_grad(i,k),nv)*omega[n];
550  }
551  }
552  k++;
553  }
554 
555  // For selected pair of elements:
556  for (int n=0; n<2; n++)
557  {
558  if (!is_side_own[n]) continue;
559 
560  for (int m=0; m<2; m++)
561  {
562  for (unsigned int i=0; i<fe_values_vec_[sd[n]].n_dofs(); i++)
563  for (unsigned int j=0; j<fe_values_vec_[sd[m]].n_dofs(); j++)
564  local_matrix_[i*fe_values_vec_[sd[m]].n_dofs()+j] = 0;
565 
566  for (unsigned int i=0; i<fe_values_vec_[sd[n]].n_dofs(); i++)
567  {
568  for (unsigned int j=0; j<fe_values_vec_[sd[m]].n_dofs(); j++)
569  {
570  int index = i*fe_values_vec_[sd[m]].n_dofs()+j;
571 
572  for (k=0; k<this->quad_low_->size(); ++k)
573  {
574  local_matrix_[index] += (
575  // flux due to transport (applied on interior edges) (average times jump)
576  transport_flux*jumps[n][k*fe_->n_dofs()+i]*averages[sd[m]][k*fe_->n_dofs()+j]
577 
578  // penalty enforcing continuity across edges (applied on interior and Dirichlet edges) (jump times jump)
579  + gamma_l*jumps[n][k*fe_->n_dofs()+i]*jumps[m][k*fe_->n_dofs()+j]
580 
581  // terms due to diffusion
582  - jumps[n][k*fe_->n_dofs()+i]*waverages[m][k*fe_->n_dofs()+j]
583  - eq_data_->dg_variant*waverages[n][k*fe_->n_dofs()+i]*jumps[m][k*fe_->n_dofs()+j]
584  )*fe_values_vec_[0].JxW(k);
585  }
587  }
588  }
589  eq_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]));
590  }
591  }
592  }
593  s1++;
594  }
595  }
596  }
597 
598 
599  /// Assembles the fluxes between elements of different dimensions.
600  inline void dimjoin_intergral(DHCellAccessor cell_lower_dim, DHCellSide neighb_side) {
601  if (dim == 1) return;
602  ASSERT_EQ(cell_lower_dim.dim(), dim-1).error("Dimension of element mismatch!");
603 
604  // Note: use data members csection_ and velocity_ for appropriate quantities of lower dim element
605 
606  double comm_flux[2][2];
607  unsigned int n_dofs[2];
608  ElementAccessor<3> elm_lower_dim = cell_lower_dim.elm();
609  unsigned int n_indices = cell_lower_dim.get_dof_indices(dof_indices_);
610  for(unsigned int i=0; i<n_indices; ++i) {
612  }
613  fe_values_vb_.reinit(elm_lower_dim);
614  n_dofs[0] = fv_sb_[0]->n_dofs();
615 
616  DHCellAccessor cell_higher_dim = eq_data_->dh_->cell_accessor_from_element( neighb_side.element().idx() );
617  n_indices = cell_higher_dim.get_dof_indices(dof_indices_);
618  for(unsigned int i=0; i<n_indices; ++i) {
619  side_dof_indices_vb_[i+n_dofs[0]] = dof_indices_[i];
620  }
621  fe_values_side_.reinit(neighb_side.side());
622  n_dofs[1] = fv_sb_[1]->n_dofs();
623 
624  // Testing element if they belong to local partition.
625  bool own_element_id[2];
626  own_element_id[0] = cell_lower_dim.is_own();
627  own_element_id[1] = cell_higher_dim.is_own();
628 
629  unsigned int k;
630  for (unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++) // Optimize: SWAP LOOPS
631  {
632  for (unsigned int i=0; i<n_dofs[0]+n_dofs[1]; i++)
633  for (unsigned int j=0; j<n_dofs[0]+n_dofs[1]; j++)
634  local_matrix_[i*(n_dofs[0]+n_dofs[1])+j] = 0;
635 
636  // set transmission conditions
637  k=0;
638  for (auto p_high : this->coupling_points(neighb_side) )
639  {
640  auto p_low = p_high.lower_dim(cell_lower_dim);
641  // The communication flux has two parts:
642  // - "diffusive" term containing sigma
643  // - "advective" term representing usual upwind
644  //
645  // The calculation differs from the reference manual, since ad_coef and dif_coef have different meaning
646  // than b and A in the manual.
647  // In calculation of sigma there appears one more csection_lower in the denominator.
648  double sigma = eq_fields_->fracture_sigma[sbi](p_low)*arma::dot(eq_fields_->diffusion_coef[sbi](p_low)*fe_values_side_.normal_vector(k),fe_values_side_.normal_vector(k))*
649  2*eq_fields_->cross_section(p_high)*eq_fields_->cross_section(p_high)/(eq_fields_->cross_section(p_low)*eq_fields_->cross_section(p_low));
650 
651  double transport_flux = arma::dot(eq_fields_->advection_coef[sbi](p_high), fe_values_side_.normal_vector(k));
652 
653  comm_flux[0][0] = (sigma-min(0.,transport_flux))*fv_sb_[0]->JxW(k);
654  comm_flux[0][1] = -(sigma-min(0.,transport_flux))*fv_sb_[0]->JxW(k);
655  comm_flux[1][0] = -(sigma+max(0.,transport_flux))*fv_sb_[0]->JxW(k);
656  comm_flux[1][1] = (sigma+max(0.,transport_flux))*fv_sb_[0]->JxW(k);
657 
658  for (int n=0; n<2; n++)
659  {
660  if (!own_element_id[n]) continue;
661 
662  for (unsigned int i=0; i<n_dofs[n]; i++)
663  for (int m=0; m<2; m++)
664  for (unsigned int j=0; j<n_dofs[m]; j++)
665  local_matrix_[(i+n*n_dofs[0])*(n_dofs[0]+n_dofs[1]) + m*n_dofs[0] + j] +=
666  comm_flux[m][n]*fv_sb_[m]->shape_value(j,k)*fv_sb_[n]->shape_value(i,k) + LocalSystem::almost_zero;
667  }
668  k++;
669  }
670  eq_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]));
671  }
672  }
673 
674 
675 private:
676  shared_ptr<FiniteElement<dim>> fe_; ///< Finite element for the solution of the advection-diffusion equation.
677  shared_ptr<FiniteElement<dim-1>> fe_low_; ///< Finite element for the solution of the advection-diffusion equation (dim-1).
678 
679  /// Data objects shared with TransportDG
682 
683  /// Sub field set contains fields used in calculation.
685 
686  unsigned int ndofs_; ///< Number of dofs
687  unsigned int qsize_lower_dim_; ///< Size of quadrature of dim-1
688  FEValues<3> fe_values_; ///< FEValues of object (of P disc finite element type)
689  FEValues<3> fe_values_vb_; ///< FEValues of dim-1 object (of P disc finite element type)
690  FEValues<3> fe_values_side_; ///< FEValues of object (of P disc finite element type)
691  vector<FEValues<3>> fe_values_vec_; ///< Vector of FEValues of object (of P disc finite element types)
692  vector<FEValues<3>*> fv_sb_; ///< Auxiliary vector, holds FEValues objects for assemble element-side
693 
694  vector<LongIdx> dof_indices_; ///< Vector of global DOF indices
695  vector< vector<LongIdx> > side_dof_indices_; ///< Vector of vectors of side DOF indices
696  vector<LongIdx> side_dof_indices_vb_; ///< Vector of side DOF indices (assemble element-side fluxex)
697  vector<PetscScalar> local_matrix_; ///< Auxiliary vector for assemble methods
698 
699  vector<double*> averages; ///< Auxiliary storage for averages of shape functions.
700  vector<double*> waverages; ///< Auxiliary storage for weighted averages of shape functions.
701  vector<double*> jumps; ///< Auxiliary storage for jumps of shape functions.
702 
703  template < template<IntDim...> class DimAssembly>
704  friend class GenericAssembly;
705 
706 };
707 
708 
709 /**
710  * Auxiliary container class for Finite element and related objects of given dimension.
711  */
712 template <unsigned int dim, class Model>
713 class SourcesAssemblyDG : public AssemblyBase<dim>
714 {
715 public:
718 
719  static constexpr const char * name() { return "SourcesAssemblyDG"; }
720 
721  /// Constructor.
722  SourcesAssemblyDG(EqFields *eq_fields, EqData *eq_data)
723  : AssemblyBase<dim>(eq_data->dg_order), eq_fields_(eq_fields), eq_data_(eq_data) {
725  this->used_fields_ += eq_fields_->sources_density_out;
726  this->used_fields_ += eq_fields_->sources_conc_out;
727  this->used_fields_ += eq_fields_->sources_sigma_out;
728  }
729 
730  /// Destructor.
732 
733  /// Initialize auxiliary vectors and other data members
734  void initialize(ElementCacheMap *element_cache_map) {
735  this->element_cache_map_ = element_cache_map;
736 
737  fe_ = std::make_shared< FE_P_disc<dim> >(eq_data_->dg_order);
739  fe_values_.initialize(*this->quad_, *fe_, u);
740  if (dim==1) // print to log only one time
741  DebugOut() << "List of SourcesAssemblyDG FEValues updates flags: " << this->print_update_flags(u);
742  ndofs_ = fe_->n_dofs();
743  dof_indices_.resize(ndofs_);
744  local_rhs_.resize(ndofs_);
747  }
748 
749 
750  /// Assemble integral over element
751  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
752  {
753  ASSERT_EQ(cell.dim(), dim).error("Dimension of element mismatch!");
754 
755  ElementAccessor<3> elm = cell.elm();
756  unsigned int k;
757  double source;
758 
759  fe_values_.reinit(elm);
761 
762  // assemble the local stiffness matrix
763  for (unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
764  {
765  fill_n( &(local_rhs_[0]), ndofs_, 0 );
768 
769  k=0;
770  for (auto p : this->bulk_points(element_patch_idx) )
771  {
772  source = (eq_fields_->sources_density_out[sbi](p) + eq_fields_->sources_conc_out[sbi](p)*eq_fields_->sources_sigma_out[sbi](p))*fe_values_.JxW(k);
773 
774  for (unsigned int i=0; i<ndofs_; i++)
775  local_rhs_[i] += source*fe_values_.shape_value(i,k);
776  k++;
777  }
778  eq_data_->ls[sbi]->rhs_set_values(ndofs_, &(dof_indices_[0]), &(local_rhs_[0]));
779 
780  for (unsigned int i=0; i<ndofs_; i++)
781  {
782  k=0;
783  for (auto p : this->bulk_points(element_patch_idx) )
784  {
785  local_source_balance_vector_[i] -= eq_fields_->sources_sigma_out[sbi](p)*fe_values_.shape_value(i,k)*fe_values_.JxW(k);
786  k++;
787  }
788 
790  }
791  eq_data_->balance_->add_source_values(eq_data_->subst_idx()[sbi], elm.region().bulk_idx(),
792  cell.get_loc_dof_indices(),
794  }
795  }
796 
797  /// Implements @p AssemblyBase::begin.
798  void begin() override
799  {
800  eq_data_->balance_->start_source_assembly( eq_data_->subst_idx() );
801  }
802 
803  /// Implements @p AssemblyBase::end.
804  void end() override
805  {
806  eq_data_->balance_->finish_source_assembly( eq_data_->subst_idx() );
807  }
808 
809 
810  private:
811  shared_ptr<FiniteElement<dim>> fe_; ///< Finite element for the solution of the advection-diffusion equation.
812 
813  /// Data objects shared with TransportDG
816 
817  /// Sub field set contains fields used in calculation.
819 
820  unsigned int ndofs_; ///< Number of dofs
821  FEValues<3> fe_values_; ///< FEValues of object (of P disc finite element type)
822 
823  vector<LongIdx> dof_indices_; ///< Vector of global DOF indices
824  vector<PetscScalar> local_rhs_; ///< Auxiliary vector for set_sources method.
825  vector<PetscScalar> local_source_balance_vector_; ///< Auxiliary vector for set_sources method.
826  vector<PetscScalar> local_source_balance_rhs_; ///< Auxiliary vector for set_sources method.
827 
828  template < template<IntDim...> class DimAssembly>
829  friend class GenericAssembly;
830 
831 };
832 
833 
834 /**
835  * Assembles the r.h.s. components corresponding to the Dirichlet boundary conditions..
836  */
837 template <unsigned int dim, class Model>
839 {
840 public:
843 
844  static constexpr const char * name() { return "BdrConditionAssemblyDG"; }
845 
846  /// Constructor.
847  BdrConditionAssemblyDG(EqFields *eq_fields, EqData *eq_data)
848  : AssemblyBase<dim>(eq_data->dg_order), eq_fields_(eq_fields), eq_data_(eq_data) {
850  this->used_fields_ += eq_fields_->advection_coef;
851  this->used_fields_ += eq_fields_->diffusion_coef;
852  this->used_fields_ += eq_fields_->cross_section;
853  this->used_fields_ += eq_fields_->bc_type;
854  this->used_fields_ += eq_fields_->bc_dirichlet_value;
855  this->used_fields_ += eq_fields_->bc_robin_sigma;
856  this->used_fields_ += eq_fields_->bc_flux;
857  }
858 
859  /// Destructor.
861 
862  /// Initialize auxiliary vectors and other data members
863  void initialize(ElementCacheMap *element_cache_map) {
864  this->element_cache_map_ = element_cache_map;
865 
866  fe_ = std::make_shared< FE_P_disc<dim> >(eq_data_->dg_order);
869  if (dim==1) // print to log only one time
870  DebugOut() << "List of BdrConditionAssemblyDG FEValues updates flags: " << this->print_update_flags(u);
871  ndofs_ = fe_->n_dofs();
872  dof_indices_.resize(ndofs_);
873  local_rhs_.resize(ndofs_);
875  }
876 
877 
878  /// Implements @p AssemblyBase::boundary_side_integral.
879  inline void boundary_side_integral(DHCellSide cell_side)
880  {
881  unsigned int k;
882 
883  ElementAccessor<3> bc_elm = cell_side.cond().element_accessor();
884 
885  fe_values_side_.reinit(cell_side.side());
886 
887  const DHCellAccessor &cell = cell_side.cell();
889 
890  for (unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
891  {
892  fill_n(&(local_rhs_[0]), ndofs_, 0);
895 
896  double side_flux = advective_flux(eq_fields_->advection_coef[sbi], this->boundary_points(cell_side), fe_values_side_);
897  double transport_flux = side_flux/cell_side.measure();
898 
899  auto p_side = *( this->boundary_points(cell_side)).begin();
900  auto p_bdr = p_side.point_bdr(cell_side.cond().element_accessor() );
901  unsigned int bc_type = eq_fields_->bc_type[sbi](p_bdr);
902  if (bc_type == AdvectionDiffusionModel::abc_inflow && side_flux < 0)
903  {
904  k=0;
905  for (auto p : this->boundary_points(cell_side) )
906  {
907  auto p_bdr = p.point_bdr(bc_elm);
908  double bc_term = -transport_flux*eq_fields_->bc_dirichlet_value[sbi](p_bdr)*fe_values_side_.JxW(k);
909  for (unsigned int i=0; i<ndofs_; i++)
910  local_rhs_[i] += bc_term*fe_values_side_.shape_value(i,k);
911  k++;
912  }
913  for (unsigned int i=0; i<ndofs_; i++)
915  }
916  else if (bc_type == AdvectionDiffusionModel::abc_dirichlet)
917  {
918  double side_flux = advective_flux(eq_fields_->advection_coef[sbi], this->boundary_points(cell_side), fe_values_side_);
919  double transport_flux = side_flux/cell_side.measure();
920 
921  double gamma_l = DG_penalty_boundary(cell_side.side(),
922  diffusion_delta(eq_fields_->diffusion_coef[sbi], this->boundary_points(cell_side), fe_values_side_.normal_vector(0)),
923  transport_flux,
924  eq_fields_->dg_penalty[sbi](p_bdr));
925 
926  k=0;
927  for (auto p : this->boundary_points(cell_side) )
928  {
929  auto p_bdr = p.point_bdr(bc_elm);
930  double bc_term = gamma_l*eq_fields_->bc_dirichlet_value[sbi](p_bdr)*fe_values_side_.JxW(k);
931  arma::vec3 bc_grad = -eq_fields_->bc_dirichlet_value[sbi](p_bdr)*fe_values_side_.JxW(k)*eq_data_->dg_variant*(arma::trans(eq_fields_->diffusion_coef[sbi](p))*fe_values_side_.normal_vector(k));
932  for (unsigned int i=0; i<ndofs_; i++)
933  local_rhs_[i] += bc_term*fe_values_side_.shape_value(i,k)
934  + arma::dot(bc_grad,fe_values_side_.shape_grad(i,k));
935  k++;
936  }
937  k=0;
938  for (auto p : this->boundary_points(cell_side) )
939  {
940  for (unsigned int i=0; i<ndofs_; i++)
941  {
942  local_flux_balance_vector_[i] += (arma::dot(eq_fields_->advection_coef[sbi](p), fe_values_side_.normal_vector(k))*fe_values_side_.shape_value(i,k)
943  - arma::dot(eq_fields_->diffusion_coef[sbi](p)*fe_values_side_.shape_grad(i,k),fe_values_side_.normal_vector(k))
944  + gamma_l*fe_values_side_.shape_value(i,k))*fe_values_side_.JxW(k);
945  }
946  k++;
947  }
948  if (eq_data_->time_->step().index() > 0)
949  for (unsigned int i=0; i<ndofs_; i++)
951  }
952  else if (bc_type == AdvectionDiffusionModel::abc_total_flux)
953  {
954  k=0;
955  for (auto p : this->boundary_points(cell_side) )
956  {
957  auto p_bdr = p.point_bdr(bc_elm);
958  double bc_term = eq_fields_->cross_section(p) * (eq_fields_->bc_robin_sigma[sbi](p_bdr)*eq_fields_->bc_dirichlet_value[sbi](p_bdr) +
959  eq_fields_->bc_flux[sbi](p_bdr)) * fe_values_side_.JxW(k);
960  for (unsigned int i=0; i<ndofs_; i++)
961  local_rhs_[i] += bc_term*fe_values_side_.shape_value(i,k);
962  k++;
963  }
964 
965  for (unsigned int i=0; i<ndofs_; i++)
966  {
967  k=0;
968  for (auto p : this->boundary_points(cell_side) ) {
969  auto p_bdr = p.point_bdr(bc_elm);
970  local_flux_balance_vector_[i] += eq_fields_->cross_section(p) * eq_fields_->bc_robin_sigma[sbi](p_bdr) *
972  k++;
973  }
975  }
976  }
978  {
979  k=0;
980  for (auto p : this->boundary_points(cell_side) )
981  {
982  auto p_bdr = p.point_bdr(bc_elm);
983  double bc_term = eq_fields_->cross_section(p) * (eq_fields_->bc_robin_sigma[sbi](p_bdr)*eq_fields_->bc_dirichlet_value[sbi](p_bdr) +
984  eq_fields_->bc_flux[sbi](p_bdr)) * fe_values_side_.JxW(k);
985  for (unsigned int i=0; i<ndofs_; i++)
986  local_rhs_[i] += bc_term*fe_values_side_.shape_value(i,k);
987  k++;
988  }
989 
990  for (unsigned int i=0; i<ndofs_; i++)
991  {
992  k=0;
993  for (auto p : this->boundary_points(cell_side) ) {
994  auto p_bdr = p.point_bdr(bc_elm);
995  local_flux_balance_vector_[i] += eq_fields_->cross_section(p)*(arma::dot(eq_fields_->advection_coef[sbi](p), fe_values_side_.normal_vector(k)) +
996  eq_fields_->bc_robin_sigma[sbi](p_bdr))*fe_values_side_.JxW(k)*fe_values_side_.shape_value(i,k);
997  k++;
998  }
1000  }
1001  }
1002  else if (bc_type == AdvectionDiffusionModel::abc_inflow && side_flux >= 0)
1003  {
1004  k=0;
1005  for (auto p : this->boundary_points(cell_side) )
1006  {
1007  for (unsigned int i=0; i<ndofs_; i++)
1009  k++;
1010  }
1011  }
1012  eq_data_->ls[sbi]->rhs_set_values(ndofs_, &(dof_indices_[0]), &(local_rhs_[0]));
1013 
1014  eq_data_->balance_->add_flux_values(eq_data_->subst_idx()[sbi], cell_side,
1015  cell.get_loc_dof_indices(),
1017  }
1018  }
1019 
1020  /// Implements @p AssemblyBase::begin.
1021  void begin() override
1022  {
1023  eq_data_->balance_->start_flux_assembly( eq_data_->subst_idx() );
1024  }
1025 
1026  /// Implements @p AssemblyBase::end.
1027  void end() override
1028  {
1029  eq_data_->balance_->finish_flux_assembly( eq_data_->subst_idx() );
1030  }
1031 
1032 
1033  private:
1034  shared_ptr<FiniteElement<dim>> fe_; ///< Finite element for the solution of the advection-diffusion equation.
1035 
1036  /// Data objects shared with TransportDG
1039 
1040  /// Sub field set contains fields used in calculation.
1042 
1043  unsigned int ndofs_; ///< Number of dofs
1044  FEValues<3> fe_values_side_; ///< FEValues of object (of P disc finite element type)
1045 
1046  vector<LongIdx> dof_indices_; ///< Vector of global DOF indices
1047  vector<PetscScalar> local_rhs_; ///< Auxiliary vector for set_sources method.
1048  vector<PetscScalar> local_flux_balance_vector_; ///< Auxiliary vector for set_boundary_conditions method.
1049  PetscScalar local_flux_balance_rhs_; ///< Auxiliary variable for set_boundary_conditions method.
1050 
1051  template < template<IntDim...> class DimAssembly>
1052  friend class GenericAssembly;
1053 
1054 };
1055 
1056 
1057 /**
1058  * Auxiliary container class sets the initial condition.
1059  */
1060 template <unsigned int dim, class Model>
1062 {
1063 public:
1066 
1067  static constexpr const char * name() { return "InitProjectionAssemblyDG"; }
1068 
1069  /// Constructor.
1071  : AssemblyBase<dim>(eq_data->dg_order), eq_fields_(eq_fields), eq_data_(eq_data) {
1073  this->used_fields_ += eq_fields_->init_condition;
1074  }
1075 
1076  /// Destructor.
1078 
1079  /// Initialize auxiliary vectors and other data members
1080  void initialize(ElementCacheMap *element_cache_map) {
1081  this->element_cache_map_ = element_cache_map;
1082 
1083  fe_ = std::make_shared< FE_P_disc<dim> >(eq_data_->dg_order);
1085  fe_values_.initialize(*this->quad_, *fe_, u);
1086  // if (dim==1) // print to log only one time
1087  // DebugOut() << "List of InitProjectionAssemblyDG FEValues updates flags: " << this->print_update_flags(u);
1088  ndofs_ = fe_->n_dofs();
1089  dof_indices_.resize(ndofs_);
1090  local_matrix_.resize(4*ndofs_*ndofs_);
1091  local_rhs_.resize(ndofs_);
1092  }
1093 
1094 
1095  /// Assemble integral over element
1096  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
1097  {
1098  ASSERT_EQ(cell.dim(), dim).error("Dimension of element mismatch!");
1099 
1100  unsigned int k;
1101  ElementAccessor<3> elem = cell.elm();
1103  fe_values_.reinit(elem);
1104 
1105  for (unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
1106  {
1107  for (unsigned int i=0; i<ndofs_; i++)
1108  {
1109  local_rhs_[i] = 0;
1110  for (unsigned int j=0; j<ndofs_; j++)
1111  local_matrix_[i*ndofs_+j] = 0;
1112  }
1113 
1114  k=0;
1115  for (auto p : this->bulk_points(element_patch_idx) )
1116  {
1117  double rhs_term = eq_fields_->init_condition[sbi](p)*fe_values_.JxW(k);
1118 
1119  for (unsigned int i=0; i<ndofs_; i++)
1120  {
1121  for (unsigned int j=0; j<ndofs_; j++)
1123 
1124  local_rhs_[i] += fe_values_.shape_value(i,k)*rhs_term;
1125  }
1126  k++;
1127  }
1128  eq_data_->ls[sbi]->set_values(ndofs_, &(dof_indices_[0]), ndofs_, &(dof_indices_[0]), &(local_matrix_[0]), &(local_rhs_[0]));
1129  }
1130  }
1131 
1132 
1133  private:
1134  shared_ptr<FiniteElement<dim>> fe_; ///< Finite element for the solution of the advection-diffusion equation.
1135 
1136  /// Data objects shared with TransportDG
1139 
1140  /// Sub field set contains fields used in calculation.
1142 
1143  unsigned int ndofs_; ///< Number of dofs
1144  FEValues<3> fe_values_; ///< FEValues of object (of P disc finite element type)
1145 
1146  vector<LongIdx> dof_indices_; ///< Vector of global DOF indices
1147  vector<PetscScalar> local_matrix_; ///< Auxiliary vector for assemble methods
1148  vector<PetscScalar> local_rhs_; ///< Auxiliary vector for set_sources method.
1149 
1150  template < template<IntDim...> class DimAssembly>
1151  friend class GenericAssembly;
1152 
1153 };
1154 
1155 
1156 /**
1157  * Auxiliary container class sets the initial condition.
1158  */
1159 template <unsigned int dim, class Model>
1161 {
1162 public:
1165 
1166  static constexpr const char * name() { return "InitConditionAssemblyDG"; }
1167 
1168  /// Constructor.
1170  : AssemblyBase<dim>(), eq_fields_(eq_fields), eq_data_(eq_data) {
1172  this->used_fields_ += eq_fields_->init_condition;
1173 
1174  this->quad_ = new Quadrature(dim, RefElement<dim>::n_nodes);
1175  for(unsigned int i = 0; i<RefElement<dim>::n_nodes; i++)
1176  {
1177  this->quad_->weight(i) = 1.0;
1178  this->quad_->set(i) = RefElement<dim>::node_coords(i);
1179  }
1180  }
1181 
1182  /// Destructor.
1184 
1185  /// Initialize auxiliary vectors and other data members
1186  void initialize(ElementCacheMap *element_cache_map) {
1187  this->element_cache_map_ = element_cache_map;
1188  }
1189 
1190 
1191  /// Assemble integral over element
1192  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
1193  {
1194  ASSERT_EQ(cell.dim(), dim).error("Dimension of element mismatch!");
1195 
1196  unsigned int k;
1197 
1198  for (unsigned int sbi=0; sbi<eq_data_->n_substances(); sbi++)
1199  {
1200  k=0;
1201  for (auto p : this->bulk_points(element_patch_idx) )
1202  {
1203  double val = eq_fields_->init_condition[sbi](p);
1204 
1205  eq_data_->output_vec[sbi].set(cell.get_loc_dof_indices()[k], val);
1206  k++;
1207  }
1208  }
1209  }
1210 
1211 
1212  private:
1213  /// Data objects shared with TransportDG
1216 
1217  /// Sub field set contains fields used in calculation.
1219 
1220  template < template<IntDim...> class DimAssembly>
1221  friend class GenericAssembly;
1222 
1223 };
1224 
1225 #endif /* ASSEMBLY_DG_HH_ */
1226 
double elem_anisotropy(ElementAccessor< 3 > e)
Definition: assembly_dg.hh:160
double DG_penalty_boundary(Side side, const double &diff_delta, const double flux, const double alpha)
Computes the penalty parameter of the DG method on a given boundary edge.
Definition: assembly_dg.hh:204
double diffusion_delta(Field< 3, FieldValue< 3 >::TensorFixed > &diff_coef, Range< BoundaryPoint > pts, const arma::vec3 &nv)
Computes average normal diffusivity over a set of points.
Definition: assembly_dg.hh:181
double advective_flux(Field< 3, FieldValue< 3 >::VectorFixed > &advection_coef, Range< PointType > pts, FEValues< 3 > &fv)
Computes advective flux.
Definition: assembly_dg.hh:222
#define ASSERT(expr)
Definition: asserts.hh:351
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:333
Range< BulkPoint > bulk_points(unsigned int element_patch_idx) const
Return BulkPoint range of appropriate dimension.
Range< EdgePoint > edge_points(const DHCellSide &cell_side) const
Return EdgePoint range of appropriate dimension.
Quadrature * quad_
Quadrature used in assembling methods.
std::string print_update_flags(UpdateFlags u) const
Print update flags to string format.
Quadrature * quad_low_
Quadrature used in assembling methods (dim-1).
Range< CouplingPoint > coupling_points(const DHCellSide &cell_side) const
Return CouplingPoint range of appropriate dimension.
int active_integrals_
Holds mask of active integrals.
Range< BoundaryPoint > boundary_points(const DHCellSide &cell_side) const
Return BoundaryPoint range of appropriate dimension.
ElementCacheMap * element_cache_map_
ElementCacheMap shared with GenericAssembly object.
static constexpr const char * name()
Definition: assembly_dg.hh:844
FieldSet used_fields_
Sub field set contains fields used in calculation.
vector< PetscScalar > local_flux_balance_vector_
Auxiliary vector for set_boundary_conditions method.
void boundary_side_integral(DHCellSide cell_side)
Implements AssemblyBase::boundary_side_integral.
Definition: assembly_dg.hh:879
FEValues< 3 > fe_values_side_
FEValues of object (of P disc finite element type)
TransportDG< Model >::EqData EqData
Definition: assembly_dg.hh:842
TransportDG< Model >::EqFields EqFields
Definition: assembly_dg.hh:841
void begin() override
Implements AssemblyBase::begin.
~BdrConditionAssemblyDG()
Destructor.
Definition: assembly_dg.hh:860
PetscScalar local_flux_balance_rhs_
Auxiliary variable for set_boundary_conditions method.
shared_ptr< FiniteElement< dim > > fe_
Finite element for the solution of the advection-diffusion equation.
void initialize(ElementCacheMap *element_cache_map)
Initialize auxiliary vectors and other data members.
Definition: assembly_dg.hh:863
vector< LongIdx > dof_indices_
Vector of global DOF indices.
EqFields * eq_fields_
Data objects shared with TransportDG.
void end() override
Implements AssemblyBase::end.
vector< PetscScalar > local_rhs_
Auxiliary vector for set_sources method.
unsigned int ndofs_
Number of dofs.
BdrConditionAssemblyDG(EqFields *eq_fields, EqData *eq_data)
Constructor.
Definition: assembly_dg.hh:847
ElementAccessor< 3 > element_accessor()
Cell accessor allow iterate over DOF handler cells.
const ElementAccessor< 3 > elm() const
Return ElementAccessor to element of loc_ele_idx_.
bool is_own() const
Return true if accessor represents own element (false for ghost element)
LocDofVec get_loc_dof_indices() const
Returns the local indices of dofs associated to the cell on the local process.
unsigned int get_dof_indices(std::vector< LongIdx > &indices) const
Fill vector of the global indices of dofs associated to the cell.
unsigned int dim() const
Return dimension of element appropriate to cell.
Side accessor allows to iterate over sides of DOF handler cell.
Side side() const
Return Side of given cell and side_idx.
Boundary cond() const
const DHCellAccessor & cell() const
Return DHCellAccessor appropriate to the side.
unsigned int dim() const
Return dimension of element appropriate to the side.
double measure() const
ElementAccessor< 3 > element() const
NodeAccessor< 3 > node(unsigned int ni) const
Definition: accessors.hh:230
Region region() const
Definition: accessors.hh:198
unsigned int idx() const
We need this method after replacing Region by RegionIdx, and movinf RegionDB instance into particular...
Definition: accessors.hh:215
Directing class of FieldValueCache.
unsigned int n_nodes() const
Definition: elements.h:125
double JxW(const unsigned int point_no)
Return the product of Jacobian determinant and the quadrature weight at given quadrature point.
Definition: fe_values.hh:223
double shape_value(const unsigned int function_no, const unsigned int point_no) const
Return the value of the function_no-th shape function at the point_no-th quadrature point.
Definition: fe_values.hh:149
void initialize(Quadrature &_quadrature, FiniteElement< DIM > &_fe, UpdateFlags _flags)
Initialize structures and calculates cell-independent data.
Definition: fe_values.cc:137
void reinit(const ElementAccessor< spacedim > &cell)
Update cell-dependent data (gradients, Jacobians etc.)
Definition: fe_values.cc:537
arma::vec::fixed< spacedim > normal_vector(unsigned int point_no)
Returns the normal vector to a side at given quadrature point.
Definition: fe_values.hh:257
arma::vec::fixed< spacedim > shape_grad(const unsigned int function_no, const unsigned int point_no) const
Return the gradient of the function_no-th shape function at the point_no-th quadrature point.
Definition: fe_values.hh:164
Discontinuous Lagrangean finite element on dim dimensional simplex.
Definition: fe_p.hh:108
Container for various descendants of FieldCommonBase.
Definition: field_set.hh:160
Class template representing a field with values dependent on: point, element, and region.
Definition: field.hh:92
Abstract class for the description of a general finite element on a reference simplex in dim dimensio...
Generic class of assemblation.
FieldSet used_fields_
Sub field set contains fields used in calculation.
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
Assemble integral over element.
static constexpr const char * name()
~InitConditionAssemblyDG()
Destructor.
void initialize(ElementCacheMap *element_cache_map)
Initialize auxiliary vectors and other data members.
InitConditionAssemblyDG(EqFields *eq_fields, EqData *eq_data)
Constructor.
EqFields * eq_fields_
Data objects shared with TransportDG.
TransportDG< Model >::EqData EqData
TransportDG< Model >::EqFields EqFields
EqFields * eq_fields_
Data objects shared with TransportDG.
vector< PetscScalar > local_rhs_
Auxiliary vector for set_sources method.
vector< LongIdx > dof_indices_
Vector of global DOF indices.
TransportDG< Model >::EqData EqData
FieldSet used_fields_
Sub field set contains fields used in calculation.
unsigned int ndofs_
Number of dofs.
shared_ptr< FiniteElement< dim > > fe_
Finite element for the solution of the advection-diffusion equation.
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
Assemble integral over element.
FEValues< 3 > fe_values_
FEValues of object (of P disc finite element type)
static constexpr const char * name()
vector< PetscScalar > local_matrix_
Auxiliary vector for assemble methods.
InitProjectionAssemblyDG(EqFields *eq_fields, EqData *eq_data)
Constructor.
~InitProjectionAssemblyDG()
Destructor.
TransportDG< Model >::EqFields EqFields
void initialize(ElementCacheMap *element_cache_map)
Initialize auxiliary vectors and other data members.
virtual void rhs_set_values(int nrow, int *rows, double *vals)=0
virtual void mat_set_values(int nrow, int *rows, int ncol, int *cols, double *vals)=0
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.
Definition: linsys.hh:386
static constexpr double almost_zero
vector< LongIdx > dof_indices_
Vector of global DOF indices.
Definition: assembly_dg.hh:148
vector< PetscScalar > local_mass_balance_vector_
Same as previous.
Definition: assembly_dg.hh:151
TransportDG< Model >::EqFields EqFields
Definition: assembly_dg.hh:39
FieldSet used_fields_
Sub field set contains fields used in calculation.
Definition: assembly_dg.hh:143
FEValues< 3 > fe_values_
FEValues of object (of P disc finite element type)
Definition: assembly_dg.hh:146
vector< PetscScalar > local_matrix_
Auxiliary vector for assemble methods.
Definition: assembly_dg.hh:149
void end() override
Implements AssemblyBase::end.
Definition: assembly_dg.hh:130
~MassAssemblyDG()
Destructor.
Definition: assembly_dg.hh:53
shared_ptr< FiniteElement< dim > > fe_
Finite element for the solution of the advection-diffusion equation.
Definition: assembly_dg.hh:136
EqData * eq_data_
Definition: assembly_dg.hh:140
void begin() override
Implements AssemblyBase::begin.
Definition: assembly_dg.hh:124
static constexpr const char * name()
Definition: assembly_dg.hh:42
void initialize(ElementCacheMap *element_cache_map)
Initialize auxiliary vectors and other data members.
Definition: assembly_dg.hh:56
unsigned int ndofs_
Number of dofs.
Definition: assembly_dg.hh:145
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
Assemble integral over element.
Definition: assembly_dg.hh:74
TransportDG< Model >::EqData EqData
Definition: assembly_dg.hh:40
EqFields * eq_fields_
Data objects shared with TransportDG.
Definition: assembly_dg.hh:139
vector< PetscScalar > local_retardation_balance_vector_
Auxiliary vector for assemble mass matrix.
Definition: assembly_dg.hh:150
MassAssemblyDG(EqFields *eq_fields, EqData *eq_data)
Constructor.
Definition: assembly_dg.hh:45
Base class for quadrature rules on simplices in arbitrary dimensions.
Definition: quadrature.hh:48
unsigned int size() const
Returns number of quadrature points.
Definition: quadrature.hh:86
Armor::Array< double >::ArrayMatSet set(uint i)
Definition: quadrature.hh:93
double weight(unsigned int i) const
Returns the ith weight.
Definition: quadrature.hh:103
IterConvert< ObjectIn, ObjectOut > begin()
Iterator to begin item of range.
Range helper class.
static LocalPoint node_coords(unsigned int nid)
Definition: ref_element.hh:619
unsigned int bulk_idx() const
Returns index of the region in the bulk set.
Definition: region.hh:90
double measure() const
Calculate metrics of the side.
Definition: accessors.cc:27
Boundary cond() const
ElementAccessor< 3 > element() const
Returns iterator to the element of the side.
double diameter() const
Calculate the side diameter.
Definition: accessors.cc:132
vector< PetscScalar > local_rhs_
Auxiliary vector for set_sources method.
Definition: assembly_dg.hh:824
TransportDG< Model >::EqData EqData
Definition: assembly_dg.hh:717
TransportDG< Model >::EqFields EqFields
Definition: assembly_dg.hh:716
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
Assemble integral over element.
Definition: assembly_dg.hh:751
~SourcesAssemblyDG()
Destructor.
Definition: assembly_dg.hh:731
shared_ptr< FiniteElement< dim > > fe_
Finite element for the solution of the advection-diffusion equation.
Definition: assembly_dg.hh:811
vector< PetscScalar > local_source_balance_vector_
Auxiliary vector for set_sources method.
Definition: assembly_dg.hh:825
void end() override
Implements AssemblyBase::end.
Definition: assembly_dg.hh:804
FEValues< 3 > fe_values_
FEValues of object (of P disc finite element type)
Definition: assembly_dg.hh:821
static constexpr const char * name()
Definition: assembly_dg.hh:719
EqFields * eq_fields_
Data objects shared with TransportDG.
Definition: assembly_dg.hh:814
vector< PetscScalar > local_source_balance_rhs_
Auxiliary vector for set_sources method.
Definition: assembly_dg.hh:826
void initialize(ElementCacheMap *element_cache_map)
Initialize auxiliary vectors and other data members.
Definition: assembly_dg.hh:734
FieldSet used_fields_
Sub field set contains fields used in calculation.
Definition: assembly_dg.hh:818
unsigned int ndofs_
Number of dofs.
Definition: assembly_dg.hh:820
vector< LongIdx > dof_indices_
Vector of global DOF indices.
Definition: assembly_dg.hh:823
void begin() override
Implements AssemblyBase::begin.
Definition: assembly_dg.hh:798
SourcesAssemblyDG(EqFields *eq_fields, EqData *eq_data)
Constructor.
Definition: assembly_dg.hh:722
TransportDG< Model >::EqData EqData
Definition: assembly_dg.hh:242
void edge_integral(RangeConvert< DHEdgeSide, DHCellSide > edge_side_range)
Assembles the fluxes between sides of elements of the same dimension.
Definition: assembly_dg.hh:436
StiffnessAssemblyDG(EqFields *eq_fields, EqData *eq_data)
Constructor.
Definition: assembly_dg.hh:247
FieldSet used_fields_
Sub field set contains fields used in calculation.
Definition: assembly_dg.hh:684
unsigned int ndofs_
Number of dofs.
Definition: assembly_dg.hh:686
vector< vector< LongIdx > > side_dof_indices_
Vector of vectors of side DOF indices.
Definition: assembly_dg.hh:695
shared_ptr< FiniteElement< dim-1 > > fe_low_
Finite element for the solution of the advection-diffusion equation (dim-1).
Definition: assembly_dg.hh:677
shared_ptr< FiniteElement< dim > > fe_
Finite element for the solution of the advection-diffusion equation.
Definition: assembly_dg.hh:676
void boundary_side_integral(DHCellSide cell_side)
Assembles the fluxes on the boundary.
Definition: assembly_dg.hh:357
vector< double * > jumps
Auxiliary storage for jumps of shape functions.
Definition: assembly_dg.hh:701
vector< double * > waverages
Auxiliary storage for weighted averages of shape functions.
Definition: assembly_dg.hh:700
vector< FEValues< 3 > * > fv_sb_
Auxiliary vector, holds FEValues objects for assemble element-side.
Definition: assembly_dg.hh:692
void dimjoin_intergral(DHCellAccessor cell_lower_dim, DHCellSide neighb_side)
Assembles the fluxes between elements of different dimensions.
Definition: assembly_dg.hh:600
void initialize(ElementCacheMap *element_cache_map)
Initialize auxiliary vectors and other data members.
Definition: assembly_dg.hh:268
vector< LongIdx > side_dof_indices_vb_
Vector of side DOF indices (assemble element-side fluxex)
Definition: assembly_dg.hh:696
FEValues< 3 > fe_values_side_
FEValues of object (of P disc finite element type)
Definition: assembly_dg.hh:690
vector< FEValues< 3 > > fe_values_vec_
Vector of FEValues of object (of P disc finite element types)
Definition: assembly_dg.hh:691
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
Assembles the cell (volume) integral into the stiffness matrix.
Definition: assembly_dg.hh:318
TransportDG< Model >::EqFields EqFields
Definition: assembly_dg.hh:241
vector< double * > averages
Auxiliary storage for averages of shape functions.
Definition: assembly_dg.hh:699
vector< PetscScalar > local_matrix_
Auxiliary vector for assemble methods.
Definition: assembly_dg.hh:697
~StiffnessAssemblyDG()
Destructor.
Definition: assembly_dg.hh:261
static constexpr const char * name()
Definition: assembly_dg.hh:244
vector< LongIdx > dof_indices_
Vector of global DOF indices.
Definition: assembly_dg.hh:694
FEValues< 3 > fe_values_vb_
FEValues of dim-1 object (of P disc finite element type)
Definition: assembly_dg.hh:689
FEValues< 3 > fe_values_
FEValues of object (of P disc finite element type)
Definition: assembly_dg.hh:688
EqFields * eq_fields_
Data objects shared with TransportDG.
Definition: assembly_dg.hh:680
unsigned int qsize_lower_dim_
Size of quadrature of dim-1.
Definition: assembly_dg.hh:687
const TimeStep & step(int index=-1) const
unsigned int index() const
std::shared_ptr< DOFHandlerMultiDim > dh_
Object for distribution of dofs.
std::vector< VectorMPI > output_vec
Vector of solution data.
LinSys ** ls_dt
Linear algebra system for the time derivative (actually it is used only for handling the matrix struc...
int dg_variant
DG variant ((non-)symmetric/incomplete.
TimeGovernor * time_
std::shared_ptr< Balance > balance_
unsigned int dg_order
Polynomial order of finite elements.
LinSys ** ls
Linear algebra system for the transport equation.
std::vector< Vec > ret_vec
Auxiliary vectors for calculation of sources in balance due to retardation (e.g. sorption).
unsigned int max_edg_sides
Maximal number of edge sides (evaluate from dim 1,2,3)
MultiField< 3, FieldValue< 3 >::Scalar > dg_penalty
Penalty enforcing inter-element continuity of solution (for each substance).
MultiField< 3, FieldValue< 3 >::Scalar > fracture_sigma
Transition parameter for diffusive transfer on fractures (for each substance).
Definitions of basic Lagrangean finite elements with polynomial shape functions.
Class FEValues calculates finite element data on the actual cells such as shape function values,...
@ coupling
@ boundary
@ bulk
@ edge
#define DebugOut()
Macro defining 'debug' record of log.
Definition: logger.hh:284
unsigned int IntDim
A dimension index type.
Definition: mixed.hh:19
Definitions of particular quadrature rules on simplices.
Discontinuous Galerkin method for equation of transport with dispersion.
UpdateFlags
Enum type UpdateFlags indicates which quantities are to be recomputed on each finite element cell.
Definition: update_flags.hh:68
@ update_values
Shape function values.
Definition: update_flags.hh:87
@ update_normal_vectors
Normal vectors.
@ update_JxW_values
Transformed quadrature weights.
@ update_side_JxW_values
Transformed quadrature weight for cell sides.
@ update_gradients
Shape function gradients.
Definition: update_flags.hh:95
@ update_quadrature_points
Transformed quadrature points.