Flow123d  JS_before_hm-62-ge56f9d5
hm_iterative.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 hm_iterative.cc
15  * @brief
16  * @author Jan Stebel
17  */
18 
19 #include "hm_iterative.hh"
20 #include "system/sys_profiler.hh"
21 #include "input/input_type.hh"
22 #include "flow/richards_lmh.hh"
23 #include "fields/field_fe.hh" // for create_field()
24 
25 
26 FLOW123D_FORCE_LINK_IN_CHILD(coupling_iterative)
27 
28 
29 namespace it = Input::Type;
30 
31 
32 
33 /** Create elementwise FieldFE with parallel VectorMPI */
34 template <int spacedim, class Value>
35 std::shared_ptr<FieldFE<spacedim, Value> > create_field(Mesh & mesh, int n_comp)
36 {
37  FiniteElement<0> *fe0; // Finite element objects (allow to create DOF handler)
38  FiniteElement<1> *fe1;
39  FiniteElement<2> *fe2;
40  FiniteElement<3> *fe3;
41 
42  switch (n_comp) { // prepare FEM objects for DOF handler by number of components
43  case 1: { // scalar
44  fe0 = new FE_P_disc<0>(0);
45  fe1 = new FE_P_disc<1>(0);
46  fe2 = new FE_P_disc<2>(0);
47  fe3 = new FE_P_disc<3>(0);
48  break;
49  }
50  case -1: { // scalar with dof on sides
51  fe0 = new FE_CR<0>;
52  fe1 = new FE_CR<1>;
53  fe2 = new FE_CR<2>;
54  fe3 = new FE_CR<3>;
55  break;
56  }
57  case 3: { // vector
58  std::shared_ptr< FiniteElement<0> > fe0_ptr = std::make_shared< FE_P_disc<0> >(0);
59  std::shared_ptr< FiniteElement<1> > fe1_ptr = std::make_shared< FE_P_disc<1> >(0);
60  std::shared_ptr< FiniteElement<2> > fe2_ptr = std::make_shared< FE_P_disc<2> >(0);
61  std::shared_ptr< FiniteElement<3> > fe3_ptr = std::make_shared< FE_P_disc<3> >(0);
62  fe0 = new FESystem<0>(fe0_ptr, FEType::FEVector, 3);
63  fe1 = new FESystem<1>(fe1_ptr, FEType::FEVector, 3);
64  fe2 = new FESystem<2>(fe2_ptr, FEType::FEVector, 3);
65  fe3 = new FESystem<3>(fe3_ptr, FEType::FEVector, 3);
66  break;
67  }
68  case 9: { // tensor
69  std::shared_ptr< FiniteElement<0> > fe0_ptr = std::make_shared< FE_P_disc<0> >(0);
70  std::shared_ptr< FiniteElement<1> > fe1_ptr = std::make_shared< FE_P_disc<1> >(0);
71  std::shared_ptr< FiniteElement<2> > fe2_ptr = std::make_shared< FE_P_disc<2> >(0);
72  std::shared_ptr< FiniteElement<3> > fe3_ptr = std::make_shared< FE_P_disc<3> >(0);
73  fe0 = new FESystem<0>(fe0_ptr, FEType::FETensor, 9);
74  fe1 = new FESystem<1>(fe1_ptr, FEType::FETensor, 9);
75  fe2 = new FESystem<2>(fe2_ptr, FEType::FETensor, 9);
76  fe3 = new FESystem<3>(fe3_ptr, FEType::FETensor, 9);
77  break;
78  }
79  default:
80  ASSERT(false).error("Should not happen!\n");
81  }
82 
83  // Prepare DOF handler
84  std::shared_ptr<DOFHandlerMultiDim> dh_par = std::make_shared<DOFHandlerMultiDim>(mesh);
85  std::shared_ptr<DiscreteSpace> ds = std::make_shared<EqualOrderDiscreteSpace>( &mesh, fe0, fe1, fe2, fe3);
86  dh_par->distribute_dofs(ds);
87 
88  // Construct FieldFE
89  std::shared_ptr< FieldFE<spacedim, Value> > field_ptr = std::make_shared< FieldFE<spacedim, Value> >();
90  field_ptr->set_fe_data( dh_par, 0, dh_par->create_vector() );
91  return field_ptr;
92 }
93 
94 
95 
97  return it::Record("Coupling_Iterative",
98  "Record with data for iterative coupling of flow and mechanics.\n")
100  .declare_key("flow_equation", RichardsLMH::get_input_type(),
102  "Flow equation, provides the velocity field as a result.")
103  .declare_key("mechanics_equation", Elasticity::get_input_type(),
104  "Mechanics, provides the displacement field.")
106  "Time governor setting for the HM coupling.")
107  .declare_key("input_fields", it::Array(
109  .make_field_descriptor_type("Coupling_Iterative")),
111  "Input fields of the HM coupling.")
112  .declare_key( "iteration_parameter", it::Double(), it::Default("1"),
113  "Tuning parameter for iterative splitting. Its default value"
114  "corresponds to a theoretically optimal value with fastest convergence." )
115  .declare_key( "max_it", it::Integer(0), it::Default("100"),
116  "Maximal count of HM iterations." )
117  .declare_key( "min_it", it::Integer(0), it::Default("1"),
118  "Minimal count of HM iterations." )
119  .declare_key( "a_tol", it::Double(0), it::Default("0"),
120  "Absolute tolerance for difference in HM iteration." )
121  .declare_key( "r_tol", it::Double(0), it::Default("1e-7"),
122  "Relative tolerance for difference in HM iteration." )
123  .close();
124 }
125 
126 
127 const int HM_Iterative::registrar = Input::register_class< HM_Iterative, Mesh &, const Input::Record >("Coupling_Iterative")
129 
130 
132 {
133  *this += alpha.name("biot_alpha")
134  .units(UnitSI().dimensionless())
135  .input_default("0.0")
136  .flags_add(FieldFlag::in_rhs);
137 
138  *this += density.name("fluid_density")
139  .units(UnitSI().kg().m(-3))
140  .input_default("0.0")
141  .flags_add(FieldFlag::in_rhs);
142 
143  *this += gravity.name("gravity")
144  .units(UnitSI().m().s(-2))
145  .input_default("9.81")
146  .flags_add(FieldFlag::in_rhs);
147 
148  *this += beta.name("relaxation_beta")
149  .units(UnitSI().dimensionless())
151 
152  *this += pressure_potential.name("pressure_potential")
153  .units(UnitSI().m())
155 
156  *this += flow_source.name("extra_flow_source")
157  .units(UnitSI().s(-1))
159 }
160 
161 
163 {
164  // initialize coupling fields with FieldFE
165  set_mesh(mesh);
166 
167  potential_ptr_ = create_field<3, FieldValue<3>::Scalar>(mesh, -1);
168  pressure_potential.set_field(mesh.region_db().get_region_set("ALL"), potential_ptr_);
169 
170  beta_ptr_ = create_field<3, FieldValue<3>::Scalar>(mesh, 1);
171  beta.set_field(mesh.region_db().get_region_set("ALL"), beta_ptr_);
172 
173  flow_source_ptr_ = create_field<3, FieldValue<3>::Scalar>(mesh, 1);
174  flow_source.set_field(mesh.region_db().get_region_set("ALL"), flow_source_ptr_);
175 
176  old_pressure_ptr_ = create_field<3, FieldValue<3>::Scalar>(mesh, 1);
177  old_iter_pressure_ptr_ = create_field<3, FieldValue<3>::Scalar>(mesh, 1);
178  div_u_ptr_ = create_field<3, FieldValue<3>::Scalar>(mesh, 1);
179  old_div_u_ptr_ = create_field<3, FieldValue<3>::Scalar>(mesh, 1);
180 }
181 
182 
183 
185 : DarcyFlowInterface(mesh, in_record)
186 {
187  START_TIMER("HM constructor");
188  using namespace Input;
189 
190  time_ = new TimeGovernor(in_record.val<Record>("time"));
191 
192  // setup flow equation
193  Record flow_rec = in_record.val<Record>("flow_equation");
194  // Need explicit template types here, since reference is used (automatically passing by value)
195  flow_ = std::make_shared<RichardsLMH>(*mesh_, flow_rec, time_);
196  flow_->initialize();
197  std::stringstream ss; // print warning message with table of uninitialized fields
198  if ( FieldCommon::print_message_table(ss, "flow") )
199  WarningOut() << ss.str();
200 
201  // setup mechanics
202  Record mech_rec = in_record.val<Record>("mechanics_equation");
203  mechanics_ = std::make_shared<Elasticity>(*mesh_, mech_rec, this->time_);
204  mechanics_->data()["cross_section"].copy_from(flow_->data()["cross_section"]);
205  mechanics_->initialize();
206 
207  // read parameters controlling the iteration
208  beta_ = in_record.val<double>("iteration_parameter");
209  min_it_ = in_record.val<unsigned int>("min_it");
210  max_it_ = in_record.val<unsigned int>("max_it");
211  a_tol_ = in_record.val<double>("a_tol");
212  r_tol_ = in_record.val<double>("r_tol");
213 
214  this->eq_data_ = &data_;
215 
216  // setup input fields
217  data_.set_input_list( in_record.val<Input::Array>("input_fields"), time() );
218 
219  data_.initialize(*mesh_);
220  mechanics_->set_potential_load(data_.pressure_potential);
221 }
222 
223 
225 {
226 }
227 
228 
229 template<int dim, class Value>
230 void copy_field(const Field<dim, Value> &from_field, FieldFE<dim, Value> &to_field)
231 {
232  auto dh = to_field.get_dofhandler();
233  auto vec = to_field.get_data_vec();
234 
235  for ( auto cell : dh->own_range() )
236  vec[cell.local_idx()] = from_field.value(cell.elm().centre(), cell.elm());
237 
238 // vec.local_to_ghost_begin();
239 // vec.local_to_ghost_end();
240 }
241 
242 
243 template<int dim, class Value>
245 {
246  auto dh = field.get_dofhandler();
247  auto vec = field.get_data_vec();
248 
249  for ( auto cell : dh->own_range() )
250  {
251  auto elm = cell.elm();
252  vec[cell.local_idx()] = mh_dh.element_scalar(elm);
253  }
254 }
255 
256 
257 
258 
260 {
262  std::stringstream ss;
263  if ( FieldCommon::print_message_table(ss, "coupling_iterative") )
264  WarningOut() << ss.str();
265 
266  flow_->zero_time_step();
268  mechanics_->zero_time_step();
269 
272  copy_field(mechanics_->data().output_divergence, *data_.div_u_ptr_);
273 }
274 
275 
277 {
278  unsigned it = 0;
279  double difference = 0;
280  double norm = 1;
281 
282  time_->next_time();
283  time_->view("HM");
285 
286  while (it < min_it_ ||
287  (it < max_it_ && difference > a_tol_ && difference/norm > r_tol_)
288  )
289  {
290  it++;
291 
292  // pass displacement (divergence) to flow
293  // and solve flow problem
295  flow_->solve_time_step(false);
296 
297  // pass pressure to mechanics and solve mechanics
299  mechanics_->solve_linear_system();
300  mechanics_->output_vector_gather();
301 
302  // update displacement divergence
303  copy_field(mechanics_->data().output_divergence, *data_.div_u_ptr_);
304 
305  // TODO: compute difference of iterates
306  compute_iteration_error(difference, norm);
307 
308  MessageOut().fmt("HM Iteration {} abs. difference: {} rel. difference: {}\n"
309  "--------------------------------------------------------",
310  it, difference, difference/norm);
312  }
313 
314  flow_->output_data();
315  mechanics_->output_data();
316 
318  copy_field(mechanics_->data().output_divergence, *data_.old_div_u_ptr_);
319 }
320 
321 
323 {
324  auto potential_vec_ = data_.potential_ptr_->get_data_vec();
325  auto dh = data_.potential_ptr_->get_dofhandler();
326  double difference2 = 0, norm2 = 0;
327  std::vector<int> dof_indices(dh->max_elem_dofs());
328  for ( auto ele : dh->local_range() )
329  {
330  auto elm = ele.elm();
331  ele.get_loc_dof_indices(dof_indices);
332  for ( auto side : ele.side_range() )
333  {
334  double alpha = data_.alpha.value(side.centre(), elm);
335  double density = data_.density.value(side.centre(), elm);
336  double gravity = data_.gravity.value(side.centre(), elm);
337  double pressure = flow_->get_mh_dofhandler().side_scalar(side.side());
338  double potential = -alpha*density*gravity*pressure;
339 
340  if (ele.is_own())
341  {
342  difference2 += pow(potential_vec_[dof_indices[side.side_idx()]] - potential,2);
343  norm2 += pow(potential,2);
344  }
345 
346  potential_vec_[dof_indices[side.side_idx()]] = potential;
347  }
348  }
349 
350  double send_data[] = { difference2, norm2 };
351  double recv_data[2];
352  MPI_Allreduce(&send_data, &recv_data, 2, MPI_DOUBLE, MPI_SUM, PETSC_COMM_WORLD);
353  difference2 = recv_data[0];
354  norm2 = recv_data[1];
355 
356  double dif2norm;
357  if (norm2 == 0)
358  dif2norm = (difference2 == 0)?0:numeric_limits<double>::max();
359  else
360  dif2norm = sqrt(difference2/norm2);
361  DebugOut() << "Relative potential difference: " << dif2norm << endl;
362 
363  if (dif2norm > numeric_limits<double>::epsilon())
364  {
366  mechanics_->set_potential_load(data_.pressure_potential);
367  }
368 }
369 
370 
372 {
373  auto beta_vec = data_.beta_ptr_->get_data_vec();
374  auto src_vec = data_.flow_source_ptr_->get_data_vec();
375  auto dh = data_.beta_ptr_->get_dofhandler();
376  double beta_diff2 = 0, beta_norm2 = 0, src_diff2 = 0, src_norm2 = 0;
377  for ( auto ele : dh->local_range() )
378  {
379  auto elm = ele.elm();
380 
381  double alpha = data_.alpha.value(elm.centre(), elm);
382  double young = mechanics_->data().young_modulus.value(elm.centre(), elm);
383  double poisson = mechanics_->data().poisson_ratio.value(elm.centre(), elm);
384  double beta = beta_ * 0.5*alpha*alpha/(2*lame_mu(young, poisson)/elm.dim() + lame_lambda(young, poisson));
385 
386  double old_p = data_.old_pressure_ptr_->value(elm.centre(), elm);
387  double p = flow_->get_mh_dofhandler().element_scalar(elm);
388  double div_u = data_.div_u_ptr_->value(elm.centre(), elm);
389  double old_div_u = data_.old_div_u_ptr_->value(elm.centre(), elm);
390  double src = (beta*(p-old_p) + alpha*(old_div_u - div_u)) / time_->dt();
391 
392  if (ele.is_own())
393  {
394  beta_diff2 += pow(beta_vec[ele.local_idx()] - beta,2);
395  beta_norm2 += pow(beta,2);
396  src_diff2 += pow(src_vec[ele.local_idx()] - src,2);
397  src_norm2 += pow(src,2);
398  }
399 
400  beta_vec[ele.local_idx()] = beta;
401  src_vec[ele.local_idx()] = src;
402  }
403 
404  double send_data[] = { beta_diff2, beta_norm2, src_diff2, src_norm2 };
405  double recv_data[4];
406  MPI_Allreduce(&send_data, &recv_data, 4, MPI_DOUBLE, MPI_SUM, PETSC_COMM_WORLD);
407  beta_diff2 = recv_data[0];
408  beta_norm2 = recv_data[1];
409  src_diff2 = recv_data[2];
410  src_norm2 = recv_data[3];
411 
412  double beta_dif2norm, src_dif2norm;
413  if (beta_norm2 == 0)
414  beta_dif2norm = (beta_diff2 == 0)?0:numeric_limits<double>::max();
415  else
416  beta_dif2norm = sqrt(beta_diff2/beta_norm2);
417  if (src_norm2 == 0)
418  src_dif2norm = (src_diff2 == 0)?0:numeric_limits<double>::max();
419  else
420  src_dif2norm = sqrt(src_diff2/src_norm2);
421  DebugOut() << "Relative difference in beta: " << beta_dif2norm << endl;
422  DebugOut() << "Relative difference in extra_source: " << src_dif2norm << endl;
423 
424  if (beta_dif2norm > numeric_limits<double>::epsilon())
425  {
427  flow_->set_extra_storativity(data_.beta);
428  }
429  if (src_dif2norm > numeric_limits<double>::epsilon())
430  {
432  flow_->set_extra_source(data_.flow_source);
433  }
434 }
435 
436 
437 void HM_Iterative::compute_iteration_error(double& difference, double& norm)
438 {
439  auto dh = data_.beta_ptr_->get_dofhandler();
440  double p_dif2 = 0, p_norm2 = 0;
441  for (auto cell : dh->own_range())
442  {
443  auto elm = cell.elm();
444  double new_p = flow_->get_mh_dofhandler().element_scalar(elm);
445  double old_p = data_.old_iter_pressure_ptr_->value(elm.centre(), elm);
446  p_dif2 += pow(new_p - old_p, 2)*elm.measure();
447  p_norm2 += pow(old_p, 2)*elm.measure();
448  }
449 
450  double send_data[] = { p_dif2, p_norm2 };
451  double recv_data[2];
452  MPI_Allreduce(&send_data, &recv_data, 2, MPI_DOUBLE, MPI_SUM, PETSC_COMM_WORLD);
453  difference = sqrt(recv_data[0]);
454  norm = sqrt(recv_data[1]);
455 }
456 
457 
458 
460 {
461  return flow_->get_mh_dofhandler();
462 }
463 
464 
466  flow_.reset();
467  mechanics_.reset();
468 }
469 
470 
471 
TimeGovernor & time()
Definition: equation.hh:148
FieldSet * eq_data_
Definition: equation.hh:232
Accessor to input data conforming to declared Array.
Definition: accessors.hh:567
unsigned int max_it_
Maximal number of iterations.
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > old_div_u_ptr_
Definition: hm_iterative.hh:73
unsigned int size() const
Returns number of keys in the Record.
Definition: type_record.hh:598
double beta_
Tuning parameter for iterative splitting.
void update_field_from_mh_dofhandler(const MH_DofHandler &mh_dh, FieldFE< dim, Value > &field)
double r_tol_
Relative tolerance for difference between two succeeding iterations.
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
static const int registrar
Definition: hm_iterative.hh:94
#define MessageOut()
Macro defining &#39;message&#39; record of log.
Definition: logger.hh:243
void update_potential()
Abstract linear system class.
Definition: balance.hh:37
VectorMPI get_data_vec() const
Definition: field_fe.hh:141
Class template representing a field with values dependent on: point, element, and region...
Definition: field.hh:83
void initialize(Mesh &mesh)
void next_time()
Proceed to the next time according to current estimated time step.
static const Input::Type::Record & get_input_type()
Declare input record type for the equation TransportDG.
Definition: elasticity.cc:44
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:110
#define MPI_SUM
Definition: mpi.h:196
const MH_DofHandler & get_mh_dofhandler() override
Definition: mesh.h:76
void update_flow_fields()
Mat< double, N, 1 > vec
Definition: armor.hh:211
double lame_mu(double young, double poisson)
Definition: elasticity.cc:157
void zero_time_step() override
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:347
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > potential_ptr_
FieldFE for pressure_potential field.
Definition: hm_iterative.hh:67
const TimeStep & step(int index=-1) const
Class for declaration of the integral input data.
Definition: type_base.hh:490
Basic time management functionality for unsteady (and steady) solvers (class Equation).
double a_tol_
Absolute tolerance for difference between two succeeding iterations.
static const Input::Type::Record & get_input_type()
Define input record.
Definition: hm_iterative.cc:96
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:304
Class for declaration of inputs sequences.
Definition: type_base.hh:346
void view(const char *name="") const
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > old_pressure_ptr_
Definition: hm_iterative.hh:70
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > div_u_ptr_
Definition: hm_iterative.hh:72
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:196
double element_scalar(ElementAccessor< 3 > &ele) const
temporary replacement for DofHandler accessor, scalar (pressure) on element
void update_solution() override
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:541
static constexpr Mask equation_result
Match result fields. These are never given by input or copy of input.
Definition: field_flag.hh:55
Mesh & mesh()
Definition: equation.hh:176
Compound finite element on dim dimensional simplex.
Definition: fe_system.hh:101
Field< 3, FieldValue< 3 >::Scalar > pressure_potential
Potential -alpha*pressure whose gradient is passed to mechanics as additional load.
Definition: hm_iterative.hh:63
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > flow_source_ptr_
Definition: hm_iterative.hh:69
static constexpr Mask equation_external_output
Match an output field, that can be also copy of other field.
Definition: field_flag.hh:58
void set_time_result_changed()
Manually mark flag that the field has been changed.
void copy_field(const Field< dim, Value > &from_field, FieldFE< dim, Value > &to_field)
Accessor to the data with type Type::Record.
Definition: accessors.hh:292
Field< 3, FieldValue< 3 >::Scalar > alpha
Biot coefficient.
Definition: hm_iterative.hh:57
const Ret val(const string &key) const
std::shared_ptr< Elasticity > mechanics_
solute transport with chemistry through operator splitting
#define START_TIMER(tag)
Starts a timer with specified tag.
Mesh * mesh_
Definition: equation.hh:223
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm) const
Definition: field.hh:389
Field< 3, FieldValue< 3 >::Scalar > gravity
Standard gravity.
Definition: hm_iterative.hh:59
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
static Input::Type::Abstract & get_input_type()
static constexpr Mask in_rhs
A field is part of the right hand side of the equation.
Definition: field_flag.hh:51
Field< 3, FieldValue< 3 >::Scalar > flow_source
Definition: hm_iterative.hh:64
void initialize() override
std::shared_ptr< FieldFE< spacedim, Value > > create_field(Mesh &mesh, int n_comp)
Definition: hm_iterative.cc:35
Field< 3, FieldValue< 3 >::Scalar > beta
Definition: hm_iterative.hh:60
#define MPI_DOUBLE
Definition: mpi.h:156
std::shared_ptr< DOFHandlerMultiDim > get_dofhandler() const
Definition: field_fe.hh:137
#define MPI_Allreduce(sendbuf, recvbuf, count, datatype, op, comm)
Definition: mpi.h:612
void set_input_list(Input::Array input_list, const TimeGovernor &tg)
Definition: field_set.hh:190
unsigned int min_it_
Minimal number of iterations to perform.
static const Input::Type::Record & get_input_type()
Definition: richards_lmh.cc:70
double dt() const
HM_Iterative(Mesh &mesh, Input::Record in_record)
bool set_time(const TimeStep &time, LimitSide limit_side)
Definition: field_set.cc:157
double lame_lambda(double young, double poisson)
Definition: elasticity.cc:163
static const Input::Type::Record & get_input_type()
#define WarningOut()
Macro defining &#39;warning&#39; record of log.
Definition: logger.hh:246
Record type proxy class.
Definition: type_record.hh:182
Class for representation SI units of Fields.
Definition: unit_si.hh:40
std::shared_ptr< RichardsLMH > flow_
steady or unsteady water flow simulator based on MH scheme
Definition: hm_iterative.hh:97
void compute_iteration_error(double &difference, double &norm)
#define DebugOut()
Macro defining &#39;debug&#39; record of log.
Definition: logger.hh:252
static bool print_message_table(ostream &stream, std::string equation_name)
Definition: field_common.cc:96
Crouzeix-Raviart finite element on dim dimensional simplex.
Definition: fe_p.hh:126
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > old_iter_pressure_ptr_
Definition: hm_iterative.hh:71
Field< 3, FieldValue< 3 >::Scalar > density
Density of fluid.
Definition: hm_iterative.hh:58
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Definition: global_defs.h:180
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > beta_ptr_
Definition: hm_iterative.hh:68
TimeGovernor * time_
Definition: equation.hh:224
Definition: field.hh:56