Flow123d  DF_patch_fe_darcy_complete-579fe1e
assembly_reaction.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_reaction.hh
15  * @brief
16  */
17 
18 #ifndef ASSEMBLY_REACTION_HH_
19 #define ASSEMBLY_REACTION_HH_
20 
24 #include "reaction/isotherm.hh"
25 #include "fem/fe_p.hh"
26 #include "fem/fe_values.hh"
28 //#include "coupling/balance.hh"
29 #include "fem/element_cache_map.hh"
30 
31 
32 
33 template <unsigned int dim, class TEqData>
35 {
36 public:
37  typedef typename TEqData::EqFields EqFields;
38  typedef TEqData EqData;
39 
40  static constexpr const char * name() { return "Dp_InitCondition_Assembly"; }
41 
42  /// Constructor.
44  : AssemblyBase<dim>(0, asm_internals), eq_fields_(eq_data->eq_fields_.get()), eq_data_(eq_data),
45  mass_integral_( this->create_bulk_integral(this->quad_) ) {
46  this->used_fields_ += eq_fields_->init_conc_immobile;
47  }
48 
49  /// Destructor.
51 
52  /// Initialize auxiliary vectors and other data members
53  void initialize() {}
54 
55 
56  /// Assemble integral over element
57  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
58  {
59  ASSERT_EQ(cell.dim(), dim).error("Dimension of element mismatch!");
60 
61  dof_p0_ = cell.get_loc_dof_indices()[0];
62  auto p = *( mass_integral_->points(element_patch_idx).begin() );
63 
64  //setting initial solid concentration for substances involved in adsorption
65  for (unsigned int sbi = 0; sbi < eq_data_->substances_.size(); sbi++)
66  {
67  eq_fields_->conc_immobile_fe[sbi]->vec().set( dof_p0_, eq_fields_->init_conc_immobile[sbi](p) );
68  }
69  }
70 
71 
72 private:
73  /// Data objects shared with Elasticity
76 
77  /// Sub field set contains fields used in calculation.
79 
80  IntIdx dof_p0_; ///< Index of local DOF
81 
82  std::shared_ptr<BulkIntegralAcc<dim>> mass_integral_; ///< Bulk integral of assembly class
83 
84  template < template<IntDim...> class DimAssembly>
85  friend class GenericAssembly;
86 };
87 
88 template <unsigned int dim, class TEqData>
89 class ReactionAssemblyDp : public AssemblyBase<dim>
90 {
91 public:
92  typedef typename TEqData::EqFields EqFields;
93  typedef TEqData EqData;
94 
95  static constexpr const char * name() { return "Dp_InitCondition_Assembly"; }
96 
97  /// Constructor.
98  ReactionAssemblyDp(EqData *eq_data, AssemblyInternals *asm_internals)
99  : AssemblyBase<dim>(0, asm_internals), eq_fields_(eq_data->eq_fields_.get()), eq_data_(eq_data),
100  mass_integral_( this->create_bulk_integral(this->quad_) ) {
101  this->used_fields_ += eq_fields_->porosity;
102  this->used_fields_ += eq_fields_->porosity_immobile;
103  this->used_fields_ += eq_fields_->diffusion_rate_immobile;
104  }
105 
106  /// Destructor.
108 
109  /// Initialize auxiliary vectors and other data members
110  void initialize() {}
111 
112 
113  /// Assemble integral over element
114  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
115  {
116  ASSERT_EQ(cell.dim(), dim).error("Dimension of element mismatch!");
117 
118  auto p = *( mass_integral_->points(element_patch_idx).begin() );
119 
120  // if porosity_immobile == 0 then mobile concentration stays the same
121  // and immobile concentration cannot change
122  por_immob_ = eq_fields_->porosity_immobile(p);
123  if (por_immob_ == 0.0) return;
124 
125  // get data from fields
126  dof_p0_ = cell.get_loc_dof_indices()[0];
127  por_mob_ = eq_fields_->porosity(p);
128  arma::Col<double> diff_vec(eq_data_->substances_.size());
129  for (sbi_=0; sbi_<eq_data_->substances_.size(); sbi_++) // Optimize: SWAP LOOPS
130  diff_vec[sbi_] = eq_fields_->diffusion_rate_immobile[sbi_](p);
131 
132  temp_exponent_ = (por_mob_ + por_immob_) / (por_mob_ * por_immob_) * eq_data_->time_->dt();
133 
134  for (sbi_ = 0; sbi_ < eq_data_->substances_.size(); sbi_++) //over all substances
135  {
136  exponent_ = diff_vec[sbi_] * temp_exponent_;
137  //previous values
138  previous_conc_mob_ = eq_fields_->conc_mobile_fe[sbi_]->vec().get(dof_p0_);
139  previous_conc_immob_ = eq_fields_->conc_immobile_fe[sbi_]->vec().get(dof_p0_);
140 
141  // ---compute average concentration------------------------------------------
143  / (por_mob_ + por_immob_);
144 
146 
147  // the following 2 conditions guarantee:
148  // 1) stability of forward Euler's method
149  // 2) the error of forward Euler's method will not be large
150  if(eq_data_->time_->dt() <= por_mob_*por_immob_/(max(diff_vec)*(por_mob_+por_immob_)) &&
151  conc_max_ <= (2*eq_data_->scheme_tolerance_/(exponent_*exponent_)*conc_average_)) // forward euler
152  {
153  temp_ = diff_vec[sbi_]*(previous_conc_immob_ - previous_conc_mob_) * eq_data_->time_->dt();
154  // ---compute concentration in mobile area
156 
157  // ---compute concentration in immobile area
159  }
160  else //analytic solution
161  {
162  temp_ = exp(-exponent_);
163  // ---compute concentration in mobile area
165 
166  // ---compute concentration in immobile area
168  }
169 
170  eq_fields_->conc_mobile_fe[sbi_]->vec().set(dof_p0_, conc_mob_);
171  eq_fields_->conc_immobile_fe[sbi_]->vec().set(dof_p0_, conc_immob_);
172  }
173  }
174 
175 
176 private:
177  /// Data objects shared with Elasticity
180 
181  /// Sub field set contains fields used in calculation.
183 
184  unsigned int sbi_; ///< Index of substance
185  IntIdx dof_p0_; ///< Index of local DOF
186  double conc_average_; ///< weighted (by porosity) average of concentration
187  double conc_mob_, conc_immob_; ///< new mobile and immobile concentration
188  double previous_conc_mob_, previous_conc_immob_; ///< mobile and immobile concentration in previous time step
189  double conc_max_; ///< difference between concentration and average concentration
190  double por_mob_, por_immob_; ///< mobile and immobile porosity
191  double exponent_, temp_exponent_, temp_; ///< Precomputed values
192  std::shared_ptr<BulkIntegralAcc<dim>> mass_integral_; ///< Bulk integral of assembly class
193 
194  template < template<IntDim...> class DimAssembly>
195  friend class GenericAssembly;
196 };
197 
198 template <unsigned int dim, class TEqData>
200 {
201 public:
202  typedef typename TEqData::EqFields EqFields;
203  typedef TEqData EqData;
204 
205  static constexpr const char * name() { return "Sorp_InitCondition_Assembly"; }
206 
207  /// Constructor.
209  : AssemblyBase<dim>(0, asm_internals), eq_fields_(eq_data->eq_fields_.get()), eq_data_(eq_data),
210  mass_integral_( this->create_bulk_integral(this->quad_) ) {
211  this->used_fields_ += eq_fields_->init_conc_solid;
212  }
213 
214  /// Destructor.
216 
217  /// Initialize auxiliary vectors and other data members
218  void initialize() {}
219 
220 
221  /// Assemble integral over element
222  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
223  {
224  ASSERT_EQ(cell.dim(), dim).error("Dimension of element mismatch!");
225 
226  dof_p0_ = cell.get_loc_dof_indices()[0];
227  auto p = *( mass_integral_->points(element_patch_idx).begin() );
228 
229  //setting initial solid concentration for substances involved in adsorption
230  for (unsigned int sbi = 0; sbi < eq_data_->n_substances_; sbi++)
231  {
232  eq_fields_->conc_solid_fe[ eq_data_->substance_global_idx_[sbi] ]->vec().set( dof_p0_, eq_fields_->init_conc_solid[sbi](p) );
233  }
234  }
235 
236 
237 private:
238  /// Data objects shared with Elasticity
241 
242  /// Sub field set contains fields used in calculation.
244 
245  IntIdx dof_p0_; ///< Index of local DOF
246  std::shared_ptr<BulkIntegralAcc<dim>> mass_integral_; ///< Bulk integral of assembly class
247 
248  template < template<IntDim...> class DimAssembly>
249  friend class GenericAssembly;
250 };
251 
252 template <unsigned int dim, class TEqData>
254 {
255 public:
256  typedef typename TEqData::EqFields EqFields;
257  typedef TEqData EqData;
258 
259  static constexpr const char * name() { return "Sorp_Reaction_Assembly"; }
260 
261  /// Constructor.
263  : AssemblyBase<dim>(0, asm_internals), eq_fields_(eq_data->eq_fields_.get()), eq_data_(eq_data),
264  mass_integral_( this->create_bulk_integral(this->quad_) ) {
265  this->used_fields_ += eq_fields_->scale_aqua;
266  this->used_fields_ += eq_fields_->scale_sorbed;
267  this->used_fields_ += eq_fields_->no_sorbing_surface_cond;
268  this->used_fields_ += eq_fields_->sorption_type;
269  this->used_fields_ += eq_fields_->distribution_coefficient;
270  this->used_fields_ += eq_fields_->isotherm_other;
271  }
272 
273  /// Destructor.
275 
276  /// Initialize auxiliary vectors and other data members
277  void initialize() {}
278 
279 
280  /// Assemble integral over element
281  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
282  {
283  ASSERT_EQ(cell.dim(), dim).error("Dimension of element mismatch!");
284 
285  unsigned int i_subst, subst_id;
286  auto p = *( mass_integral_->points(element_patch_idx).begin() );
287 
288  reg_idx_ = cell.elm().region().bulk_idx();
289  dof_p0_ = cell.get_loc_dof_indices()[0];
290 
291  double scale_aqua = eq_fields_->scale_aqua(p);
292  double scale_sorbed = eq_fields_->scale_sorbed(p);
293  double no_sorbing_surface_cond = eq_fields_->no_sorbing_surface_cond(p);
294 
295  for(i_subst = 0; i_subst < eq_data_->n_substances_; i_subst++)
296  {
297  subst_id = eq_data_->substance_global_idx_[i_subst];
298 
299  Isotherm & isotherm = eq_data_->isotherms[reg_idx_][i_subst];
300 
301  bool limited_solubility_on = eq_data_->solubility_vec_[i_subst] > 0.0;
302 
303  // in case of no sorbing surface, set isotherm type None
304  if( no_sorbing_surface_cond <= std::numeric_limits<double>::epsilon())
305  {
306  isotherm.reinit(Isotherm::none, false, eq_data_->solvent_density_,
307  scale_aqua, scale_sorbed,
308  0,0,0);
309  } else {
310  if ( scale_sorbed <= 0.0)
311  THROW( SorptionBase::ExcNotPositiveScaling() << SorptionBase::EI_Subst(i_subst) );
312 
313  isotherm.reinit(Isotherm::SorptionType(eq_fields_->sorption_type[i_subst](p)),
314  limited_solubility_on, eq_data_->solvent_density_,
315  scale_aqua, scale_sorbed,
316  eq_data_->solubility_vec_[i_subst],
317  eq_fields_->distribution_coefficient[i_subst](p),
318  eq_fields_->isotherm_other[i_subst](p));
319  }
320 
321  double c_aqua = eq_fields_->conc_mobile_fe[subst_id]->vec().get(dof_p0_);
322  double c_sorbed = eq_fields_->conc_solid_fe[subst_id]->vec().get(dof_p0_);
323  isotherm.compute(c_aqua, c_sorbed);
324  eq_fields_->conc_mobile_fe[subst_id]->vec().set(dof_p0_, c_aqua);
325  eq_fields_->conc_solid_fe[subst_id]->vec().set(dof_p0_, c_sorbed);
326 
327  // update maximal concentration per region (optimization for interpolation)
328  if(eq_data_->table_limit_[i_subst] < 0)
329  eq_data_->max_conc[reg_idx_][i_subst] = std::max(eq_data_->max_conc[reg_idx_][i_subst],
330  eq_fields_->conc_mobile_fe[subst_id]->vec().get(dof_p0_));
331  }
332  }
333 
334 
335 private:
336  /// Data objects shared with Elasticity
339 
340  /// Sub field set contains fields used in calculation.
342 
343  IntIdx dof_p0_; ///< Index of local DOF
344  int reg_idx_; ///< Bulk region idx
345  //unsigned int sbi_; ///< Index of substance
346  std::shared_ptr<BulkIntegralAcc<dim>> mass_integral_; ///< Bulk integral of assembly class
347 
348 
349  template < template<IntDim...> class DimAssembly>
350  friend class GenericAssembly;
351 };
352 
353 #endif /* ASSEMBLY_REACTION_HH_ */
354 
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:333
Quadrature * quad_
Quadrature used in assembling methods.
std::shared_ptr< BulkIntegralAcc< dim > > create_bulk_integral(Quadrature *quad)
Cell accessor allow iterate over DOF handler cells.
LocDofVec get_loc_dof_indices() const
Returns the local indices of dofs associated to the cell on the local process.
unsigned int dim() const
Return dimension of element appropriate to cell.
ElementAccessor< 3 > elm() const
Return ElementAccessor to element of loc_ele_idx_.
Region region() const
Definition: accessors.hh:198
Container for various descendants of FieldCommonBase.
Definition: field_set.hh:159
Generic class of assemblation.
EqFields * eq_fields_
Data objects shared with Elasticity.
~InitConditionAssemblyDp()
Destructor.
void initialize()
Initialize auxiliary vectors and other data members.
InitConditionAssemblyDp(EqData *eq_data, AssemblyInternals *asm_internals)
Constructor.
static constexpr const char * name()
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
Assemble integral over element.
IntIdx dof_p0_
Index of local DOF.
TEqData::EqFields EqFields
FieldSet used_fields_
Sub field set contains fields used in calculation.
std::shared_ptr< BulkIntegralAcc< dim > > mass_integral_
Bulk integral of assembly class.
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
Assemble integral over element.
InitConditionAssemblySorp(EqData *eq_data, AssemblyInternals *asm_internals)
Constructor.
void initialize()
Initialize auxiliary vectors and other data members.
static constexpr const char * name()
FieldSet used_fields_
Sub field set contains fields used in calculation.
EqFields * eq_fields_
Data objects shared with Elasticity.
std::shared_ptr< BulkIntegralAcc< dim > > mass_integral_
Bulk integral of assembly class.
IntIdx dof_p0_
Index of local DOF.
void compute(double &c_aqua, double &c_sorbed)
Definition: isotherm.cc:68
SorptionType
Type of adsorption isotherm.
Definition: isotherm.hh:174
void reinit(enum SorptionType sorption_type, bool limited_solubility_on, double aqua_density, double scale_aqua, double scale_sorbed, double c_aqua_limit, double mult_coef, double second_coef)
Definition: isotherm.cc:44
double conc_max_
difference between concentration and average concentration
EqFields * eq_fields_
Data objects shared with Elasticity.
double temp_
Precomputed values.
double conc_immob_
new mobile and immobile concentration
double conc_average_
weighted (by porosity) average of concentration
~ReactionAssemblyDp()
Destructor.
IntIdx dof_p0_
Index of local DOF.
double previous_conc_immob_
mobile and immobile concentration in previous time step
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
Assemble integral over element.
static constexpr const char * name()
FieldSet used_fields_
Sub field set contains fields used in calculation.
TEqData::EqFields EqFields
void initialize()
Initialize auxiliary vectors and other data members.
ReactionAssemblyDp(EqData *eq_data, AssemblyInternals *asm_internals)
Constructor.
std::shared_ptr< BulkIntegralAcc< dim > > mass_integral_
Bulk integral of assembly class.
double por_immob_
mobile and immobile porosity
unsigned int sbi_
Index of substance.
std::shared_ptr< BulkIntegralAcc< dim > > mass_integral_
Bulk integral of assembly class.
TEqData::EqFields EqFields
static constexpr const char * name()
~ReactionAssemblySorp()
Destructor.
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
Assemble integral over element.
ReactionAssemblySorp(EqData *eq_data, AssemblyInternals *asm_internals)
Constructor.
int reg_idx_
Bulk region idx.
void initialize()
Initialize auxiliary vectors and other data members.
EqFields * eq_fields_
Data objects shared with Elasticity.
FieldSet used_fields_
Sub field set contains fields used in calculation.
IntIdx dof_p0_
Index of local DOF.
unsigned int bulk_idx() const
Returns index of the region in the bulk set.
Definition: region.hh:90
Class Dual_por_exchange implements the model of dual porosity.
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,...
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
int IntIdx
Definition: index_types.hh:25
unsigned int IntDim
A dimension index type.
Definition: mixed.hh:19
Definitions of particular quadrature rules on simplices.
Holds common data shared between GenericAssemblz and Assembly<dim> classes.