Flow123d  release_3.0.0-973-g92f55e826
assembly_lmh.hh
Go to the documentation of this file.
1 /*
2  * assembly_lmh.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 "mesh/long_idx.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 AssemblyLMH : public AssemblyMH<dim> {
49 public:
50 
51  typedef std::shared_ptr<RichardsLMH::EqData> AssemblyDataPtr;
52 
54  : AssemblyMH<dim>(data),
55  ad_(data),
56  genuchten_on(false),
57  cross_section(1.0),
58  soil_model(data->soil_model_)
59  {}
60 
62  genuchten_on = (this->ad_->genuchten_p_head_scale.field_result({ele.region()}) != result_zeros);
63  if (genuchten_on) {
64  SoilData soil_data;
65  soil_data.n = this->ad_->genuchten_n_exponent.value(ele.centre(), ele.element_accessor());
66  soil_data.alpha = this->ad_->genuchten_p_head_scale.value(ele.centre(), ele.element_accessor());
67  soil_data.Qr = this->ad_->water_content_residual.value(ele.centre(), ele.element_accessor());
68  soil_data.Qs = this->ad_->water_content_saturated.value(ele.centre(), ele.element_accessor());
69  soil_data.Ks = this->ad_->conductivity.value(ele.centre(), ele.element_accessor());
70  //soil_data.cut_fraction = 0.99; // set by model
71 
72  soil_model->reset(soil_data);
73  }
74 
75  }
76 
78  reset_soil_model(ele);
79  double storativity = this->ad_->storativity.value(ele.centre(), ele.element_accessor());
80  for (unsigned int i=0; i<ele.element_accessor()->n_sides(); i++) {
81  double capacity = 0;
82  double water_content = 0;
83  double phead = ad_->phead_edge_[ele.edge_local_idx(i)];
84  if (genuchten_on) {
85 
86  fadbad::B<double> x_phead(phead);
87  fadbad::B<double> evaluated( soil_model->water_content_diff(x_phead) );
88  evaluated.diff(0,1);
89  water_content = evaluated.val();
90  capacity = x_phead.d(0);
91  }
92  ad_->capacity[ele.side_local_idx(i)] = capacity + storativity;
93  ad_->water_content_previous_it[ele.side_local_idx(i)] = water_content + storativity * phead;
94  }
95  }
96 
98  {
99  reset_soil_model(ele);
100  cross_section = this->ad_->cross_section.value(ele.centre(), ele.element_accessor());
101 
102 
103  double conductivity, head;
104  if (genuchten_on) {
105  conductivity=0;
106  head=0;
107  for (unsigned int i=0; i<ele.element_accessor()->n_sides(); i++)
108  {
109  uint local_edge = ele.edge_local_idx(i);
110  double phead = ad_->phead_edge_[local_edge];
111  conductivity += soil_model->conductivity(phead);
112  head += ad_->phead_edge_[local_edge];
113  }
114  conductivity /= ele.n_sides();
115  head /= ele.n_sides();
116  } else {
117  conductivity = this->ad_->conductivity.value(ele.centre(), ele.element_accessor());
118  }
119 
120  double scale = 1 / cross_section / conductivity;
121  this->assemble_sides_scale(ele,scale);
122  }
123 
124  /***
125  * Called from assembly_local_matrix, assumes precomputed:
126  * cross_section, genuchten_on, soil_model
127  */
129  {
130 
131  // set lumped source
132  double diagonal_coef = ele.measure() * cross_section / ele.n_sides();
133 
134 
135  double source_diagonal = diagonal_coef * this->ad_->water_source_density.value(ele.centre(), ele.element_accessor());
136 
138  for (unsigned int i=0; i<ele.element_accessor()->n_sides(); i++)
139  {
140 
141  uint local_edge = ele.edge_local_idx(i);
142  uint local_side = ele.side_local_idx(i);
143  uint edge_row = ele.edge_row(i);
144  if (this->dirichlet_edge[i] == 0) {
145 
146  double capacity = this->ad_->capacity[local_side];
147  double water_content_diff = -ad_->water_content_previous_it[local_side] + ad_->water_content_previous_time[local_side];
148  double mass_diagonal = diagonal_coef * capacity;
149 
150  /*
151  DebugOut().fmt("w diff: {:g} mass: {:g} w prev: {:g} w time: {:g} c: {:g} p: {:g} z: {:g}",
152  water_content_diff,
153  mass_diagonal * ad_->phead_edge_[local_edge],
154  -ad_->water_content_previous_it[local_side],
155  ad_->water_content_previous_time[local_side],
156  capacity,
157  ad_->phead_edge_[local_edge],
158  ele.centre()[0] );
159  */
160 
161 
162  double mass_rhs = mass_diagonal * ad_->phead_edge_[local_edge] / this->ad_->time_step_
163  + diagonal_coef * water_content_diff / this->ad_->time_step_;
164 
165 // DBGCOUT(<< "source [" << loc_system_.row_dofs[this->loc_edge_dofs[i]] << ", " << loc_system_.row_dofs[this->loc_edge_dofs[i]]
166 // << "] mat: " << -mass_diagonal/this->ad_->time_step_
167 // << " rhs: " << -source_diagonal - mass_rhs
168 // << "\n");
169  this->loc_system_.add_value(this->loc_edge_dofs[i], this->loc_edge_dofs[i],
170  -mass_diagonal/this->ad_->time_step_,
171  -source_diagonal - mass_rhs);
172  }
173 
174  if (ad_->balance != nullptr) {
175  ad_->balance->add_mass_vec_value(ad_->water_balance_idx, ele.region().bulk_idx(),
176  diagonal_coef*ad_->water_content_previous_it[local_side]);
177  ad_->balance->add_source_vec_values(ad_->water_balance_idx, ele.region().bulk_idx(), {(LongIdx)edge_row}, {source_diagonal});
178  }
179  }
180 
181  }
182 
184 
187  std::shared_ptr<SoilModelBase> soil_model;
188 };
189 
190 
191 
192 #endif /* SRC_FLOW_ASSEMBLY_LMH_HH_ */
AssemblyMH::assemble_sides_scale
void assemble_sides_scale(LocalElementAccessorBase< 3 > ele_ac, double scale)
Definition: darcy_flow_assembly.hh:389
AssemblyLMH::assemble_sides
void assemble_sides(LocalElementAccessorBase< 3 > ele) override
Definition: assembly_lmh.hh:97
result_zeros
@ result_zeros
Definition: field_algo_base.hh:72
LocalElementAccessorBase::n_sides
uint n_sides()
Definition: mh_dofhandler.hh:128
AssemblyLMH::soil_model
std::shared_ptr< SoilModelBase > soil_model
Definition: assembly_lmh.hh:187
AssemblyMH
Definition: darcy_flow_assembly.hh:98
SoilData::n
double n
Definition: soil_models.hh:39
AssemblyLMH::reset_soil_model
void reset_soil_model(LocalElementAccessorBase< 3 > ele)
Definition: assembly_lmh.hh:61
SoilData::Qr
double Qr
Definition: soil_models.hh:41
LocalElementAccessorBase< 3 >
AssemblyLMH
Definition: assembly_lmh.hh:48
uint
unsigned int uint
Definition: mh_dofhandler.hh:108
LocalElementAccessorBase::measure
double measure() const
Definition: mh_dofhandler.hh:140
darcy_flow_assembly.hh
AssemblyLMH::genuchten_on
bool genuchten_on
Definition: assembly_lmh.hh:185
LocalElementAccessorBase::centre
const arma::vec3 centre() const
Definition: mh_dofhandler.hh:136
AssemblyLMH::cross_section
double cross_section
Definition: assembly_lmh.hh:186
AssemblyLMH::AssemblyDataPtr
std::shared_ptr< RichardsLMH::EqData > AssemblyDataPtr
Definition: assembly_lmh.hh:51
soil_models.hh
LocalElementAccessorBase::edge_row
uint edge_row(uint i)
Definition: mh_dofhandler.hh:172
LocalElementAccessorBase::edge_local_idx
uint edge_local_idx(uint i)
Definition: mh_dofhandler.hh:168
AssemblyLMH::AssemblyLMH
AssemblyLMH(AssemblyDataPtr data)
Definition: assembly_lmh.hh:53
LocalElementAccessorBase::element_accessor
ElementAccessor< 3 > element_accessor()
Definition: mh_dofhandler.hh:132
AssemblyLMH::assemble_source_term
void assemble_source_term(LocalElementAccessorBase< 3 > ele) override
Definition: assembly_lmh.hh:128
SoilData::alpha
double alpha
Definition: soil_models.hh:40
SoilData::Ks
double Ks
Definition: soil_models.hh:44
SoilData
Definition: soil_models.hh:38
long_idx.hh
balance.hh
LocalElementAccessorBase::side_local_idx
uint side_local_idx(uint i)
Definition: mh_dofhandler.hh:193
LocalElementAccessorBase::region
Region region() const
Definition: mh_dofhandler.hh:144
RegionIdx::bulk_idx
unsigned int bulk_idx() const
Returns index of the region in the bulk set.
Definition: region.hh:91
AssemblyLMH::ad_
AssemblyDataPtr ad_
Definition: assembly_lmh.hh:183
SoilData::Qs
double Qs
Definition: soil_models.hh:42
AssemblyLMH::update_water_content
void update_water_content(LocalElementAccessorBase< 3 > ele) override
Definition: assembly_lmh.hh:77