Flow123d  last_with_con_2.0.0-4-g42e6930
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_fields", IT::Array(make_output_selection("conc_solid", "Sorption_Output")),
40  // IT::Default("\"conc_solid\""), "List of fields to write to output stream.")
41  .declare_key("output", make_output_type("Sorption", "conc_solid"),
42  IT::Default("{ \"fields\": [ \"conc_solid\" ] }"),
43  "Setting of the fields output.")
44 
45  .close();
46 }
47 
49  : SorptionBase(init_mesh, in_rec)
50 {
51  data_ = new EqData("conc_solid");
52  this->eq_data_ = data_;
53  //output_selection = make_output_selection(
54  // "SorptionSimple_output_fields",
55  // "Selection of field names of Simple Sorption model available for output.");
56 }
57 
58 const int SorptionSimple::registrar =
59  Input::register_class< SorptionSimple, Mesh &, Input::Record >("Sorption") +
61 
63 {}
64 
66 {
67  START_TIMER("SorptionSimple::isotherm_reinit");
68 
69  double rock_density = data_->rock_density.value(elem.centre(),elem);
70  double por_m = data_->porosity.value(elem.centre(),elem);
71 
72  // List of types of isotherms in particular regions
73  arma::uvec adsorption_type = data_->sorption_type.value(elem.centre(),elem);
74  arma::Col<double> mult_coef_vec = data_->isotherm_mult.value(elem.centre(),elem);
75  arma::Col<double> second_coef_vec = data_->isotherm_other.value(elem.centre(),elem);
76 
77  for(unsigned int i_subst = 0; i_subst < n_substances_; i_subst++)
78  {
79  double mult_coef = mult_coef_vec[i_subst];
80  double second_coef = second_coef_vec[i_subst];
81  Isotherm & isotherm = isotherms_vec[i_subst];
82 
83  //scales are different for the case of sorption in mobile and immobile pores
84  double scale_aqua = por_m,
85  scale_sorbed = (1 - por_m) * rock_density * substances_[substance_global_idx_[i_subst]].molar_mass();
86 
87  bool limited_solubility_on = false;
88  double table_limit;
89  if (solubility_vec_[i_subst] <= 0.0) {
90  limited_solubility_on = false;
91  table_limit=table_limit_[i_subst];
92  } else {
93  limited_solubility_on = true;
94  table_limit=solubility_vec_[i_subst];
95  }
96 
97  if( (1-por_m) <= std::numeric_limits<double>::epsilon()) //means there is no sorbing surface
98  {
99  isotherm.reinit(Isotherm::none, false, solvent_density_, scale_aqua, scale_sorbed,table_limit,0,0);
100  continue;
101  }
102 
103  if ( scale_sorbed <= 0.0)
104  xprintf(UsrErr, "Scaling parameter in sorption is not positive. Check the input for rock density and molar mass of %d. substance.",i_subst);
105 
106  isotherm.reinit(Isotherm::SorptionType(adsorption_type[i_subst]), limited_solubility_on,
107  solvent_density_, scale_aqua, scale_sorbed, table_limit, mult_coef, second_coef);
108 
109  }
110 
111  END_TIMER("SorptionSimple::isotherm_reinit");
112 }
113 
114 
115 /*********************************** *********************************************************/
116 /*********************************** SORPTION_DUAL *********************************************************/
117 /*********************************** *********************************************************/
118 
120  const string &output_conc_name,
121  const string &output_selection_name)
122  : SorptionBase(init_mesh, in_rec)
123 {
124  data_ = new EqData(output_conc_name);
127  .name("porosity_immobile");
128  this->eq_data_ = data_;
129  //output_selection = make_output_selection(output_conc_name, output_selection_name);
130 }
131 
133 {}
134 
135 /********************************** *******************************************************/
136 /*********************************** SORPTION_MOBILE *******************************************************/
137 /********************************** *******************************************************/
138 
140  return IT::Record("SorptionMobile", "Sorption model in the mobile zone, following the dual porosity model.")
143  //.declare_key("output_fields", IT::Array(make_output_selection("conc_solid", "SorptionMobile_Output")),
144  // IT::Default("\"conc_solid\""), "List of fields to write to output stream.")
145  .declare_key("output", make_output_type("SorptionMobile", "conc_solid"),
146  IT::Default("{ \"fields\": [ \"conc_solid\" ] }"),
147  "Setting of the fields output.")
148 
149  .close();
150 }
151 
152 
153 const int SorptionMob::registrar =
154  Input::register_class< SorptionMob, Mesh &, Input::Record >("SorptionMobile") +
156 
157 
159  : SorptionDual(init_mesh, in_rec, "conc_solid", "SorptionMobile_Output")
160 {}
161 
162 
164 {}
165 
166 /*
167 double SorptionMob::compute_sorbing_scale(double por_m, double por_imm)
168 {
169  double phi = por_m/(por_m + por_imm);
170  return phi;
171 }
172 */
173 
175 {
176  START_TIMER("SorptionMob::isotherm_reinit");
177 
178  double rock_density = data_->rock_density.value(elem.centre(),elem);
179 
180  double por_m = data_->porosity.value(elem.centre(),elem);
181  double por_imm = immob_porosity_.value(elem.centre(),elem);
182  double phi = por_m/(por_m + por_imm);
183 
184  // List of types of isotherms in particular regions
185  arma::uvec adsorption_type = data_->sorption_type.value(elem.centre(),elem);
186  arma::Col<double> mult_coef_vec = data_->isotherm_mult.value(elem.centre(),elem);
187  arma::Col<double> second_coef_vec = data_->isotherm_other.value(elem.centre(),elem);
188 
189  for(unsigned int i_subst = 0; i_subst < n_substances_; i_subst++)
190  {
191  double mult_coef = mult_coef_vec[i_subst];
192  double second_coef = second_coef_vec[i_subst];
193  Isotherm & isotherm = isotherms_vec[i_subst];
194 
195  //scales are different for the case of sorption in mobile and immobile pores
196  double scale_aqua = por_m,
197  scale_sorbed = phi * (1 - por_m - por_imm) * rock_density * substances_[substance_global_idx_[i_subst]].molar_mass();
198 
199  bool limited_solubility_on;
200  double table_limit;
201  if (solubility_vec_[i_subst] <= 0.0) {
202  limited_solubility_on = false;
203  table_limit=table_limit_[i_subst];
204 
205  } else {
206  limited_solubility_on = true;
207  table_limit=solubility_vec_[i_subst];
208  }
209 
210  if( (1-por_m-por_imm) <= std::numeric_limits<double>::epsilon()) //means there is no sorbing surface
211  {
212  isotherm.reinit(Isotherm::none, false, solvent_density_, scale_aqua, scale_sorbed,table_limit,0,0);
213  continue;
214  }
215 
216  if ( scale_sorbed <= 0.0)
217  xprintf(UsrErr, "Scaling parameter in sorption is not positive. Check the input for rock density and molar mass of %d. substance.",i_subst);
218 
219  isotherm.reinit(Isotherm::SorptionType(adsorption_type[i_subst]), limited_solubility_on,
220  solvent_density_, scale_aqua, scale_sorbed, table_limit, mult_coef, second_coef);
221 
222  }
223 
224  END_TIMER("SorptionMob::isotherm_reinit");
225 }
226 
227 
228 /*********************************** *****************************************************/
229 /*********************************** SORPTION_IMMOBILE *****************************************************/
230 /*********************************** *****************************************************/
231 
233  return IT::Record("SorptionImmobile", "Sorption model in the immobile zone, following the dual porosity model.")
236  //.declare_key("output_fields", IT::Array(make_output_selection("conc_immobile_solid", "SorptionImmobile_Output")),
237  // IT::Default("\"conc_immobile_solid\""), "List of fields to write to output stream.")
238  .declare_key("output", make_output_type("SorptionImmobile", "conc_immobile_solid"),
239  IT::Default("{ \"fields\": [ \"conc_immobile_solid\" ] }"),
240  "Setting of the fields output.")
241 
242  .close();
243 }
244 
245 const int SorptionImmob::registrar =
246  Input::register_class< SorptionImmob, Mesh &, Input::Record >("SorptionImmobile") +
248 
250 : SorptionDual(init_mesh, in_rec, "conc_immobile_solid", "SorptionImmobile_Output")
251 {}
252 
254 {}
255 
256 /*
257 double SorptionImmob::compute_sorbing_scale(double por_m, double por_imm)
258 {
259  double phi = por_imm / (por_m + por_imm);
260  return phi;
261 }
262 */
263 
265 {
266  START_TIMER("SorptionImmob::isotherm_reinit");
267 
268  double rock_density = data_->rock_density.value(elem.centre(),elem);
269 
270  double por_m = data_->porosity.value(elem.centre(),elem);
271  double por_imm = immob_porosity_.value(elem.centre(),elem);
272  double phi = por_m/(por_m + por_imm);
273 
274  // List of types of isotherms in particular regions
275  arma::uvec adsorption_type = data_->sorption_type.value(elem.centre(),elem);
276  arma::Col<double> mult_coef_vec = data_->isotherm_mult.value(elem.centre(),elem);
277  arma::Col<double> second_coef_vec = data_->isotherm_other.value(elem.centre(),elem);
278 
279  for(unsigned int i_subst = 0; i_subst < n_substances_; i_subst++)
280  {
281  double mult_coef = mult_coef_vec[i_subst];
282  double second_coef = second_coef_vec[i_subst];
283  Isotherm & isotherm = isotherms_vec[i_subst];
284 
285  //scales are different for the case of sorption in mobile and immobile pores
286  double scale_aqua = por_imm,
287  scale_sorbed = (1 - phi) * (1 - por_m - por_imm) * rock_density * substances_[substance_global_idx_[i_subst]].molar_mass();
288 
289  bool limited_solubility_on;
290  double table_limit;
291  if (solubility_vec_[i_subst] <= 0.0) {
292  limited_solubility_on = false;
293  table_limit=table_limit_[i_subst];
294 
295  } else {
296  limited_solubility_on = true;
297  table_limit=solubility_vec_[i_subst];
298  }
299 
300  if( (1-por_m-por_imm) <= std::numeric_limits<double>::epsilon()) //means there is no sorbing surface
301  {
302  isotherm.reinit(Isotherm::none, false, solvent_density_, scale_aqua, scale_sorbed,0,0,0);
303  continue;
304  }
305 
306  if ( scale_sorbed <= 0.0)
307  xprintf(UsrErr, "Scaling parameter in sorption is not positive. Check the input for rock density and molar mass of %d. substance.",i_subst);
308 
309  isotherm.reinit(Isotherm::SorptionType(adsorption_type[i_subst]), limited_solubility_on,
310  solvent_density_, scale_aqua, scale_sorbed, table_limit, mult_coef, second_coef);
311 
312  }
313 
314  END_TIMER("SorptionImmob::isotherm_reinit");
315 }
FieldSet * eq_data_
Definition: equation.hh:230
double solvent_density_
~SorptionDual(void)
Destructor.
Definition: sorption.cc:132
unsigned int size() const
Returns number of keys in the Record.
Definition: type_record.hh:582
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:50
static Input::Type::Abstract & get_input_type()
FieldCommon & flags_add(FieldFlag::Flags::Mask mask)
~SorptionMob(void)
Destructor.
Definition: sorption.cc:163
Abstract class of sorption model in case dual porosity is considered.
Definition: sorption.hh:65
SubstanceList substances_
Names belonging to substances.
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:174
Definition: mesh.h:95
static const Input::Type::Record & get_input_type()
Definition: sorption.cc:35
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:286
std::vector< unsigned int > substance_global_idx_
Mapping from local indexing of substances to global.
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:277
#define xprintf(...)
Definition: system.hh:87
#define START_TIMER(tag)
Starts a timer with specified tag.
static const Input::Type::Record & get_input_type()
Definition: sorption.cc:139
MultiField< 3, FieldValue< 3 >::Scalar > isotherm_mult
Multiplication coefficients (k, omega) for all types of isotherms.
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm) const
Definition: field.hh:342
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:468
MultiField< 3, FieldValue< 3 >::Enum > sorption_type
Discrete need Selection for initialization.
static Input::Type::Instance make_output_type(const string &equation_name, const string &output_field_name)
SorptionType
Type of adsorption isotherm.
Definition: isotherm.hh:170
Record & copy_keys(const Record &other)
Copy keys from other record.
Definition: type_record.cc:212
Definition: system.hh:59
const double epsilon
Definition: mathfce.h:23
SorptionImmob(Mesh &init_mesh, Input::Record in_rec)
Constructor.
Definition: sorption.cc:249
static const int registrar
Registrar of class to factory.
Definition: sorption.hh:58
virtual MultiFieldValue::return_type value(const Point &p, const ElementAccessor< spacedim > &elm) const
void isotherm_reinit(std::vector< Isotherm > &isotherms, const ElementAccessor< 3 > &elm) override
Reinitializes the isotherm.
Definition: sorption.cc:65
SorptionSimple(Mesh &init_mesh, Input::Record in_rec)
Constructor.
Definition: sorption.cc:48
static const int registrar
Registrar of class to factory.
Definition: sorption.hh:144
~SorptionSimple(void)
Destructor.
Definition: sorption.cc:62
FieldCommon & name(const string &name)
Definition: field_common.hh:86
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:171
static const Input::Type::Record & get_input_type()
unsigned int n_substances_
SorptionDual(Mesh &init_mesh, Input::Record in_rec, const string &output_conc_name, const string &output_selection_name)
Constructor.
Definition: sorption.cc:119
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:264
Other possible transformation of coordinates:
static const Input::Type::Record & get_input_type()
Definition: sorption.cc:232
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:158
~SorptionImmob(void)
Destructor.
Definition: sorption.cc:253