Flow123d  release_3.0.0-973-g92f55e826
richards_lmh.cc
Go to the documentation of this file.
1 /*
2  * richards_lmh.cc
3  *
4  * Created on: Sep 16, 2015
5  * Author: jb
6  */
7 
8 
9 #include "system/global_defs.h"
10 #include "system/sys_profiler.hh"
11 
12 
13 #include "input/input_type.hh"
14 #include "input/factory.hh"
15 #include "flow/richards_lmh.hh"
17 #include "tools/time_governor.hh"
18 
19 #include "petscmat.h"
20 #include "petscviewer.h"
21 #include "petscerror.h"
22 #include <armadillo>
23 
24 #include "la/schur.hh"
25 
26 #include "coupling/balance.hh"
27 
28 #include "la/vector_mpi.hh"
29 
30 // in the third_party/FADBAD++ dir, namespace "fadbad"
31 #include "fadbad.h"
32 #include "badiff.h"
33 #include "fadiff.h"
34 
35 #include "flow/assembly_lmh.hh"
36 
37 
38 FLOW123D_FORCE_LINK_IN_CHILD(richards_lmh);
39 
40 
41 namespace it=Input::Type;
42 
43 
45 {
46  *this += water_content_saturated.name("water_content_saturated")
47  .description(R"(Saturated water content (($ \theta_s $)).
48  Relative volume of water in a reference volume of a saturated porous media.)")
49  .input_default("0.0")
51 
52  *this += water_content_residual.name("water_content_residual")
53  .description(R"(Residual water content (($ \theta_r $)).
54  Relative volume of water in a reference volume of an ideally dry porous media.)")
55  .input_default("0.0")
57 
58  *this += genuchten_p_head_scale.name("genuchten_p_head_scale")
59  .description(R"(The van Genuchten pressure head scaling parameter (($ \alpha $)).
60  It is related to the inverse of the air entry pressure, i.e. the pressure
61  where the relative water content starts to decrease below 1.)")
62  .input_default("0.0")
63  .units( UnitSI().m(-1) );
64 
65  *this += genuchten_n_exponent.name("genuchten_n_exponent")
66  .description("The van Genuchten exponent parameter (($ n $)).")
67  .input_default("2.0")
69 }
70 
71 
73  it::Record field_descriptor = it::Record("RichardsLMH_Data",FieldCommon::field_descriptor_record_description("RichardsLMH_Data"))
75  .copy_keys( RichardsLMH::EqData().make_field_descriptor_type("RichardsLMH_Data_aux") )
76  .close();
77 
78  auto model_selection = it::Selection("Soil_Model_Type", "")
79  .add_value(SoilModelBase::van_genuchten, "van_genuchten", "Van Genuchten soil model with cutting near zero.")
80  .add_value(SoilModelBase::irmay, "irmay", "Irmay model for conductivity, Van Genuchten model for the water content. Suitable for bentonite.")
81  .close();
82 
83  auto soil_rec = it::Record("SoilModel", "Soil model settings.")
84  .allow_auto_conversion("model_type")
85  .declare_key("model_type", model_selection, it::Default("\"van_genuchten\""),
86  "Selection of the globally applied soil model. In future we replace this key by a field for selection of the model."
87  "That will allow usage of different soil model in a single simulation.")
88  .declare_key("cut_fraction", it::Double(0.0,1.0), it::Default("0.999"),
89  "Fraction of the water content where we cut and rescale the curve.")
90  .close();
91 
92  return it::Record("Flow_Richards_LMH", "Lumped Mixed-Hybrid solver for unsteady unsaturated Darcy flow.")
95  .declare_key("input_fields", it::Array( field_descriptor ), it::Default::obligatory(),
96  "Input data for Darcy flow model.")
97  .declare_key("soil_model", soil_rec, it::Default("\"van_genuchten\""),
98  "Soil model settings.")
99  .close();
100 }
101 
102 
103 const int RichardsLMH::registrar =
104  Input::register_class< RichardsLMH, Mesh &, const Input::Record >("Flow_Richards_LMH") +
106 
107 
108 
110  : DarcyMH(mesh_in, in_rec)
111 {
112  data_ = make_shared<EqData>();
115  //data_->edge_new_local_4_mesh_idx_ = &(this->edge_new_local_4_mesh_idx_);
116 }
117 
119 
120  auto model_rec = input_record_.val<Input::Record>("soil_model");
121  auto model_type = model_rec.val<SoilModelBase::SoilModelType>("model_type");
122  double fraction= model_rec.val<double>("cut_fraction");
123  if (model_type == SoilModelBase::van_genuchten)
124  data_->soil_model_ = std::make_shared<SoilModel_VanGenuchten>(fraction);
125  else if (model_type == SoilModelBase::irmay)
126  data_->soil_model_ = std::make_shared<SoilModel_Irmay>(fraction);
127  else
128  ASSERT(false);
129 
130  // create edge vectors
131  unsigned int n_local_edges = mh_dh.edge_new_local_4_mesh_idx_.size();
132  unsigned int n_local_sides = mh_dh.side_ds->lsize();
133  data_->phead_edge_.resize( n_local_edges);
134  data_->water_content_previous_it.resize(n_local_sides);
135  data_->water_content_previous_time.resize(n_local_sides);
136  data_->capacity.resize(n_local_sides);
137 
138  Distribution ds_split_edges(n_local_edges, PETSC_COMM_WORLD);
139  vector<int> local_edge_rows(n_local_edges);
140 
141  IS is_loc;
142  for(auto item : mh_dh.edge_new_local_4_mesh_idx_) {
143  local_edge_rows[item.second]=mh_dh.row_4_edge[item.first];
144  }
145  ISCreateGeneral(PETSC_COMM_SELF, local_edge_rows.size(),
146  &(local_edge_rows[0]), PETSC_COPY_VALUES, &(is_loc));
147 
148  VecScatterCreate(schur0->get_solution(), is_loc,
149  data_->phead_edge_.petsc_vec(), PETSC_NULL, &solution_2_edge_scatter_);
150  chkerr(ISDestroy(&is_loc));
151 
152 }
153 
154 
156 {
157 
158 }
159 
160 
162 {
163  // apply initial condition
164  // cycle over local element rows
165  double init_value;
166 
167  for (unsigned int i_loc_el = 0; i_loc_el < mh_dh.el_ds->lsize(); i_loc_el++) {
168  auto ele_ac = mh_dh.accessor(i_loc_el);
169 
170  init_value = data_->init_pressure.value(ele_ac.centre(), ele_ac.element_accessor());
171 
172  for (unsigned int i=0; i<ele_ac.element_accessor()->n_sides(); i++) {
173  int edge_row = ele_ac.edge_row(i);
174  uint n_sides_of_edge = ele_ac.element_accessor().side(i)->edge()->n_sides;
175  VecSetValue(schur0->get_solution(),edge_row, init_value/n_sides_of_edge, ADD_VALUES);
176  }
177  VecSetValue(schur0->get_solution(),ele_ac.ele_row(), init_value,ADD_VALUES);
178  }
179  VecAssemblyBegin(schur0->get_solution());
180  VecAssemblyEnd(schur0->get_solution());
181 
182  // set water_content
183  // pretty ugly since postprocess change fluxes, which cause bad balance, so we must set them back
184  VecCopy(schur0->get_solution(), previous_solution); // store solution vector
185  postprocess();
186  VecSwap(schur0->get_solution(), previous_solution); // restore solution vector
187 
188  //DebugOut() << "init sol:\n";
189  //VecView( schur0->get_solution(), PETSC_VIEWER_STDOUT_WORLD);
190  //DebugOut() << "init water content:\n";
191  //VecView( data_->water_content_previous_it.petsc_vec(), PETSC_VIEWER_STDOUT_WORLD);
192 
194 }
195 
196 
198 {
200  data_->water_content_previous_time.copy(data_->water_content_previous_it);
201  //VecCopy(schur0->get_solution(), previous_solution);
202 }
203 
204 bool RichardsLMH::zero_time_term(bool time_global) {
205  if (time_global) {
206  return (data_->storativity.input_list_size() == 0)
207  && (data_->water_content_saturated.input_list_size() == 0);
208 
209  } else {
210  return (data_->storativity.field_result(mesh_->region_db().get_region_set("BULK"))
211  == result_zeros)
212  && (data_->water_content_saturated.field_result(mesh_->region_db().get_region_set("BULK"))
213  == result_zeros);
214  }
215 }
216 
217 
219 {
220 
221  START_TIMER("RicharsLMH::assembly_linear_system");
222 
223  VecScatterBegin(solution_2_edge_scatter_, schur0->get_solution(), data_->phead_edge_.petsc_vec() , INSERT_VALUES, SCATTER_FORWARD);
224  VecScatterEnd(solution_2_edge_scatter_, schur0->get_solution(), data_->phead_edge_.petsc_vec() , INSERT_VALUES, SCATTER_FORWARD);
225 
226  data_->is_linear = data_->genuchten_p_head_scale.field_result(mesh_->region_db().get_region_set("BULK")) == result_zeros;
227 
228  bool is_steady = zero_time_term();
229  //DebugOut() << "Assembly linear system\n";
230  START_TIMER("full assembly");
231  if (typeid(*schur0) != typeid(LinSys_BDDC)) {
232  schur0->start_add_assembly(); // finish allocation and create matrix
233  }
234  data_->time_step_ = time_->dt();
235  auto multidim_assembler = AssemblyBase::create< AssemblyLMH >(data_);
236 
237 
240 
241  balance_->start_source_assembly(data_->water_balance_idx);
242  balance_->start_mass_assembly(data_->water_balance_idx);
243 
244  assembly_mh_matrix( multidim_assembler ); // fill matrix
245 
246  balance_->finish_source_assembly(data_->water_balance_idx);
247  balance_->finish_mass_assembly(data_->water_balance_idx);
248  //MatView( *const_cast<Mat*>(schur0->get_matrix()), PETSC_VIEWER_STDOUT_WORLD );
249  //VecView( *const_cast<Vec*>(schur0->get_rhs()), PETSC_VIEWER_STDOUT_WORLD);
250 
253 
254 
255  if (! is_steady) {
256  START_TIMER("fix time term");
257  //DebugOut() << "setup time term\n";
258  // assembly time term and rhs
260  }
261 }
262 
263 
264 
266 {
267  FEAL_ASSERT(false).error("Shold not be called.");
268 }
269 
270 
271 
272 
273 
275 
276  // update structures for balance of water volume
278 
279 
280 
281  int side_rows[4];
282  double values[4];
283 
284 
285  VecScatterBegin(solution_2_edge_scatter_, schur0->get_solution(), data_->phead_edge_.petsc_vec() , INSERT_VALUES, SCATTER_FORWARD);
286  VecScatterEnd(solution_2_edge_scatter_, schur0->get_solution(), data_->phead_edge_.petsc_vec() , INSERT_VALUES, SCATTER_FORWARD);
287 
288 
289  // modify side fluxes in parallel
290  // for every local edge take time term on digonal and add it to the corresponding flux
291  //PetscScalar *loc_prev_sol;
292  auto multidim_assembler = AssemblyBase::create< AssemblyLMH >(data_);
293 
294  //VecGetArray(previous_solution, &loc_prev_sol);
295  for (unsigned int i_loc = 0; i_loc < mh_dh.el_ds->lsize(); i_loc++) {
296  auto ele_ac = mh_dh.accessor(i_loc);
297  multidim_assembler[ele_ac.dim()-1]->update_water_content(ele_ac);
298 
299  double ele_scale = ele_ac.measure() *
300  data_->cross_section.value(ele_ac.centre(), ele_ac.element_accessor()) / ele_ac.n_sides();
301  double ele_source = data_->water_source_density.value(ele_ac.centre(), ele_ac.element_accessor());
302  //double storativity = data_->storativity.value(ele_ac.centre(), ele_ac.element_accessor());
303 
304  for (unsigned int i=0; i<ele_ac.element_accessor()->n_sides(); i++) {
305  //unsigned int loc_edge_row = ele_ac.edge_local_row(i);
306  side_rows[i] = ele_ac.side_row(i);
307  double water_content = data_->water_content_previous_it[ele_ac.side_local_idx(i)];
308  double water_content_previous_time = data_->water_content_previous_time[ele_ac.side_local_idx(i)];
309 
310  values[i] = ele_scale * ele_source - ele_scale * (water_content - water_content_previous_time) / time_->dt();
311  }
312  VecSetValues(schur0->get_solution(), ele_ac.n_sides(), side_rows, values, ADD_VALUES);
313  }
314 
315 
316  VecAssemblyBegin(schur0->get_solution());
317  //VecRestoreArray(previous_solution, &loc_prev_sol);
318  VecAssemblyEnd(schur0->get_solution());
319 
320 }
FieldCommon::units
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
Definition: field_common.hh:140
DarcyMH::balance_
std::shared_ptr< Balance > balance_
Definition: darcy_flow_mh.hh:345
EquationBase::mesh_
Mesh * mesh_
Definition: equation.hh:221
result_zeros
@ result_zeros
Definition: field_algo_base.hh:72
LinSys::get_solution
const Vec & get_solution()
Definition: linsys.hh:282
DarcyMH::previous_solution
Vec previous_solution
Definition: darcy_flow_mh.hh:375
TimeGovernor::dt
double dt() const
Definition: time_governor.hh:542
RichardsLMH::RichardsLMH
RichardsLMH(Mesh &mesh, const Input::Record in_rec)
Definition: richards_lmh.cc:109
UnitSI::dimensionless
static UnitSI & dimensionless()
Returns dimensionless unit.
Definition: unit_si.cc:55
factory.hh
vector_mpi.hh
Distribution::lsize
unsigned int lsize(int proc) const
get local size
Definition: distribution.hh:115
EquationBase::eq_data_
FieldSet * eq_data_
Definition: equation.hh:230
time_governor.hh
Basic time management class.
RichardsLMH::EqData::water_content_saturated
Field< 3, FieldValue< 3 >::Scalar > water_content_saturated
Definition: richards_lmh.hh:71
RichardsLMH::EqData::water_content_residual
Field< 3, FieldValue< 3 >::Scalar > water_content_residual
Definition: richards_lmh.hh:72
ASSERT
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:346
DarcyMH::type_field_descriptor
static const Input::Type::Record & type_field_descriptor()
Definition: darcy_flow_mh.cc:116
EquationBase::time_
TimeGovernor * time_
Definition: equation.hh:222
assembly_lmh.hh
RichardsLMH::EqData::EqData
EqData()
Definition: richards_lmh.cc:44
Input::Record::val
const Ret val(const string &key) const
Definition: accessors_impl.hh:31
richards_lmh.hh
Input::Type::Selection::close
const Selection & close() const
Close the Selection, no more values can be added.
Definition: type_selection.cc:65
Input::Type::Double
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:534
LinSys::rhs_zero_entries
virtual PetscErrorCode rhs_zero_entries()
Definition: linsys.hh:273
MH_DofHandler::edge_new_local_4_mesh_idx_
std::unordered_map< unsigned int, unsigned int > edge_new_local_4_mesh_idx_
Definition: mh_dofhandler.hh:93
chkerr
void chkerr(unsigned int ierr)
Replacement of new/delete operator in the spirit of xmalloc.
Definition: system.hh:147
RichardsLMH::zero_time_term
bool zero_time_term(bool time_global=false) override
Definition: richards_lmh.cc:204
LinSys::mat_zero_entries
virtual PetscErrorCode mat_zero_entries()
Definition: linsys.hh:264
std::vector< int >
RichardsLMH::postprocess
void postprocess() override
Definition: richards_lmh.cc:274
RichardsLMH::EqData::genuchten_p_head_scale
Field< 3, FieldValue< 3 >::Scalar > genuchten_p_head_scale
Definition: richards_lmh.hh:73
uint
unsigned int uint
Definition: mh_dofhandler.hh:108
LocalElementAccessorBase::measure
double measure() const
Definition: mh_dofhandler.hh:140
RichardsLMH::setup_time_term
void setup_time_term() override
Definition: richards_lmh.cc:265
RichardsLMH::prepare_new_time_step
void prepare_new_time_step() override
postprocess velocity field (add sources)
Definition: richards_lmh.cc:197
LinSys::set_matrix_changed
void set_matrix_changed()
Definition: linsys.hh:212
FLOW123D_FORCE_LINK_IN_CHILD
FLOW123D_FORCE_LINK_IN_CHILD(richards_lmh)
RichardsLMH::EqData
Definition: richards_lmh.hh:67
DarcyMH::assembly_mh_matrix
void assembly_mh_matrix(MultidimAssembly &assembler)
Definition: darcy_flow_mh.cc:696
Input::Type::Record::size
unsigned int size() const
Returns number of keys in the Record.
Definition: type_record.hh:598
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:195
Distribution
Definition: distribution.hh:50
FEAL_ASSERT
#define FEAL_ASSERT(expr)
Definition of assert for debug and release mode.
Definition: asserts.hh:279
Input::Record
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
sys_profiler.hh
darcy_flow_mh_output.hh
Output class for darcy_flow_mh model.
Input::Type::Record::allow_auto_conversion
virtual Record & allow_auto_conversion(const string &from_key)
Allows shorter input of the Record providing only value of the from_key given as the parameter.
Definition: type_record.cc:132
schur.hh
Assembly explicit Schur complement for the given linear system. Provides method for resolution of the...
MH_DofHandler::accessor
LocalElementAccessorBase< 3 > accessor(uint local_ele_idx)
Definition: mh_dofhandler.cc:289
RichardsLMH::data_
std::shared_ptr< EqData > data_
Definition: richards_lmh.hh:114
Input::Type::Default::obligatory
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:110
UnitSI
Class for representation SI units of Fields.
Definition: unit_si.hh:40
Mesh::region_db
const RegionDB & region_db() const
Definition: mesh.h:147
LinSys_BDDC
Definition: linsys_BDDC.hh:41
MH_DofHandler::side_ds
Distribution * side_ds
Definition: mh_dofhandler.hh:87
EquationBase::input_record_
Input::Record input_record_
Definition: equation.hh:223
RegionDB::get_region_set
RegionSet get_region_set(const std::string &set_name) const
Definition: region.cc:328
FieldCommon::field_descriptor_record_description
static const std::string field_descriptor_record_description(const string &record_name)
Definition: field_common.cc:73
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:501
SoilModelBase::van_genuchten
@ van_genuchten
Definition: soil_models.hh:55
RichardsLMH::solution_2_edge_scatter_
VecScatter solution_2_edge_scatter_
PETSC scatter from the solution vector to the parallel edge vector with ghost values.
Definition: richards_lmh.hh:116
DarcyMH::schur0
LinSys * schur0
Definition: darcy_flow_mh.hh:365
Input::Type::Selection
Template for classes storing finite set of named values.
Definition: type_selection.hh:65
DarcyFlowInterface::get_input_type
static Input::Type::Abstract & get_input_type()
Definition: darcy_flow_interface.hh:21
LinSys::start_add_assembly
virtual void start_add_assembly()
Definition: linsys.hh:341
Input::Type::Record::close
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:303
Input::Type
Definition: balance.hh:38
Input::Type::Record
Record type proxy class.
Definition: type_record.hh:182
DarcyMH::mh_dh
MH_DofHandler mh_dh
Definition: darcy_flow_mh.hh:342
DarcyMH::data_
std::shared_ptr< EqData > data_
Definition: darcy_flow_mh.hh:377
MH_DofHandler::el_ds
Distribution * el_ds
Definition: mh_dofhandler.hh:86
FieldCommon::input_default
FieldCommon & input_default(const string &input_default)
Definition: field_common.hh:127
input_type.hh
Mesh
Definition: mesh.h:80
Input::Type::Record::copy_keys
Record & copy_keys(const Record &other)
Copy keys from other record.
Definition: type_record.cc:215
Input::Type::Array
Class for declaration of inputs sequences.
Definition: type_base.hh:339
RichardsLMH::get_input_type
static const Input::Type::Record & get_input_type()
Definition: richards_lmh.cc:72
DarcyMH::get_input_type
static const Input::Type::Record & get_input_type()
Definition: darcy_flow_mh.cc:131
LinSys::finish_assembly
virtual void finish_assembly()=0
global_defs.h
Global macros to enhance readability and debugging, general constants.
RichardsLMH::registrar
static const int registrar
Registrar of class to factory.
Definition: richards_lmh.hh:99
RichardsLMH::EqData::genuchten_n_exponent
Field< 3, FieldValue< 3 >::Scalar > genuchten_n_exponent
Definition: richards_lmh.hh:74
SoilModelBase::SoilModelType
SoilModelType
Definition: soil_models.hh:54
RichardsLMH::assembly_source_term
void assembly_source_term() override
Source term is implemented differently in LMH version.
Definition: richards_lmh.cc:155
balance.hh
FieldCommon::description
FieldCommon & description(const string &description)
Definition: field_common.hh:115
DarcyMH::solution_changed_for_scatter
bool solution_changed_for_scatter
Definition: darcy_flow_mh.hh:340
RichardsLMH::read_initial_condition
void read_initial_condition() override
Definition: richards_lmh.cc:161
RichardsLMH::assembly_linear_system
void assembly_linear_system() override
Definition: richards_lmh.cc:218
Input::Type::Selection::add_value
Selection & add_value(const int value, const std::string &key, const std::string &description="", TypeBase::attribute_map attributes=TypeBase::attribute_map())
Adds one new value with name given by key to the Selection.
Definition: type_selection.cc:50
DarcyMH
Mixed-hybrid model of linear Darcy flow, possibly unsteady.
Definition: darcy_flow_mh.hh:126
START_TIMER
#define START_TIMER(tag)
Starts a timer with specified tag.
Definition: sys_profiler.hh:119
SoilModelBase::irmay
@ irmay
Definition: soil_models.hh:56
RichardsLMH::initialize_specific
void initialize_specific() override
Definition: richards_lmh.cc:118
MH_DofHandler::row_4_edge
LongIdx * row_4_edge
Definition: mh_dofhandler.hh:82
FieldCommon::name
FieldCommon & name(const string &name)
Definition: field_common.hh:108