Flow123d  release_1.8.2-1603-g0109a2b
transport_operator_splitting.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 transport_operator_splitting.cc
15  * @brief
16  */
17 
18 #include <iostream>
19 #include <iomanip>
20 
21 #include "system/system.hh"
22 #include "system/sys_profiler.hh"
23 #include "system/xio.h"
24 
26 #include <petscmat.h>
27 
28 #include "io/output_time.hh"
29 #include "tools/time_governor.hh"
30 #include "system/sys_vector.hh"
31 #include "coupling/equation.hh"
32 #include "coupling/balance.hh"
33 #include "transport/transport.h"
34 #include "mesh/mesh.h"
35 
39 #include "reaction/sorption.hh"
41 
43 
44 #include "la/distribution.hh"
45 #include "input/input_type.hh"
46 #include "input/accessors.hh"
47 #include "input/factory.hh"
48 
49 FLOW123D_FORCE_LINK_IN_CHILD(transportOperatorSplitting);
50 
51 FLOW123D_FORCE_LINK_IN_PARENT(firstOrderReaction);
52 FLOW123D_FORCE_LINK_IN_PARENT(radioactiveDecay);
53 FLOW123D_FORCE_LINK_IN_PARENT(dualPorosity);
54 FLOW123D_FORCE_LINK_IN_PARENT(sorptionMobile);
55 FLOW123D_FORCE_LINK_IN_PARENT(sorptionImmobile);
57 
58 
59 using namespace Input::Type;
60 
61 
62 
64  return Abstract("Transport",
65  "Transport of substances.")
66  .close();
67 }
68 
69 
71  return Record("Transport_OS",
72  "Transport by convection and/or diffusion\n"
73  "coupled with reaction and adsorption model (ODE per element)\n"
74  " via operator splitting.")
77  "Time governor setting for the secondary equation.")
79  "Settings for computing balance.")
81  "Parameters of output stream.")
83  "Specification of transported substances.")
84  // input data
86  "Type of numerical method for solute transport.")
88  "Reaction model involved in transport.")
89 /*
90  .declare_key("output_fields", Array(ConvectionTransport::get_output_selection()),
91  Default("\"conc\""),
92  "List of fields to write to output file.")*/
93  .close();
94 }
95 
96 
98  Input::register_class< TransportOperatorSplitting, Mesh &, const Input::Record>("Transport_OS") +
100 
101 
102 
103 
104 
105 
106 
108 {
109 
110  ADD_FIELD(porosity, "Mobile porosity", "1");
111  porosity.units( UnitSI::dimensionless() ).flags_add(in_time_term & in_main_matrix & in_rhs);
112 
113  ADD_FIELD(cross_section, "");
114  cross_section.flags( FieldFlag::input_copy ).flags_add(in_time_term & in_main_matrix & in_rhs);
115 
116  ADD_FIELD(sources_density, "Density of concentration sources.", "0");
117  sources_density.units( UnitSI().kg().m(-3).s(-1) )
118  .flags_add(in_rhs);
119 
120  ADD_FIELD(sources_sigma, "Concentration flux.", "0");
121  sources_sigma.units( UnitSI().s(-1) )
122  .flags_add(in_main_matrix & in_rhs);
123 
124  ADD_FIELD(sources_conc, "Concentration sources threshold.", "0");
125  sources_conc.units( UnitSI().kg().m(-3) )
126  .flags_add(in_rhs);
127 }
128 
129 
130 
131 
132 
133 
134 
135 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
136 
137 
138 
140 : AdvectionProcessBase(init_mesh, in_rec),
141  convection(NULL),
142  Semchem_reactions(NULL)
143 {
144  START_TIMER("TransportOperatorSpliting");
145 
146  Distribution *el_distribution;
147  int *el_4_loc;
148 
149  Input::AbstractRecord trans = in_rec.val<Input::AbstractRecord>("transport");
150  convection = trans.factory< ConcentrationTransportBase, Mesh &, const Input::Record >(init_mesh, trans);
151 
152  convection->set_time_governor(*(new TimeGovernor(in_rec.val<Input::Record>("time"))));
153 
154  // Initialize list of substances.
155  convection->substances().initialize(in_rec.val<Input::Array>("substances"));
156 
157  // Initialize output stream.
158  convection->set_output_stream(OutputTime::create_output_stream(in_rec.val<Input::Record>("output_stream")));
159 
160 
161  // initialization of balance object
163  if (it->val<bool>("balance_on"))
164  {
165  balance_ = boost::make_shared<Balance>("mass", mesh_, *it);
166  balance_->units(UnitSI().kg(1));
167  convection->set_balance_object(balance_);
168  }
169 
170  convection->initialize();
171 
172  time_ = new TimeGovernor(in_rec.val<Input::Record>("time"), convection->mark_type());
173 
174  this->eq_data_ = &(convection->data());
175 
176  convection->get_par_info(el_4_loc, el_distribution);
177  Input::Iterator<Input::AbstractRecord> reactions_it = in_rec.find<Input::AbstractRecord>("reaction_term");
178  if ( reactions_it ) {
179  // TODO: allowed instances in this case are only
180  // FirstOrderReaction, RadioactiveDecay, SorptionSimple and DualPorosity
181  reaction = (*reactions_it).factory< ReactionTerm, Mesh &, Input::Record >(init_mesh, *reactions_it);
182 
183  reaction->substances(convection->substances())
184  .concentration_matrix(convection->get_concentration_matrix(),
185  el_distribution, el_4_loc, convection->get_row_4_el())
186  .output_stream(convection->output_stream())
187  .set_time_governor((TimeGovernor &)convection->time());
188 
189  reaction->initialize();
190 
191  } else {
192  reaction = nullptr;
193  Semchem_reactions = nullptr;
194  }
195 
196  //coupling - passing fields
197  if(reaction)
198  if( typeid(*reaction) == typeid(SorptionSimple) ||
199  typeid(*reaction) == typeid(DualPorosity)
200  )
201  {
202  reaction->data().set_field("porosity", convection->data()["porosity"]);
203  }
204 }
205 
207 {
208  //delete field_output;
210  delete time_;
211 }
212 
213 
214 
215 
217 
218 
219  START_TIMER("TOS-output data");
220 
221 
222  convection->output_data();
223  if(reaction) reaction->output_data(); // do not perform write_time_frame
224  convection->output_stream()->write_time_frame();
225 
226  if (balance_ != nullptr && time_->is_current( time_->marks().type_output() ))
227  {
228  START_TIMER("TOS-balance");
229  convection->calculate_instant_balance();
230  balance_->output(time_->t());
231  END_TIMER("TOS-balance");
232  }
233 
234  END_TIMER("TOS-output data");
235 }
236 
237 
239 {
240  //DBGMSG("tos ZERO TIME STEP.\n");
241  convection->zero_time_step();
242  if(reaction) reaction->zero_time_step();
243  convection->output_stream()->write_time_frame();
244  if (balance_ != nullptr) balance_->output(time_->t());
245 
246 }
247 
248 
249 
251 
252  vector<double> source(convection->n_substances()), region_mass(mesh_->region_db().bulk_size());
253 
254  time_->next_time();
255  time_->view("TOS"); //show time governor
256 
257  convection->set_target_time(time_->t());
258 
259  START_TIMER("TOS-one step");
260  int steps=0;
261  while ( convection->time().step().lt(time_->t()) )
262  {
263  steps++;
264  // one internal step
265  double cfl_convection, cfl_reaction;
266  bool cfl_changed = convection->evaluate_time_constraint(cfl_convection);
267  //|| reaction->evaluate_time_constraint(cfl_reaction);
268  if (cfl_changed)
269  //|| reaction->assess_time_constraint(cfl_reaction)
270  {
271  DBGMSG("CFL changed.\n");
272  convection->time().set_upper_constraint(cfl_convection, "Time step constrained due to CFL condition (including both flow and sources).");
273 // convection->time_->set_upper_constraint(std::min(cfl_convection, cfl_reaction));
274 
275  // fix step with new constraint
276  convection->time().fix_dt_until_mark();
277  }
278 
279  if (steps == 1 || cfl_changed) convection->time().view("Convection"); // write TG only once on change
280 
281  convection->update_solution();
282 
283 
284  if (balance_ != nullptr && balance_->cumulative())
285  {
286  START_TIMER("TOS-balance");
287 
288  // save mass after transport step
289  for (unsigned int sbi=0; sbi<convection->n_substances(); sbi++)
290  {
291  balance_->calculate_mass(convection->get_subst_idx()[sbi], convection->get_solution(sbi), region_mass);
292  source[sbi] = 0;
293  for (unsigned int ri=0; ri<mesh_->region_db().bulk_size(); ri++)
294  source[sbi] -= region_mass[ri];
295  }
296 
297  END_TIMER("TOS-balance");
298  }
299 
300  if(reaction) {
301  convection->calculate_concentration_matrix();
302  reaction->update_solution();
303  convection->update_after_reactions(true);
304  }
305  else
306  convection->update_after_reactions(false);
307 
309 
310 
311 
312  if (balance_ != nullptr && balance_->cumulative())
313  {
314  START_TIMER("TOS-balance");
315 
316  for (unsigned int sbi=0; sbi<convection->n_substances(); sbi++)
317  {
318  // compute mass difference due to reactions
319  balance_->calculate_mass(convection->get_subst_idx()[sbi], convection->get_solution(sbi), region_mass);
320  for (unsigned int ri=0; ri<mesh_->region_db().bulk_size(); ri++)
321  source[sbi] += region_mass[ri];
322 
323  // update balance of sources due to reactions
324  balance_->add_cumulative_source(sbi, source[sbi]);
325  }
326 
327  END_TIMER("TOS-balance");
328  }
329  }
330 
331  xprintf( MsgLog, " CONVECTION: steps: %d\n",steps);
332 }
333 
334 
335 
336 
337 
339 {
340  convection->set_velocity_field( dh );
341 };
342 
343 
344 
345 
FieldSet * eq_data_
Definition: equation.hh:230
static const Input::Type::Record & get_input_type()
Main balance input record type.
Definition: balance.cc:42
Abstract base class for equation clasess.
#define DBGMSG(...)
Definition: global_defs.h:229
#define ADD_FIELD(name,...)
Definition: field_set.hh:275
Accessor to input data conforming to declared Array.
Definition: accessors.hh:552
unsigned int size() const
Returns number of keys in the Record.
Definition: type_record.hh:578
unsigned int bulk_size() const
Definition: region.cc:261
static const Input::Type::Record & get_input_type()
Declare input record type for the equation TransportOperatorSplittiong.
static Input::Type::Abstract & get_input_type()
virtual void set_velocity_field(const MH_DofHandler &dh) override
void next_time()
Proceed to the next time according to current estimated time step.
TimeMark::Type type_output()
Definition: time_marks.hh:190
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:99
Definition: mesh.h:99
Iterator< Ret > find(const string &key) const
bool is_current(const TimeMark::Type &mask) const
const RegionDB & region_db() const
Definition: mesh.h:156
static const Input::Type::Record & get_input_type()
The specification of output stream.
Definition: output_time.cc:34
static const Input::Type::Record & get_input_type()
Input type for a substance.
Definition: substance.cc:29
TransportOperatorSplitting(Mesh &init_mesh, const Input::Record in_rec)
Constructor.
static Input::Type::Abstract & get_input_type()
Common specification of the input record for secondary equations.
double t() const
Abstract & close()
Can be used to close the Abstract for further declarations of keys.
I/O functions with filename storing, able to track current line in opened file. All standard stdio fu...
Basic time management functionality for unsteady (and steady) solvers (class Equation).
static TimeMarks & marks()
Definition: system.hh:59
Basic time management class.
Class for declaration of inputs sequences.
Definition: type_base.hh:316
void view(const char *name="") const
Class ReactionTerm is an abstract class representing reaction term in transport.
Class Dual_por_exchange implements the model of dual porosity.
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:193
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:113
static Input::Type::Abstract & get_input_type()
Common specification of the input record for secondary equations.
std::shared_ptr< ReactionTerm > reaction
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:39
Accessor to the data with type Type::Record.
Definition: accessors.hh:277
const Ret val(const string &key) const
#define xprintf(...)
Definition: system.hh:87
#define START_TIMER(tag)
Starts a timer with specified tag.
Mesh * mesh_
Definition: equation.hh:221
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:459
const Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:271
FLOW123D_FORCE_LINK_IN_CHILD(transportOperatorSplitting)
Class for declaration of polymorphic Record.
Class representing dual porosity model in transport.
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:444
static std::shared_ptr< OutputTime > create_output_stream(const Input::Record &in_rec)
This method delete all object instances of class OutputTime stored in output_streams vector...
Definition: output_time.cc:134
virtual void set_time_governor(TimeGovernor &time)
Definition: equation.cc:55
Support classes for parallel programing.
void output_data() override
Write computed fields.
std::shared_ptr< ConcentrationTransportBase > convection
FLOW123D_FORCE_LINK_IN_PARENT(firstOrderReaction)
Vector classes to support both Iterator, index and Id access and creating co-located vectors...
static const Input::Type::Record & get_input_type()
#define END_TIMER(tag)
Ends a timer with specified tag.
boost::shared_ptr< Balance > balance_
object for calculation and writing the mass balance to file.
Definition: equation.hh:233
Simple sorption model without dual porosity.
Definition: sorption.hh:39
Record type proxy class.
Definition: type_record.hh:171
const std::shared_ptr< Type > factory(Arguments...arguments) const
Class for representation SI units of Fields.
Definition: unit_si.hh:40
static UnitSI & dimensionless()
Returns dimensionless unit.
Definition: unit_si.cc:53
This file contains classes representing sorption model. Sorption model can be computed both in case t...
TimeGovernor * time_
Definition: equation.hh:222
virtual ~TransportOperatorSplitting()
Destructor.
static const int registrar
Registrar of class to factory.