Flow123d  last_with_con_2.0.0-4-g42e6930
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 "fields/vec_seq_double.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 
47 
49 R"(
50 Saturated water content (($ \theta_s $)).
51 relative volume of the water in a reference volume of a saturated porous media.
52 )" , "0.0");
54 
56 R"(
57 Residual water content (($ \theta_r $)).
58 Relative volume of the water in a reference volume of an ideally dry porous media.
59 )" , "0.0");
61 
63 R"(
64 The van Genuchten pressure head scaling parameter (($ \alpha $)).
65 The parameter of the van Genuchten's model to scale the pressure head.
66 Related to the inverse of the air entry pressure, i.e. the pressure where the relative water content starts to decrease below 1.
67 )" ,"0.0");
69 
71  "The van Genuchten exponent parameter (($ n $)).", "2.0");
73 
74 }
75 
76 
78  it::Record field_descriptor = it::Record("RichardsLMH_Data",FieldCommon::field_descriptor_record_description("RichardsLMH_Data"))
80  .copy_keys( RichardsLMH::EqData().make_field_descriptor_type("RichardsLMH_Data_aux") )
81  .close();
82 
83  auto model_selection = it::Selection("Flow_Darcy_BC_Type")
84  .add_value(SoilModelBase::van_genuchten, "van_genuchten", "Van Genuchten soil model with cutting near zero.")
85  .add_value(SoilModelBase::irmay, "irmay", "Irmay model for conductivity, Van Genuchten model for the water content. Suitable for bentonite.")
86  .close();
87 
88 
89  return it::Record("Flow_Richards_LMH", "Lumped Mixed-Hybrid solver for unsteady saturated Darcy flow.")
92  .declare_key("input_fields", it::Array( field_descriptor ), it::Default::obligatory(),
93  "Input data for Darcy flow model.")
94  .declare_key("soil_model", model_selection, it::Default("\"van_genuchten\""),
95  "Selection of the globally applied soil model. In future we replace this key by a field for selection of the model."
96  "That will allow usage of different soil model in a single simulation.")
97  .close();
98 }
99 
100 
101 const int RichardsLMH::registrar =
102  Input::register_class< RichardsLMH, Mesh &, const Input::Record >("Flow_Richards_LMH") +
104 
105 
106 
108  : DarcyMH(mesh_in, in_rec)
109 {
110  data_ = make_shared<EqData>();
113  //data_->edge_new_local_4_mesh_idx_ = &(this->edge_new_local_4_mesh_idx_);
114 }
115 
117 
118  auto model_type = input_record_.val<SoilModelBase::SoilModelType>("soil_model");
119  if (model_type == SoilModelBase::van_genuchten)
120  data_->soil_model_ = std::make_shared<SoilModel_VanGenuchten>();
121  else if (model_type == SoilModelBase::irmay)
122  data_->soil_model_ = std::make_shared<SoilModel_Irmay>();
123  else
124  ASSERT(false);
125 
126  // create edge vectors
127  unsigned int n_local_edges = mh_dh.edge_new_local_4_mesh_idx_.size();
128  unsigned int n_local_sides = mh_dh.side_ds->lsize();
129  data_->phead_edge_.resize( n_local_edges);
130  data_->water_content_previous_it.resize(n_local_sides);
131  data_->water_content_previous_time.resize(n_local_sides);
132  data_->capacity.resize(n_local_sides);
133 
134  Distribution ds_split_edges(n_local_edges, PETSC_COMM_WORLD);
135  vector<int> local_edge_rows(n_local_edges);
136 
137  IS is_loc;
138  for(auto item : mh_dh.edge_new_local_4_mesh_idx_) {
139  local_edge_rows[item.second]=mh_dh.row_4_edge[item.first];
140  }
141  ISCreateGeneral(PETSC_COMM_SELF, local_edge_rows.size(),
142  &(local_edge_rows[0]), PETSC_COPY_VALUES, &(is_loc));
143 
144  VecScatterCreate(schur0->get_solution(), is_loc,
145  data_->phead_edge_.petsc_vec(), PETSC_NULL, &solution_2_edge_scatter_);
146  ISDestroy(&is_loc);
147 
148 }
149 
150 
152 {
153 
154 }
155 
156 
158 {
159  // apply initial condition
160  // cycle over local element rows
161  double init_value;
162 
163  for (unsigned int i_loc_el = 0; i_loc_el < mh_dh.el_ds->lsize(); i_loc_el++) {
164  auto ele_ac = mh_dh.accessor(i_loc_el);
165 
166  init_value = data_->init_pressure.value(ele_ac.centre(), ele_ac.element_accessor());
167 
168  FOR_ELEMENT_SIDES(ele_ac.full_iter(),i) {
169  int edge_row = ele_ac.edge_row(i);
170  uint n_sides_of_edge = ele_ac.full_iter()->side(i)->edge()->n_sides;
171  VecSetValue(schur0->get_solution(),edge_row, init_value/n_sides_of_edge, ADD_VALUES);
172  }
173  VecSetValue(schur0->get_solution(),ele_ac.ele_row(), init_value,ADD_VALUES);
174  }
175  VecAssemblyBegin(schur0->get_solution());
176  VecAssemblyEnd(schur0->get_solution());
177 
178  // set water_content
179  // pretty ugly since postprocess change fluxes, which cause bad balance, so we must set them back
180  VecCopy(schur0->get_solution(), previous_solution); // store solution vector
181  postprocess();
182  VecSwap(schur0->get_solution(), previous_solution); // restore solution vector
183 
184  //DebugOut() << "init sol:\n";
185  //VecView( schur0->get_solution(), PETSC_VIEWER_STDOUT_WORLD);
186  //DebugOut() << "init water content:\n";
187  //VecView( data_->water_content_previous_it.petsc_vec(), PETSC_VIEWER_STDOUT_WORLD);
188 
190 }
191 
192 
194 {
196  data_->water_content_previous_time.copy(data_->water_content_previous_it);
197  //VecCopy(schur0->get_solution(), previous_solution);
198 }
199 
201  return data_->storativity.field_result(mesh_->region_db().get_region_set("BULK")) == result_zeros &&
202  data_->genuchten_p_head_scale.field_result(mesh_->region_db().get_region_set("BULK")) == result_zeros;
203 }
204 
205 
207 {
208 
209  START_TIMER("RicharsLMH::assembly_linear_system");
210 
211  VecScatterBegin(solution_2_edge_scatter_, schur0->get_solution(), data_->phead_edge_.petsc_vec() , INSERT_VALUES, SCATTER_FORWARD);
212  VecScatterEnd(solution_2_edge_scatter_, schur0->get_solution(), data_->phead_edge_.petsc_vec() , INSERT_VALUES, SCATTER_FORWARD);
213 
214  is_linear_ = data_->genuchten_p_head_scale.field_result(mesh_->region_db().get_region_set("BULK")) == result_zeros;
215 
216  bool is_steady = zero_time_term();
217  //DebugOut() << "Assembly linear system\n";
218  START_TIMER("full assembly");
219  if (typeid(*schur0) != typeid(LinSys_BDDC)) {
220  schur0->start_add_assembly(); // finish allocation and create matrix
221  }
222  data_->time_step_ = time_->dt();
223  auto multidim_assembler = AssemblyBase::create< AssemblyLMH >(data_);
224 
225 
228 
229  if (balance_ != nullptr) {
230  balance_->start_source_assembly(water_balance_idx_);
231  balance_->start_mass_assembly(water_balance_idx_);
232  }
233 
234  assembly_mh_matrix( multidim_assembler ); // fill matrix
235 
236  if (balance_ != nullptr) {
237  balance_->finish_source_assembly(water_balance_idx_);
238  balance_->finish_mass_assembly(water_balance_idx_);
239  }
240  //MatView( *const_cast<Mat*>(schur0->get_matrix()), PETSC_VIEWER_STDOUT_WORLD );
241  //VecView( *const_cast<Vec*>(schur0->get_rhs()), PETSC_VIEWER_STDOUT_WORLD);
242 
245 
246 
247  if (! is_steady) {
248  START_TIMER("fix time term");
249  //DebugOut() << "setup time term\n";
250  // assembly time term and rhs
252  }
253 }
254 
255 
256 
258 {
259  FEAL_ASSERT(false).error("Shold not be called.");
260 }
261 
262 
263 
264 
265 
267 
268  // update structures for balance of water volume
269  if (balance_ != nullptr)
271 
272 
273 
274  int side_rows[4];
275  double values[4];
276 
277 
278  VecScatterBegin(solution_2_edge_scatter_, schur0->get_solution(), data_->phead_edge_.petsc_vec() , INSERT_VALUES, SCATTER_FORWARD);
279  VecScatterEnd(solution_2_edge_scatter_, schur0->get_solution(), data_->phead_edge_.petsc_vec() , INSERT_VALUES, SCATTER_FORWARD);
280 
281 
282  // modify side fluxes in parallel
283  // for every local edge take time term on digonal and add it to the corresponding flux
284  //PetscScalar *loc_prev_sol;
285  auto multidim_assembler = AssemblyBase::create< AssemblyLMH >(data_);
286 
287  //VecGetArray(previous_solution, &loc_prev_sol);
288  for (unsigned int i_loc = 0; i_loc < mh_dh.el_ds->lsize(); i_loc++) {
289  auto ele_ac = mh_dh.accessor(i_loc);
290  multidim_assembler[ele_ac.dim()-1]->update_water_content(ele_ac);
291 
292  double ele_scale = ele_ac.measure() *
293  data_->cross_section.value(ele_ac.centre(), ele_ac.element_accessor()) / ele_ac.n_sides();
294  double ele_source = data_->water_source_density.value(ele_ac.centre(), ele_ac.element_accessor());
295  //double storativity = data_->storativity.value(ele_ac.centre(), ele_ac.element_accessor());
296 
297  FOR_ELEMENT_SIDES(ele_ac.full_iter(),i) {
298  //unsigned int loc_edge_row = ele_ac.edge_local_row(i);
299  side_rows[i] = ele_ac.side_row(i);
300  double water_content = data_->water_content_previous_it[ele_ac.side_local_idx(i)];
301  double water_content_previous_time = data_->water_content_previous_time[ele_ac.side_local_idx(i)];
302 
303  values[i] = ele_scale * ele_source - ele_scale * (water_content - water_content_previous_time) / time_->dt();
304  }
305  VecSetValues(schur0->get_solution(), ele_ac.n_sides(), side_rows, values, ADD_VALUES);
306  }
307 
308 
309  VecAssemblyBegin(schur0->get_solution());
310  //VecRestoreArray(previous_solution, &loc_prev_sol);
311  VecAssemblyEnd(schur0->get_solution());
312 
313 }
314 
void initialize_specific() override
FieldSet * eq_data_
Definition: equation.hh:230
Distribution * side_ds
#define ADD_FIELD(name,...)
Definition: field_set.hh:271
Output class for darcy_flow_mh model.
void assembly_mh_matrix(MultidimAssembler ma)
unsigned int uint
unsigned int size() const
Returns number of keys in the Record.
Definition: type_record.hh:582
int is_linear_
void postprocess() override
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:50
virtual void start_add_assembly()
Definition: linsys.hh:297
virtual PetscErrorCode mat_zero_entries()
Definition: linsys.hh:239
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:99
RegionSet get_region_set(const string &set_name) const
Definition: region.cc:328
Definition: mesh.h:95
static const Input::Type::Record & type_field_descriptor()
Distribution * el_ds
#define FOR_ELEMENT_SIDES(i, j)
Definition: elements.h:189
virtual void finish_assembly()=0
const RegionDB & region_db() const
Definition: mesh.h:152
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:347
static const std::string field_descriptor_record_description(const string &record_name)
Definition: field_common.cc:67
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
bool solution_changed_for_scatter
std::shared_ptr< EqData > data_
FLOW123D_FORCE_LINK_IN_CHILD(richards_lmh)
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:286
Basic time management class.
Class for declaration of inputs sequences.
Definition: type_base.hh:321
std::unordered_map< unsigned int, unsigned int > edge_new_local_4_mesh_idx_
void prepare_new_time_step() override
postprocess velocity field (add sources)
Assembly explicit Schur complement for the given linear system. Provides method for resolution of the...
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:195
VecScatter solution_2_edge_scatter_
PETSC scatter from the solution vector to the parallel edge vector with ghost values.
Global macros to enhance readability and debugging, general constants.
std::shared_ptr< Balance > balance_
const Vec & get_solution()
Definition: linsys.hh:257
Field< 3, FieldValue< 3 >::Scalar > water_content_saturated
Definition: richards_lmh.hh:57
Selection & add_value(const int value, const std::string &key, const std::string &description="")
Adds one new value with name given by key to the Selection.
Accessor to the data with type Type::Record.
Definition: accessors.hh:277
const Ret val(const string &key) const
#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:468
static Input::Type::Abstract & get_input_type()
void setup_time_term()
LinSys * schur0
virtual PetscErrorCode rhs_zero_entries()
Definition: linsys.hh:248
std::shared_ptr< EqData > data_
Record & copy_keys(const Record &other)
Copy keys from other record.
Definition: type_record.cc:212
Field< 3, FieldValue< 3 >::Scalar > genuchten_p_head_scale
Definition: richards_lmh.hh:59
MH_DofHandler mh_dh
Field< 3, FieldValue< 3 >::Scalar > water_content_residual
Definition: richards_lmh.hh:58
const Selection & close() const
Close the Selection, no more values can be added.
Input::Record input_record_
Definition: equation.hh:223
static const Input::Type::Record & get_input_type()
Definition: richards_lmh.cc:77
double dt() const
LocalElementAccessorBase< 3 > accessor(uint local_ele_idx)
unsigned int water_balance_idx_
index of water balance within the Balance object.
Field< 3, FieldValue< 3 >::Scalar > genuchten_n_exponent
Definition: richards_lmh.hh:60
void read_initial_condition() override
void assembly_linear_system() override
void set_matrix_changed()
Definition: linsys.hh:187
Record type proxy class.
Definition: type_record.hh:171
static const int registrar
Registrar of class to factory.
Definition: richards_lmh.hh:85
Class for representation SI units of Fields.
Definition: unit_si.hh:40
RichardsLMH(Mesh &mesh, const Input::Record in_rec)
static UnitSI & dimensionless()
Returns dimensionless unit.
Definition: unit_si.cc:53
Vec previous_solution
Template for classes storing finite set of named values.
Input::Type::Record make_field_descriptor_type(const std::string &equation_name) const
Definition: field_set.cc:61
static const Input::Type::Record & get_input_type()
TimeGovernor * time_
Definition: equation.hh:222
bool zero_time_term() override
void assembly_source_term() override
Source term is implemented differently in LMH version.
#define FEAL_ASSERT(expr)
Definition of assert for debug and release mode.
Definition: asserts.hh:280
Mixed-hybrid of steady Darcy flow with sources and variable density.
unsigned int lsize(int proc) const
get local size