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