Flow123d  release_1.8.2-1603-g0109a2b
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 #include "input/input_type.hh"
9 #include "input/factory.hh"
10 #include "flow/richards_lmh.hh"
12 #include "tools/time_governor.hh"
13 
14 #include "petscmat.h"
15 #include "petscviewer.h"
16 #include "petscerror.h"
17 #include <armadillo>
18 
19 #include "system/global_defs.h"
20 #include "system/sys_profiler.hh"
21 #include "la/schur.hh"
22 
23 #include "coupling/balance.hh"
24 
25 #include "fields/vec_seq_double.hh"
26 
27 FLOW123D_FORCE_LINK_IN_CHILD(richards_lmh);
28 
29 
30 namespace it=Input::Type;
32  return it::Record("UnsteadyDarcy_LMH", "Lumped Mixed-Hybrid solver for unsteady saturated Darcy flow.")
36  "Time governor setting for the unsteady Darcy flow model.")
37  .close();
38 }
39 
40 
42  Input::register_class< DarcyFlowLMH_Unsteady, Mesh &, const Input::Record >("UnsteadyDarcy_LMH") +
44 
45 
46 
48  : DarcyFlowMH_Steady(mesh_in, in_rec)
49 {
50  /*
51  time_ = new TimeGovernor(in_rec.val<Input::Record>("time"));
52  data_.mark_input_times(this->mark_type());
53  data_.set_time(time_->step(), LimitSide::right);
54 
55  output_object = new DarcyFlowMHOutput(this, in_rec.val<Input::Record>("output"));
56  //balance_->units(output_object->get_output_fields().field_ele_pressure.units()*data_.cross_section.units()*data_.storativity.units());
57 
58  //time_->fix_dt_until_mark();
59  create_linear_system();
60  if ( typeid(SchurComplement) != typeid(*(this->schur0)) ) {
61  DBGMSG( "%s != %s\n", typeid(LinSys_PETSC).name(),typeid(*(this->schur0)).name() );
62  THROW( ExcMessage() << EI_Message("Only SchurComplement linear solver currently allowed for DarcyFlowLMH.") );
63  }
64 
65  VecDuplicate(schur0->get_solution(), &previous_solution);
66  VecCreateMPI(PETSC_COMM_WORLD,rows_ds->lsize(),PETSC_DETERMINE,&(steady_diagonal));
67  VecDuplicate(steady_diagonal,& new_diagonal);
68  VecDuplicate(*( schur0->get_rhs()), &steady_rhs);
69 
70  assembly_linear_system();
71  read_init_condition();
72  output_data();
73  */
74 }
75 
76 
77 
78 
80 {
81  VecDuplicate(schur0->get_solution(), &previous_solution);
82  VecCreateMPI(PETSC_COMM_WORLD,rows_ds->lsize(),PETSC_DETERMINE,&(steady_diagonal));
83  VecDuplicate(steady_diagonal,& new_diagonal);
84  VecDuplicate(*( schur0->get_rhs()), &steady_rhs);
85 
86  VecZeroEntries(schur0->get_solution());
87 
88  // apply initial condition
89  // cycle over local element rows
90 
92  double init_value;
93 
94  for (unsigned int i_loc_el = 0; i_loc_el < el_ds->lsize(); i_loc_el++) {
95  ele = mesh_->element(el_4_loc[i_loc_el]);
96 
97  init_value = data_.init_pressure.value(ele->centre(), ele->element_accessor());
98 
99  FOR_ELEMENT_SIDES(ele,i) {
100  int edge_row = row_4_edge[ele->side(i)->edge_idx()];
101  VecSetValue(schur0->get_solution(),edge_row,init_value/ele->n_sides(),ADD_VALUES);
102  }
103  }
104  VecAssemblyBegin(schur0->get_solution());
105  VecAssemblyEnd(schur0->get_solution());
106 
108 }
109 
110 
111 
113 {
114  // save diagonal of steady matrix
115  MatGetDiagonal(*( schur0->get_matrix() ), steady_diagonal);
116  // save RHS
117  VecCopy(*( schur0->get_rhs()),steady_rhs);
118 
119  VecZeroEntries(new_diagonal);
120 
121  // modify matrix diagonal
122  // cycle over local element rows
124  DBGMSG("setup time term with dt: %f\n", time_->dt());
125 
126  if (balance_ != nullptr)
127  balance_->start_mass_assembly(water_balance_idx_);
128 
129  for (unsigned int i_loc_el = 0; i_loc_el < el_ds->lsize(); i_loc_el++) {
130  ele = mesh_->element(el_4_loc[i_loc_el]);
131 
132  data_.init_pressure.value(ele->centre(), ele->element_accessor());
133 
134  FOR_ELEMENT_SIDES(ele,i) {
135  int edge_row = row_4_edge[ele->side(i)->edge_idx()];
136  // set new diagonal
137  double diagonal_coef = ele->measure() *
138  data_.storativity.value(ele->centre(), ele->element_accessor()) *
139  data_.cross_section.value(ele->centre(), ele->element_accessor())
140  / ele->n_sides();
141  VecSetValue(new_diagonal, edge_row, -diagonal_coef / time_->dt(), ADD_VALUES);
142 
143  if (balance_ != nullptr)
144  balance_->add_mass_matrix_values(water_balance_idx_, ele->region().bulk_idx(), {edge_row}, {diagonal_coef});
145 
146 
147  }
148  }
149  VecAssemblyBegin(new_diagonal);
150  VecAssemblyEnd(new_diagonal);
151 
152  MatDiagonalSet(*( schur0->get_matrix() ),new_diagonal, ADD_VALUES);
153 
156 
157  if (balance_ != nullptr)
158  balance_->finish_mass_assembly(water_balance_idx_);
159 }
160 
162  START_TIMER("modify system");
163  //if (time_->step().index()>0)
164  // DBGMSG("dt: %f dt-1: %f indexchanged: %d matrix: %d\n", time_->step().length(), time_->step(-1).length(), time_->is_changed_dt(), schur0->is_matrix_changed() );
165 
166  if (time_->is_changed_dt() && time_->step().index()>0) {
167  // if time step has changed and setup_time_term not called
168 
169  double scale_factor=time_->step(-2).length()/time_->step().length();
170  if (scale_factor != 1.0) {
171  MatDiagonalSet(*( schur0->get_matrix() ),steady_diagonal, INSERT_VALUES);
172 
173  //DBGMSG("Scale factor: %f\n",scale_factor);
174  VecScale(new_diagonal, scale_factor);
175  MatDiagonalSet(*( schur0->get_matrix() ),new_diagonal, ADD_VALUES);
177  }
178  }
179 
180  // modify RHS - add previous solution
181  VecPointwiseMult(*( schur0->get_rhs()), new_diagonal, schur0->get_solution());
182  VecAXPY(*( schur0->get_rhs()), 1.0, steady_rhs);
184 
185  // swap solutions
187 }
188 
189 
191 {
192  if (balance_ != nullptr)
193  balance_->start_source_assembly(water_balance_idx_);
194 
195  for (unsigned int i_loc = 0; i_loc < el_ds->lsize(); i_loc++)
196  {
197  ElementFullIter ele = mesh_->element(el_4_loc[i_loc]);
198 
199  // set lumped source
200  double diagonal_coef = ele->measure()
201  * data_.cross_section.value(ele->centre(), ele->element_accessor())
202  * data_.water_source_density.value(ele->centre(), ele->element_accessor())
203  / ele->n_sides();
204 
205  FOR_ELEMENT_SIDES(ele,i)
206  {
207  int edge_row = row_4_edge[ele->side(i)->edge_idx()];
208 
209  schur0->rhs_set_value(edge_row, -diagonal_coef);
210 
211  if (balance_ != nullptr)
212  balance_->add_source_rhs_values(water_balance_idx_, ele->region().bulk_idx(), {edge_row}, {diagonal_coef});
213  }
214  }
215 
216  if (balance_ != nullptr)
217  balance_->finish_source_assembly(water_balance_idx_);
218 }
219 
220 
222  int side_row, loc_edge_row, i;
223  Edge* edg;
224  ElementIter ele;
225  double new_pressure, old_pressure, time_coef;
226 
227  PetscScalar *loc_prev_sol;
228  VecGetArray(previous_solution, &loc_prev_sol);
229 
230  // modify side fluxes in parallel
231  // for every local edge take time term on diagonal and add it to the corresponding flux
232  for (unsigned int i_loc = 0; i_loc < edge_ds->lsize(); i_loc++) {
233 
234  edg = &( mesh_->edges[ edge_4_loc[i_loc] ] );
235  loc_edge_row = side_ds->lsize() + el_ds->lsize() + i_loc;
236 
237  new_pressure = (schur0->get_solution_array())[loc_edge_row];
238  old_pressure = loc_prev_sol[loc_edge_row];
239  FOR_EDGE_SIDES(edg,i) {
240  ele = edg->side(i)->element();
241  side_row = side_row_4_id[ mh_dh.side_dof( edg->side(i) ) ];
242  time_coef = - ele->measure() *
244  data_.storativity.value(ele->centre(), ele->element_accessor()) /
245  time_->dt() / ele->n_sides();
246  VecSetValue(schur0->get_solution(), side_row, time_coef * (new_pressure - old_pressure), ADD_VALUES);
247  }
248  }
249  VecRestoreArray(previous_solution, &loc_prev_sol);
250 
251  VecAssemblyBegin(schur0->get_solution());
252  VecAssemblyEnd(schur0->get_solution());
253 
254  int side_rows[4];
255  double values[4];
256 
257  // modify side fluxes in parallel
258  // for every local edge take time term on digonal and add it to the corresponding flux
259 
260  for (unsigned int i_loc = 0; i_loc < el_ds->lsize(); i_loc++) {
261  ele = mesh_->element(el_4_loc[i_loc]);
262  FOR_ELEMENT_SIDES(ele,i) {
263  side_rows[i] = side_row_4_id[ mh_dh.side_dof( ele->side(i) ) ];
264  values[i] = 1.0 * ele->measure() *
267  ele->n_sides();
268  }
269  VecSetValues(schur0->get_solution(), ele->n_sides(), side_rows, values, ADD_VALUES);
270  }
271  VecAssemblyBegin(schur0->get_solution());
272  VecAssemblyEnd(schur0->get_solution());
273 }
274 
#define DBGMSG(...)
Definition: global_defs.h:229
double measure() const
Definition: elements.cc:89
Output class for darcy_flow_mh model.
virtual void postprocess()
postprocess velocity field (add sources)
Field< 3, FieldValue< 3 >::Scalar > water_source_density
unsigned int size() const
Returns number of keys in the Record.
Definition: type_record.hh:578
#define FOR_EDGE_SIDES(i, j)
Definition: edges.h:41
static const int registrar
Registrar of class to factory.
Definition: richards_lmh.hh:53
Field< 3, FieldValue< 3 >::Scalar > cross_section
void set_rhs_changed()
Definition: linsys.hh:192
static Default obligatory()
The factory function to make an empty default value which is obligatory.
Definition: type_record.hh:99
#define ELEMENT_FULL_ITER(_mesh_, i)
Definition: mesh.h:416
Definition: mesh.h:99
#define FOR_ELEMENT_SIDES(i, j)
Definition: elements.h:140
DarcyFlowLMH_Unsteady(Mesh &mesh, const Input::Record in_rec)
Definition: richards_lmh.cc:47
boost::shared_ptr< Distribution > rows_ds
Definition: edges.h:26
const TimeStep & step(int index=-1) const
unsigned int water_balance_idx_
index of water balance within the Balance object.
FLOW123D_FORCE_LINK_IN_CHILD(richards_lmh)
Basic time management class.
void modify_system() override
static const Input::Type::Record & get_input_type()
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:193
Global macros to enhance readability and debugging, general constants.
double * get_solution_array()
Definition: linsys.hh:280
const Vec & get_solution()
Definition: linsys.hh:256
Accessor to the data with type Type::Record.
Definition: accessors.hh:277
unsigned int n_sides() const
bool is_changed_dt() const
#define START_TIMER(tag)
Starts a timer with specified tag.
Mesh * mesh_
Definition: equation.hh:221
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm) const
Definition: field.hh:337
MH_DofHandler mh_dh
double length() const
unsigned int side_dof(const SideIter side) const
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:459
static Input::Type::Abstract & get_input_type()
void read_initial_condition() override
Definition: richards_lmh.cc:79
SideIter side(const unsigned int loc_index)
const Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:271
virtual const Vec * get_rhs()
Definition: linsys.hh:177
Record & copy_keys(const Record &other)
Copy keys from other record.
Definition: type_record.cc:211
Distribution * el_ds
ElementFullIter element() const
Definition: side_impl.hh:51
boost::shared_ptr< Balance > balance_
object for calculation and writing the water balance to file.
double dt() const
arma::vec3 centre() const
Definition: elements.cc:120
std::vector< Edge > edges
Vector of MH edges, this should not be part of the geometrical mesh.
Definition: mesh.h:236
static const Input::Type::Record & get_input_type()
Mixed-hybrid model of linear Darcy flow, possibly unsteady.
void assembly_source_term() override
Source term is implemented differently in LMH version.
void set_matrix_changed()
Definition: linsys.hh:186
ElementAccessor< 3 > element_accessor() const
Gets ElementAccessor of this element.
Definition: elements.cc:148
unsigned int index() const
static const Input::Type::Record & get_input_type()
Definition: richards_lmh.cc:31
Record type proxy class.
Definition: type_record.hh:171
Distribution * side_ds
Distribution * edge_ds
virtual const Mat * get_matrix()
Definition: linsys.hh:161
Field< 3, FieldValue< 3 >::Scalar > storativity
SideIter side(const unsigned int i) const
Definition: edges.h:31
void rhs_set_value(int row, double val)
Definition: linsys.hh:336
TimeGovernor * time_
Definition: equation.hh:222
Field< 3, FieldValue< 3 >::Scalar > init_pressure
ElementVector element
Vector of elements of the mesh.
Definition: mesh.h:225
unsigned int lsize(int proc) const
get local size