Flow123d  DF_patch_fe_values-dbc06cd
assembly_lmh.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file assembly_lmh.hh
15  * @brief
16  */
17 
18 #ifndef ASSEMBLY_LMH_HH_
19 #define ASSEMBLY_LMH_HH_
20 
23 #include "flow/darcy_flow_lmh.hh"
24 #include "fem/element_cache_map.hh"
25 
26 #include "system/index_types.hh"
27 #include "mesh/mesh.h"
28 #include "mesh/accessors.hh"
29 #include "mesh/neighbours.h"
30 #include "fem/fe_p.hh"
31 #include "fem/fe_rt.hh"
32 #include "fem/fe_system.hh"
33 #include "fem/patch_op_impl.hh"
35 
36 #include "la/linsys_PETSC.hh"
37 #include "la/schur.hh"
38 #include "la/local_system.hh"
39 #include "la/local_constraint.hh"
40 
41 #include "coupling/balance.hh"
42 
43 
44 template <unsigned int dim, class TEqData>
46 {
47 public:
48  typedef typename TEqData::EqFields EqFields;
49  typedef TEqData EqData;
50 
51  static constexpr const char * name() { return "Darcy_ReadInitCond_Assembly"; }
52 
53  /// Constructor.
55  : AssemblyBasePatch<dim>(0, asm_internals), eq_fields_(eq_data->eq_fields_.get()), eq_data_(eq_data),
56  bulk_integral_( this->create_bulk_integral(this->quad_) ) {
57  this->used_fields_ += eq_fields_->init_pressure;
58  }
59 
60  /// Destructor.
62 
63  /// Initialize auxiliary vectors and other data members
64  void initialize() {}
65 
66 
67  /// Assemble integral over element
68  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
69  {
70  ASSERT_EQ(cell.dim(), dim).error("Dimension of element mismatch!");
71 
73  ASSERT(l_indices_.n_elem == cell.elm().element()->n_sides());
74 
75  // set initial condition
76  auto p = *( bulk_integral_->points(element_patch_idx).begin() );
77  double init_value = eq_fields_->init_pressure(p);
78 
79  for (unsigned int i=0; i<cell.elm()->n_sides(); i++) {
80  double init_value_on_edge = init_value / cell.elm().side(i)->edge().n_sides();
81  eq_data_->p_edge_solution.add(l_indices_[i], init_value_on_edge);
82  }
83  }
84 
85  /// Implements @p AssemblyBase::end.
86  void end() override
87  {
88  eq_data_->p_edge_solution.ghost_to_local_begin();
89  eq_data_->p_edge_solution.ghost_to_local_end();
90  eq_data_->p_edge_solution.local_to_ghost_begin();
91  eq_data_->p_edge_solution.local_to_ghost_end();
92  }
93 
94 
95 
96 protected:
97  /// Sub field set contains fields used in calculation.
99 
100  /// Data objects shared with Flow equation
103 
104  /// Vector of pre-computed local DOF indices
106 
107  std::shared_ptr<BulkIntegralAcc<dim>> bulk_integral_; ///< Bulk integral of assembly class
108 
109  template < template<IntDim...> class DimAssembly>
110  friend class GenericAssembly;
111 
112 };
113 
114 template <unsigned int dim, class TEqData>
116 {
117 public:
118  typedef typename TEqData::EqFields EqFields;
119  typedef TEqData EqData;
120 
121  DECLARE_EXCEPTION( ExcBCNotSupported, << "BC type not supported.\n" );
122 
123  static constexpr const char * name() { return "Darcy_MHMatrix_Assembly"; }
124 
125  /// Constructor.
126  MHMatrixAssemblyLMH(EqData *eq_data, AssemblyInternals *asm_internals)
127  : AssemblyBasePatch<dim>(0, asm_internals), eq_fields_(eq_data->eq_fields_.get()), eq_data_(eq_data), quad_rt_(dim, 2),
128  bulk_integral_( this->create_bulk_integral(this->quad_)) ,
132  JxW_( asm_sides_integral_->JxW() ),
133  velocity_( asm_sides_integral_->vector_shape(0) ),
134  normal_join_( coupling_integral_->normal_vector() ) {
135  this->used_fields_ += eq_fields_->cross_section;
136  this->used_fields_ += eq_fields_->conductivity;
137  this->used_fields_ += eq_fields_->anisotropy;
138  this->used_fields_ += eq_fields_->sigma;
139  this->used_fields_ += eq_fields_->water_source_density;
140  this->used_fields_ += eq_fields_->extra_source;
141  this->used_fields_ += eq_fields_->storativity;
142  this->used_fields_ += eq_fields_->extra_storativity;
143  this->used_fields_ += eq_fields_->bc_type;
144  this->used_fields_ += eq_fields_->bc_pressure;
145  this->used_fields_ += eq_fields_->bc_flux;
146  this->used_fields_ += eq_fields_->bc_robin_sigma;
147  this->used_fields_ += eq_fields_->bc_switch_pressure;
148  }
149 
150  /// Destructor.
151  virtual ~MHMatrixAssemblyLMH() {}
152 
153  /// Initialize auxiliary vectors and other data members
154  void initialize() {
155  //this->balance_ = eq_data_->balance_;
156 
157  // local numbering of dofs for MH system
158  // note: this shortcut supposes that the fe_system is the same on all elements
159  // TODO the function should be DiscreteSpace.fe(ElementAccessor)
160  // and correct form fe(ad_->dh_->own_range().begin()->elm()) (see documentation of DiscreteSpace::fe)
161  auto fe = eq_data_->dh_->ds()->fe()[Dim<dim>{}];
162  FESystem<dim>* fe_system = dynamic_cast<FESystem<dim>*>(fe.get());
163  eq_data_->loc_side_dofs[dim-1] = fe_system->fe_dofs(0);
164  eq_data_->loc_ele_dof[dim-1] = fe_system->fe_dofs(1)[0];
165  eq_data_->loc_edge_dofs[dim-1] = fe_system->fe_dofs(2);
166 
167  // reconstructed vector for the velocity and pressure
168  // length = local Schur complement offset in LocalSystem
169  eq_data_->schur_offset_[dim-1] = eq_data_->loc_edge_dofs[dim-1][0];
170  reconstructed_solution_.zeros(eq_data_->schur_offset_[dim-1]);
171 
172  n_dofs_ = this->asm_internals_->fe_values_.template fe_comp<dim>(this->asm_internals_->fe_values_.template fe_dim<dim>(), 0)->n_dofs();
173  }
174 
175 
176  /**
177  * Integral over element.
178  *
179  * Override in descendants.
180  */
181  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
182  {
183  ASSERT_EQ(cell.dim(), dim).error("Dimension of element mismatch!");
184 
185  // evaluation point
186  auto p = *( bulk_integral_->points(element_patch_idx).begin() );
187  bulk_local_idx_ = cell.local_idx();
188 
189  this->asm_sides(p, eq_fields_->conductivity(p), element_patch_idx);
190  this->asm_element();
191  this->asm_source_term_darcy(cell, p);
192  }
193 
194 
195  /**
196  * Assembles between boundary element and corresponding side on bulk element.
197  *
198  * Override in descendants.
199  */
200  inline void boundary_side_integral(DHCellSide cell_side)
201  {
202  ASSERT_EQ(cell_side.dim(), dim).error("Dimension of element mismatch!");
203  if (!cell_side.cell().is_own()) return;
204 
205  auto p_side = *( bdr_integral_->points(cell_side).begin() );
206  auto p_bdr = p_side.point_bdr(cell_side.cond().element_accessor() );
207  ElementAccessor<3> b_ele = cell_side.side().cond().element_accessor(); // ??
208 
209  precompute_boundary_side(cell_side, p_side, p_bdr);
210 
212  this->use_dirichlet_switch(cell_side, b_ele, p_bdr);
213  }
214 
215  this->boundary_side_integral_in(cell_side, b_ele, p_bdr);
216  }
217 
218 
219  /**
220  * Assembles the fluxes between elements of different dimensions.
221  *
222  * Common in all descendants.
223  */
224  inline void dimjoin_intergral(DHCellAccessor cell_lower_dim, DHCellSide neighb_side) {
225  if (dim == 3) return;
226  ASSERT_EQ(cell_lower_dim.dim(), dim).error("Dimension of element mismatch!");
227 
228  unsigned int neigh_idx = ngh_idx(cell_lower_dim, neighb_side); // TODO use better evaluation of neighbour_idx
229  unsigned int loc_dof_higher = (2*(cell_lower_dim.dim()+1) + 1) + neigh_idx; // loc dof of higher ele edge
230  bulk_local_idx_ = cell_lower_dim.local_idx();
231 
232  // Evaluation points
233  auto p_high = *( coupling_integral_->points(neighb_side).begin() );
234  auto p_low = p_high.lower_dim(cell_lower_dim);
235 
236  nv_ = normal_join_(p_high);
237 
238  ngh_value_ = eq_fields_->sigma(p_low) *
239  2*eq_fields_->conductivity(p_low) *
240  arma::dot(eq_fields_->anisotropy(p_low)*nv_, nv_) *
241  eq_fields_->cross_section(p_high) * // cross-section of higher dim. (2d)
242  eq_fields_->cross_section(p_high) /
243  eq_fields_->cross_section(p_low) * // crossection of lower dim.
244  neighb_side.measure();
245 
246  eq_data_->loc_system_[bulk_local_idx_].add_value(eq_data_->loc_ele_dof[dim-1], eq_data_->loc_ele_dof[dim-1], -ngh_value_);
247  eq_data_->loc_system_[bulk_local_idx_].add_value(eq_data_->loc_ele_dof[dim-1], loc_dof_higher, ngh_value_);
248  eq_data_->loc_system_[bulk_local_idx_].add_value(loc_dof_higher, eq_data_->loc_ele_dof[dim-1], ngh_value_);
249  eq_data_->loc_system_[bulk_local_idx_].add_value(loc_dof_higher, loc_dof_higher, -ngh_value_);
250 
251 // // update matrix for weights in BDDCML
252 // if ( typeid(*eq_data_->lin_sys) == typeid(LinSys_BDDC) ) {
253 // int ind = eq_data_->loc_system_[bulk_local_idx_].row_dofs[p];
254 // // there is -value on diagonal in block C!
255 // static_cast<LinSys_BDDC*>(eq_data_->lin_sys)->diagonal_weights_set_value( ind, -value );
256 // }
257  }
258 
259 
260  /// Implements @p AssemblyBase::begin.
261  void begin() override
262  {
263  this->begin_mh_matrix();
264  }
265 
266 
267  /// Implements @p AssemblyBase::end.
268  void end() override
269  {
270  this->end_mh_matrix();
271  }
272 
273 protected:
274  /// Common code of begin method of MH matrix assembly (Darcy and Richards)
276  {
277  // DebugOut() << "assembly_mh_matrix \n";
278  // set auxiliary flag for switchting Dirichlet like BC
279  eq_data_->force_no_neumann_bc = eq_data_->use_steady_assembly_ && (eq_data_->nonlinear_iteration_ == 0);
280 
281  eq_data_->reset();
282 
283  eq_data_->balance_->start_flux_assembly(eq_data_->water_balance_idx);
284  eq_data_->balance_->start_source_assembly(eq_data_->water_balance_idx);
285  eq_data_->balance_->start_mass_assembly(eq_data_->water_balance_idx);
286 
287  this->set_dofs();
288  }
289 
290 
291  /// Common code of end method of MH matrix assembly (Darcy and Richards)
293  {
294  std::sort(eq_data_->loc_constraint_.begin(), eq_data_->loc_constraint_.end());
295  eq_data_->loc_constraint_.emplace_back(uint(-1), 0, 0.0); // add constraint of invalid element to end of vector
296  unsigned int i_constr = 0;
297  for ( DHCellAccessor dh_cell : eq_data_->dh_cr_->own_range() ) {
298  this->set_loc_schur(dh_cell);
299  while (eq_data_->loc_constraint_[i_constr].i_element() == dh_cell.local_idx()) {
300  this->loc_schur_.set_solution(eq_data_->loc_constraint_[i_constr]);
301  i_constr++;
302  }
303  eq_data_->loc_system_[dh_cell.local_idx()].compute_schur_complement(
304  eq_data_->schur_offset_[dh_cell.dim()-1], this->loc_schur_, true);
305 
306  // for seepage BC, save local system
307  if (eq_data_->save_local_system_[dh_cell.local_idx()])
308  eq_data_->seepage_bc_systems[dh_cell.elm_idx()] = eq_data_->loc_system_[dh_cell.local_idx()];
309 
311  eq_data_->lin_sys_schur->set_local_system(this->loc_schur_, eq_data_->dh_cr_->get_local_to_global_map());
312 
313  // TODO:
314  // if (mortar_assembly)
315  // mortar_assembly->assembly(dh_cell);
316  }
317 
318  eq_data_->balance_->finish_mass_assembly(eq_data_->water_balance_idx);
319  eq_data_->balance_->finish_source_assembly(eq_data_->water_balance_idx);
320  eq_data_->balance_->finish_flux_assembly(eq_data_->water_balance_idx);
321 
322  eq_data_->loc_constraint_.clear();
323  }
324 
325 
326  /// Common code of begin method of Reconstruct Schur assembly (Darcy and Richards)
328  {
329  this->eq_data_->full_solution.zero_entries();
330  this->eq_data_->p_edge_solution.local_to_ghost_begin();
331  this->eq_data_->p_edge_solution.local_to_ghost_end();
332  }
333 
334 
335  /// Common code of end method of Reconstruct Schur assembly (Darcy and Richards)
337  {
338  for ( DHCellAccessor dh_cell : this->eq_data_->dh_cr_->own_range() ) {
339  this->bulk_local_idx_ = dh_cell.local_idx();
340  this->set_loc_schur(dh_cell);
341  arma::vec schur_solution = this->eq_data_->p_edge_solution.get_subvec(this->loc_schur_.row_dofs);
342  // reconstruct the velocity and pressure
343  this->eq_data_->loc_system_[this->bulk_local_idx_].reconstruct_solution_schur(this->eq_data_->schur_offset_[dh_cell.dim()-1],
344  schur_solution, this->reconstructed_solution_);
345 
346  this->reconstructed_solution_ += this->eq_data_->postprocess_solution_[this->bulk_local_idx_];
347 
348  this->eq_data_->full_solution.set_subvec(this->eq_data_->loc_system_[this->bulk_local_idx_].row_dofs.head(
349  this->eq_data_->schur_offset_[dh_cell.dim()-1]), this->reconstructed_solution_);
350  this->eq_data_->full_solution.set_subvec(this->eq_data_->loc_system_[this->bulk_local_idx_].row_dofs.tail(
351  this->loc_schur_.row_dofs.n_elem), schur_solution);
352  }
353 
354  this->eq_data_->full_solution.local_to_ghost_begin();
355  this->eq_data_->full_solution.local_to_ghost_end();
356 
357  eq_data_->loc_constraint_.clear();
358  }
359 
360  /// Part of cell_integral method, common in all descendants
361  inline void asm_sides(BulkPoint &p, double conductivity, unsigned int element_patch_idx)
362  {
363  double scale_sides = 1 / eq_fields_->cross_section(p) / conductivity;
364  arma::mat33 aniso_inv = (eq_fields_->anisotropy(p)).i();
365 
366  for (auto p_rt : asm_sides_integral_->points(element_patch_idx) ) {
367  for (unsigned int i=0; i<n_dofs_; i++){
368  double rhs_val = arma::dot( eq_data_->gravity_vec_, velocity_.shape(i)(p_rt) )
369  * JxW_(p_rt);
370  eq_data_->loc_system_[bulk_local_idx_].add_value(i, rhs_val);
371 
372  for (unsigned int j=0; j<n_dofs_; j++){
373  double mat_val =
374  arma::dot( velocity_.shape(i)(p_rt), aniso_inv * velocity_.shape(j)(p_rt) )
375  * scale_sides * JxW_(p_rt);
376 
377  eq_data_->loc_system_[bulk_local_idx_].add_value(i, j, mat_val);
378  }
379  }
380  }
381 
382  // assemble matrix for weights in BDDCML
383  // approximation to diagonal of
384  // S = -C - B*inv(A)*B'
385  // as
386  // diag(S) ~ - diag(C) - 1./diag(A)
387  // the weights form a partition of unity to average a discontinuous solution from neighbouring subdomains
388  // to a continuous one
389  // it is important to scale the effect - if conductivity is low for one subdomain and high for the other,
390  // trust more the one with low conductivity - it will be closer to the truth than an arithmetic average
391 // if ( typeid(*ad_->lin_sys) == typeid(LinSys_BDDC) ) {
392 // const arma::mat& local_matrix = loc_system_.get_matrix();
393 // for(unsigned int i=0; i < ndofs; i++) {
394 // double val_side = local_matrix(i,i);
395 // double val_edge = -1./local_matrix(i,i);
396 //
397 // unsigned int side_row = loc_system_.row_dofs[loc_side_dofs[i]];
398 // unsigned int edge_row = loc_system_.row_dofs[loc_edge_dofs[i]];
399 // static_cast<LinSys_BDDC*>(ad_->lin_sys)->diagonal_weights_set_value( side_row, val_side );
400 // static_cast<LinSys_BDDC*>(ad_->lin_sys)->diagonal_weights_set_value( edge_row, val_edge );
401 // }
402 // }
403  }
404 
405  /// Part of cell_integral method, common in all descendants
406  inline void asm_element()
407  {
408  // set block B, B': element-side, side-element
409 
410  for(unsigned int side = 0; side < eq_data_->loc_side_dofs[dim-1].size(); side++){
411  eq_data_->loc_system_[bulk_local_idx_].add_value(eq_data_->loc_ele_dof[dim-1], eq_data_->loc_side_dofs[dim-1][side], -1.0);
412  eq_data_->loc_system_[bulk_local_idx_].add_value(eq_data_->loc_side_dofs[dim-1][side], eq_data_->loc_ele_dof[dim-1], -1.0);
413  }
414 
415 // if ( typeid(*ad_->lin_sys) == typeid(LinSys_BDDC) ) {
416 // double val_ele = 1.;
417 // static_cast<LinSys_BDDC*>(ad_->lin_sys)->
418 // diagonal_weights_set_value( loc_system_.row_dofs[loc_ele_dof], val_ele );
419 // }
420  }
421 
422  /// Part of cell_integral method, specialized in Darcy equation
423  inline void asm_source_term_darcy(const DHCellAccessor& cell, BulkPoint &p)
424  {
425  // compute lumped source
426  uint n_sides = cell.elm()->n_sides();
427  coef_ = (1.0 / n_sides) * cell.elm().measure() * eq_fields_->cross_section(p);
428  source_term_ = coef_ * (eq_fields_->water_source_density(p) + eq_fields_->extra_source(p));
429 
430  // in unsteady, compute time term
431  time_term_diag_ = 0.0;
432  time_term_ = 0.0;
433  time_term_rhs_ = 0.0;
434 
435  if(! eq_data_->use_steady_assembly_)
436  {
437  time_term_ = coef_ * (eq_fields_->storativity(p) + eq_fields_->extra_storativity(p));
438  }
439 
440  const DHCellAccessor cr_cell = cell.cell_with_other_dh(eq_data_->dh_cr_.get());
441  auto loc_dof_vec = cr_cell.get_loc_dof_indices();
442 
443  for (unsigned int i=0; i<n_sides; i++)
444  {
445  if(! eq_data_->use_steady_assembly_)
446  {
447  time_term_diag_ = time_term_ / eq_data_->time_step_;
448  time_term_rhs_ = time_term_diag_ * eq_data_->p_edge_solution_previous_time.get(loc_dof_vec[i]);
449 
450  eq_data_->balance_->add_mass_values(eq_data_->water_balance_idx, cell,
451  {eq_data_->loc_system_[bulk_local_idx_].row_dofs[eq_data_->loc_edge_dofs[dim-1][i]]}, {time_term_}, 0);
452  }
453  else
454  {
455  // Add zeros explicitely to keep the sparsity pattern.
456  // Otherwise Petsc would compress out the zeros in FinishAssembly.
457  eq_data_->balance_->add_mass_values(eq_data_->water_balance_idx, cell,
458  {eq_data_->loc_system_[bulk_local_idx_].row_dofs[eq_data_->loc_edge_dofs[dim-1][i]]}, {0}, 0);
459  }
460 
461  eq_data_->loc_system_[bulk_local_idx_].add_value(eq_data_->loc_edge_dofs[dim-1][i], eq_data_->loc_edge_dofs[dim-1][i],
464 
465  eq_data_->balance_->add_source_values(eq_data_->water_balance_idx, cell.elm().region().bulk_idx(),
466  {eq_data_->loc_system_[bulk_local_idx_].row_dofs[eq_data_->loc_edge_dofs[dim-1][i]]}, {0}, {source_term_});
467  }
468  }
469 
470  /// Precompute values used in boundary side integral on given DHCellSide
471  inline void precompute_boundary_side(DHCellSide &cell_side, BoundaryPoint &p_side, BulkPoint &p_bdr)
472  {
473  bulk_local_idx_ = cell_side.cell().local_idx();
474 
475  cross_section_ = eq_fields_->cross_section(p_side);
476  type_ = (DarcyLMH::EqFields::BC_Type)eq_fields_->bc_type(p_bdr);
477 
478  sidx_ = cell_side.side_idx();
479  side_row_ = eq_data_->loc_side_dofs[dim-1][sidx_]; //local
480  edge_row_ = eq_data_->loc_edge_dofs[dim-1][sidx_]; //local
481  }
482 
483  /// Update BC switch dirichlet in MH matrix assembly if BC type is seepage
484  inline void use_dirichlet_switch(DHCellSide &cell_side, const ElementAccessor<3> &b_ele, BulkPoint &p_bdr)
485  {
486  char & switch_dirichlet = eq_data_->bc_switch_dirichlet[b_ele.idx()];
487  if (switch_dirichlet) {
488  // check and possibly switch to flux BC
489  // The switch raise error on the corresponding edge row.
490  // Magnitude of the error is abs(solution_flux - side_flux).
491 
492  // try reconstructing local system for seepage BC
493  auto reconstr_solution = this->load_local_system(cell_side.cell());
494  double side_flux = -eq_fields_->bc_flux(p_bdr) * b_ele.measure() * cross_section_;
495 
496  if ( reconstr_solution[side_row_] < side_flux) {
497  //DebugOut().fmt("x: {}, to neum, p: {} f: {} -> f: {}\n", b_ele.centre()[0], bc_pressure, reconstructed_solution_[side_row_], side_flux);
498  switch_dirichlet = 0;
499  }
500  } else {
501  // check and possibly switch to pressure BC
502  // TODO: What is the appropriate DOF in not local?
503  // The switch raise error on the corresponding side row.
504  // Magnitude of the error is abs(solution_head - bc_pressure)
505  // Since usually K is very large, this error would be much
506  // higher then error caused by the inverse switch, this
507  // cause that a solution with the flux violating the
508  // flux inequality leading may be accepted, while the error
509  // in pressure inequality is always satisfied.
510 
511  const DHCellAccessor cr_cell = cell_side.cell().cell_with_other_dh(eq_data_->dh_cr_.get());
512  auto loc_dof_vec = cr_cell.get_loc_dof_indices();
513  double solution_head = eq_data_->p_edge_solution.get(loc_dof_vec[sidx_]);
514  double bc_pressure = eq_fields_->bc_switch_pressure(p_bdr);
515 
516  if ( solution_head > bc_pressure) {
517  //DebugOut().fmt("x: {}, to dirich, p: {} -> p: {} f: {}\n",b_ele.centre()[0], solution_head, bc_pressure, bc_flux);
518  switch_dirichlet=1;
519  }
520  }
521  }
522 
523  /**
524  * Common code of boundary_side_integral.
525  */
526  inline void boundary_side_integral_in(DHCellSide cell_side, const ElementAccessor<3> &b_ele, BulkPoint &p_bdr)
527  {
528  if ( type_ == DarcyLMH::EqFields::none) {
529  // homogeneous neumann
530  } else if ( type_ == DarcyLMH::EqFields::dirichlet ) {
531  eq_data_->loc_constraint_.emplace_back( bulk_local_idx_, sidx_, eq_fields_->bc_pressure(p_bdr) );
532 
533  } else if ( type_ == DarcyLMH::EqFields::total_flux) {
534  // internally we work with outward flux
535  eq_data_->loc_system_[bulk_local_idx_].add_value(edge_row_, edge_row_,
536  -b_ele.measure() * eq_fields_->bc_robin_sigma(p_bdr) * cross_section_,
537  (-eq_fields_->bc_flux(p_bdr) - eq_fields_->bc_robin_sigma(p_bdr) * eq_fields_->bc_pressure(p_bdr)) * b_ele.measure() * cross_section_);
538  } else if (type_==DarcyLMH::EqFields::seepage) {
539  eq_data_->is_linear=false;
540 
541  double bc_pressure = eq_fields_->bc_switch_pressure(p_bdr);
542  double side_flux = -eq_fields_->bc_flux(p_bdr) * b_ele.measure() * cross_section_;
543 
544  eq_data_->save_local_system_[bulk_local_idx_] = (bool) eq_data_->bc_switch_dirichlet[b_ele.idx()];
545 
546  // ** Apply BCUpdate BC type. **
547  // Force Dirichlet type during the first iteration of the unsteady case.
548  if (eq_data_->save_local_system_[bulk_local_idx_] || eq_data_->force_no_neumann_bc ) {
549  //DebugOut().fmt("x: {}, dirich, bcp: {}\n", b_ele.centre()[0], bc_pressure);
550  eq_data_->loc_constraint_.emplace_back(bulk_local_idx_, sidx_, bc_pressure);
551  } else {
552  //DebugOut()("x: {}, neuman, q: {} bcq: {}\n", b_ele.centre()[0], side_flux, bc_flux);
553  eq_data_->loc_system_[bulk_local_idx_].add_value(edge_row_, side_flux);
554  }
555 
556  } else if (type_==DarcyLMH::EqFields::river) {
557  eq_data_->is_linear=false;
558 
559  double bc_pressure = eq_fields_->bc_pressure(p_bdr);
560  double bc_switch_pressure = eq_fields_->bc_switch_pressure(p_bdr);
561  double bc_flux = -eq_fields_->bc_flux(p_bdr);
562  double bc_sigma = eq_fields_->bc_robin_sigma(p_bdr);
563 
564  const DHCellAccessor cr_cell = cell_side.cell().cell_with_other_dh(eq_data_->dh_cr_.get());
565  auto loc_dof_vec = cr_cell.get_loc_dof_indices();
566  double solution_head = eq_data_->p_edge_solution.get(loc_dof_vec[sidx_]);
567 
568  // Force Robin type during the first iteration of the unsteady case.
569  if (solution_head > bc_switch_pressure || eq_data_->force_no_neumann_bc) {
570  // Robin BC
571  //DebugOut().fmt("x: {}, robin, bcp: {}\n", b_ele.centre()[0], bc_pressure);
572  eq_data_->loc_system_[bulk_local_idx_].add_value(edge_row_, edge_row_,
573  -b_ele.measure() * bc_sigma * cross_section_,
574  b_ele.measure() * cross_section_ * (bc_flux - bc_sigma * bc_pressure) );
575  } else {
576  // Neumann BC
577  //DebugOut().fmt("x: {}, neuman, q: {} bcq: {}\n", b_ele.centre()[0], bc_switch_pressure, bc_pressure);
578  double bc_total_flux = bc_flux + bc_sigma*(bc_switch_pressure - bc_pressure);
579 
580  eq_data_->loc_system_[bulk_local_idx_].add_value(edge_row_, bc_total_flux * b_ele.measure() * cross_section_);
581  }
582  }
583  else {
584  THROW( ExcBCNotSupported() );
585  }
586 
587  eq_data_->balance_->add_flux_values(eq_data_->water_balance_idx, cell_side,
588  {eq_data_->loc_system_[bulk_local_idx_].row_dofs[eq_data_->loc_side_dofs[dim-1][sidx_]]},
589  {1}, 0);
590  }
591 
592  /// Precompute loc_system and loc_schur data members.
593  void set_dofs() {
594  unsigned int size, loc_size, elm_dim;;
595  for ( DHCellAccessor dh_cell : eq_data_->dh_->local_range() ) {
596  const ElementAccessor<3> ele = dh_cell.elm();
597 
598  elm_dim = ele.dim();
599  size = (elm_dim+1) + 1 + (elm_dim+1); // = n_sides + 1 + n_sides
600  loc_size = size + ele->n_neighs_vb();
601  LocDofVec dofs(loc_size);
602 
603  // add full vec indices
604  dofs.head(dh_cell.n_dofs()) = dh_cell.get_loc_dof_indices();
605 
606  if(ele->n_neighs_vb() != 0)
607  {
608  //D, E',E block: compatible connections: element-edge
609  unsigned int i = 0;
610 
611  for ( DHCellSide neighb_side : dh_cell.neighb_sides() ) {
612 
613  // read neighbor dofs (dh dofhandler)
614  // neighbor cell owning neighb_side
615  DHCellAccessor dh_neighb_cell = neighb_side.cell();
616 
617  // read neighbor dofs (dh_cr dofhandler)
618  // neighbor cell owning neighb_side
619  DHCellAccessor dh_neighb_cr_cell = dh_neighb_cell.cell_with_other_dh(eq_data_->dh_cr_.get());
620 
621  // local index of pedge dof in local system
622  const unsigned int p = size+i;
623  // local index of pedge dof on neighboring cell
624  const unsigned int t = dh_neighb_cell.n_dofs() - dh_neighb_cr_cell.n_dofs() + neighb_side.side().side_idx();
625  dofs[p] = dh_neighb_cell.get_loc_dof_indices()[t];
626  i++;
627  }
628  }
629  eq_data_->loc_system_[dh_cell.local_idx()].reset(dofs, dofs);
630 
631  // Set side-edge (flux-lambda) terms
632  for (DHCellSide dh_side : dh_cell.side_range()) {
633  unsigned int sidx = dh_side.side_idx();
634  // side-edge (flux-lambda) terms
635  eq_data_->loc_system_[dh_cell.local_idx()].add_value(eq_data_->loc_side_dofs[elm_dim-1][sidx], eq_data_->loc_edge_dofs[elm_dim-1][sidx], 1.0);
636  eq_data_->loc_system_[dh_cell.local_idx()].add_value(eq_data_->loc_edge_dofs[elm_dim-1][sidx], eq_data_->loc_side_dofs[elm_dim-1][sidx], 1.0);
637  }
638  }
639  }
640 
641 
642  /// Precompute loc_schur data member of given cell.
643  void set_loc_schur(const DHCellAccessor dh_cr_cell) {
644  const ElementAccessor<3> ele = dh_cr_cell.elm();
645 
646  unsigned int loc_size_schur = ele->n_sides() + ele->n_neighs_vb();
647  LocDofVec dofs_schur(loc_size_schur);
648 
649  // add schur vec indices
650  dofs_schur.head(dh_cr_cell.n_dofs()) = dh_cr_cell.get_loc_dof_indices();
651 
652  if(ele->n_neighs_vb() != 0)
653  {
654  //D, E',E block: compatible connections: element-edge
655  unsigned int i = 0;
656 
657  for ( DHCellSide neighb_side : dh_cr_cell.neighb_sides() ) {
658 
659  // read neighbor dofs (dh dofhandler)
660  // neighbor cell owning neighb_side
661  DHCellAccessor dh_neighb_cr_cell = neighb_side.cell();
662 
663  // local index of pedge dof in local schur system
664  const unsigned int tt = dh_cr_cell.n_dofs()+i;
665  dofs_schur[tt] = dh_neighb_cr_cell.get_loc_dof_indices()[neighb_side.side().side_idx()];
666  i++;
667  }
668  }
669 
670 
671  loc_schur_.reset(dofs_schur, dofs_schur);
672  }
673 
674 
675  /// Temporary method find neighbour index in higher-dim cell
676  inline unsigned int ngh_idx(DHCellAccessor &dh_cell, DHCellSide &neighb_side) {
677  for (uint n_i=0; n_i<dh_cell.elm()->n_neighs_vb(); ++n_i) {
678  auto side = dh_cell.elm()->neigh_vb[n_i]->side();
679  if ( (side->elem_idx() == neighb_side.elem_idx()) && (side->side_idx() == neighb_side.side_idx()) ) return n_i;
680  }
681  ASSERT_PERMANENT(false)(dh_cell.elm_idx())(neighb_side.side_idx()).error("Side is not a part of neighbour!\n");
682  return 0;
683  }
684 
685 
686  /** Loads the local system from a map: element index -> LocalSystem,
687  * if it exits, or if the full solution is not yet reconstructed,
688  * and reconstructs the full solution on the element.
689  * Currently used only for seepage BC.
690  */
692  {
693  // possibly find the corresponding local system
694  auto ls = eq_data_->seepage_bc_systems.find(dh_cell.elm_idx());
695  if (ls != eq_data_->seepage_bc_systems.end())
696  {
697  const DHCellAccessor cr_cell = dh_cell.cell_with_other_dh(eq_data_->dh_cr_.get());
698  auto loc_dof_vec = cr_cell.get_loc_dof_indices();
699  arma::vec schur_solution = eq_data_->p_edge_solution.get_subvec(loc_dof_vec);
700  // reconstruct the velocity and pressure
701  ls->second.reconstruct_solution_schur(eq_data_->schur_offset_[dim-1], schur_solution, reconstructed_solution_);
702 
703  unsigned int pos_in_cache = this->asm_internals_->element_cache_map_.position_in_cache(dh_cell.elm_idx());
704  auto p = *( bulk_integral_->points(pos_in_cache).begin() );
705  postprocess_velocity_darcy(dh_cell, p, reconstructed_solution_);
706 
707  eq_data_->bc_fluxes_reconstruted[bulk_local_idx_] = true;
708  }
709 
710  return reconstructed_solution_;
711  }
712 
713 
714  /**
715  * Precompute edge_scale and edge_source_term.
716  *
717  * This method must be calls in methods postprocess_velocity_darcy and postprocess_velocity_richards
718  */
720  {
721  edge_scale_ = dh_cell.elm().measure()
722  * eq_fields_->cross_section(p)
723  / dh_cell.elm()->n_sides();
724 
725  edge_source_term_ = edge_scale_ *
726  ( eq_fields_->water_source_density(p)
727  + eq_fields_->extra_source(p));
728  }
729 
730 
731  /// Postprocess velocity during loading of local system and after calculating of cell integral.
732  void postprocess_velocity_darcy(const DHCellAccessor& dh_cell, BulkPoint &p, arma::vec& solution)
733  {
734  postprocess_velocity(dh_cell, p);
735 
736  time_term_ = 0.0;
737  const DHCellAccessor cr_cell = dh_cell.cell_with_other_dh(eq_data_->dh_cr_.get());
738  auto loc_dof_vec = cr_cell.get_loc_dof_indices();
739 
740  for (unsigned int i=0; i<dh_cell.elm()->n_sides(); i++) {
741 
742  if( ! eq_data_->use_steady_assembly_)
743  {
744  double new_pressure = eq_data_->p_edge_solution.get(loc_dof_vec[i]);
745  double old_pressure = eq_data_->p_edge_solution_previous_time.get(loc_dof_vec[i]);
746  time_term_ = edge_scale_ * (eq_fields_->storativity(p) + eq_fields_->extra_storativity(p))
747  / eq_data_->time_step_ * (new_pressure - old_pressure);
748  }
749  solution[eq_data_->loc_side_dofs[dim-1][i]] += edge_source_term_ - time_term_;
750  }
751  }
752 
753 
754  /// Sub field set contains fields used in calculation.
756 
757  /// Data objects shared with DarcyFlow
760 
761  /// Assembly volume integrals
763 
764  /// Vector for reconstructed solution (velocity and pressure on element) from Schur complement.
766 
767  double coef_, source_term_; ///< Variables used in compute lumped source.
768  double time_term_diag_, time_term_, time_term_rhs_; ///< Variables used in compute time term (unsteady)
769  double cross_section_; ///< Precomputed cross-section value
770  unsigned int bulk_local_idx_; ///< Local idx of bulk element
771  unsigned int sidx_, side_row_, edge_row_; ///< Helper indices in boundary assembly
772  DarcyLMH::EqFields::BC_Type type_; ///< Type of boundary condition
773  arma::vec3 nv_; ///< Normal vector
774  double ngh_value_; ///< Precomputed ngh value
775  double edge_scale_, edge_source_term_; ///< Precomputed values in postprocess_velocity
776 
778  unsigned int n_dofs_; ///< Number of DOFs of fe_rt component
779 
780  std::shared_ptr<BulkIntegralAcc<dim>> bulk_integral_; ///< Bulk integral of assembly class
781  std::shared_ptr<BulkIntegralAcc<dim>> asm_sides_integral_; ///< Bulk integral defined on quadrature of higher order
782  std::shared_ptr<BoundaryIntegralAcc<dim>> bdr_integral_; ///< Boundary integral of assembly class
783  std::shared_ptr<CouplingIntegralAcc<dim>> coupling_integral_; ///< Coupling integral of assembly class
784 
785  /// Following data members represent Element quantities and FE quantities
789 
790  template < template<IntDim...> class DimAssembly>
791  friend class GenericAssembly;
792 
793 };
794 
795 template <unsigned int dim, class TEqData>
797 {
798 public:
799  typedef typename TEqData::EqFields EqFields;
800  typedef TEqData EqData;
801 
802  static constexpr const char * name() { return "Darcy_ReconstructSchur_Assembly"; }
803 
804  /// Constructor.
806  : MHMatrixAssemblyLMH<dim, TEqData>(eq_data, asm_internals) {}
807 
808  /// Integral over element.
809  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
810  {
811  ASSERT_EQ(cell.dim(), dim).error("Dimension of element mismatch!");
812 
813  // evaluation point
814  auto p = *( this->bulk_integral_->points(element_patch_idx).begin() );
815  this->bulk_local_idx_ = cell.local_idx();
816 
817  { // postprocess the velocity
818  this->eq_data_->postprocess_solution_[this->bulk_local_idx_].zeros(this->eq_data_->schur_offset_[dim-1]);
819  this->postprocess_velocity_darcy(cell, p, this->eq_data_->postprocess_solution_[this->bulk_local_idx_]);
820  }
821  }
822 
823 
824  /// Assembles between boundary element and corresponding side on bulk element.
826  {}
827 
828  inline void dimjoin_intergral(FMT_UNUSED DHCellAccessor cell_lower_dim, FMT_UNUSED DHCellSide neighb_side)
829  {}
830 
831 
832  /// Implements @p AssemblyBase::begin.
833  void begin() override
834  {
835  this->begin_reconstruct_schur();
836  }
837 
838 
839  /// Implements @p AssemblyBase::end.
840  void end() override
841  {
842  this->end_reconstruct_schur();
843  }
844 
845 };
846 
847 #endif /* ASSEMBLY_LMH_HH_ */
848 
#define ASSERT(expr)
Definition: asserts.hh:351
#define ASSERT_PERMANENT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:348
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:333
std::shared_ptr< CouplingIntegralAcc< dim > > create_coupling_integral(Quadrature *quad)
std::shared_ptr< BulkIntegralAcc< dim > > create_bulk_integral(Quadrature *quad)
Quadrature * quad_low_
Quadrature used in assembling methods (dim-1).
Quadrature * quad_
Quadrature used in assembling methods.
AssemblyInternals * asm_internals_
Holds shared internals data with GeneriAssembly.
std::shared_ptr< BoundaryIntegralAcc< dim > > create_boundary_integral(Quadrature *quad)
Point accessor allow iterate over quadrature points of given side defined in local element coordinate...
ElementAccessor< 3 > element_accessor()
Base point accessor class.
Cell accessor allow iterate over DOF handler cells.
unsigned int n_dofs() const
Return number of dofs on given cell.
RangeConvert< DHNeighbSide, DHCellSide > neighb_sides() const
Returns range of neighbour cell of lower dimension corresponding to cell of higher dimension.
bool is_own() const
Return true if accessor represents own element (false for ghost element)
LocDofVec get_loc_dof_indices() const
Returns the local indices of dofs associated to the cell on the local process.
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...
unsigned int dim() const
Return dimension of element appropriate to cell.
unsigned int elm_idx() const
Return serial idx to element of loc_ele_idx_.
ElementAccessor< 3 > elm() const
Return ElementAccessor to element of loc_ele_idx_.
unsigned int local_idx() const
Return local index to element (index of DOF handler).
Side accessor allows to iterate over sides of DOF handler cell.
unsigned int elem_idx() const
Side side() const
Return Side of given cell and side_idx.
Boundary cond() const
const DHCellAccessor & cell() const
Return DHCellAccessor appropriate to the side.
unsigned int dim() const
Return dimension of element appropriate to the side.
double measure() const
unsigned int side_idx() const
unsigned int n_sides() const
Returns number of sides aligned with the edge.
Definition: accessors.hh:329
double measure() const
Computes the measure of the element.
SideIter side(const unsigned int loc_index)
unsigned int idx() const
We need this method after replacing Region by RegionIdx, and movinf RegionDB instance into particular...
Definition: accessors.hh:215
unsigned int dim() const
Definition: accessors.hh:188
const Element * element() const
Definition: accessors.hh:193
Neighbour ** neigh_vb
Definition: elements.h:83
unsigned int n_neighs_vb() const
Return number of neighbours.
Definition: elements.h:65
unsigned int n_sides() const
Definition: elements.h:131
Compound finite element on dim dimensional simplex.
Definition: fe_system.hh:102
std::vector< unsigned int > fe_dofs(unsigned int fe_index)
Return dof indices belonging to given sub-FE.
Definition: fe_system.cc:267
Container for various descendants of FieldCommonBase.
Definition: field_set.hh:160
Generic class of assemblation.
void set_solution(uint loc_dof, double solution, double diag=0.0)
Set the position and value of known solution. E.g. Dirichlet boundary condition.
Definition: local_system.cc:82
void eliminate_solution()
LocDofVec row_dofs
Definition: local_system.hh:54
double time_term_rhs_
Variables used in compute time term (unsteady)
void asm_sides(BulkPoint &p, double conductivity, unsigned int element_patch_idx)
Part of cell_integral method, common in all descendants.
unsigned int n_dofs_
Number of DOFs of fe_rt component.
arma::vec load_local_system(const DHCellAccessor &dh_cell)
unsigned int edge_row_
Helper indices in boundary assembly.
LocalSystem loc_schur_
void begin_mh_matrix()
Common code of begin method of MH matrix assembly (Darcy and Richards)
void end_reconstruct_schur()
Common code of end method of Reconstruct Schur assembly (Darcy and Richards)
void begin_reconstruct_schur()
Common code of begin method of Reconstruct Schur assembly (Darcy and Richards)
virtual ~MHMatrixAssemblyLMH()
Destructor.
FieldSet used_fields_
Sub field set contains fields used in calculation.
TEqData::EqFields EqFields
void set_dofs()
Precompute loc_system and loc_schur data members.
unsigned int bulk_local_idx_
Local idx of bulk element.
void begin() override
Implements AssemblyBase::begin.
ElQ< Vector > normal_join_
void postprocess_velocity_darcy(const DHCellAccessor &dh_cell, BulkPoint &p, arma::vec &solution)
Postprocess velocity during loading of local system and after calculating of cell integral.
void initialize()
Initialize auxiliary vectors and other data members.
arma::vec reconstructed_solution_
Vector for reconstructed solution (velocity and pressure on element) from Schur complement.
static constexpr const char * name()
void set_loc_schur(const DHCellAccessor dh_cr_cell)
Precompute loc_schur data member of given cell.
double cross_section_
Precomputed cross-section value.
EqFields * eq_fields_
Data objects shared with DarcyFlow.
void boundary_side_integral_in(DHCellSide cell_side, const ElementAccessor< 3 > &b_ele, BulkPoint &p_bdr)
QGauss quad_rt_
Assembly volume integrals.
void asm_element()
Part of cell_integral method, common in all descendants.
DarcyLMH::EqFields::BC_Type type_
Type of boundary condition.
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
double source_term_
Variables used in compute lumped source.
void end() override
Implements AssemblyBase::end.
std::shared_ptr< CouplingIntegralAcc< dim > > coupling_integral_
Coupling integral of assembly class.
void asm_source_term_darcy(const DHCellAccessor &cell, BulkPoint &p)
Part of cell_integral method, specialized in Darcy equation.
arma::vec3 nv_
Normal vector.
void dimjoin_intergral(DHCellAccessor cell_lower_dim, DHCellSide neighb_side)
void boundary_side_integral(DHCellSide cell_side)
DECLARE_EXCEPTION(ExcBCNotSupported,<< "BC type not supported.\n")
double ngh_value_
Precomputed ngh value.
unsigned int ngh_idx(DHCellAccessor &dh_cell, DHCellSide &neighb_side)
Temporary method find neighbour index in higher-dim cell.
FeQ< Scalar > JxW_
Following data members represent Element quantities and FE quantities.
void end_mh_matrix()
Common code of end method of MH matrix assembly (Darcy and Richards)
std::shared_ptr< BulkIntegralAcc< dim > > bulk_integral_
Bulk integral of assembly class.
void use_dirichlet_switch(DHCellSide &cell_side, const ElementAccessor< 3 > &b_ele, BulkPoint &p_bdr)
Update BC switch dirichlet in MH matrix assembly if BC type is seepage.
MHMatrixAssemblyLMH(EqData *eq_data, AssemblyInternals *asm_internals)
Constructor.
std::shared_ptr< BoundaryIntegralAcc< dim > > bdr_integral_
Boundary integral of assembly class.
FeQArray< Vector > velocity_
void precompute_boundary_side(DHCellSide &cell_side, BoundaryPoint &p_side, BulkPoint &p_bdr)
Precompute values used in boundary side integral on given DHCellSide.
void postprocess_velocity(const DHCellAccessor &dh_cell, BulkPoint &p)
std::shared_ptr< BulkIntegralAcc< dim > > asm_sides_integral_
Bulk integral defined on quadrature of higher order.
SideIter side() const
Definition: neighbours.h:147
unsigned int n_dofs() const
Returns the number of shape functions.
Symmetric Gauss-Legendre quadrature formulae on simplices.
static constexpr const char * name()
Definition: assembly_lmh.hh:51
void initialize()
Initialize auxiliary vectors and other data members.
Definition: assembly_lmh.hh:64
virtual ~ReadInitCondAssemblyLMH()
Destructor.
Definition: assembly_lmh.hh:61
FieldSet used_fields_
Sub field set contains fields used in calculation.
Definition: assembly_lmh.hh:98
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
Assemble integral over element.
Definition: assembly_lmh.hh:68
std::shared_ptr< BulkIntegralAcc< dim > > bulk_integral_
Bulk integral of assembly class.
ReadInitCondAssemblyLMH(EqData *eq_data, AssemblyInternals *asm_internals)
Constructor.
Definition: assembly_lmh.hh:54
LocDofVec l_indices_
Vector of pre-computed local DOF indices.
EqFields * eq_fields_
Data objects shared with Flow equation.
void end() override
Implements AssemblyBase::end.
Definition: assembly_lmh.hh:86
TEqData::EqFields EqFields
Definition: assembly_lmh.hh:48
ReconstructSchurAssemblyLMH(EqData *eq_data, AssemblyInternals *asm_internals)
Constructor.
void dimjoin_intergral(FMT_UNUSED DHCellAccessor cell_lower_dim, FMT_UNUSED DHCellSide neighb_side)
static constexpr const char * name()
void begin() override
Implements AssemblyBase::begin.
void boundary_side_integral(FMT_UNUSED DHCellSide cell_side)
Assembles between boundary element and corresponding side on bulk element.
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
Integral over element.
void end() override
Implements AssemblyBase::end.
TEqData::EqFields EqFields
Boundary cond() const
Edge edge() const
Returns pointer to the edge connected to the side.
Lumped mixed-hybrid model of linear Darcy flow, possibly unsteady.
Definitions of basic Lagrangean finite elements with polynomial shape functions.
Definitions of Raviart-Thomas finite elements.
Class FESystem for compound finite elements.
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
arma::Col< IntIdx > LocDofVec
Definition: index_types.hh:28
Solver based on the original PETSc solver using MPIAIJ matrix and succesive Schur complement construc...
unsigned int uint
unsigned int IntDim
A dimension index type.
Definition: mixed.hh:19
ArmaVec< double, N > vec
Definition: armor.hh:933
Store finite element reinit functions.
#define FMT_UNUSED
Definition: posix.h:75
Definitions of particular quadrature rules on simplices.
Assembly explicit Schur complement for the given linear system. Provides method for resolution of the...
Holds common data shared between GenericAssemblz and Assembly<dim> classes.
PatchFEValues< 3 > fe_values_
Common FEValues object over all dimensions.
Definition: mixed.hh:25