Flow123d  release_1.8.2-2141-g34b6400
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"( Saturated water content (($ \theta_s $)). relative volume of the water in a reference volume of a saturated porous media. )" , "0.0");
51 
53 R"( Residual water content (($ \theta_r $)). Relative volume of the water in a reference volume of an ideally dry porous media. )" , "0.0");
55 
57 R"( The van Genuchten pressure head scaling parameter (($ \alpha $)). The parameter of the van Genuchten's model to scale the pressure head. Related to the inverse of the air entry pressure, i.e. the pressure where the relative water content starts to decrease below 1. )" ,"0.0");
59 
61  "The van Genuchten exponent parameter (($ n $)).", "2.0");
63 
64 }
65 
66 
68  it::Record field_descriptor = it::Record("RichardsLMH_Data",FieldCommon::field_descriptor_record_description("RichardsLMH_Data"))
70  .copy_keys( RichardsLMH::EqData().make_field_descriptor_type("RichardsLMH_Data_aux") )
71  .close();
72 
73  auto model_selection = it::Selection("Flow_Darcy_BC_Type")
74  .add_value(SoilModelBase::van_genuchten, "van_genuchten", "Van Genuchten soil model with cutting near zero.")
75  .add_value(SoilModelBase::irmay, "irmay", "Irmay model for conductivity, Van Genuchten model for the water content. Suitable for bentonite.")
76  .close();
77 
78 
79  return it::Record("Flow_Richards_LMH", "Lumped Mixed-Hybrid solver for unsteady saturated Darcy flow.")
82  .declare_key("input_fields", it::Array( field_descriptor ), it::Default::obligatory(),
83  "Input data for Darcy flow model.")
84  .declare_key("soil_model", model_selection, it::Default("\"van_genuchten\""),
85  "Selection of the globally applied soil model. In future we replace this key by a field for selection of the model."
86  "That will allow usage of different soil model in a single simulation.")
87  .close();
88 }
89 
90 
91 const int RichardsLMH::registrar =
92  Input::register_class< RichardsLMH, Mesh &, const Input::Record >("Flow_Richards_LMH") +
94 
95 
96 
97 RichardsLMH::RichardsLMH(Mesh &mesh_in, const Input::Record in_rec)
98  : DarcyMH(mesh_in, in_rec)
99 {
100  data_ = make_shared<EqData>();
103  //data_->edge_new_local_4_mesh_idx_ = &(this->edge_new_local_4_mesh_idx_);
104 }
105 
108  auto model_type = input_record_.val<SoilModelBase::SoilModelType>("soil_model");
109  if (model_type == SoilModelBase::van_genuchten)
110  data_->soil_model_ = std::make_shared<SoilModel_VanGenuchten>();
111  else if (model_type == SoilModelBase::irmay)
112  data_->soil_model_ = std::make_shared<SoilModel_Irmay>();
113  else
114  ASSERT(false);
115 
116  // create edge vectors
117  unsigned int n_local_edges = mh_dh.edge_new_local_4_mesh_idx_.size();
118  unsigned int n_local_sides = mh_dh.side_ds->lsize();
119  data_->phead_edge_.resize( n_local_edges);
120  data_->water_content_previous_it.resize(n_local_sides);
121  data_->water_content_previous_time.resize(n_local_sides);
122  data_->capacity.resize(n_local_sides);
123 
124  Distribution ds_split_edges(n_local_edges, PETSC_COMM_WORLD);
125  vector<int> local_edge_rows(n_local_edges);
126 
127  IS is_loc;
128  for(auto item : mh_dh.edge_new_local_4_mesh_idx_) {
129  local_edge_rows[item.second]=mh_dh.row_4_edge[item.first];
130  }
131  ISCreateGeneral(PETSC_COMM_SELF, local_edge_rows.size(),
132  &(local_edge_rows[0]), PETSC_COPY_VALUES, &(is_loc));
133 
134  VecScatterCreate(schur0->get_solution(), is_loc,
135  data_->phead_edge_.petsc_vec(), PETSC_NULL, &solution_2_edge_scatter_);
136  ISDestroy(&is_loc);
137 
138 }
139 
140 
142 {
143 
144 }
145 
146 
148 {
149  // apply initial condition
150  // cycle over local element rows
151  double init_value;
152 
153  for (unsigned int i_loc_el = 0; i_loc_el < mh_dh.el_ds->lsize(); i_loc_el++) {
154  auto ele_ac = mh_dh.accessor(i_loc_el);
155 
156  init_value = data_->init_pressure.value(ele_ac.centre(), ele_ac.element_accessor());
158  FOR_ELEMENT_SIDES(ele_ac.full_iter(),i) {
159  int edge_row = ele_ac.edge_row(i);
160  uint n_sides_of_edge = ele_ac.full_iter()->side(i)->edge()->n_sides;
161  VecSetValue(schur0->get_solution(),edge_row, init_value/n_sides_of_edge, ADD_VALUES);
162  }
163  VecSetValue(schur0->get_solution(),ele_ac.ele_row(), init_value,ADD_VALUES);
164  }
165  VecAssemblyBegin(schur0->get_solution());
166  VecAssemblyEnd(schur0->get_solution());
167 
168  // set water_content
169  // pretty ugly since postprocess change fluxes, which cause bad balance, so we must set them back
170  VecCopy(schur0->get_solution(), previous_solution); // store solution vector
171  postprocess();
172  VecSwap(schur0->get_solution(), previous_solution); // restore solution vector
173 
174  //DebugOut() << "init sol:\n";
175  //VecView( schur0->get_solution(), PETSC_VIEWER_STDOUT_WORLD);
176  //DebugOut() << "init water content:\n";
177  //VecView( data_->water_content_previous_it.petsc_vec(), PETSC_VIEWER_STDOUT_WORLD);
178 
180 }
181 
182 
184 {
186  data_->water_content_previous_time.copy(data_->water_content_previous_it);
187  //VecCopy(schur0->get_solution(), previous_solution);
188 }
189 
191  return data_->storativity.field_result(mesh_->region_db().get_region_set("BULK")) == result_zeros &&
192  data_->genuchten_p_head_scale.field_result(mesh_->region_db().get_region_set("BULK")) == result_zeros;
193 }
194 
195 
197 {
198 
199  START_TIMER("RicharsLMH::assembly_linear_system");
201  VecScatterBegin(solution_2_edge_scatter_, schur0->get_solution(), data_->phead_edge_.petsc_vec() , INSERT_VALUES, SCATTER_FORWARD);
202  VecScatterEnd(solution_2_edge_scatter_, schur0->get_solution(), data_->phead_edge_.petsc_vec() , INSERT_VALUES, SCATTER_FORWARD);
203 
204  is_linear_ = data_->genuchten_p_head_scale.field_result(mesh_->region_db().get_region_set("BULK")) == result_zeros;
205 
206  bool is_steady = zero_time_term();
207  //DebugOut() << "Assembly linear system\n";
208  START_TIMER("full assembly");
209  if (typeid(*schur0) != typeid(LinSys_BDDC)) {
210  schur0->start_add_assembly(); // finish allocation and create matrix
211  }
212  data_->time_step_ = time_->dt();
213  auto multidim_assembler = AssemblyBase::create< AssemblyLMH >(data_);
214 
215 
218 
219  if (balance_ != nullptr) {
220  balance_->start_source_assembly(water_balance_idx_);
221  balance_->start_mass_assembly(water_balance_idx_);
222  }
223 
224  assembly_mh_matrix( multidim_assembler ); // fill matrix
225 
226  if (balance_ != nullptr) {
227  balance_->finish_source_assembly(water_balance_idx_);
228  balance_->finish_mass_assembly(water_balance_idx_);
229  }
230  //MatView( *const_cast<Mat*>(schur0->get_matrix()), PETSC_VIEWER_STDOUT_WORLD );
231  //VecView( *const_cast<Vec*>(schur0->get_rhs()), PETSC_VIEWER_STDOUT_WORLD);
232 
235 
236 
237  if (! is_steady) {
238  START_TIMER("fix time term");
239  //DebugOut() << "setup time term\n";
240  // assembly time term and rhs
242  }
243 }
244 
245 
246 
248 {
249  FEAL_ASSERT(false).error("Shold not be called.");
250 }
251 
252 
253 
254 
255 
258  // update structures for balance of water volume
259  if (balance_ != nullptr)
261 
262 
263 
264  int side_rows[4];
265  double values[4];
267 
268  VecScatterBegin(solution_2_edge_scatter_, schur0->get_solution(), data_->phead_edge_.petsc_vec() , INSERT_VALUES, SCATTER_FORWARD);
269  VecScatterEnd(solution_2_edge_scatter_, schur0->get_solution(), data_->phead_edge_.petsc_vec() , INSERT_VALUES, SCATTER_FORWARD);
270 
271 
272  // modify side fluxes in parallel
273  // for every local edge take time term on digonal and add it to the corresponding flux
274  //PetscScalar *loc_prev_sol;
275  auto multidim_assembler = AssemblyBase::create< AssemblyLMH >(data_);
276 
277  //VecGetArray(previous_solution, &loc_prev_sol);
278  for (unsigned int i_loc = 0; i_loc < mh_dh.el_ds->lsize(); i_loc++) {
279  auto ele_ac = mh_dh.accessor(i_loc);
280  multidim_assembler[ele_ac.dim()-1]->update_water_content(ele_ac);
281 
282  double ele_scale = ele_ac.measure() *
283  data_->cross_section.value(ele_ac.centre(), ele_ac.element_accessor()) / ele_ac.n_sides();
284  double ele_source = data_->water_source_density.value(ele_ac.centre(), ele_ac.element_accessor());
285  //double storativity = data_->storativity.value(ele_ac.centre(), ele_ac.element_accessor());
286 
287  FOR_ELEMENT_SIDES(ele_ac.full_iter(),i) {
288  //unsigned int loc_edge_row = ele_ac.edge_local_row(i);
289  side_rows[i] = ele_ac.side_row(i);
290  double water_content = data_->water_content_previous_it[ele_ac.side_local_idx(i)];
291  double water_content_previous_time = data_->water_content_previous_time[ele_ac.side_local_idx(i)];
292 
293  values[i] = ele_scale * ele_source - ele_scale * (water_content - water_content_previous_time) / time_->dt();
294  }
295  VecSetValues(schur0->get_solution(), ele_ac.n_sides(), side_rows, values, ADD_VALUES);
296  }
297 
298 
299  VecAssemblyBegin(schur0->get_solution());
300  //VecRestoreArray(previous_solution, &loc_prev_sol);
301  VecAssemblyEnd(schur0->get_solution());
302 
303 }
304 
305 
void initialize_specific() override
FieldSet * eq_data_
Definition: equation.hh:230
Distribution * side_ds
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
#define ADD_FIELD(name,...)
Definition: field_set.hh:271
FieldCommon & units(const UnitSI &units)
Set basic units of the field.
bool solution_changed_for_scatter
std::shared_ptr< EqData > data_
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.
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Definition: global_defs.h:180
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