Flow123d  JS_before_hm-2088-g1c00063e5
assembly_richards_old.hh
Go to the documentation of this file.
1 /*
2  * assembly_richards_old.hh
3  *
4  * Created on: Apr 30, 2016
5  * Author: jb
6  */
7 
8 #ifndef SRC_FLOW_ASSEMBLY_LMH_HH_
9 #define SRC_FLOW_ASSEMBLY_LMH_HH_
10 
11 #include "system/index_types.hh"
12 #include "flow/assembly_lmh_old.hh"
13 #include "soil_models.hh"
14 #include "coupling/balance.hh"
15 
16 #include "badiff.h"
17 
18 
19 /**
20  * Prove of concept for general assembly scheme.
21  * Ideas:
22  * - Local assembly class for given DIM provides assembly methods for:
23  * - local assembly on elements of dimension DIM
24  * - local assembly on edges/faces of neighbouring elemnts of dimension DIM
25  * - local assembly of interactiong elements DIM and OTHER_DIM with OTHER_DIM < DIM
26  * - Such class template would be necessary to create particular instance of Assembler class, that
27  * takes job of pass through the mesh, precomputing necessary fields, etc.
28  * This allows to manage order of assembled entities in arbitrary way in order to use caches and vectorisation efficiently.
29  * - Separate local assembly template would be necessary for every pass through the mesh, but it may delegate its actions
30  * to a single general local assembly class.
31  * - The local assembly class gets an Accessor object for particular domain of the assembly, i.e. ElementAccessor for element assembly,
32  * FaceAccessor for interface intergrals assembly, and InteractionAccessor for assembly of interaction of two elements, e.g. for XFEM
33  * there may be an interaction between every 3D element within the enrichment with appropriate 1D elemnt on the well.
34  * These accessors provides methods to access fields values as well as the DOF indices on the element(s).
35  * - Results of the assembly are passed to the global linear algebra objects collected in the RichardSystem class, global indices
36  * (which are still local indicies of the single process) provided by accessors are used.
37  *
38  *
39  * TODO:
40  * - finish functional Richards model
41  * - move whole internals of the assembly_mh_matrix into local assembly classes
42  * - mean while: imporve accessors, imporve mesh and DOF handler interface; possibly create new mesh implementation used in Darcy first and then
43  * apply it to other equations
44  */
45 
46 
47 template<int dim>
48 class AssemblyRichards : public AssemblyLMH<dim> {
49 public:
50 
51  typedef std::shared_ptr<RichardsLMH::EqFields> AssemblyFieldsPtrRichards;
52  typedef std::shared_ptr<RichardsLMH::EqData> AssemblyDataPtrRichards;
53 
55  : AssemblyLMH<dim>(fields, data),
56  af_(fields),
57  ad_(data),
58  genuchten_on(false),
59  cross_section(1.0),
60  cr_disc_dofs(dim+1)
61  {}
62 
63 protected:
64  void reset_soil_model(const DHCellAccessor& dh_cell) {
65  ElementAccessor<3> ele = dh_cell.elm();
66  genuchten_on = (af_->genuchten_p_head_scale.field_result({ele.region()}) != result_zeros);
67  if (genuchten_on) {
68  SoilData soil_data;
69  soil_data.n = af_->genuchten_n_exponent.value(ele.centre(), ele);
70  soil_data.alpha = af_->genuchten_p_head_scale.value(ele.centre(), ele);
71  soil_data.Qr = af_->water_content_residual.value(ele.centre(), ele);
72  soil_data.Qs = af_->water_content_saturated.value(ele.centre(), ele);
73  soil_data.Ks = af_->conductivity.value(ele.centre(), ele);
74  //soil_data.cut_fraction = 0.99; // set by model
75 
76  ad_->soil_model_->reset(soil_data);
77  }
78  }
79 
81  {
82  double conductivity = 0;
83  if (genuchten_on) {
84  for (unsigned int i=0; i<ele->n_sides(); i++)
85  {
86  double phead = ad_->p_edge_solution.get( this->loc_schur_.row_dofs[i] );
87  conductivity += ad_->soil_model_->conductivity(phead);
88  }
89  conductivity /= ele->n_sides();
90  }
91  else {
92  conductivity = this->af_->conductivity.value(ele.centre(), ele);
93  }
94  return conductivity;
95  }
96 
97  void update_water_content(const DHCellAccessor& dh_cell) {
98 
99  // dof indices for edge pressure must be updated
100  // since update_water_content is called also outside assemble cycle (init condition)
101  update_dofs(dh_cell);
102 
103  reset_soil_model(dh_cell);
104  const ElementAccessor<3> ele = dh_cell.elm();
105  double storativity = af_->storativity.value(ele.centre(), ele)
106  + af_->extra_storativity.value(ele.centre(), ele);
107  VectorMPI water_content_vec = af_->water_content_ptr->vec();
108 
109  for (unsigned int i=0; i<ele->n_sides(); i++) {
110  double capacity = 0;
111  double water_content = 0;
112  double phead = ad_->p_edge_solution.get( edge_indices_[i] );
113  if (genuchten_on) {
114 
115  fadbad::B<double> x_phead(phead);
116  fadbad::B<double> evaluated( ad_->soil_model_->water_content_diff(x_phead) );
117  evaluated.diff(0,1);
118  water_content = evaluated.val();
119  capacity = x_phead.d(0);
120  }
121  ad_->capacity.set( cr_disc_dofs[i], capacity + storativity );
122  water_content_vec.set( cr_disc_dofs[i], water_content + storativity * phead);
123  }
124  }
125 
126  void assemble_sides(const DHCellAccessor& dh_cell) override
127  {
128  reset_soil_model(dh_cell);
129  const ElementAccessor<3> ele = dh_cell.elm();
130  cross_section = af_->cross_section.value(ele.centre(), ele);
131 
132  double conductivity = compute_conductivity(ele);
133  double scale = 1 / cross_section / conductivity;
134  this->assemble_sides_scale(dh_cell,scale);
135  }
136 
137  /***
138  * Called from assembly_local_matrix, assumes precomputed:
139  * cross_section, genuchten_on, soil_model
140  */
141  void assemble_source_term(const DHCellAccessor& dh_cell) override
142  {
143  update_water_content(dh_cell);
144  const ElementAccessor<3> ele = dh_cell.elm();
145 
146  // set lumped source
147  double diagonal_coef = ele.measure() * cross_section / ele->n_sides();
148  double source_diagonal = diagonal_coef *
149  ( af_->water_source_density.value(ele.centre(), ele)
150  + af_->extra_source.value(ele.centre(), ele));
151 
152  VectorMPI water_content_vec = af_->water_content_ptr->vec();
153 
154  for (unsigned int i=0; i<ele->n_sides(); i++)
155  {
156 
157  const int local_side = cr_disc_dofs[i];
158  if (this->dirichlet_edge[i] == 0) {
159 
160  double capacity = ad_->capacity.get(local_side);
161  double water_content_diff = -water_content_vec.get(local_side) + ad_->water_content_previous_time.get(local_side);
162  double mass_diagonal = diagonal_coef * capacity;
163 
164  /*
165  DebugOut().fmt("w diff: {:g} mass: {:g} w prev: {:g} w time: {:g} c: {:g} p: {:g} z: {:g}",
166  water_content_diff,
167  mass_diagonal * ad_->p_edge_solution[local_edge],
168  -ad_->water_content_previous_it[local_side],
169  ad_->water_content_previous_time[local_side],
170  capacity,
171  ad_->p_edge_solution[local_edge],
172  ele.centre()[0] );
173  */
174 
175 
176  double mass_rhs = mass_diagonal * ad_->p_edge_solution.get( this->loc_schur_.row_dofs[i] ) / ad_->time_step_
177  + diagonal_coef * water_content_diff / ad_->time_step_;
178 
179 // DBGCOUT(<< "source [" << loc_system_.row_dofs[this->loc_edge_dofs[i]] << ", " << loc_system_.row_dofs[this->loc_edge_dofs[i]]
180 // << "] mat: " << -mass_diagonal/this->ad_->time_step_
181 // << " rhs: " << -source_diagonal - mass_rhs
182 // << "\n");
183  this->loc_system_.add_value(this->loc_edge_dofs[i], this->loc_edge_dofs[i],
184  -mass_diagonal/ad_->time_step_,
185  -source_diagonal - mass_rhs);
186  }
187 
188  ad_->balance->add_mass_values(ad_->water_balance_idx, dh_cell, {local_side},
189  {0.0}, diagonal_coef*water_content_vec.get(local_side));
190  ad_->balance->add_source_values(ad_->water_balance_idx, ele.region().bulk_idx(),
191  {this->loc_system_.row_dofs[this->loc_edge_dofs[i]]},
192  {0},{source_diagonal});
193  }
194 
195  }
196 
197  /// Updates DoFs for edge pressure vector (dh CR) and for water content vector (dh CR_disc)
198  /// Be sure to call it before @p update_water_content().
199  void update_dofs(const DHCellAccessor& dh_cell)
200  {
201  edge_indices_ = dh_cell.cell_with_other_dh(ad_->dh_cr_.get()).get_loc_dof_indices();
202  cr_disc_dofs = dh_cell.cell_with_other_dh(ad_->dh_cr_disc_.get()).get_loc_dof_indices();
203  }
204 
206  double edge_scale, double edge_source_term) override
207  {
208  update_water_content(dh_cell);
209 
210  const ElementAccessor<3> ele = dh_cell.elm();
211 
212  VectorMPI water_content_vec = af_->water_content_ptr->vec();
213 
214  for (unsigned int i=0; i<ele->n_sides(); i++) {
215 
216  double water_content = water_content_vec.get( cr_disc_dofs[i] );
217  double water_content_previous_time = ad_->water_content_previous_time.get( cr_disc_dofs[i] );
218 
219  solution[this->loc_side_dofs[i]]
220  += edge_source_term - edge_scale * (water_content - water_content_previous_time) / ad_->time_step_;
221  }
222 
223  IntIdx p_dof = dh_cell.cell_with_other_dh(ad_->dh_p_.get()).get_loc_dof_indices()(0);
224  af_->conductivity_ptr->vec().set( p_dof, compute_conductivity(ele) );
225  }
226 
229 
232  LocDofVec cr_disc_dofs; ///< Dofs of discontinuous fields on element edges.
233  LocDofVec edge_indices_; ///< Dofs of discontinuous fields on element edges.
234 };
235 
236 
237 
238 #endif /* SRC_FLOW_ASSEMBLY_LMH_HH_ */
LocDofVec
arma::Col< IntIdx > LocDofVec
Definition: index_types.hh:28
result_zeros
@ result_zeros
Definition: field_algo_base.hh:74
Armor::vec
ArmaVec< double, N > vec
Definition: armor.hh:885
AssemblyRichards::cr_disc_dofs
LocDofVec cr_disc_dofs
Dofs of discontinuous fields on element edges.
Definition: assembly_richards_old.hh:232
AssemblyRichards::compute_conductivity
double compute_conductivity(ElementAccessor< 3 > ele)
Definition: assembly_richards_old.hh:80
AssemblyRichards::update_dofs
void update_dofs(const DHCellAccessor &dh_cell)
Definition: assembly_richards_old.hh:199
AssemblyRichards
Definition: assembly_richards_old.hh:48
SoilData::n
double n
Definition: soil_models.hh:40
IntIdx
int IntIdx
Definition: index_types.hh:25
AssemblyRichards::assemble_sides
void assemble_sides(const DHCellAccessor &dh_cell) override
Definition: assembly_richards_old.hh:126
SoilData::Qr
double Qr
Definition: soil_models.hh:42
AssemblyRichards::cross_section
double cross_section
Definition: assembly_richards_old.hh:231
AssemblyLMH::assemble_sides_scale
void assemble_sides_scale(const DHCellAccessor &dh_cell, double scale)
Definition: assembly_lmh_old.hh:383
ElementAccessor< 3 >
AssemblyRichards::genuchten_on
bool genuchten_on
Definition: assembly_richards_old.hh:230
AssemblyLMH
Definition: assembly_lmh_old.hh:39
AssemblyRichards::AssemblyDataPtrRichards
std::shared_ptr< RichardsLMH::EqData > AssemblyDataPtrRichards
Definition: assembly_richards_old.hh:52
AssemblyRichards::ad_
AssemblyDataPtrRichards ad_
Definition: assembly_richards_old.hh:228
AssemblyRichards::update_water_content
void update_water_content(const DHCellAccessor &dh_cell)
Updates water content in Richards.
Definition: assembly_richards_old.hh:97
AssemblyRichards::af_
AssemblyFieldsPtrRichards af_
Definition: assembly_richards_old.hh:227
index_types.hh
VectorMPI::set
void set(unsigned int pos, double val)
Set value on given position.
Definition: vector_mpi.hh:111
AssemblyRichards::AssemblyRichards
AssemblyRichards(AssemblyFieldsPtrRichards fields, AssemblyDataPtrRichards data)
Definition: assembly_richards_old.hh:54
DHCellAccessor::cell_with_other_dh
DHCellAccessor cell_with_other_dh(const DOFHandlerMultiDim *dh) const
Create new accessor with same local idx and given DOF handler. Actual and given DOF handler must be c...
Definition: dh_cell_accessor.hh:135
DHCellAccessor::elm
const ElementAccessor< 3 > elm() const
Return ElementAccessor to element of loc_ele_idx_.
Definition: dh_cell_accessor.hh:71
soil_models.hh
Element::n_sides
unsigned int n_sides() const
Definition: elements.h:131
DHCellAccessor
Cell accessor allow iterate over DOF handler cells.
Definition: dh_cell_accessor.hh:43
AssemblyRichards::assemble_source_term
void assemble_source_term(const DHCellAccessor &dh_cell) override
Definition: assembly_richards_old.hh:141
AssemblyRichards::postprocess_velocity_specific
void postprocess_velocity_specific(const DHCellAccessor &dh_cell, arma::vec &solution, double edge_scale, double edge_source_term) override
Definition: assembly_richards_old.hh:205
ElementAccessor::region
Region region() const
Definition: accessors.hh:201
SoilData::alpha
double alpha
Definition: soil_models.hh:41
SoilData::Ks
double Ks
Definition: soil_models.hh:45
DHCellAccessor::get_loc_dof_indices
LocDofVec get_loc_dof_indices() const
Returns the local indices of dofs associated to the cell on the local process.
Definition: dh_cell_accessor.hh:88
assembly_lmh_old.hh
SoilData
Definition: soil_models.hh:39
AssemblyRichards::edge_indices_
LocDofVec edge_indices_
Dofs of discontinuous fields on element edges.
Definition: assembly_richards_old.hh:233
VectorMPI::get
double get(unsigned int pos) const
Return value on given position.
Definition: vector_mpi.hh:105
balance.hh
AssemblyRichards::reset_soil_model
void reset_soil_model(const DHCellAccessor &dh_cell)
Definition: assembly_richards_old.hh:64
AssemblyRichards::AssemblyFieldsPtrRichards
std::shared_ptr< RichardsLMH::EqFields > AssemblyFieldsPtrRichards
Definition: assembly_richards_old.hh:51
VectorMPI
Definition: vector_mpi.hh:43
RegionIdx::bulk_idx
unsigned int bulk_idx() const
Returns index of the region in the bulk set.
Definition: region.hh:91
SoilData::Qs
double Qs
Definition: soil_models.hh:43
ElementAccessor::measure
double measure() const
Computes the measure of the element.
Definition: accessors_impl.hh:67
ElementAccessor::centre
arma::vec::fixed< spacedim > centre() const
Computes the barycenter.
Definition: accessors_impl.hh:89