Flow123d  release_3.0.0-506-g34af125
sorption_base.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_base.cc
15  * @brief
16  */
17 
18 #include <boost/foreach.hpp>
19 
25 #include "reaction/isotherm.hh"
26 
27 #include "system/system.hh"
28 #include "system/sys_profiler.hh"
29 
30 #include "la/distribution.hh"
31 #include "mesh/mesh.h"
32 #include "mesh/elements.h"
33 #include "mesh/accessors.hh"
34 #include "input/type_selection.hh"
35 
36 #include "fields/field_set.hh"
37 #include "fields/field_fe.hh"
39 
40 using namespace Input::Type;
41 
43  return Selection("SorptionType")
44  .add_value(Isotherm::none,"none", "No sorption considered.")
45  .add_value(Isotherm::linear, "linear",
46  "Linear isotherm runs the concentration exchange between liquid and solid.")
47  .add_value(Isotherm::langmuir, "langmuir",
48  "Langmuir isotherm runs the concentration exchange between liquid and solid.")
49  .add_value(Isotherm::freundlich, "freundlich",
50  "Freundlich isotherm runs the concentration exchange between liquid and solid.")
51  .close();
52 }
53 
54 
55 
57  return Record("SorptionAux", "AUXILIARY RECORD. Should not be directly part of the input tree.")
58  .declare_key("substances", Array(String(),1), Default::obligatory(),
59  "Names of the substances that take part in the sorption model.")
60  .declare_key("solvent_density", Double(0.0), Default("1.0"),
61  "Density of the solvent.")
62  .declare_key("substeps", Integer(1), Default("1000"),
63  "Number of equidistant substeps, molar mass and isotherm intersections")
64  .declare_key("solubility", Array(Double(0.0)), Default::optional(), //("-1.0"), //
65  "Specifies solubility limits of all the sorbing species.")
66  .declare_key("table_limits", Array(Double(-1.0)), Default::optional(), //("-1.0"), //
67  "Specifies the highest aqueous concentration in the isotherm function interpolation table. "
68  "Use any negative value for an automatic choice according to current maximal concentration (default and recommended). "
69  "Use '0' to always evaluate isotherm function directly (can be very slow). "
70  "Use a positive value to set the interpolation table limit manually "
71  "(if aqueous concentration is higher, then the isotherm function is evaluated directly).")
72  .declare_key("input_fields", Array(EqData("").input_data_set_.make_field_descriptor_type("Sorption")), Default::obligatory(), //
73  "Containes region specific data necessary to construct isotherms.")//;
74  .declare_key("reaction_liquid", ReactionTerm::it_abstract_reaction(), Default::optional(), "Reaction model following the sorption in the liquid.")
75  .declare_key("reaction_solid", ReactionTerm::it_abstract_reaction(), Default::optional(), "Reaction model following the sorption in the solid.")
76  .close();
77 }
78 
79 
80 SorptionBase::EqData::EqData(const string &output_field_name)
81 {
82  ADD_FIELD(rock_density, "Rock matrix density.", "0.0");
83  rock_density.units( UnitSI().kg().m(-3) );
84 
85  ADD_FIELD(sorption_type,"Considered sorption is described by selected isotherm. If porosity on an element is equal or even higher than 1.0 (meaning no sorbing surface), then type 'none' will be selected automatically."); //
86  sorption_type.input_selection(get_sorption_type_selection());
87  sorption_type.units( UnitSI::dimensionless() );
88 
89  ADD_FIELD(distribution_coefficient,"Multiplication parameters (k, omega) in either Langmuir c_s = omega * (alpha*c_a)/(1- alpha*c_a) or in linear c_s = k * c_a isothermal description.","1.0");
90  distribution_coefficient.units( UnitSI().m(3).kg(-1) );
91 
92  ADD_FIELD(isotherm_other,"Second parameters (alpha, ...) defining isotherm c_s = omega * (alpha*c_a)/(1- alpha*c_a).","1.0");
93  isotherm_other.units( UnitSI::dimensionless() );
94 
95  ADD_FIELD(init_conc_solid, "Initial solid concentration of substances."
96  " Vector, one value for every substance.", "0");
97  init_conc_solid.units( UnitSI().mol().kg(-1) );
98 
99  input_data_set_ += *this;
100 
101  // porosity field is set from governing equation (transport) later
102  // hence we do not add it to the input_data_set_
103  *this += porosity
104  .name("porosity")
105  .units( UnitSI::dimensionless() )
106  .flags(FieldFlag::input_copy)
107  .set_limits(0.0);
108 
109  output_fields += *this;
110  output_fields += conc_solid.name(output_field_name).units( UnitSI().dimensionless() ).flags(FieldFlag::equation_result);
111 }
112 
113 
115  : ReactionTerm(init_mesh, in_rec),
116  data_(nullptr)
117 {
118  // creating reaction from input and setting their parameters
119  make_reactions();
120 }
121 
122 
124 {
125  if (data_ != nullptr) delete data_;
126 
127  chkerr(VecScatterDestroy(&(vconc_out_scatter)));
128  if (vconc_solid != NULL) {
129 
130 
131  for (unsigned int sbi = 0; sbi < substances_.size(); sbi++)
132  {
133  //no mpi vectors
134  chkerr(VecDestroy( &(vconc_solid[sbi]) ));
135  delete [] conc_solid[sbi];
136  }
137  delete [] vconc_solid;
138  delete [] conc_solid;
139  }
140 }
141 
143 {
145 
146  reactions_it = input_record_.find<Input::AbstractRecord>("reaction_liquid");
147  if ( reactions_it )
148  {
149  // TODO: allowed instances in this case are only
150  // FirstOrderReaction, RadioactiveDecay
151  reaction_liquid = (*reactions_it).factory< ReactionTerm, Mesh &, Input::Record >(*mesh_, *reactions_it);
152  } else
153  {
154  reaction_liquid = nullptr;
155  }
156 
157  reactions_it = input_record_.find<Input::AbstractRecord>("reaction_solid");
158  if ( reactions_it )
159  {
160  // TODO: allowed instances in this case are only
161  // FirstOrderReaction, RadioactiveDecay
162  reaction_solid = (*reactions_it).factory< ReactionTerm, Mesh &, Input::Record >(*mesh_, *reactions_it);
163  } else
164  {
165  reaction_solid = nullptr;
166  }
167 }
168 
170 {
171  OLD_ASSERT(distribution_ != nullptr, "Distribution has not been set yet.\n");
172  OLD_ASSERT(time_ != nullptr, "Time governor has not been set yet.\n");
173  OLD_ASSERT(output_stream_,"Null output stream.");
175 
176  initialize_substance_ids(); //computes present substances and sets indices
177  initialize_from_input(); //reads non-field data from input
178 
179  //isotherms array resized bellow
180  unsigned int nr_of_regions = mesh_->region_db().bulk_size();
181  isotherms.resize(nr_of_regions);
182  max_conc.resize(nr_of_regions);
183  for(unsigned int i_reg = 0; i_reg < nr_of_regions; i_reg++)
184  {
185  isotherms[i_reg].resize(n_substances_);
186  max_conc[i_reg].resize(n_substances_, 0.0);
187  for(unsigned int i_subst = 0; i_subst < n_substances_; i_subst++)
188  {
189  isotherms[i_reg][i_subst] = Isotherm();
190  }
191  }
192 
193  //allocating new array for sorbed concentrations
194  conc_solid = new double* [substances_.size()];
195  conc_solid_out.clear();
196  conc_solid_out.resize( substances_.size() );
197  output_field_ptr.clear();
198  output_field_ptr.resize( substances_.size() );
199  for (unsigned int sbi = 0; sbi < substances_.size(); sbi++)
200  {
201  conc_solid[sbi] = new double [distribution_->lsize()];
202  conc_solid_out[sbi].resize( distribution_->size() );
203  //zero initialization of solid concentration for all substances
204  for(unsigned int i=0; i < distribution_->lsize(); i++)
205  conc_solid[sbi][i] = 0;
206  }
207 
209 
211 
212  if(reaction_liquid)
213  {
214  reaction_liquid->substances(substances_)
215  .concentration_matrix(concentration_matrix_, distribution_, el_4_loc_, row_4_el_)
216  .set_time_governor(*time_);
217  reaction_liquid->initialize();
218  }
219  if(reaction_solid)
220  {
221  reaction_solid->substances(substances_)
222  .concentration_matrix(conc_solid, distribution_, el_4_loc_, row_4_el_)
223  .set_time_governor(*time_);
224  reaction_solid->initialize();
225  }
226 }
227 
228 
230 {
231  Input::Array substances_array = input_record_.val<Input::Array>("substances");
232  unsigned int k, global_idx, i_subst = 0;
233  bool found;
234  Input::Iterator<string> spec_iter = substances_array.begin<string>();
235 
236  for(; spec_iter != substances_array.end(); ++spec_iter, i_subst++)
237  {
238  //finding the name of a substance in the global array of names
239  found = false;
240  for(k = 0; k < substances_.size(); k++)
241  {
242  if (*spec_iter == substances_[k].name())
243  {
244  global_idx = k;
245  found = true;
246  break;
247  }
248  }
249 
250  if(!found)
251  THROW(ReactionTerm::ExcUnknownSubstance()
252  << ReactionTerm::EI_Substance(*spec_iter)
253  << substances_array.ei_address());
254 
255  //finding the global index of substance in the local array
256  found = false;
257  for(k = 0; k < substance_global_idx_.size(); k++)
258  {
259  if(substance_global_idx_[k] == global_idx)
260  {
261  found = true;
262  break;
263  }
264  }
265 
266  if(!found)
267  {
268  substance_global_idx_.push_back(global_idx);
269  }
270 
271  }
273 }
274 
276 {
277  // read number of interpolation steps - value checked by the record definition
278  n_interpolation_steps_ = input_record_.val<int>("substeps");
279 
280  // read the density of solvent - value checked by the record definition
281  solvent_density_ = input_record_.val<double>("solvent_density");
282 
283  // read the solubility vector
284  Input::Iterator<Input::Array> solub_iter = input_record_.find<Input::Array>("solubility");
285  if( solub_iter )
286  {
287  if (solub_iter->Array::size() != n_substances_)
288  {
289  THROW(SorptionBase::ExcSubstanceCountMatch()
290  << SorptionBase::EI_ArrayName("solubility")
292  // there is no way to get ei_address from 'solub_iter', only as a string
293  }
294 
295  else solub_iter->copy_to(solubility_vec_);
296  }
297  else{
298  // fill solubility_vec_ with zeros
299  solubility_vec_.clear();
300  solubility_vec_.resize(n_substances_,0.0);
301  }
302 
303  // read the interpolation table limits
304  Input::Iterator<Input::Array> interp_table_limits = input_record_.find<Input::Array>("table_limits");
305  if( interp_table_limits )
306  {
307  if (interp_table_limits->Array::size() != n_substances_)
308  {
309  THROW(SorptionBase::ExcSubstanceCountMatch()
310  << SorptionBase::EI_ArrayName("table_limits")
312  // there is no way to get ei_address from 'interp_table_limits', only as a string
313  }
314 
315  else interp_table_limits->copy_to(table_limit_);
316  }
317  else{
318  // fill table_limit_ with negative values -> automatic limit
319  table_limit_.clear();
320  table_limit_.resize(n_substances_,-1.0);
321  }
322 }
323 
325 {
326  OLD_ASSERT(n_substances_ > 0, "Number of substances is wrong, they might have not been set yet.\n");
327 
328  // create vector of substances that are involved in sorption
329  // and initialize data_ with their names
330  std::vector<std::string> substances_sorption;
331  for (unsigned int i : substance_global_idx_)
332  substances_sorption.push_back(substances_[i].name());
333  data_->set_components(substances_sorption);
334 
335  // read fields from input file
337 
338  data_->set_mesh(*mesh_);
339 
340  //initialization of output
341  //output_array = input_record_.val<Input::Array>("output_fields");
346  for (unsigned int sbi=0; sbi<substances_.size(); sbi++)
347  {
348  // create shared pointer to a FieldFE and push this Field to output_field on all regions
349  output_field_ptr[sbi] = conc_solid_out[sbi].create_field<3, FieldValue<3>::Scalar>(*mesh_, 1);
350  data_->conc_solid[sbi].set_field(mesh_->region_db().get_region_set("ALL"), output_field_ptr[sbi], 0);
351  }
352  //output_stream_->add_admissible_field_names(output_array);
354 }
355 
356 
358 {
359  OLD_ASSERT(distribution_ != nullptr, "Distribution has not been set yet.\n");
360  OLD_ASSERT(time_ != nullptr, "Time governor has not been set yet.\n");
361  OLD_ASSERT(output_stream_,"Null output stream.");
363 
365  std::stringstream ss; // print warning message with table of uninitialized fields
366  if ( FieldCommon::print_message_table(ss, "sorption") ) {
367  WarningOut() << ss.str();
368  }
370 
371  update_max_conc();
372  make_tables();
373 
374  // write initial condition
375  //output_vector_gather();
376  //data_->output_fields.set_time(time_->step(), LimitSide::right);
377  //data_->output_fields.output(output_stream_);
378 
379  if(reaction_liquid) reaction_liquid->zero_time_step();
380  if(reaction_solid) reaction_solid->zero_time_step();
381 
382  output_data();
383 }
384 
386 {
387  for (unsigned int loc_el = 0; loc_el < distribution_->lsize(); loc_el++)
388  {
389  unsigned int index = el_4_loc_[loc_el];
390  ElementAccessor<3> ele_acc = mesh_->element_accessor(index);
391 
392  //setting initial solid concentration for substances involved in adsorption
393  for (unsigned int sbi = 0; sbi < n_substances_; sbi++)
394  {
395  int subst_id = substance_global_idx_[sbi];
396  conc_solid[subst_id][loc_el] = data_->init_conc_solid[sbi].value(ele_acc.centre(), ele_acc);
397  }
398  }
399 }
400 
401 
403 {
404  data_->set_time(time_->step(), LimitSide::right); // set to the last computed time
405 
406  // if parameters changed during last time step, reinit isotherms and eventualy
407  // update interpolation tables in the case of constant rock matrix parameters
408  make_tables();
409  clear_max_conc();
410 
411  START_TIMER("Sorption");
412  for (unsigned int loc_el = 0; loc_el < distribution_->lsize(); loc_el++)
413  {
415  }
416  END_TIMER("Sorption");
417 
418  if(reaction_liquid) reaction_liquid->update_solution();
419  if(reaction_solid) reaction_solid->update_solution();
420 }
421 
422 void SorptionBase::isotherm_reinit(unsigned int i_subst, const ElementAccessor<3> &elem)
423 {
424  START_TIMER("SorptionBase::isotherm_reinit");
425 
426  double mult_coef = data_->distribution_coefficient[i_subst].value(elem.centre(),elem);
427  double second_coef = data_->isotherm_other[i_subst].value(elem.centre(),elem);
428 
429  int reg_idx = elem.region().bulk_idx();
430  Isotherm & isotherm = isotherms[reg_idx][i_subst];
431 
432  bool limited_solubility_on = solubility_vec_[i_subst] > 0.0;
433 
434  // in case of no sorbing surface, set isotherm type None
435  if( common_ele_data.no_sorbing_surface_cond <= std::numeric_limits<double>::epsilon())
436  {
437  isotherm.reinit(Isotherm::none, false, solvent_density_,
439  0,0,0);
440  return;
441  }
442 
443  if ( common_ele_data.scale_sorbed <= 0.0)
444  xprintf(UsrErr, "Scaling parameter in sorption is not positive. Check the input for rock density and molar mass of %d. substance.",i_subst);
445 
446  isotherm.reinit(Isotherm::SorptionType(data_->sorption_type[i_subst].value(elem.centre(),elem)),
447  limited_solubility_on, solvent_density_,
449  solubility_vec_[i_subst], mult_coef, second_coef);
450 }
451 
453 {
454  for(unsigned int i_subst = 0; i_subst < n_substances_; i_subst++)
455  {
456  isotherm_reinit(i_subst, elem);
457  }
458 }
459 
461 {
462  unsigned int reg_idx, i_subst, subst_id;
463 
464  // clear max concetrations array
465  unsigned int nr_of_regions = mesh_->region_db().bulk_size();
466  for(reg_idx = 0; reg_idx < nr_of_regions; reg_idx++)
467  for(unsigned int i_subst = 0; i_subst < n_substances_; i_subst++)
468  max_conc[reg_idx][i_subst] = 0.0;
469 }
470 
472 {
473  unsigned int reg_idx, i_subst, subst_id;
474 
475  clear_max_conc();
476 
477  for (unsigned int loc_el = 0; loc_el < distribution_->lsize(); loc_el++){
479  reg_idx = ele.region().bulk_idx();
480  for(i_subst = 0; i_subst < n_substances_; i_subst++){
481  subst_id = substance_global_idx_[i_subst];
482  max_conc[reg_idx][i_subst] = std::max(max_conc[reg_idx][i_subst], concentration_matrix_[subst_id][loc_el]);
483  }
484  }
485 }
486 
488 {
489  START_TIMER("SorptionBase::make_tables");
490  try
491  {
492  ElementAccessor<3> elm;
493  for(const Region &reg_iter: this->mesh_->region_db().get_region_set("BULK"))
494  {
495  int reg_idx = reg_iter.bulk_idx();
496  // true if data has been changed and are constant on the region
497  bool call_reinit = data_->changed() && data_->is_constant(reg_iter);
498 
499  if(call_reinit)
500  {
501  ElementAccessor<3> elm(this->mesh_, reg_iter);
502 // DebugOut().fmt("isotherm reinit\n");
504  isotherm_reinit_all(elm);
505  }
506 
507  // find table limit and create interpolation table for every substance
508  for(unsigned int i_subst = 0; i_subst < n_substances_; i_subst++){
509 
510  // clear interpolation tables, if not spacially constant OR switched off
511  if(! data_->is_constant(reg_iter) || table_limit_[i_subst] == 0.0){
512  isotherms[reg_idx][i_subst].clear_table();
513 // DebugOut().fmt("limit: 0.0 -> clear table\n");
514  continue;
515  }
516 
517  // if true then make_table will be called at the end
518  bool call_make_table = call_reinit;
519  // initialy try to keep the current table limit (it is zero at zero time step)
520  double subst_table_limit = isotherms[reg_idx][i_subst].table_limit();
521 
522  // if automatic, possibly remake tables with doubled range when table maximum was reached
523  if(table_limit_[i_subst] < 0.0)
524  {
525  if(subst_table_limit < max_conc[reg_idx][i_subst])
526  {
527  call_make_table = true;
528  subst_table_limit = 2*max_conc[reg_idx][i_subst];
529 // DebugOut().fmt("limit: max conc\n");
530  }
531  }
532  // if not automatic, set given table limit
533  else
534  {
535  subst_table_limit = table_limit_[i_subst];
536  }
537 
538  if(call_make_table){
539  isotherms[reg_idx][i_subst].make_table(n_interpolation_steps_, subst_table_limit);
540 // DebugOut().fmt("reg: {} i_subst {}: table_limit = {}\n", reg_idx, i_subst, isotherms[reg_idx][i_subst].table_limit());
541  }
542  }
543  }
544  }
545  catch(ExceptionBase const &e)
546  {
547  e << input_record_.ei_address();
548  throw;
549  }
550 }
551 
552 double **SorptionBase::compute_reaction(double **concentrations, int loc_el)
553 {
555  int reg_idx = elem.region().bulk_idx();
556  unsigned int i_subst, subst_id;
557  // for checking, that the common element data are computed once at maximum
558  bool is_common_ele_data_valid = false;
559 
560  try{
561  for(i_subst = 0; i_subst < n_substances_; i_subst++)
562  {
563  subst_id = substance_global_idx_[i_subst];
564  Isotherm & isotherm = isotherms[reg_idx][i_subst];
565  if (isotherm.is_precomputed()){
566 // DebugOut().fmt("isotherms precomputed - interpolate, subst[{}]\n", i_subst);
567  isotherm.interpolate(concentration_matrix_[subst_id][loc_el],
568  conc_solid[subst_id][loc_el]);
569  }
570  else{
571 // DebugOut().fmt("isotherms reinit - compute , subst[{}]\n", i_subst);
572  if(! is_common_ele_data_valid){
574  is_common_ele_data_valid = true;
575  }
576 
577  isotherm_reinit(i_subst, elem);
578  isotherm.compute(concentration_matrix_[subst_id][loc_el],
579  conc_solid[subst_id][loc_el]);
580  }
581 
582  // update maximal concentration per region (optimization for interpolation)
583  if(table_limit_[i_subst] < 0)
584  max_conc[reg_idx][i_subst] = std::max(max_conc[reg_idx][i_subst],
585  concentration_matrix_[subst_id][loc_el]);
586  }
587  }
588  catch(ExceptionBase const &e)
589  {
590  e << input_record_.ei_address();
591  throw;
592  }
593 
594  return concentrations;
595 }
596 
597 
598 /**************************************** OUTPUT ***************************************************/
599 
601 {
602  int sbi, n_subst;
603  n_subst = substances_.size();
604 
605  vconc_solid = new Vec [n_subst];
606 
607  for (sbi = 0; sbi < n_subst; sbi++) {
608  VecCreateMPIWithArray(PETSC_COMM_WORLD,1, distribution_->lsize(), mesh_->n_elements(), conc_solid[sbi],
609  &vconc_solid[sbi]);
610  VecZeroEntries(vconc_solid[sbi]);
611 
612  VecZeroEntries(conc_solid_out[sbi].get_data_petsc());
613  }
614 
615  // creating output vector scatter
616  IS is;
617  ISCreateGeneral(PETSC_COMM_SELF, mesh_->n_elements(), row_4_el_, PETSC_COPY_VALUES, &is); //WithArray
618  VecScatterCreate(vconc_solid[0], is, conc_solid_out[0].get_data_petsc(), PETSC_NULL, &vconc_out_scatter);
619  ISDestroy(&(is));
620 }
621 
622 
624 {
625  unsigned int sbi;
626 
627  for (sbi = 0; sbi < substances_.size(); sbi++) {
628  VecScatterBegin(vconc_out_scatter, vconc_solid[sbi], conc_solid_out[sbi].get_data_petsc(), INSERT_VALUES, SCATTER_FORWARD);
629  VecScatterEnd(vconc_out_scatter, vconc_solid[sbi], conc_solid_out[sbi].get_data_petsc(), INSERT_VALUES, SCATTER_FORWARD);
630  }
631 }
632 
633 
635 {
639  }
640 
641  for (unsigned int sbi = 0; sbi < substances_.size(); sbi++) {
642  conc_solid_out[sbi].fill_output_data(output_field_ptr[sbi]);
643  }
644 
645  // Register fresh output data
646  data_->output_fields.output(time().step());
647 }
TimeGovernor & time()
Definition: equation.hh:148
void output_type(OutputTime::DiscreteSpace rt)
Definition: field_set.hh:211
unsigned int size() const
get global size
std::shared_ptr< ReactionTerm > reaction_solid
Iterator< ValueType > begin() const
void allocate_output_mpi(void)
Allocates petsc vectors, prepares them for output and creates vector scatter.
MultiField< 3, FieldValue< 3 >::Scalar > conc_solid
Calculated sorbed concentrations, for output only.
RegionSet get_region_set(const std::string &set_name) const
Definition: region.cc:329
void make_reactions()
std::vector< VectorSeqDouble > conc_solid_out
sorbed concentration array output (gathered - sequential)
Accessor to input data conforming to declared Array.
Definition: accessors.hh:567
double solvent_density_
EI_Address ei_address() const
Definition: accessors.cc:314
void compute(double &c_aqua, double &c_sorbed)
Definition: isotherm.cc:68
std::vector< std::vector< Isotherm > > isotherms
virtual ~SorptionBase(void)
void initialize_substance_ids()
Reads names of substances from input and creates indexing to global vector of substance.
double ** concentration_matrix_
unsigned int bulk_size() const
Definition: region.cc:269
const std::vector< std::string > & names()
Definition: substance.hh:85
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
EqData(const string &output_field_name)
Collect all fields.
void output(TimeStep step)
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:110
SubstanceList substances_
Names belonging to substances.
void zero_time_step() override
Definition: mesh.h:80
Iterator< Ret > find(const string &key) const
EquationOutput output_fields
Fields indended for output, i.e. all input fields plus those representing solution.
static const Input::Type::Selection & get_sorption_type_selection()
void chkerr(unsigned int ierr)
Replacement of new/delete operator in the spirit of xmalloc.
Definition: system.hh:147
const RegionDB & region_db() const
Definition: mesh.h:147
const TimeStep & step(int index=-1) const
std::vector< double > table_limit_
Class for declaration of the integral input data.
Definition: type_base.hh:490
static Input::Type::Abstract & it_abstract_reaction()
#define ADD_FIELD(name,...)
Definition: field_set.hh:279
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
unsigned int size() const
Definition: substance.hh:87
Class for declaration of inputs sequences.
Definition: type_base.hh:346
virtual ElementAccessor< 3 > element_accessor(unsigned int idx) const
Create and return ElementAccessor to element of given idx.
Definition: mesh.cc:719
std::shared_ptr< OutputTime > output_stream_
Pointer to a transport output stream.
ReactionTerm(Mesh &init_mesh, Input::Record in_rec)
Constructor.
Class ReactionTerm is an abstract class representing reaction term in transport.
std::vector< unsigned int > substance_global_idx_
Mapping from local indexing of substances to global.
void initialize_fields()
Initializes field sets.
void isotherm_reinit(unsigned int i_subst, const ElementAccessor< 3 > &elm)
Reinitializes the isotherm.
Class Dual_por_exchange implements the model of dual porosity.
IteratorBase end() const
arma::vec::fixed< spacedim > centre() const
Computes the barycenter.
Definition: accessors.hh:285
EI_Address ei_address() const
Definition: accessors.cc:178
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:124
#define OLD_ASSERT(...)
Definition: global_defs.h:131
void setup_components()
MultiField< 3, FieldValue< 3 >::Scalar > isotherm_other
Langmuir sorption coeficients alpha (in fraction c_s = omega * (alpha*c_a)/(1- alpha*c_a)).
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:541
Distribution * distribution_
Pointer to reference to distribution of elements between processors.
static constexpr Mask equation_result
Match result fields. These are never given by input or copy of input.
Definition: field_flag.hh:55
void output_data(void) override
Output method.
static constexpr Mask input_copy
Definition: field_flag.hh:44
Vec * vconc_solid
PETSC sorbed concentration vector (parallel).
std::vector< std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > > output_field_ptr
Fields correspond with conc_solid_out.
MultiField< 3, FieldValue< 3 >::Scalar > init_conc_solid
Initial sorbed concentrations.
void initialize_from_input()
Initializes private members of sorption from the input record.
std::vector< double > solubility_vec_
Accessor to the data with type Type::Record.
Definition: accessors.hh:292
unsigned int n_interpolation_steps_
const Ret val(const string &key) const
#define xprintf(...)
Definition: system.hh:92
void make_tables(void)
#define START_TIMER(tag)
Starts a timer with specified tag.
#define OLD_ASSERT_LESS(a, b)
Definition: global_defs.h:134
Mesh * mesh_
Definition: equation.hh:223
Selection & add_value(const int value, const std::string &key, const std::string &description="", TypeBase::attribute_map attributes=TypeBase::attribute_map())
Adds one new value with name given by key to the Selection.
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:501
void update_max_conc()
Computes maximal aqueous concentration at the current step.
virtual void compute_common_ele_data(const ElementAccessor< 3 > &elem)=0
MultiField< 3, FieldValue< 3 >::Enum > sorption_type
Discrete need Selection for initialization.
void output_vector_gather(void) override
Gathers all the parallel vectors to enable them to be output.
void update_solution(void) override
Updates the solution.
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:459
Region region() const
Definition: accessors.hh:95
SorptionType
Type of adsorption isotherm.
Definition: isotherm.hh:174
double ** compute_reaction(double **concentrations, int loc_el) override
Definition: system.hh:64
Support classes for parallel programing.
void set_input_list(Input::Array input_list, const TimeGovernor &tg)
Definition: field_set.hh:190
virtual unsigned int n_elements(bool boundary=false) const
Returns count of boundary or bulk elements.
Definition: mesh.h:346
Class SorptionBase is abstract class representing model of sorption in transport. ...
void interpolate(double &c_aqua, double &c_sorbed)
Definition: isotherm.cc:84
void initialize(std::shared_ptr< OutputTime > stream, Mesh *mesh, Input::Record in_rec, const TimeGovernor &tg)
const Selection & close() const
Close the Selection, no more values can be added.
Input::Record input_record_
Definition: equation.hh:225
void set_components(const std::vector< string > &names)
Definition: field_set.hh:177
void set_initial_condition()
Reads and sets initial condition for concentration in solid.
LongIdx * row_4_el_
Indices of rows belonging to elements.
bool set_time(const TimeStep &time, LimitSide limit_side)
Definition: field_set.cc:157
bool is_constant(Region reg) const
Definition: field_set.cc:173
unsigned int bulk_idx() const
Returns index of the region in the bulk set.
Definition: region.hh:91
#define WarningOut()
Macro defining &#39;warning&#39; record of log.
Definition: logger.hh:246
#define END_TIMER(tag)
Ends a timer with specified tag.
void clear_max_conc()
Sets max conc to zeros on all regins.
bool is_precomputed(void)
Definition: isotherm.hh:239
double ** conc_solid
void set_mesh(const Mesh &mesh)
Definition: field_set.hh:183
void set_components(const std::vector< string > &names)
Record type proxy class.
Definition: type_record.hh:182
static const Input::Type::Record & get_input_type()
VecScatter vconc_out_scatter
Output vector scatter.
bool is_field_output_time(const FieldCommon &field, TimeStep step) const
void isotherm_reinit_all(const ElementAccessor< 3 > &elm)
Calls isotherm_reinit for all isotherms.
Base of exceptions used in Flow123d.
Definition: exceptions.hh:75
MultiField< 3, FieldValue< 3 >::Scalar > distribution_coefficient
Multiplication coefficients (k, omega) for all types of isotherms.
LongIdx * el_4_loc_
Indices of elements belonging to local dofs.
unsigned int n_substances_
Class for representation SI units of Fields.
Definition: unit_si.hh:40
EqData * data_
Pointer to equation data. The object is constructed in descendants.
static UnitSI & dimensionless()
Returns dimensionless unit.
Definition: unit_si.cc:55
static bool print_message_table(ostream &stream, std::string equation_name)
Definition: field_common.cc:96
std::vector< std::vector< double > > max_conc
Other possible transformation of coordinates:
Class for declaration of the input data that are in string format.
Definition: type_base.hh:589
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
bool changed() const
Definition: field_set.cc:165
Template for classes storing finite set of named values.
Input::Type::Record make_field_descriptor_type(const std::string &equation_name) const
Definition: field_set.cc:62
struct SorptionBase::CommonElementData common_ele_data
TimeGovernor * time_
Definition: equation.hh:224
FieldSet input_data_set_
Input data set - fields in this set are read from the input file.
std::shared_ptr< ReactionTerm > reaction_liquid
unsigned int lsize(int proc) const
get local size
void initialize() override
Prepares the object to usage.