Flow123d  JS_before_hm-1804-gf2ad740aa
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/index_types.hh"
24 
26 #include <petscmat.h>
27 
28 #include "io/output_time.hh"
29 #include "tools/time_governor.hh"
30 #include "coupling/equation.hh"
31 #include "coupling/balance.hh"
32 #include "transport/transport.h"
33 #include "mesh/mesh.h"
34 
38 #include "reaction/sorption.hh"
40 
41 #include "la/distribution.hh"
42 #include "input/input_type.hh"
43 #include "input/accessors.hh"
44 #include "input/factory.hh"
46 #include "fem/fe_p.hh"
47 
48 FLOW123D_FORCE_LINK_IN_CHILD(transportOperatorSplitting)
49 
50 FLOW123D_FORCE_LINK_IN_PARENT(firstOrderReaction)
51 FLOW123D_FORCE_LINK_IN_PARENT(radioactiveDecay)
53 FLOW123D_FORCE_LINK_IN_PARENT(sorptionMobile)
54 FLOW123D_FORCE_LINK_IN_PARENT(sorptionImmobile)
56 
57 
58 using namespace Input::Type;
59 
60 
61 
63  return Abstract("Solute",
64  "Transport of soluted substances.")
65  .close();
66 }
67 
68 
70  return Record("Coupling_OperatorSplitting",
71  "Transport by convection and/or diffusion\n"
72  "coupled with reaction and adsorption model (ODE per element)\n"
73  " via operator splitting.")
75  .add_attribute( FlowAttribute::subfields_address(), "\"/problem/solute_equation/substances/*/name\"")
77  .declare_key("balance", Balance::get_input_type(), Default("{}"),
78  "Settings for computing mass balance.")
79  .declare_key("output_stream", OutputTime::get_input_type(), Default("{}"),
80  "Output stream settings.\n Specify file format, precision etc.")
82  "Specification of transported substances.")
83  // input data
85  "Type of the numerical method for the transport equation.")
87  "Reaction model involved in transport.")
88 /*
89  .declare_key("output_fields", Array(ConvectionTransport::get_output_selection()),
90  Default("\"conc\""),
91  "List of fields to write to output file.")*/
92  .close();
93 }
94 
95 
97  Input::register_class< TransportOperatorSplitting, Mesh &, const Input::Record>("Coupling_OperatorSplitting") +
99 
100 
101 
102 
103 
104 
105 
107 {
108  *this += porosity.name("porosity")
109  .description("Porosity of the mobile phase.")
110  .input_default("1.0")
111  .units( UnitSI::dimensionless() )
112  .flags_add(in_main_matrix & in_rhs);
113 
114  *this += water_content.name("water_content")
115  .description("INTERNAL. Water content passed from unsaturated Darcy flow model.")
116  .units( UnitSI::dimensionless() )
117  .flags_add(input_copy & in_time_term & in_main_matrix & in_rhs);
118 
119  *this += cross_section.name("cross_section")
120  .flags( FieldFlag::input_copy )
121  .flags_add(in_time_term & in_main_matrix & in_rhs);
122 
123  *this += flow_flux.name("flow_flux")
124  .flags( FieldFlag::input_copy )
125  .flags_add(in_time_term & in_main_matrix & in_rhs);
126 
127  *this += sources_density.name("sources_density")
128  .description("Density of concentration sources.")
129  .input_default("0.0")
130  .units( UnitSI().kg().m(-3).s(-1) )
131  .flags_add(in_rhs);
132 
133  *this += sources_sigma.name("sources_sigma")
134  .description("Concentration flux.")
135  .input_default("0.0")
136  .units( UnitSI().s(-1) )
137  .flags_add(in_main_matrix & in_rhs);
138 
139  *this += sources_conc.name("sources_conc")
140  .description("Concentration sources threshold.")
141  .input_default("0.0")
142  .units( UnitSI().kg().m(-3) )
143  .flags_add(in_rhs);
144 }
145 
146 
147 
148 
149 
150 
151 
152 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
153 
154 
155 
157 : AdvectionProcessBase(init_mesh, in_rec),
158  cfl_convection(numeric_limits<double>::max())
159 {
160  START_TIMER("TransportOperatorSpliting");
161 
162  Distribution *el_distribution;
163  LongIdx *el_4_loc;
164 
165  Input::AbstractRecord trans = in_rec.val<Input::AbstractRecord>("transport");
166  convection = trans.factory< ConcentrationTransportBase, Mesh &, const Input::Record >(init_mesh, trans);
167 
168  time_ = new TimeGovernor(in_rec.val<Input::Record>("time"), TimeMark::none_type, false);
169  ASSERT( time_->is_default() == false ).error("Missing key 'time' in Coupling_OperatorSplitting.");
170  convection->set_time_governor(time());
171 
172  // Initialize list of substances.
173  convection->substances().initialize(in_rec.val<Input::Array>("substances"));
174 
175  // Initialize output stream.
176  std::shared_ptr<OutputTime> stream = OutputTime::create_output_stream("solute", in_rec.val<Input::Record>("output_stream"), time().get_unit_conversion());
177  convection->set_output_stream(stream);
178 
179 
180  // initialization of balance object
181 
182  balance_ = make_shared<Balance>("mass", mesh_);
183  balance_->init_from_input(in_rec.val<Input::Record>("balance"), this->time());
184 
185  balance_->units(UnitSI().kg(1));
186  convection->set_balance_object(balance_);
187 
188  convection->initialize(); //
189 
190 
191 
192 
193  time_ = new TimeGovernor(in_rec.val<Input::Record>("time"), convection->mark_type());
194 
195  this->eq_fieldset_ = &(convection->eq_fieldset());
196 
197  convection->get_par_info(el_4_loc, el_distribution);
198  Input::Iterator<Input::AbstractRecord> reactions_it = in_rec.find<Input::AbstractRecord>("reaction_term");
199  if ( reactions_it ) {
200  // TODO: allowed instances in this case are only
201  // FirstOrderReaction, RadioactiveDecay, SorptionSimple and DualPorosity
202  reaction = (*reactions_it).factory< ReactionTerm, Mesh &, Input::Record >(init_mesh, *reactions_it);
203 
204  //initialization of DOF handler
205  static MixedPtr<FE_P_disc> fe(0);
206  shared_ptr<DOFHandlerMultiDim> dof_handler = make_shared<DOFHandlerMultiDim>(*mesh_);
207  shared_ptr<DiscreteSpace> ds = make_shared<EqualOrderDiscreteSpace>( mesh_, fe);
208  dof_handler->distribute_dofs(ds);
209 
210  reaction->substances(convection->substances())
211  .concentration_fields(convection->get_p0_interpolation())
212  .output_stream(stream)
213  .set_time_governor((TimeGovernor &)convection->time());
214 
215  reaction->initialize();
216 
217  } else {
218  reaction = nullptr;
219  //Semchem_reactions = nullptr;
220  }
221 }
222 
224 {
225  //delete field_output;
226  //if (Semchem_reactions) delete Semchem_reactions;
227  delete time_;
228 }
229 
230 
232 {
233  //coupling - passing fields
234  if(reaction)
235  if( typeid(*reaction) == typeid(SorptionSimple) ||
236  typeid(*reaction) == typeid(DualPorosity)
237  )
238  {
239  reaction->eq_fieldset().set_field("porosity", convection->eq_fieldset()["porosity"]);
240  }
241 }
242 
243 
244 
245 
247 
248 
249  START_TIMER("TOS-output data");
250 
251 
252  convection->output_data();
253  if(reaction) reaction->output_data(); // do not perform write_time_frame
254 
255  END_TIMER("TOS-output data");
256 }
257 
258 
260 {
261  //DebugOut() << "tos ZERO TIME STEP.\n";
262  convection->zero_time_step();
263  convection->compute_p0_interpolation(); // due to reading of init_conc in reactions
264  if(reaction)
265  {
266  reaction->zero_time_step();
267  reaction->output_data(); // do not perform write_time_frame
268  }
269 
270 }
271 
272 
273 
275 
276  vector<double> source(convection->n_substances()), region_mass(mesh_->region_db().bulk_size());
277 
278  time_->next_time();
279  time_->view("TOS"); //show time governor
280 
281  convection->set_target_time(time_->t());
282 
283  START_TIMER("TOS-one step");
284  int steps=0;
285  while ( convection->time().step().lt(time_->t()) )
286  {
287  steps++;
288  // one internal step
289  bool cfl_changed = convection->evaluate_time_constraint(cfl_convection);
290 
291  if (steps == 1 || cfl_changed)
292  {
293  convection->time().set_upper_constraint(cfl_convection, "Time step constrained by transport CFL condition (including both flow and sources).");
294 
295  // fix step with new constraint
296  convection->time().fix_dt_until_mark();
297 
298  convection->time().view("Convection"); // write TG only once on change
299  }
300 
301  convection->update_solution();
302 
303 
304  if (balance_->cumulative())
305  {
306  START_TIMER("TOS-balance");
307 
308  // save mass after transport step
309  for (unsigned int sbi=0; sbi<convection->n_substances(); sbi++)
310  {
311  balance_->calculate_mass(convection->get_subst_idx()[sbi], convection->get_component_vec(sbi), region_mass);
312  source[sbi] = 0;
313  for (unsigned int ri=0; ri<mesh_->region_db().bulk_size(); ri++)
314  source[sbi] -= region_mass[ri];
315  }
316 
317  END_TIMER("TOS-balance");
318  }
319 
320  if(reaction) {
321  convection->compute_p0_interpolation();
322  reaction->update_solution();
323  convection->update_after_reactions(true);
324  }
325  else
326  convection->update_after_reactions(false);
327 
328  //if(Semchem_reactions) Semchem_reactions->update_solution();
329 
330 
331 
332  if (balance_->cumulative())
333  {
334  START_TIMER("TOS-balance");
335 
336  for (unsigned int sbi=0; sbi<convection->n_substances(); sbi++)
337  {
338  // compute mass difference due to reactions
339  balance_->calculate_mass(convection->get_subst_idx()[sbi], convection->get_component_vec(sbi), region_mass);
340  for (unsigned int ri=0; ri<mesh_->region_db().bulk_size(); ri++)
341  source[sbi] += region_mass[ri];
342 
343  // update balance of sources due to reactions
344  balance_->add_cumulative_source(sbi, source[sbi]);
345  }
346 
347  END_TIMER("TOS-balance");
348  }
349  }
350 
351  LogOut().fmt("CONVECTION: steps: {}\n", steps);
352 }
OutputTime::create_output_stream
static std::shared_ptr< OutputTime > create_output_stream(const std::string &equation_name, const Input::Record &in_rec, const std::shared_ptr< TimeUnitConversion > &time_unit_conv)
This method delete all object instances of class OutputTime stored in output_streams vector.
Definition: output_time.cc:187
EquationBase::mesh_
Mesh * mesh_
Definition: equation.hh:218
Input::AbstractRecord::factory
const std::shared_ptr< Type > factory(Arguments... arguments) const
Definition: accessors_impl.hh:135
TransportOperatorSplitting::registrar
static const int registrar
Registrar of class to factory.
Definition: transport_operator_splitting.hh:241
UnitSI::dimensionless
static UnitSI & dimensionless()
Returns dimensionless unit.
Definition: unit_si.cc:55
factory.hh
time_governor.hh
Basic time management class.
ASSERT
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:347
TransportOperatorSplitting::zero_time_step
void zero_time_step() override
Definition: transport_operator_splitting.cc:259
EquationBase::time_
TimeGovernor * time_
Definition: equation.hh:219
distribution.hh
Support classes for parallel programing.
Input::Record::val
const Ret val(const string &key) const
Definition: accessors_impl.hh:31
EquationBase::time
TimeGovernor & time()
Definition: equation.hh:149
FLOW123D_FORCE_LINK_IN_CHILD
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Definition: global_defs.h:157
std::vector< double >
system.hh
DualPorosity
Class representing dual porosity model in transport.
Definition: dual_porosity.hh:50
index_types.hh
fe_p.hh
Definitions of basic Lagrangean finite elements with polynomial shape functions.
TransportOperatorSplitting::initialize
void initialize() override
Definition: transport_operator_splitting.cc:231
Input::Iterator
Definition: accessors.hh:143
TransportOperatorSplitting::TransportOperatorSplitting
TransportOperatorSplitting(Mesh &init_mesh, const Input::Record in_rec)
Constructor.
Definition: transport_operator_splitting.cc:156
Input::Type::Record::size
unsigned int size() const
Returns number of keys in the Record.
Definition: type_record.hh:602
Input::Type::Default
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
Input::Type::Record::derive_from
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:196
Distribution
Definition: distribution.hh:50
LogOut
#define LogOut()
Macro defining 'log' record of log.
Definition: logger.hh:281
EquationBase::balance_
std::shared_ptr< Balance > balance_
object for calculation and writing the mass balance to file.
Definition: equation.hh:230
Input::Record
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
Input::Type::Record::add_attribute
Record & add_attribute(std::string key, TypeBase::json_string value)
Add TYPE key as obligatory.
Definition: type_record.cc:354
sys_profiler.hh
AdvectionProcessBase
Definition: advection_process_base.hh:19
RegionDB::bulk_size
unsigned int bulk_size() const
Definition: region.cc:268
accessors.hh
TransportOperatorSplitting::get_input_type
static const Input::Type::Record & get_input_type()
Declare input record type for the equation TransportOperatorSplittiong.
Definition: transport_operator_splitting.cc:69
flow_attribute_lib.hh
TimeGovernor
Basic time management functionality for unsteady (and steady) solvers (class Equation).
Definition: time_governor.hh:310
TransportOperatorSplitting::update_solution
void update_solution() override
Definition: transport_operator_splitting.cc:274
output_time.hh
TransportOperatorSplitting::reaction
std::shared_ptr< ReactionTerm > reaction
Definition: transport_operator_splitting.hh:244
sorption.hh
This file contains classes representing sorption model. Sorption model can be computed both in case t...
TransportOperatorSplitting::output_data
void output_data() override
Write computed fields.
Definition: transport_operator_splitting.cc:246
Input::AbstractRecord
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:458
Input::Type::Default::obligatory
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:110
Input::Type::Abstract
Class for declaration of polymorphic Record.
Definition: type_abstract.hh:62
UnitSI
Class for representation SI units of Fields.
Definition: unit_si.hh:40
Mesh::region_db
const RegionDB & region_db() const
Definition: mesh.h:187
first_order_reaction.hh
Input::Type::Record::declare_key
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:503
AdvectionProcessBase::get_input_type
static Input::Type::Abstract & get_input_type()
Common specification of the input record for secondary equations.
Definition: advection_process_base.hh:27
TransportEqFields::TransportEqFields
TransportEqFields()
Definition: transport_operator_splitting.cc:106
mesh.h
equation.hh
Abstract base class for equation clasess.
FLOW123D_FORCE_LINK_IN_PARENT
#define FLOW123D_FORCE_LINK_IN_PARENT(x)
Definition: global_defs.h:160
Input::Record::find
Iterator< Ret > find(const string &key) const
Definition: accessors_impl.hh:91
SorptionSimple
Simple sorption model without dual porosity.
Definition: sorption.hh:52
TimeGovernor::view
void view(const char *name="") const
Definition: time_governor.cc:769
FieldFlag::input_copy
static constexpr Mask input_copy
Definition: field_flag.hh:44
Input::Type::Record::close
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
Input::Type
Definition: balance.hh:41
TransportOperatorSplitting::cfl_convection
double cfl_convection
Time restriction due to transport.
Definition: transport_operator_splitting.hh:246
Input::Type::Record
Record type proxy class.
Definition: type_record.hh:182
TimeMark::none_type
static const Type none_type
Mark Type with all bits unset.
Definition: time_marks.hh:95
LongIdx
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
Definition: index_types.hh:24
input_type.hh
Substance::get_input_type
static const Input::Type::Record & get_input_type()
Input type for a substance.
Definition: substance.cc:29
ConcentrationTransportBase
Definition: transport_operator_splitting.hh:61
Mesh
Definition: mesh.h:98
OutputTime::get_input_type
static const Input::Type::Record & get_input_type()
The specification of output stream.
Definition: output_time.cc:38
Input::Type::Record::copy_keys
Record & copy_keys(const Record &other)
Copy keys from other record.
Definition: type_record.cc:216
Input::Type::Array
Class for declaration of inputs sequences.
Definition: type_base.hh:339
dual_porosity.hh
Class Dual_por_exchange implements the model of dual porosity.
FlowAttribute::subfields_address
static string subfields_address()
Definition: flow_attribute_lib.hh:56
Input::Array
Accessor to input data conforming to declared Array.
Definition: accessors.hh:566
ReactionTerm::it_abstract_term
static Input::Type::Abstract & it_abstract_term()
Definition: reaction_term.cc:25
TransportOperatorSplitting::convection
std::shared_ptr< ConcentrationTransportBase > convection
Definition: transport_operator_splitting.hh:243
EquationBase::record_template
static Input::Type::Record & record_template()
Template Record with common keys for derived equations.
Definition: equation.cc:35
MixedPtr< FE_P_disc >
TimeGovernor::is_default
bool is_default()
Definition: time_governor.hh:381
transport.h
ConcentrationTransportBase::get_input_type
static Input::Type::Abstract & get_input_type()
Common specification of the input record for secondary equations.
Definition: transport_operator_splitting.cc:62
EquationBase::eq_fieldset_
FieldSet * eq_fieldset_
Definition: equation.hh:227
balance.hh
reaction_term.hh
Class ReactionTerm is an abstract class representing reaction term in transport.
ReactionTerm
Definition: reaction_term.hh:45
TimeGovernor::next_time
void next_time()
Proceed to the next time according to current estimated time step.
Definition: time_governor.cc:667
radioactive_decay.hh
Input::Type::Default::optional
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:124
START_TIMER
#define START_TIMER(tag)
Starts a timer with specified tag.
Definition: sys_profiler.hh:115
Input::Type::Abstract::close
Abstract & close()
Close the Abstract and add its to type repository (see TypeRepository::add_type).
Definition: type_abstract.cc:190
transport_operator_splitting.hh
TransportOperatorSplitting::~TransportOperatorSplitting
virtual ~TransportOperatorSplitting()
Destructor.
Definition: transport_operator_splitting.cc:223
Balance::get_input_type
static const Input::Type::Record & get_input_type()
Main balance input record type.
Definition: balance.cc:50
END_TIMER
#define END_TIMER(tag)
Ends a timer with specified tag.
Definition: sys_profiler.hh:149
TimeGovernor::t
double t() const
Definition: time_governor.hh:535