Flow123d
transport_operator_splitting.cc
Go to the documentation of this file.
1 /*
2  * transport_operator_splitting.cc
3  *
4  * Created on: May 21, 2011
5  * Author: jiri
6  */
7 
8 #include <iostream>
9 #include <iomanip>
10 
11 #include "system/system.hh"
12 #include "system/sys_profiler.hh"
13 #include "system/xio.h"
14 
16 #include <petscmat.h>
17 #include "system/sys_vector.hh"
19 #include "coupling/equation.hh"
20 #include "transport/transport.h"
21 #include "mesh/mesh.h"
22 #include "flow/old_bcd.hh"
23 
24 #include "reaction/reaction.hh"
28 #include "reaction/sorption.hh"
30 
32 
33 #include "la/distribution.hh"
34 #include "io/output.h"
35 
36 #include "input/input_type.hh"
37 #include "input/accessors.hh"
38 
39 using namespace Input::Type;
40 
42  = AbstractRecord("Transport", "Secondary equation for transport of substances.")
44  "Time governor setting for the secondary equation.")
46  "Parameters of output stream.")
47  .declare_key("mass_balance", MassBalance::input_type, Default::optional(), "Settings for computing mass balance.");
48 
49 
51  = Record("TransportOutput", "Output setting for transport equations.")
53  "Parameters of output stream.");
54 
55 
57  = Record("TransportOperatorSplitting",
58  "Explicit FVM transport (no diffusion)\n"
59  "coupled with reaction and adsorption model (ODE per element)\n"
60  " via operator splitting.")
62  .declare_key("substances", Array(String()), Default::obligatory(),
63  "Names of transported substances.")
64  // input data
66  "Reaction model involved in transport.")
67 
68  .declare_key("input_fields", Array(
69  ConvectionTransport::EqData().make_field_descriptor_type("TransportOperatorSplitting")
70  .declare_key(OldBcdInput::transport_old_bcd_file_key(), IT::FileName::input(), "File with mesh dependent boundary conditions (obsolete).")
71  ), IT::Default::obligatory(), "")
73  Default("conc"),
74  "List of fields to write to output file.");
75 
76 
78 {
79 
80  ADD_FIELD(porosity, "Mobile porosity", "1");
81  ADD_FIELD(cross_section, "");
82  cross_section.just_copy();
83 
84  ADD_FIELD(sources_density, "Density of concentration sources.", "0");
85  ADD_FIELD(sources_sigma, "Concentration flux.", "0");
86  ADD_FIELD(sources_conc, "Concentration sources threshold.", "0");
87 
88 }
89 
90 
92 : AdvectionProcessBase(mesh, in_rec ),
93  mh_dh(nullptr),
94  mass_balance_(nullptr)
95 {
96 }
97 
99 {
100 }
101 
102 
103 
104 
105 
106 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
107 
108 
109 
111 : TransportBase(init_mesh, in_rec),
112  reaction(nullptr),
113  convection(NULL),
114  Semchem_reactions(NULL)
115 {
116  Distribution *el_distribution;
117  int *el_4_loc;
118 
119  // double problem_save_step = OptGetDbl("Global", "Save_step", "1.0");
120 
121  in_rec.val<Input::Array>("substances").copy_to(subst_names_);
122  n_subst_ = subst_names_.size();
123  convection = new ConvectionTransport(*mesh_, in_rec);
124  this->eq_data_ = &(convection->data());
125 
126  //output_mark_type = convection->mark_type() | TimeGovernor::marks().type_fixed_time() | TimeGovernor::marks().type_output();
127  time_ = new TimeGovernor(in_rec.val<Input::Record>("time"), convection->mark_type() );
128 
129 
130  convection->get_par_info(el_4_loc, el_distribution);
131  Input::Iterator<Input::AbstractRecord> reactions_it = in_rec.find<Input::AbstractRecord>("reaction_term");
132  if ( reactions_it ) {
133  if (reactions_it->type() == Linear_reaction::input_type ) {
134  reaction = new Linear_reaction(init_mesh, *reactions_it);
135  } else
136  if (reactions_it->type() == Pade_approximant::input_type) {
137  reaction = new Pade_approximant(init_mesh, *reactions_it);
138  } else
139  if (reactions_it->type() == SorptionSimple::input_type ) {
140  reaction = new SorptionSimple(init_mesh, *reactions_it);
141  static_cast<SorptionSimple *> (reaction) -> set_porosity(convection->get_data()->porosity);
142 
143  } else
144  if (reactions_it->type() == DualPorosity::input_type ) {
145  reaction = new DualPorosity(init_mesh, *reactions_it);
146  static_cast<DualPorosity *> (reaction) -> set_porosity(convection->get_data()->porosity);
147 
148  } else
149  if (reactions_it->type() == Semchem_interface::input_type ) {
150  Semchem_reactions = new Semchem_interface(0.0, mesh_, n_subst_, false); //false instead of convection->get_dual_porosity
151  Semchem_reactions->set_el_4_loc(el_4_loc);
153 
154  } else {
155  xprintf(UsrErr, "Wrong reaction type.\n");
156  }
157  //temporary, until new mass balance considering reaction term is created
158  xprintf(Warn, "The mass balance is not computed correctly when reaction term is present. "
159  "Only the mass flux over boundaries is correct.\n");
160 
163  el_distribution, el_4_loc, convection->get_row_4_el())
164  .output_stream(*(convection->output_stream()))
166 
167  } else {
168  reaction = nullptr;
169  Semchem_reactions = nullptr;
170  }
171 }
172 
174 {
175  //delete field_output;
176  delete convection;
177  if (reaction) delete reaction;
179  delete time_;
180 }
181 
182 
183 
184 
186 
187 
188  START_TIMER("TOS-output data");
189 
190  time_->view("TOS"); //show time governor
192  if(reaction) reaction->output_data(); // do not perform write_time_frame
194 
195 }
196 
197 
199 {
203 
204 }
205 
206 
207 
209 
210 
211 
212  time_->next_time();
213 
214 
217 
218  //xprintf( Msg, "TOS: time: %f CONVECTION: time: %f dt_estimate: %f\n",
219  // time_->t(), convection->time().t(), convection->time().estimate_dt() );
220 
221 
222  START_TIMER("TOS-one step");
223  int steps=0;
224  while ( convection->time().lt(time_->t()) )
225  {
226  steps++;
227  // one internal step
231  if (convection->mass_balance() != NULL)
233 
234  }
235  END_TIMER("TOS-one step");
236 
237 
238 
239  xprintf( MsgLog, " CONVECTION: steps: %d\n",steps);
240 }
241 
242 
243 
244 
245 
247 {
248  mh_dh = &dh;
250 };
251 
252 
253 //DELETE
254 // void TransportOperatorSplitting::get_parallel_solution_vector(Vec &vec){
255 // convection->update_solution();
256 // };
257 //
258 //
259 //
260 // void TransportOperatorSplitting::get_solution_vector(double * &x, unsigned int &a){
261 // convection->update_solution();
262 // };
263 
264 
265 /*
266 void TransportOperatorSplitting::set_cross_section_field(const Field< 3, FieldValue<3>::Scalar > &cross_section)
267 {
268  convection->set_cross_section_field(cross_section);
269 
270  }
271 */
272 
273 
274 void TransportOperatorSplitting::calc_fluxes(vector<vector<double> > &bcd_balance, vector<vector<double> > &bcd_plus_balance, vector<vector<double> > &bcd_minus_balance)
275 {}
276 
278 {}
279 
280 
281 
282 
283