Flow123d  JS_constraints-e651b99
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"
27 //#include "coupling/balance.hh"
28 #include "fem/element_cache_map.hh"
29 
30 
31 
32 template <unsigned int dim, class TEqData>
34 {
35 public:
36  typedef typename TEqData::EqFields EqFields;
37  typedef TEqData EqData;
38 
39  static constexpr const char * name() { return "Dp_InitCondition_Assembly"; }
40 
41  /// Constructor.
43  : AssemblyBasePatch<dim>(0, asm_internals), eq_fields_(eq_data->eq_fields_.get()), eq_data_(eq_data),
44  mass_integral_( this->create_bulk_integral(this->quad_) ) {
45  this->used_fields_ += eq_fields_->init_conc_immobile;
46  }
47 
48  /// Destructor.
50 
51  /// Initialize auxiliary vectors and other data members
52  void initialize() {}
53 
54 
55  /// Assemble integral over element
56  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
57  {
58  ASSERT_EQ(cell.dim(), dim).error("Dimension of element mismatch!");
59 
60  dof_p0_ = cell.get_loc_dof_indices()[0];
61  auto p = *( mass_integral_->points(element_patch_idx).begin() );
62 
63  //setting initial solid concentration for substances involved in adsorption
64  for (unsigned int sbi = 0; sbi < eq_data_->substances_.size(); sbi++)
65  {
66  eq_fields_->conc_immobile_fe[sbi]->vec().set( dof_p0_, eq_fields_->init_conc_immobile[sbi](p) );
67  }
68  }
69 
70 
71 private:
72  /// Data objects shared with Elasticity
75 
76  /// Sub field set contains fields used in calculation.
78 
79  IntIdx dof_p0_; ///< Index of local DOF
80 
81  std::shared_ptr<BulkIntegralAcc<dim>> mass_integral_; ///< Bulk integral of assembly class
82 
83  template < template<IntDim...> class DimAssembly>
84  friend class GenericAssembly;
85 };
86 
87 template <unsigned int dim, class TEqData>
89 {
90 public:
91  typedef typename TEqData::EqFields EqFields;
92  typedef TEqData EqData;
93 
94  static constexpr const char * name() { return "Dp_InitCondition_Assembly"; }
95 
96  /// Constructor.
97  ReactionAssemblyDp(EqData *eq_data, AssemblyInternals *asm_internals)
98  : AssemblyBasePatch<dim>(0, asm_internals), eq_fields_(eq_data->eq_fields_.get()), eq_data_(eq_data),
99  mass_integral_( this->create_bulk_integral(this->quad_) ) {
100  this->used_fields_ += eq_fields_->porosity;
101  this->used_fields_ += eq_fields_->porosity_immobile;
102  this->used_fields_ += eq_fields_->diffusion_rate_immobile;
103  }
104 
105  /// Destructor.
107 
108  /// Initialize auxiliary vectors and other data members
109  void initialize() {}
110 
111 
112  /// Assemble integral over element
113  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
114  {
115  ASSERT_EQ(cell.dim(), dim).error("Dimension of element mismatch!");
116 
117  auto p = *( mass_integral_->points(element_patch_idx).begin() );
118 
119  // if porosity_immobile == 0 then mobile concentration stays the same
120  // and immobile concentration cannot change
121  por_immob_ = eq_fields_->porosity_immobile(p);
122  if (por_immob_ == 0.0) return;
123 
124  // get data from fields
125  dof_p0_ = cell.get_loc_dof_indices()[0];
126  por_mob_ = eq_fields_->porosity(p);
127  arma::Col<double> diff_vec(eq_data_->substances_.size());
128  for (sbi_=0; sbi_<eq_data_->substances_.size(); sbi_++) // Optimize: SWAP LOOPS
129  diff_vec[sbi_] = eq_fields_->diffusion_rate_immobile[sbi_](p);
130 
131  temp_exponent_ = (por_mob_ + por_immob_) / (por_mob_ * por_immob_) * eq_data_->time_->dt();
132 
133  for (sbi_ = 0; sbi_ < eq_data_->substances_.size(); sbi_++) //over all substances
134  {
135  exponent_ = diff_vec[sbi_] * temp_exponent_;
136  //previous values
137  previous_conc_mob_ = eq_fields_->conc_mobile_fe[sbi_]->vec().get(dof_p0_);
138  previous_conc_immob_ = eq_fields_->conc_immobile_fe[sbi_]->vec().get(dof_p0_);
139 
140  // ---compute average concentration------------------------------------------
142  / (por_mob_ + por_immob_);
143 
145 
146  // the following 2 conditions guarantee:
147  // 1) stability of forward Euler's method
148  // 2) the error of forward Euler's method will not be large
149  if(eq_data_->time_->dt() <= por_mob_*por_immob_/(max(diff_vec)*(por_mob_+por_immob_)) &&
150  conc_max_ <= (2*eq_data_->scheme_tolerance_/(exponent_*exponent_)*conc_average_)) // forward euler
151  {
152  temp_ = diff_vec[sbi_]*(previous_conc_immob_ - previous_conc_mob_) * eq_data_->time_->dt();
153  // ---compute concentration in mobile area
155 
156  // ---compute concentration in immobile area
158  }
159  else //analytic solution
160  {
161  temp_ = exp(-exponent_);
162  // ---compute concentration in mobile area
164 
165  // ---compute concentration in immobile area
167  }
168 
169  eq_fields_->conc_mobile_fe[sbi_]->vec().set(dof_p0_, conc_mob_);
170  eq_fields_->conc_immobile_fe[sbi_]->vec().set(dof_p0_, conc_immob_);
171  }
172  }
173 
174 
175 private:
176  /// Data objects shared with Elasticity
179 
180  /// Sub field set contains fields used in calculation.
182 
183  unsigned int sbi_; ///< Index of substance
184  IntIdx dof_p0_; ///< Index of local DOF
185  double conc_average_; ///< weighted (by porosity) average of concentration
186  double conc_mob_, conc_immob_; ///< new mobile and immobile concentration
187  double previous_conc_mob_, previous_conc_immob_; ///< mobile and immobile concentration in previous time step
188  double conc_max_; ///< difference between concentration and average concentration
189  double por_mob_, por_immob_; ///< mobile and immobile porosity
190  double exponent_, temp_exponent_, temp_; ///< Precomputed values
191  std::shared_ptr<BulkIntegralAcc<dim>> mass_integral_; ///< Bulk integral of assembly class
192 
193  template < template<IntDim...> class DimAssembly>
194  friend class GenericAssembly;
195 };
196 
197 template <unsigned int dim, class TEqData>
199 {
200 public:
201  typedef typename TEqData::EqFields EqFields;
202  typedef TEqData EqData;
203 
204  static constexpr const char * name() { return "Sorp_InitCondition_Assembly"; }
205 
206  /// Constructor.
208  : AssemblyBasePatch<dim>(0, asm_internals), eq_fields_(eq_data->eq_fields_.get()), eq_data_(eq_data),
209  mass_integral_( this->create_bulk_integral(this->quad_) ) {
210  this->used_fields_ += eq_fields_->init_conc_solid;
211  }
212 
213  /// Destructor.
215 
216  /// Initialize auxiliary vectors and other data members
217  void initialize() {}
218 
219 
220  /// Assemble integral over element
221  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
222  {
223  ASSERT_EQ(cell.dim(), dim).error("Dimension of element mismatch!");
224 
225  dof_p0_ = cell.get_loc_dof_indices()[0];
226  auto p = *( mass_integral_->points(element_patch_idx).begin() );
227 
228  //setting initial solid concentration for substances involved in adsorption
229  for (unsigned int sbi = 0; sbi < eq_data_->n_substances_; sbi++)
230  {
231  eq_fields_->conc_solid_fe[ eq_data_->substance_global_idx_[sbi] ]->vec().set( dof_p0_, eq_fields_->init_conc_solid[sbi](p) );
232  }
233  }
234 
235 
236 private:
237  /// Data objects shared with Elasticity
240 
241  /// Sub field set contains fields used in calculation.
243 
244  IntIdx dof_p0_; ///< Index of local DOF
245  std::shared_ptr<BulkIntegralAcc<dim>> mass_integral_; ///< Bulk integral of assembly class
246 
247  template < template<IntDim...> class DimAssembly>
248  friend class GenericAssembly;
249 };
250 
251 template <unsigned int dim, class TEqData>
253 {
254 public:
255  typedef typename TEqData::EqFields EqFields;
256  typedef TEqData EqData;
257 
258  static constexpr const char * name() { return "Sorp_Reaction_Assembly"; }
259 
260  /// Constructor.
262  : AssemblyBasePatch<dim>(0, asm_internals), eq_fields_(eq_data->eq_fields_.get()), eq_data_(eq_data),
263  mass_integral_( this->create_bulk_integral(this->quad_) ) {
264  this->used_fields_ += eq_fields_->scale_aqua;
265  this->used_fields_ += eq_fields_->scale_sorbed;
266  this->used_fields_ += eq_fields_->no_sorbing_surface_cond;
267  this->used_fields_ += eq_fields_->sorption_type;
268  this->used_fields_ += eq_fields_->distribution_coefficient;
269  this->used_fields_ += eq_fields_->isotherm_other;
270  }
271 
272  /// Destructor.
274 
275  /// Initialize auxiliary vectors and other data members
276  void initialize() {}
277 
278 
279  /// Assemble integral over element
280  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
281  {
282  ASSERT_EQ(cell.dim(), dim).error("Dimension of element mismatch!");
283 
284  unsigned int i_subst, subst_id;
285  auto p = *( mass_integral_->points(element_patch_idx).begin() );
286 
287  reg_idx_ = cell.elm().region().bulk_idx();
288  dof_p0_ = cell.get_loc_dof_indices()[0];
289 
290  double scale_aqua = eq_fields_->scale_aqua(p);
291  double scale_sorbed = eq_fields_->scale_sorbed(p);
292  double no_sorbing_surface_cond = eq_fields_->no_sorbing_surface_cond(p);
293 
294  for(i_subst = 0; i_subst < eq_data_->n_substances_; i_subst++)
295  {
296  subst_id = eq_data_->substance_global_idx_[i_subst];
297 
298  Isotherm & isotherm = eq_data_->isotherms[reg_idx_][i_subst];
299 
300  bool limited_solubility_on = eq_data_->solubility_vec_[i_subst] > 0.0;
301 
302  // in case of no sorbing surface, set isotherm type None
303  if( no_sorbing_surface_cond <= std::numeric_limits<double>::epsilon())
304  {
305  isotherm.reinit(Isotherm::none, false, eq_data_->solvent_density_,
306  scale_aqua, scale_sorbed,
307  0,0,0);
308  } else {
309  if ( scale_sorbed <= 0.0)
310  THROW( SorptionBase::ExcNotPositiveScaling() << SorptionBase::EI_Subst(i_subst) );
311 
312  isotherm.reinit(Isotherm::SorptionType(eq_fields_->sorption_type[i_subst](p)),
313  limited_solubility_on, eq_data_->solvent_density_,
314  scale_aqua, scale_sorbed,
315  eq_data_->solubility_vec_[i_subst],
316  eq_fields_->distribution_coefficient[i_subst](p),
317  eq_fields_->isotherm_other[i_subst](p));
318  }
319 
320  double c_aqua = eq_fields_->conc_mobile_fe[subst_id]->vec().get(dof_p0_);
321  double c_sorbed = eq_fields_->conc_solid_fe[subst_id]->vec().get(dof_p0_);
322  isotherm.compute(c_aqua, c_sorbed);
323  eq_fields_->conc_mobile_fe[subst_id]->vec().set(dof_p0_, c_aqua);
324  eq_fields_->conc_solid_fe[subst_id]->vec().set(dof_p0_, c_sorbed);
325 
326  // update maximal concentration per region (optimization for interpolation)
327  if(eq_data_->table_limit_[i_subst] < 0)
328  eq_data_->max_conc[reg_idx_][i_subst] = std::max(eq_data_->max_conc[reg_idx_][i_subst],
329  eq_fields_->conc_mobile_fe[subst_id]->vec().get(dof_p0_));
330  }
331  }
332 
333 
334 private:
335  /// Data objects shared with Elasticity
338 
339  /// Sub field set contains fields used in calculation.
341 
342  IntIdx dof_p0_; ///< Index of local DOF
343  int reg_idx_; ///< Bulk region idx
344  //unsigned int sbi_; ///< Index of substance
345  std::shared_ptr<BulkIntegralAcc<dim>> mass_integral_; ///< Bulk integral of assembly class
346 
347 
348  template < template<IntDim...> class DimAssembly>
349  friend class GenericAssembly;
350 };
351 
352 #endif /* ASSEMBLY_REACTION_HH_ */
353 
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:333
std::shared_ptr< BulkIntegralAcc< dim > > create_bulk_integral(Quadrature *quad)
Quadrature * quad_
Quadrature used in assembling methods.
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:160
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.
#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.