Flow123d  release_2.2.0-48-gb04af7f
sorption.cc
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 sorption.cc
15  * @brief
16  */
17 
18 #include <vector>
19 #include <limits>
20 
21 #include "reaction/isotherm.hh"
22 #include "reaction/sorption.hh"
23 #include "system/sys_profiler.hh"
24 #include "mesh/accessors.hh"
25 #include "input/factory.hh"
26 
27 FLOW123D_FORCE_LINK_IN_CHILD(sorptionMobile)
28 FLOW123D_FORCE_LINK_IN_CHILD(sorptionImmobile)
30 
31 
32 /********************************* SORPTION_SIMPLE *********************************************************/
33 /********************************* *********************************************************/
34 
35 const IT::Record & SorptionSimple::get_input_type() {
36  return IT::Record("Sorption", "Sorption model in the reaction term of transport.")
39  .declare_key("output", make_output_type("Sorption", "conc_solid", "Concentration solution in the solid phase."),
40  IT::Default("{ \"fields\": [ \"conc_solid\" ] }"),
41  "Setting of the fields output.")
42 
43  .close();
44 }
45 
47  : SorptionBase(init_mesh, in_rec)
48 {
49  data_ = new EqData("conc_solid", "Concentration solution in the solid phase.");
50  this->eq_data_ = data_;
51 }
52 
53 const int SorptionSimple::registrar =
54  Input::register_class< SorptionSimple, Mesh &, Input::Record >("Sorption") +
56 
58 {}
59 
61 {
62  START_TIMER("SorptionSimple::isotherm_reinit");
63 
64  double rock_density = data_->rock_density.value(elem.centre(),elem);
65  double por_m = data_->porosity.value(elem.centre(),elem);
66 
67  for(unsigned int i_subst = 0; i_subst < n_substances_; i_subst++)
68  {
69  double mult_coef = data_->distribution_coefficient[i_subst].value(elem.centre(),elem);
70  double second_coef = data_->isotherm_other[i_subst].value(elem.centre(),elem);
71  Isotherm & isotherm = isotherms_vec[i_subst];
72 
73  //scales are different for the case of sorption in mobile and immobile pores
74  double scale_aqua = por_m,
75  scale_sorbed = (1 - por_m) * rock_density;
76 
77  bool limited_solubility_on = false;
78  double table_limit;
79  if (solubility_vec_[i_subst] <= 0.0) {
80  limited_solubility_on = false;
81  table_limit=table_limit_[i_subst];
82  } else {
83  limited_solubility_on = true;
84  table_limit=solubility_vec_[i_subst];
85  }
86 
87  if( (1-por_m) <= std::numeric_limits<double>::epsilon()) //means there is no sorbing surface
88  {
89  isotherm.reinit(Isotherm::none, false, solvent_density_, scale_aqua, scale_sorbed,table_limit,0,0);
90  continue;
91  }
92 
93  if ( scale_sorbed <= 0.0)
94  xprintf(UsrErr, "Scaling parameter in sorption is not positive. Check the input for rock density and molar mass of %d. substance.",i_subst);
95 
96  isotherm.reinit(Isotherm::SorptionType(data_->sorption_type[i_subst].value(elem.centre(),elem)), limited_solubility_on,
97  solvent_density_, scale_aqua, scale_sorbed, table_limit, mult_coef, second_coef);
98 
99  }
100 
101  END_TIMER("SorptionSimple::isotherm_reinit");
102 }
103 
104 
105 /*********************************** *********************************************************/
106 /*********************************** SORPTION_DUAL *********************************************************/
107 /*********************************** *********************************************************/
108 
110  const string &output_conc_name,
111  const string &output_conc_desc)
112  : SorptionBase(init_mesh, in_rec)
113 {
114  data_ = new EqData(output_conc_name, output_conc_desc);
117  .name("porosity_immobile")
118  .set_limits(0.0);
119  this->eq_data_ = data_;
120 }
121 
123 {}
124 
125 /********************************** *******************************************************/
126 /*********************************** SORPTION_MOBILE *******************************************************/
127 /********************************** *******************************************************/
128 
130  return IT::Record("SorptionMobile", "Sorption model in the mobile zone, following the dual porosity model.")
133  .declare_key("output", make_output_type("SorptionMobile", "conc_solid", "Concentration solution in the solid mobile phase."),
134  IT::Default("{ \"fields\": [ \"conc_solid\" ] }"),
135  "Setting of the fields output.")
136 
137  .close();
138 }
139 
140 
141 const int SorptionMob::registrar =
142  Input::register_class< SorptionMob, Mesh &, Input::Record >("SorptionMobile") +
144 
145 
147  : SorptionDual(init_mesh, in_rec, "conc_solid", "Concentration solution in the solid mobile phase.")
148 {}
149 
150 
152 {}
153 
154 /*
155 double SorptionMob::compute_sorbing_scale(double por_m, double por_imm)
156 {
157  double phi = por_m/(por_m + por_imm);
158  return phi;
159 }
160 */
161 
163 {
164  START_TIMER("SorptionMob::isotherm_reinit");
165 
166  double rock_density = data_->rock_density.value(elem.centre(),elem);
167 
168  double por_m = data_->porosity.value(elem.centre(),elem);
169  double por_imm = immob_porosity_.value(elem.centre(),elem);
170  double phi = por_m/(por_m + por_imm);
171 
172  for(unsigned int i_subst = 0; i_subst < n_substances_; i_subst++)
173  {
174  double mult_coef = data_->distribution_coefficient[i_subst].value(elem.centre(),elem);
175  double second_coef = data_->isotherm_other[i_subst].value(elem.centre(),elem);
176  Isotherm & isotherm = isotherms_vec[i_subst];
177 
178  //scales are different for the case of sorption in mobile and immobile pores
179  double scale_aqua = por_m,
180  scale_sorbed = phi * (1 - por_m - por_imm) * rock_density;
181 
182  bool limited_solubility_on;
183  double table_limit;
184  if (solubility_vec_[i_subst] <= 0.0) {
185  limited_solubility_on = false;
186  table_limit=table_limit_[i_subst];
187 
188  } else {
189  limited_solubility_on = true;
190  table_limit=solubility_vec_[i_subst];
191  }
192 
193  if( (1-por_m-por_imm) <= std::numeric_limits<double>::epsilon()) //means there is no sorbing surface
194  {
195  isotherm.reinit(Isotherm::none, false, solvent_density_, scale_aqua, scale_sorbed,table_limit,0,0);
196  continue;
197  }
198 
199  if ( scale_sorbed <= 0.0)
200  xprintf(UsrErr, "Scaling parameter in sorption is not positive. Check the input for rock density and molar mass of %d. substance.",i_subst);
201 
202  isotherm.reinit(Isotherm::SorptionType(data_->sorption_type[i_subst].value(elem.centre(),elem)), limited_solubility_on,
203  solvent_density_, scale_aqua, scale_sorbed, table_limit, mult_coef, second_coef);
204 
205  }
206 
207  END_TIMER("SorptionMob::isotherm_reinit");
208 }
209 
210 
211 /*********************************** *****************************************************/
212 /*********************************** SORPTION_IMMOBILE *****************************************************/
213 /*********************************** *****************************************************/
214 
216  return IT::Record("SorptionImmobile", "Sorption model in the immobile zone, following the dual porosity model.")
219  .declare_key("output", make_output_type("SorptionImmobile", "conc_immobile_solid", "Concentration solution in the solid immobile phase."),
220  IT::Default("{ \"fields\": [ \"conc_immobile_solid\" ] }"),
221  "Setting of the fields output.")
222 
223  .close();
224 }
225 
226 const int SorptionImmob::registrar =
227  Input::register_class< SorptionImmob, Mesh &, Input::Record >("SorptionImmobile") +
229 
231 : SorptionDual(init_mesh, in_rec, "conc_immobile_solid", "Concentration solution in the solid immobile phase.")
232 {}
233 
235 {}
236 
237 /*
238 double SorptionImmob::compute_sorbing_scale(double por_m, double por_imm)
239 {
240  double phi = por_imm / (por_m + por_imm);
241  return phi;
242 }
243 */
244 
246 {
247  START_TIMER("SorptionImmob::isotherm_reinit");
248 
249  double rock_density = data_->rock_density.value(elem.centre(),elem);
250 
251  double por_m = data_->porosity.value(elem.centre(),elem);
252  double por_imm = immob_porosity_.value(elem.centre(),elem);
253  double phi = por_m/(por_m + por_imm);
254 
255  for(unsigned int i_subst = 0; i_subst < n_substances_; i_subst++)
256  {
257  double mult_coef = data_->distribution_coefficient[i_subst].value(elem.centre(),elem);
258  double second_coef = data_->isotherm_other[i_subst].value(elem.centre(),elem);
259  Isotherm & isotherm = isotherms_vec[i_subst];
260 
261  //scales are different for the case of sorption in mobile and immobile pores
262  double scale_aqua = por_imm,
263  scale_sorbed = (1 - phi) * (1 - por_m - por_imm) * rock_density;
264 
265  bool limited_solubility_on;
266  double table_limit;
267  if (solubility_vec_[i_subst] <= 0.0) {
268  limited_solubility_on = false;
269  table_limit=table_limit_[i_subst];
270 
271  } else {
272  limited_solubility_on = true;
273  table_limit=solubility_vec_[i_subst];
274  }
275 
276  if( (1-por_m-por_imm) <= std::numeric_limits<double>::epsilon()) //means there is no sorbing surface
277  {
278  isotherm.reinit(Isotherm::none, false, solvent_density_, scale_aqua, scale_sorbed,0,0,0);
279  continue;
280  }
281 
282  if ( scale_sorbed <= 0.0)
283  xprintf(UsrErr, "Scaling parameter in sorption is not positive. Check the input for rock density and molar mass of %d. substance.",i_subst);
284 
285  isotherm.reinit(Isotherm::SorptionType(data_->sorption_type[i_subst].value(elem.centre(),elem)), limited_solubility_on,
286  solvent_density_, scale_aqua, scale_sorbed, table_limit, mult_coef, second_coef);
287 
288  }
289 
290  END_TIMER("SorptionImmob::isotherm_reinit");
291 }
FieldSet * eq_data_
Definition: equation.hh:232
double solvent_density_
~SorptionDual(void)
Destructor.
Definition: sorption.cc:122
unsigned int size() const
Returns number of keys in the Record.
Definition: type_record.hh:598
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
FieldCommon & flags_add(FieldFlag::Flags::Mask mask)
static Input::Type::Instance make_output_type(const string &equation_name, const string &output_field_name, const string &output_field_desc)
~SorptionMob(void)
Destructor.
Definition: sorption.cc:151
Abstract class of sorption model in case dual porosity is considered.
Definition: sorption.hh:65
Field< 3, FieldValue< 3 >::Scalar > rock_density
Rock matrix density.
void isotherm_reinit(std::vector< Isotherm > &isotherms_vec, const ElementAccessor< 3 > &elem) override
Reinitializes the isotherm.
Definition: sorption.cc:162
Definition: mesh.h:97
static const Input::Type::Record & get_input_type()
Definition: sorption.cc:35
static Input::Type::Abstract & it_abstract_mobile_term()
SorptionDual(Mesh &init_mesh, Input::Record in_rec, const string &output_conc_name, const string &output_conc_desc)
Constructor.
Definition: sorption.cc:109
std::vector< double > table_limit_
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.hh:334
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:303
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:195
MultiField< 3, FieldValue< 3 >::Scalar > isotherm_other
Langmuir sorption coeficients alpha (in fraction c_s = omega * (alpha*c_a)/(1- alpha*c_a)).
Field< 3, FieldValue< 3 >::Scalar > porosity
Porosity field copied from transport.
Field< 3, FieldValue< 3 >::Scalar > immob_porosity_
Definition: sorption.hh:86
static constexpr Mask input_copy
Definition: field_flag.hh:44
std::vector< double > solubility_vec_
Accessor to the data with type Type::Record.
Definition: accessors.hh:292
#define xprintf(...)
Definition: system.hh:92
#define START_TIMER(tag)
Starts a timer with specified tag.
static const Input::Type::Record & get_input_type()
Definition: sorption.cc:129
static Input::Type::Abstract & it_abstract_immobile_term()
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm) const
Definition: field.hh:362
Record & declare_key(const string &key, std::shared_ptr< TypeBase > type, const Default &default_value, const string &description, TypeBase::attribute_map key_attributes=TypeBase::attribute_map())
Declares a new key of the Record.
Definition: type_record.cc:490
MultiField< 3, FieldValue< 3 >::Enum > sorption_type
Discrete need Selection for initialization.
SorptionType
Type of adsorption isotherm.
Definition: isotherm.hh:170
Record & copy_keys(const Record &other)
Copy keys from other record.
Definition: type_record.cc:215
static Input::Type::Abstract & it_abstract_term()
Definition: system.hh:64
const double epsilon
Definition: mathfce.h:23
SorptionImmob(Mesh &init_mesh, Input::Record in_rec)
Constructor.
Definition: sorption.cc:230
static const int registrar
Registrar of class to factory.
Definition: sorption.hh:58
void isotherm_reinit(std::vector< Isotherm > &isotherms, const ElementAccessor< 3 > &elm) override
Reinitializes the isotherm.
Definition: sorption.cc:60
SorptionSimple(Mesh &init_mesh, Input::Record in_rec)
Constructor.
Definition: sorption.cc:46
static const int registrar
Registrar of class to factory.
Definition: sorption.hh:144
~SorptionSimple(void)
Destructor.
Definition: sorption.cc:57
FieldCommon & name(const string &name)
Definition: field_common.hh:97
static const int registrar
Registrar of class to factory.
Definition: sorption.hh:116
#define END_TIMER(tag)
Ends a timer with specified tag.
arma::vec::fixed< spacedim > centre() const
Definition: accessors.hh:91
Simple sorption model without dual porosity.
Definition: sorption.hh:39
Record type proxy class.
Definition: type_record.hh:182
static const Input::Type::Record & get_input_type()
FieldCommon & set_limits(double min, double max=std::numeric_limits< double >::max())
MultiField< 3, FieldValue< 3 >::Scalar > distribution_coefficient
Multiplication coefficients (k, omega) for all types of isotherms.
unsigned int n_substances_
EqData * data_
Pointer to equation data. The object is constructed in descendants.
void isotherm_reinit(std::vector< Isotherm > &isotherms_vec, const ElementAccessor< 3 > &elem) override
Reinitializes the isotherm.
Definition: sorption.cc:245
Other possible transformation of coordinates:
static const Input::Type::Record & get_input_type()
Definition: sorption.cc:215
This file contains classes representing sorption model. Sorption model can be computed both in case t...
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Definition: global_defs.h:180
SorptionMob(Mesh &init_mesh, Input::Record in_rec)
Constructor.
Definition: sorption.cc:146
~SorptionImmob(void)
Destructor.
Definition: sorption.cc:234