Flow123d  jenkins-Flow123d-linux-release-multijob-282
sorption_base.cc
Go to the documentation of this file.
1 #include <boost/foreach.hpp>
2 
9 #include "reaction/isotherm.hh"
10 
11 #include "system/system.hh"
12 #include "system/sys_profiler.hh"
13 
14 #include "la/distribution.hh"
15 #include "mesh/mesh.h"
16 #include "mesh/elements.h"
17 #include "input/type_selection.hh"
18 
19 #include "fields/field_set.hh"
21 
22 using namespace Input::Type;
23 
25  .add_value(Isotherm::none,"none", "No sorption considered.")
26  .add_value(Isotherm::linear, "linear",
27  "Linear isotherm runs the concentration exchange between liquid and solid.")
28  .add_value(Isotherm::langmuir, "langmuir",
29  "Langmuir isotherm runs the concentration exchange between liquid and solid.")
30  .add_value(Isotherm::freundlich, "freundlich",
31  "Freundlich isotherm runs the concentration exchange between liquid and solid.");
32 
33 
34 
36  = Record("Sorption", "AUXILIARY RECORD. Should not be directly part of the input tree.")
37  .declare_key("substances", Array(String(),1), Default::obligatory(),
38  "Names of the substances that take part in the sorption model.")
39  .declare_key("solvent_density", Double(0.0), Default("1.0"),
40  "Density of the solvent.")
41  .declare_key("substeps", Integer(1), Default("1000"),
42  "Number of equidistant substeps, molar mass and isotherm intersections")
43  .declare_key("solubility", Array(Double(0.0)), Default::optional(), //("-1.0"), //
44  "Specifies solubility limits of all the sorbing species.")
45  .declare_key("table_limits", Array(Double(0.0)), Default::optional(), //("-1.0"), //
46  "Specifies highest aqueous concentration in interpolation table.")
47  .declare_key("input_fields", Array(EqData("").input_data_set_.make_field_descriptor_type("Sorption")), Default::obligatory(), //
48  "Containes region specific data necessary to construct isotherms.")//;
49  .declare_key("reaction_liquid", ReactionTerm::input_type, Default::optional(), "Reaction model following the sorption in the liquid.")
50  .declare_key("reaction_solid", ReactionTerm::input_type, Default::optional(), "Reaction model following the sorption in the solid.");
51 
52 
53 SorptionBase::EqData::EqData(const string &output_field_name)
54 {
55  ADD_FIELD(rock_density, "Rock matrix density.", "0.0");
56  rock_density.units( UnitSI().kg().m(-3) );
57 
58  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."); //
59  sorption_type.input_selection(&sorption_type_selection);
60  sorption_type.units( UnitSI::dimensionless() );
61 
62  ADD_FIELD(isotherm_mult,"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");
63  isotherm_mult.units( UnitSI().mol().kg(-1) );
64 
65  ADD_FIELD(isotherm_other,"Second parameters (alpha, ...) defining isotherm c_s = omega * (alpha*c_a)/(1- alpha*c_a).","1.0");
66  isotherm_other.units( UnitSI::dimensionless() );
67 
68  ADD_FIELD(init_conc_solid, "Initial solid concentration of substances."
69  " Vector, one value for every substance.", "0");
70  init_conc_solid.units( UnitSI().mol().kg(-1) );
71 
72  input_data_set_ += *this;
73 
74  // porosity field is set from governing equation (transport) later
75  // hence we do not add it to the input_data_set_
76  *this += porosity
77  .name("porosity")
78  .units( UnitSI::dimensionless() )
79  .flags(FieldFlag::input_copy);
80 
81  output_fields += *this;
82  output_fields += conc_solid.name(output_field_name).units( UnitSI().kg().m(-3) );
83 }
84 
86 {
87  IT::Record rec;
88  switch(fact)
89  {
90  case SorptionRecord::mobile:
91  rec = IT::Record("SorptionMobile", "Sorption model in the mobile zone, following the dual porosity model.")
94  .declare_key("output_fields", IT::Array(make_output_selection("conc_solid", "SorptionMobile_Output")),
95  IT::Default("conc_solid"), "List of fields to write to output stream.");
96  break;
97  case SorptionRecord::immobile:
98  rec = IT::Record("SorptionImmobile", "Sorption model in the immobile zone, following the dual porosity model.")
101  .declare_key("output_fields", IT::Array(make_output_selection("conc_immobile_solid", "SorptionImmobile_Output")),
102  IT::Default("conc_immobile_solid"), "List of fields to write to output stream.");
103  break;
104 
105  default:
106  rec = IT::Record("Sorption", "Sorption model in the reaction term of transport.")
109  .declare_key("output_fields", IT::Array(make_output_selection("conc_solid", "Sorption_Output")),
110  IT::Default("conc_solid"), "List of fields to write to output stream.");
111  break;
112  }
113  return rec;
114 }
115 
116 
118  : ReactionTerm(init_mesh, in_rec),
119  data_(nullptr)
120 {
121  // creating reaction from input and setting their parameters
122  make_reactions();
123 }
124 
125 
127 {
128  if(reaction_liquid != nullptr) delete reaction_liquid;
129  if(reaction_solid != nullptr) delete reaction_solid;
130  if (data_ != nullptr) delete data_;
131 
132  VecScatterDestroy(&(vconc_out_scatter));
133  VecDestroy(vconc_solid);
134 
135  for (unsigned int sbi = 0; sbi < substances_.size(); sbi++)
136  {
137  //no mpi vectors
138  xfree(conc_solid[sbi]);
139  }
140  xfree(conc_solid);
141 }
142 
144 {
146 
147  reactions_it = input_record_.find<Input::AbstractRecord>("reaction_liquid");
148  if ( reactions_it )
149  {
150  if (reactions_it->type() == FirstOrderReaction::input_type ) {
151  reaction_liquid = new FirstOrderReaction(*mesh_, *reactions_it);
152  } else
153  if (reactions_it->type() == RadioactiveDecay::input_type) {
154  reaction_liquid = new RadioactiveDecay(*mesh_, *reactions_it);
155  } else
156  if (reactions_it->type() == SorptionBase::input_type ) {
157  THROW( ReactionTerm::ExcWrongDescendantModel()
158  << ReactionTerm::EI_Model((*reactions_it).type().type_name())
159  << (*reactions_it).ei_address());
160  } else
161  if (reactions_it->type() == DualPorosity::input_type ) {
162  THROW( ReactionTerm::ExcWrongDescendantModel()
163  << ReactionTerm::EI_Model((*reactions_it).type().type_name())
164  << (*reactions_it).ei_address());
165  } else
166  if (reactions_it->type() == Semchem_interface::input_type )
167  { THROW( ReactionTerm::ExcWrongDescendantModel()
168  << ReactionTerm::EI_Model((*reactions_it).type().type_name())
169  << EI_Message("This model is not currently supported!")
170  << (*reactions_it).ei_address());
171  } else
172  { //This point cannot be reached. The TYPE_selection will throw an error first.
173  THROW( ExcMessage()
174  << EI_Message("Descending model type selection failed (SHOULD NEVER HAPPEN).")
175  << (*reactions_it).ei_address());
176  }
177  } else
178  {
179  reaction_liquid = nullptr;
180  }
181 
182  reactions_it = input_record_.find<Input::AbstractRecord>("reaction_solid");
183  if ( reactions_it )
184  {
185  if (reactions_it->type() == FirstOrderReaction::input_type ) {
186  reaction_solid = new FirstOrderReaction(*mesh_, *reactions_it);
187  } else
188  if (reactions_it->type() == RadioactiveDecay::input_type) {
189  reaction_solid = new RadioactiveDecay(*mesh_, *reactions_it);
190  } else
191  if (reactions_it->type() == SorptionBase::input_type ) {
192  THROW( ReactionTerm::ExcWrongDescendantModel()
193  << ReactionTerm::EI_Model((*reactions_it).type().type_name())
194  << (*reactions_it).ei_address());
195  } else
196  if (reactions_it->type() == DualPorosity::input_type ) {
197  THROW( ReactionTerm::ExcWrongDescendantModel()
198  << ReactionTerm::EI_Model((*reactions_it).type().type_name())
199  << (*reactions_it).ei_address());
200  } else
201  if (reactions_it->type() == Semchem_interface::input_type )
202  { THROW( ReactionTerm::ExcWrongDescendantModel()
203  << ReactionTerm::EI_Model((*reactions_it).type().type_name())
204  << EI_Message("This model is not currently supported!")
205  << (*reactions_it).ei_address());
206  } else
207  { //This point cannot be reached. The TYPE_selection will throw an error first.
208  THROW( ExcMessage()
209  << EI_Message("Descending model type selection failed (SHOULD NEVER HAPPEN).")
210  << (*reactions_it).ei_address());
211  }
212  } else
213  {
214  reaction_solid = nullptr;
215  }
216 }
217 
219 {
220  ASSERT(distribution_ != nullptr, "Distribution has not been set yet.\n");
221  ASSERT(time_ != nullptr, "Time governor has not been set yet.\n");
222  ASSERT(output_stream_,"Null output stream.");
224 
225  initialize_substance_ids(); //computes present substances and sets indices
226  initialize_from_input(); //reads non-field data from input
227 
228  //isotherms array resized bellow
229  unsigned int nr_of_regions = mesh_->region_db().bulk_size();
230  isotherms.resize(nr_of_regions);
231  for(unsigned int i_reg = 0; i_reg < nr_of_regions; i_reg++)
232  {
233  isotherms[i_reg].resize(n_substances_);
234  for(unsigned int i_subst = 0; i_subst < n_substances_; i_subst++)
235  {
236  isotherms[i_reg][i_subst] = Isotherm();
237  }
238  }
239 
240  //allocating new array for sorbed concentrations
241  conc_solid = (double**) xmalloc(substances_.size() * sizeof(double*));//new double * [n_substances_];
242  conc_solid_out.clear();
243  conc_solid_out.resize( substances_.size() );
244  for (unsigned int sbi = 0; sbi < substances_.size(); sbi++)
245  {
246  conc_solid[sbi] = (double*) xmalloc(distribution_->lsize() * sizeof(double));//new double[ nr_of_local_elm ];
247  conc_solid_out[sbi].resize( distribution_->size() );
248  //zero initialization of solid concentration for all substances
249  for(unsigned int i=0; i < distribution_->lsize(); i++)
250  conc_solid[sbi][i] = 0;
251  }
252 
254 
256 
257  if(reaction_liquid != nullptr)
258  {
263  }
264  if(reaction_solid != nullptr)
265  {
270  }
271 }
272 
273 
275 {
276  Input::Array substances_array = input_record_.val<Input::Array>("substances");
277  unsigned int k, global_idx, i_subst = 0;
278  bool found;
279  Input::Iterator<string> spec_iter = substances_array.begin<string>();
280 
281  for(; spec_iter != substances_array.end(); ++spec_iter, i_subst++)
282  {
283  //finding the name of a substance in the global array of names
284  found = false;
285  for(k = 0; k < substances_.size(); k++)
286  {
287  if (*spec_iter == substances_[k].name())
288  {
289  global_idx = k;
290  found = true;
291  break;
292  }
293  }
294 
295  if(!found)
296  THROW(ReactionTerm::ExcUnknownSubstance()
297  << ReactionTerm::EI_Substance(*spec_iter)
298  << substances_array.ei_address());
299 
300  //finding the global index of substance in the local array
301  found = false;
302  for(k = 0; k < substance_global_idx_.size(); k++)
303  {
304  if(substance_global_idx_[k] == global_idx)
305  {
306  found = true;
307  break;
308  }
309  }
310 
311  if(!found)
312  {
313  substance_global_idx_.push_back(global_idx);
314  }
315 
316  }
318 }
319 
321 {
322  // read number of interpolation steps - value checked by the record definition
323  n_interpolation_steps_ = input_record_.val<int>("substeps");
324 
325  // read the density of solvent - value checked by the record definition
326  solvent_density_ = input_record_.val<double>("solvent_density");
327 
328  // read the solubility vector
329  Input::Iterator<Input::Array> solub_iter = input_record_.find<Input::Array>("solubility");
330  if( solub_iter )
331  {
332  if (solub_iter->Array::size() != n_substances_)
333  {
334  THROW(SorptionBase::ExcSubstanceCountMatch()
335  << SorptionBase::EI_ArrayName("solubility")
337  // there is no way to get ei_address from 'solub_iter', only as a string
338  }
339 
340  else solub_iter->copy_to(solubility_vec_);
341  }
342  else{
343  // fill solubility_vec_ with zeros
344  solubility_vec_.clear();
345  solubility_vec_.resize(n_substances_,0.0);
346  }
347 
348  // read the interpolation table limits
349  Input::Iterator<Input::Array> interp_table_limits = input_record_.find<Input::Array>("table_limits");
350  if( interp_table_limits )
351  {
352  if (interp_table_limits->Array::size() != n_substances_)
353  {
354  THROW(SorptionBase::ExcSubstanceCountMatch()
355  << SorptionBase::EI_ArrayName("table_limits")
357  // there is no way to get ei_address from 'interp_table_limits', only as a string
358  }
359 
360  else interp_table_limits->copy_to(table_limit_);
361  }
362  else{
363  // fill table_limit_ with zeros
364  table_limit_.clear();
365  table_limit_.resize(n_substances_,0.0);
366  }
367 }
368 
370 {
371  ASSERT(n_substances_ > 0, "Number of substances is wrong, they might have not been set yet.\n");
372 
373  // read fields from input file
375 
377  data_->set_mesh(*mesh_);
379 
380  //initialization of output
381  output_array = input_record_.val<Input::Array>("output_fields");
387  for (unsigned int sbi=0; sbi<substances_.size(); sbi++)
388  {
389  // create shared pointer to a FieldElementwise and push this Field to output_field on all regions
390  auto output_field_ptr = conc_solid_out[sbi].create_field<3, FieldValue<3>::Scalar>(substances_.size());
391  data_->conc_solid[sbi].set_field(mesh_->region_db().get_region_set("ALL"), output_field_ptr, 0);
392  }
394 }
395 
396 
398 {
399  ASSERT(distribution_ != nullptr, "Distribution has not been set yet.\n");
400  ASSERT(time_ != nullptr, "Time governor has not been set yet.\n");
401  ASSERT(output_stream_,"Null output stream.");
403 
404  data_->set_time(time_->step());
406  make_tables();
407 
408  // write initial condition
412 
414  if(reaction_solid != nullptr) reaction_solid->zero_time_step();
415 }
416 
418 {
419  for (unsigned int loc_el = 0; loc_el < distribution_->lsize(); loc_el++)
420  {
421  unsigned int index = el_4_loc_[loc_el];
422  ElementAccessor<3> ele_acc = mesh_->element_accessor(index);
423  arma::vec value = data_->init_conc_solid.value(ele_acc.centre(),
424  ele_acc);
425 
426  //setting initial solid concentration for substances involved in adsorption
427  for (unsigned int sbi = 0; sbi < n_substances_; sbi++)
428  {
429  int subst_id = substance_global_idx_[sbi];
430  conc_solid[subst_id][loc_el] = value(sbi);
431  }
432  }
433 }
434 
435 
437 {
438  data_->set_time(time_->step()); // set to the last computed time
439 
440  // if parameters changed during last time step, reinit isotherms and eventualy
441  // update interpolation tables in the case of constant rock matrix parameters
442  if(data_->changed())
443  make_tables();
444 
445 
446  START_TIMER("Sorption");
447  for (unsigned int loc_el = 0; loc_el < distribution_->lsize(); loc_el++)
448  {
450  }
451  END_TIMER("Sorption");
452 
455 }
456 
458 {
459  try
460  {
461  ElementAccessor<3> elm;
462  BOOST_FOREACH(const Region &reg_iter, this->mesh_->region_db().get_region_set("BULK") )
463  {
464  int reg_idx = reg_iter.bulk_idx();
465 
466  if(data_->is_constant(reg_iter))
467  {
468  ElementAccessor<3> elm(this->mesh_, reg_iter); // constant element accessor
469  isotherm_reinit(isotherms[reg_idx],elm);
470  for(unsigned int i_subst = 0; i_subst < n_substances_; i_subst++)
471  {
472  isotherms[reg_idx][i_subst].make_table(n_interpolation_steps_);
473  }
474  }
475  }
476  }
477  catch(ExceptionBase const &e)
478  {
479  e << input_record_.ei_address();
480  throw;
481  }
482 }
483 
484 double **SorptionBase::compute_reaction(double **concentrations, int loc_el)
485 {
486  ElementFullIter elem = mesh_->element(el_4_loc_[loc_el]);
487  int reg_idx = elem->region().bulk_idx();
488  unsigned int i_subst, subst_id;
489 
490  std::vector<Isotherm> & isotherms_vec = isotherms[reg_idx];
491 
492  try{
493  // Constant value of rock density and mobile porosity over the whole region
494  // => interpolation_table is precomputed
495  if (isotherms_vec[0].is_precomputed())
496  {
497  for(i_subst = 0; i_subst < n_substances_; i_subst++)
498  {
499  subst_id = substance_global_idx_[i_subst];
500 
501  isotherms_vec[i_subst].interpolate(concentration_matrix_[subst_id][loc_el],
502  conc_solid[subst_id][loc_el]);
503  }
504  }
505  else
506  {
507  isotherm_reinit(isotherms_vec, elem->element_accessor());
508 
509  for(i_subst = 0; i_subst < n_substances_; i_subst++)
510  {
511  subst_id = substance_global_idx_[i_subst];
512  isotherms_vec[i_subst].compute(concentration_matrix_[subst_id][loc_el],
513  conc_solid[subst_id][loc_el]);
514  }
515  }
516  }
517  catch(ExceptionBase const &e)
518  {
519  e << input_record_.ei_address();
520  throw;
521  }
522 
523  return concentrations;
524 }
525 
526 
527 /**************************************** OUTPUT ***************************************************/
528 
530 {
531  int sbi, n_subst;
532  n_subst = substances_.size();
533 
534  vconc_solid = (Vec*) xmalloc(n_subst * (sizeof(Vec)));
535 
536  for (sbi = 0; sbi < n_subst; sbi++) {
537  VecCreateMPIWithArray(PETSC_COMM_WORLD,1, distribution_->lsize(), mesh_->n_elements(), conc_solid[sbi],
538  &vconc_solid[sbi]);
539  VecZeroEntries(vconc_solid[sbi]);
540 
541  VecZeroEntries(conc_solid_out[sbi].get_data_petsc());
542  }
543 
544  // creating output vector scatter
545  IS is;
546  ISCreateGeneral(PETSC_COMM_SELF, mesh_->n_elements(), row_4_el_, PETSC_COPY_VALUES, &is); //WithArray
547  VecScatterCreate(vconc_solid[0], is, conc_solid_out[0].get_data_petsc(), PETSC_NULL, &vconc_out_scatter);
548  ISDestroy(&(is));
549 }
550 
551 
553 {
554  unsigned int sbi;
555 
556  for (sbi = 0; sbi < substances_.size(); sbi++) {
557  VecScatterBegin(vconc_out_scatter, vconc_solid[sbi], conc_solid_out[sbi].get_data_petsc(), INSERT_VALUES, SCATTER_FORWARD);
558  VecScatterEnd(vconc_out_scatter, vconc_solid[sbi], conc_solid_out[sbi].get_data_petsc(), INSERT_VALUES, SCATTER_FORWARD);
559  }
560 }
561 
562 
564 {
566 
567  int rank;
568  MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
569  if (rank == 0)
570  {
571  // Register fresh output data
574  }
575 
576  //for synchronization when measuring time by Profiler
578 }
void output_type(OutputTime::DiscreteSpace rt)
Definition: field_set.hh:194
unsigned int size() const
get global size
void set_input_list(Input::Array input_list)
Definition: field_set.hh:164
Iterator< ValueType > begin() const
virtual void zero_time_step()
Definition: equation.hh:97
void allocate_output_mpi(void)
Allocates petsc vectors, prepares them for output and creates vector scatter.
void set_limit_side(LimitSide side)
Definition: field_set.hh:171
MultiField< 3, FieldValue< 3 >::Scalar > conc_solid
Calculated sorbed concentrations, for output only.
OutputTime * output_stream_
Pointer to a transport output stream.
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:558
double solvent_density_
EI_Address ei_address() const
Definition: accessors.cc:297
ReactionTerm * reaction_liquid
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:252
const std::vector< std::string > & names()
Definition: substance.hh:97
virtual void initialize()
Initialize fields.
Definition: equation.hh:114
void add_admissible_field_names(const Input::Array &in_array)
Registers names of output fields that can be written using this stream.
Definition: output_time.cc:165
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:39
EqData(const string &output_field_name)
Collect all fields.
double ** compute_reaction(double **concentrations, int loc_el)
static Default obligatory()
Definition: type_record.hh:89
???
SubstanceList substances_
Names belonging to substances.
void zero_time_step() override
void set_time(const TimeStep &time)
Definition: field_set.hh:186
static Input::Type::Record input_type
RegionSet get_region_set(const string &set_name) const
Definition: region.cc:361
Definition: mesh.h:109
Iterator< Ret > find(const string &key) const
int * row_4_el_
Indices of rows belonging to elements.
Record & derive_from(AbstractRecord &parent)
Definition: type_record.cc:197
const RegionDB & region_db() const
Definition: mesh.h:155
static Input::Type::Record input_type
Input record for class FirstOrderReaction.
ElementAccessor< 3 > element_accessor(unsigned int idx, bool boundary=false)
Definition: mesh.cc:670
static Input::Type::Selection sorption_type_selection
Field< 3, FieldValue< 3 >::Vector > init_conc_solid
Initial sorbed concentrations.
const TimeStep & step(int index=-1) const
std::vector< double > table_limit_
Class for declaration of the integral input data.
Definition: type_base.hh:355
#define ADD_FIELD(name,...)
Definition: field_set.hh:260
unsigned int size() const
Definition: substance.hh:99
Class for declaration of inputs sequences.
Definition: type_base.hh:239
std::vector< unsigned int > substance_global_idx_
Mapping from local indexing of substances to global.
void initialize_fields()
Initializes field sets.
IteratorBase end() const
static Input::Type::AbstractRecord input_type
EI_Address ei_address() const
Definition: accessors.cc:187
static Default optional()
Definition: type_record.hh:102
static Input::Type::Record input_type
unsigned int n_elements() const
Definition: mesh.h:141
#define ASSERT(...)
Definition: global_defs.h:121
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:392
Distribution * distribution_
Pointer to reference to distribution of elements between processors.
void output_data(void) override
Output method.
static constexpr Mask input_copy
A field that is input of its equation and can not read from input, thus must be set by copy...
Definition: field_flag.hh:29
Vec * vconc_solid
PETSC sorbed concentration vector (parallel).
FieldSet output_fields
Fields indended for output, i.e. all input fields plus those representing solution.
void initialize_from_input()
Initializes private members of sorption from the input record.
std::vector< double > solubility_vec_
Selection & add_value(const int value, const std::string &key, const std::string &description="")
Class implements the radioactive decay chain.
Accessor to the data with type Type::Record.
Definition: accessors.hh:327
unsigned int n_interpolation_steps_
const Ret val(const string &key) const
void make_tables(void)
#define ASSERT_LESS(a, b)
Definition: global_defs.h:164
#define START_TIMER(tag)
Starts a timer with specified tag.
Mesh * mesh_
Definition: equation.hh:218
virtual void isotherm_reinit(std::vector< Isotherm > &isotherms, const ElementAccessor< 3 > &elm)=0
Reinitializes the isotherm.
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm) const
Definition: field.hh:312
ReactionTerm * reaction_solid
void set_up_components()
static Input::Type::Record input_type
static Input::Type::Record record_factory(SorptionRecord::Type)
Creates the input record for different cases of sorption model (simple or in dual porosity)...
void output_vector_gather(void) override
Gathers all the parallel vectors to enable them to be output.
Input::Array output_array
void update_solution(void) override
Updates the solution.
void * xmalloc(size_t size)
Memory allocation with checking.
Definition: system.cc:209
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:448
#define MPI_Comm_rank
Definition: mpi.h:236
virtual void set_time_governor(TimeGovernor &time)
Definition: equation.cc:80
Record & copy_keys(const Record &other)
Definition: type_record.cc:211
Support classes for parallel programing.
virtual void update_solution()
Definition: equation.hh:105
void output(OutputTime *stream)
Definition: field_set.cc:143
Input::Record input_record_
Definition: equation.hh:220
void set_components(const std::vector< string > &names)
Definition: field_set.hh:151
int * el_4_loc_
Indices of elements belonging to local dofs.
void set_initial_condition()
Reads and sets initial condition for concentration in solid.
bool is_constant(Region reg) const
Definition: field_set.cc:135
unsigned int bulk_idx() const
Returns index of the region in the bulk set.
Definition: region.hh:80
#define MPI_COMM_WORLD
Definition: mpi.h:123
#define END_TIMER(tag)
Ends a timer with specified tag.
static Input::Type::Record input_type
Input record for class RadioactiveDecay.
arma::vec::fixed< spacedim > centre() const
Definition: accessors.hh:81
double ** conc_solid
void set_mesh(const Mesh &mesh)
Definition: field_set.hh:157
void set_components(const std::vector< string > &names)
Record type proxy class.
Definition: type_record.hh:169
VecScatter vconc_out_scatter
Output vector scatter.
Base of exceptions used in Flow123d.
Definition: exceptions.hh:55
Class implements the linear reactions.
unsigned int n_substances_
#define xfree(p)
Definition: system.hh:108
Class for representation SI units of Fields.
Definition: unit_si.hh:31
#define MPI_Barrier(comm)
Definition: mpi.h:531
EqData * data_
Pointer to equation data. The object is constructed in descendants.
static UnitSI & dimensionless()
Returns dimensionless unit.
Definition: unit_si.cc:44
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:34
ReactionTerm & concentration_matrix(double **concentration, Distribution *conc_distr, int *el_4_loc, int *row_4_el)
bool changed() const
Definition: field_set.cc:127
Template for classes storing finite set of named values.
ReactionTerm & substances(SubstanceList &substances)
Sets the names of substances considered in transport.
TimeGovernor * time_
Definition: equation.hh:219
ElementVector element
Vector of elements of the mesh.
Definition: mesh.h:205
FieldSet input_data_set_
Input data set - fields in this set are read from the input file.
unsigned int lsize(int proc) const
get local size
Record & declare_key(const string &key, const KeyType &type, const Default &default_value, const string &description)
Definition: type_record.cc:430
void initialize() override
Prepares the object to usage.