Flow123d  intersections_paper-476-gbe68821
darcy_flow_assembly.hh
Go to the documentation of this file.
1 /*
2  * darcy_flow_assembly.hh
3  *
4  * Created on: Apr 21, 2016
5  * Author: jb
6  */
7 
8 #ifndef SRC_FLOW_DARCY_FLOW_ASSEMBLY_HH_
9 #define SRC_FLOW_DARCY_FLOW_ASSEMBLY_HH_
10 
11 #include "mesh/mesh.h"
12 #include "fem/mapping_p1.hh"
13 #include "fem/fe_p.hh"
14 #include "fem/fe_values.hh"
15 #include "fem/fe_rt.hh"
17 #include "flow/mh_dofhandler.hh"
18 
19 #include "la/linsys.hh"
20 #include "la/linsys_PETSC.hh"
21 #include "la/linsys_BDDC.hh"
22 #include "la/schur.hh"
23 
24 #include "la/local_system.hh"
25 
26 #include "coupling/balance.hh"
27 #include "flow/mortar_assembly.hh"
28 
29 
31 {
32 public:
33  typedef std::shared_ptr<DarcyMH::EqData> AssemblyDataPtr;
35 
36  virtual ~AssemblyBase() {}
37 
38  /**
39  * Generic creator of multidimensional assembly, i.e. vector of
40  * particular assembly objects.
41  */
42  template< template<int dim> class Impl >
43  static MultidimAssembly create(typename Impl<1>::AssemblyDataPtr data) {
44  return { std::make_shared<Impl<1> >(data),
45  std::make_shared<Impl<2> >(data),
46  std::make_shared<Impl<3> >(data) };
47 
48  }
49 
50 // virtual LocalSystem & get_local_system() = 0;
51  virtual void fix_velocity(LocalElementAccessorBase<3> ele_ac) = 0;
52  virtual void assemble(LocalElementAccessorBase<3> ele_ac) = 0;
53 
54  // assembly compatible neighbourings
55  virtual void assembly_local_vb(double *local_vb,
56  ElementFullIter ele,
57  Neighbour *ngh) = 0;
58 
59  // compute velocity value in the barycenter
60  // TODO: implement and use general interpolations between discrete spaces
62 
64  {}
65 
66 protected:
67 
68  virtual void assemble_sides(LocalElementAccessorBase<3> ele) =0;
69 
71  {}
72 };
73 
74 
75 
76 template <int dim>
78 private:
79  // assembly face integrals (BC)
83 public:
85  : side_quad_(1),
86  fe_side_values_(side_map_, side_quad_, fe_p_disc_, update_normal_vectors)
87  {}
89 
90 };
91 
92 
93 
94 template<int dim>
95 class AssemblyMH : public AssemblyBase
96 {
97 public:
99  : quad_(3),
100  fe_values_(map_, quad_, fe_rt_,
102 
103 
104  velocity_interpolation_quad_(0), // veloctiy values in barycenter
105  velocity_interpolation_fv_(map_,velocity_interpolation_quad_, fe_rt_, update_values | update_quadrature_points),
106 
107  ad_(data),
108  loc_system_(size(), size())
109  {
110  // local numbering of dofs for MH system
111  unsigned int nsides = dim+1;
112  loc_side_dofs.resize(nsides);
113  loc_ele_dof = nsides;
114  loc_edge_dofs.resize(nsides);
115  for(unsigned int i = 0; i < nsides; i++){
116  loc_side_dofs[i] = i;
117  loc_edge_dofs[i] = nsides + i + 1;
118  }
119  //DebugOut() << print_var(this) << print_var(side_quad_.size());
120 
121  if (ad_->mortar_method_ == DarcyMH::MortarP0) {
122  mortar_assembly = std::make_shared<P0_CouplingAssembler>(ad_);
123  } else if (ad_->mortar_method_ == DarcyMH::MortarP1) {
124  mortar_assembly = std::make_shared<P1_CouplingAssembler>(ad_);
125  }
126 
127  }
128 
129 
130  ~AssemblyMH<dim>() override
131  {}
132 
133 // LocalSystem& get_local_system() override
134 // { return loc_system_;}
135 
137  {
138  if (mortar_assembly)
139  mortar_assembly->fix_velocity(ele_ac);
140  }
141 
142  void assemble(LocalElementAccessorBase<3> ele_ac) override
143  {
144  ASSERT_EQ_DBG(ele_ac.dim(), dim);
145  loc_system_.reset();
146 
147  set_dofs_and_bc(ele_ac);
148 
149  assemble_sides(ele_ac);
150  assemble_element(ele_ac);
151  assemble_source_term(ele_ac);
152 
153 
154 
155  ad_->lin_sys->set_local_system(loc_system_);
156 
157  assembly_dim_connections(ele_ac);
158 
159  if (ad_->balance != nullptr)
160  add_fluxes_in_balance_matrix(ele_ac);
161 
162  if (mortar_assembly)
163  mortar_assembly->assembly(ele_ac);
164  }
165 
166  void assembly_local_vb(double *local_vb, ElementFullIter ele, Neighbour *ngh) override
167  {
168  ASSERT_LT_DBG(ele->dim(), 3);
169  //DebugOut() << "alv " << print_var(this);
170  //START_TIMER("Assembly<dim>::assembly_local_vb");
171  // compute normal vector to side
172  arma::vec3 nv;
173  ElementFullIter ele_higher = ad_->mesh->element.full_iter(ngh->side()->element());
174  ngh_values_.fe_side_values_.reinit(ele_higher, ngh->side()->el_idx());
175  nv = ngh_values_.fe_side_values_.normal_vector(0);
176 
177  double value = ad_->sigma.value( ele->centre(), ele->element_accessor()) *
178  2*ad_->conductivity.value( ele->centre(), ele->element_accessor()) *
179  arma::dot(ad_->anisotropy.value( ele->centre(), ele->element_accessor())*nv, nv) *
180  ad_->cross_section.value( ngh->side()->centre(), ele_higher->element_accessor() ) * // cross-section of higher dim. (2d)
181  ad_->cross_section.value( ngh->side()->centre(), ele_higher->element_accessor() ) /
182  ad_->cross_section.value( ele->centre(), ele->element_accessor() ) * // crossection of lower dim.
183  ngh->side()->measure();
184 
185  local_vb[0] = -value; local_vb[1] = value;
186  local_vb[2] = value; local_vb[3] = -value;
187  }
188 
189 
191  {
192  //START_TIMER("Assembly<dim>::make_element_vector");
193  arma::vec3 flux_in_center;
194  flux_in_center.zeros();
195 
196  velocity_interpolation_fv_.reinit(ele);
197  for (unsigned int li = 0; li < ele->n_sides(); li++) {
198  flux_in_center += ad_->mh_dh->side_flux( *(ele->side( li ) ) )
199  * velocity_interpolation_fv_.shape_vector(li,0);
200  }
201 
202  flux_in_center /= ad_->cross_section.value(ele->centre(), ele->element_accessor() );
203  return flux_in_center;
204  }
205 
206 protected:
207  static const unsigned int size()
208  {
209  // dofs: velocity, pressure, edge pressure
211  }
212 
214 
215  ASSERT_DBG(ele_ac.dim() == dim);
216 
217  //set global dof for element (pressure)
218  loc_system_.row_dofs[loc_ele_dof] = loc_system_.col_dofs[loc_ele_dof] = ele_ac.ele_row();
219 
220  //shortcuts
221  const unsigned int nsides = ele_ac.n_sides();
222  LinSys *ls = ad_->lin_sys;
223 
224  Boundary *bcd;
225  unsigned int side_row, edge_row;
226 
227  dirichlet_edge.resize(nsides);
228  for (unsigned int i = 0; i < nsides; i++) {
229 
230  side_row = loc_side_dofs[i]; //local
231  edge_row = loc_edge_dofs[i]; //local
232  loc_system_.row_dofs[side_row] = loc_system_.col_dofs[side_row] = ele_ac.side_row(i); //global
233  loc_system_.row_dofs[edge_row] = loc_system_.col_dofs[edge_row] = ele_ac.edge_row(i); //global
234 
235  bcd = ele_ac.side(i)->cond();
236  dirichlet_edge[i] = 0;
237  if (bcd) {
238  ElementAccessor<3> b_ele = bcd->element_accessor();
239  DarcyMH::EqData::BC_Type type = (DarcyMH::EqData::BC_Type)ad_->bc_type.value(b_ele.centre(), b_ele);
240 
241  double cross_section = ad_->cross_section.value(ele_ac.centre(), ele_ac.element_accessor());
242 
243  if ( type == DarcyMH::EqData::none) {
244  // homogeneous neumann
245  } else if ( type == DarcyMH::EqData::dirichlet ) {
246  double bc_pressure = ad_->bc_pressure.value(b_ele.centre(), b_ele);
247  loc_system_.set_solution(loc_edge_dofs[i],bc_pressure,-1);
248  dirichlet_edge[i] = 1;
249 
250  } else if ( type == DarcyMH::EqData::total_flux) {
251  // internally we work with outward flux
252  double bc_flux = -ad_->bc_flux.value(b_ele.centre(), b_ele);
253  double bc_pressure = ad_->bc_pressure.value(b_ele.centre(), b_ele);
254  double bc_sigma = ad_->bc_robin_sigma.value(b_ele.centre(), b_ele);
255 
256  dirichlet_edge[i] = 2; // to be skipped in LMH source assembly
257  loc_system_.add_value(edge_row, edge_row,
258  -bcd->element()->measure() * bc_sigma * cross_section,
259  (bc_flux - bc_sigma * bc_pressure) * bcd->element()->measure() * cross_section);
260  }
261  else if (type==DarcyMH::EqData::seepage) {
262  ad_->is_linear=false;
263 
264  unsigned int loc_edge_idx = bcd->bc_ele_idx_;
265  char & switch_dirichlet = ad_->bc_switch_dirichlet[loc_edge_idx];
266  double bc_pressure = ad_->bc_switch_pressure.value(b_ele.centre(), b_ele);
267  double bc_flux = -ad_->bc_flux.value(b_ele.centre(), b_ele);
268  double side_flux = bc_flux * bcd->element()->measure() * cross_section;
269 
270  // ** Update BC type. **
271  if (switch_dirichlet) {
272  // check and possibly switch to flux BC
273  // The switch raise error on the corresponding edge row.
274  // Magnitude of the error is abs(solution_flux - side_flux).
275  ASSERT_DBG(ad_->mh_dh->rows_ds->is_local(ele_ac.side_row(i)))(ele_ac.side_row(i));
276  unsigned int loc_side_row = ele_ac.side_local_row(i);
277  double & solution_flux = ls->get_solution_array()[loc_side_row];
278 
279  if ( solution_flux < side_flux) {
280  //DebugOut().fmt("x: {}, to neum, p: {} f: {} -> f: {}\n", b_ele.centre()[0], bc_pressure, solution_flux, side_flux);
281  solution_flux = side_flux;
282  switch_dirichlet=0;
283  }
284  } else {
285  // check and possibly switch to pressure BC
286  // TODO: What is the appropriate DOF in not local?
287  // The switch raise error on the corresponding side row.
288  // Magnitude of the error is abs(solution_head - bc_pressure)
289  // Since usually K is very large, this error would be much
290  // higher then error caused by the inverse switch, this
291  // cause that a solution with the flux violating the
292  // flux inequality leading may be accepted, while the error
293  // in pressure inequality is always satisfied.
294  ASSERT_DBG(ad_->mh_dh->rows_ds->is_local(ele_ac.edge_row(i)))(ele_ac.edge_row(i));
295  unsigned int loc_edge_row = ele_ac.edge_local_row(i);
296  double & solution_head = ls->get_solution_array()[loc_edge_row];
297 
298  if ( solution_head > bc_pressure) {
299  //DebugOut().fmt("x: {}, to dirich, p: {} -> p: {} f: {}\n",b_ele.centre()[0], solution_head, bc_pressure, bc_flux);
300  solution_head = bc_pressure;
301  switch_dirichlet=1;
302  }
303  }
304 
305  // ** Apply BCUpdate BC type. **
306  // Force Dirichlet type during the first iteration of the unsteady case.
307  if (switch_dirichlet || ad_->force_bc_switch ) {
308  //DebugOut().fmt("x: {}, dirich, bcp: {}\n", b_ele.centre()[0], bc_pressure);
309  loc_system_.set_solution(loc_edge_dofs[i],bc_pressure, -1);
310  dirichlet_edge[i] = 1;
311  } else {
312  //DebugOut()("x: {}, neuman, q: {} bcq: {}\n", b_ele.centre()[0], side_flux, bc_flux);
313  loc_system_.add_value(edge_row, side_flux);
314  }
315 
316  } else if (type==DarcyMH::EqData::river) {
317  ad_->is_linear=false;
318 
319  double bc_pressure = ad_->bc_pressure.value(b_ele.centre(), b_ele);
320  double bc_switch_pressure = ad_->bc_switch_pressure.value(b_ele.centre(), b_ele);
321  double bc_flux = -ad_->bc_flux.value(b_ele.centre(), b_ele);
322  double bc_sigma = ad_->bc_robin_sigma.value(b_ele.centre(), b_ele);
323  ASSERT_DBG(ad_->mh_dh->rows_ds->is_local(ele_ac.edge_row(i)))(ele_ac.edge_row(i));
324  unsigned int loc_edge_row = ele_ac.edge_local_row(i);
325  double & solution_head = ls->get_solution_array()[loc_edge_row];
326 
327  // Force Robin type during the first iteration of the unsteady case.
328  if (solution_head > bc_switch_pressure || ad_->force_bc_switch) {
329  // Robin BC
330  //DebugOut().fmt("x: {}, robin, bcp: {}\n", b_ele.centre()[0], bc_pressure);
331  loc_system_.add_value(edge_row, edge_row,
332  -bcd->element()->measure() * bc_sigma * cross_section,
333  bcd->element()->measure() * cross_section * (bc_flux - bc_sigma * bc_pressure) );
334  } else {
335  // Neumann BC
336  //DebugOut().fmt("x: {}, neuman, q: {} bcq: {}\n", b_ele.centre()[0], bc_switch_pressure, bc_pressure);
337  double bc_total_flux = bc_flux + bc_sigma*(bc_switch_pressure - bc_pressure);
338 
339  loc_system_.add_value(edge_row, bc_total_flux * bcd->element()->measure() * cross_section);
340  }
341  }
342  else {
343  xprintf(UsrErr, "BC type not supported.\n");
344  }
345  }
346  loc_system_.add_value(side_row, edge_row, 1.0);
347  loc_system_.add_value(edge_row, side_row, 1.0);
348  }
349 
350 // DBGCOUT(<< "ele " << ele_ac.ele_global_idx() << ": ");
351 // for (unsigned int i = 0; i < nsides; i++) cout << loc_system_.row_dofs[loc_side_dofs[i]] << " ";
352 // cout << loc_system_.row_dofs[loc_ele_dof] << " ";
353 // for (unsigned int i = 0; i < nsides; i++) cout << loc_system_.row_dofs[loc_edge_dofs[i]] << " ";
354 // cout << "\n";
355  }
356 
358  {
359  double cs = ad_->cross_section.value(ele_ac.centre(), ele_ac.element_accessor());
360  double conduct = ad_->conductivity.value(ele_ac.centre(), ele_ac.element_accessor());
361  double scale = 1 / cs /conduct;
362 
363  assemble_sides_scale(ele_ac, scale);
364  }
365 
367  {
368  arma::vec3 &gravity_vec = ad_->gravity_vec_;
369 
370  ElementFullIter ele =ele_ac.full_iter();
371  fe_values_.reinit(ele);
372  unsigned int ndofs = fe_values_.get_fe()->n_dofs();
373  unsigned int qsize = fe_values_.get_quadrature()->size();
374 
375  for (unsigned int k=0; k<qsize; k++)
376  for (unsigned int i=0; i<ndofs; i++){
377  double rhs_val =
378  arma::dot(gravity_vec,fe_values_.shape_vector(i,k))
379  * fe_values_.JxW(k);
380  loc_system_.add_value(i, rhs_val);
381 
382  for (unsigned int j=0; j<ndofs; j++){
383  double mat_val =
384  arma::dot(fe_values_.shape_vector(i,k), //TODO: compute anisotropy before
385  (ad_->anisotropy.value(ele_ac.centre(), ele_ac.element_accessor() )).i()
386  * fe_values_.shape_vector(j,k))
387  * scale * fe_values_.JxW(k);
388 
389  loc_system_.add_value(i, j, mat_val);
390  }
391  }
392 
393  // assemble matrix for weights in BDDCML
394  // approximation to diagonal of
395  // S = -C - B*inv(A)*B'
396  // as
397  // diag(S) ~ - diag(C) - 1./diag(A)
398  // the weights form a partition of unity to average a discontinuous solution from neighbouring subdomains
399  // to a continuous one
400  // it is important to scale the effect - if conductivity is low for one subdomain and high for the other,
401  // trust more the one with low conductivity - it will be closer to the truth than an arithmetic average
402  if ( typeid(*ad_->lin_sys) == typeid(LinSys_BDDC) ) {
403  const arma::mat& local_matrix = loc_system_.get_matrix();
404  for(unsigned int i=0; i < ndofs; i++) {
405  double val_side = local_matrix(i,i);
406  double val_edge = -1./local_matrix(i,i);
407 
408  unsigned int side_row = loc_system_.row_dofs[loc_side_dofs[i]];
409  unsigned int edge_row = loc_system_.row_dofs[loc_edge_dofs[i]];
410  static_cast<LinSys_BDDC*>(ad_->lin_sys)->diagonal_weights_set_value( side_row, val_side );
411  static_cast<LinSys_BDDC*>(ad_->lin_sys)->diagonal_weights_set_value( edge_row, val_edge );
412  }
413  }
414  }
415 
416 
418  // set block B, B': element-side, side-element
419 
420  for(unsigned int side = 0; side < loc_side_dofs.size(); side++){
421  loc_system_.add_value(loc_ele_dof, loc_side_dofs[side], -1.0);
422  loc_system_.add_value(loc_side_dofs[side], loc_ele_dof, -1.0);
423  }
424 
425  if ( typeid(*ad_->lin_sys) == typeid(LinSys_BDDC) ) {
426  double val_ele = 1.;
427  static_cast<LinSys_BDDC*>(ad_->lin_sys)->
428  diagonal_weights_set_value( loc_system_.row_dofs[loc_ele_dof], val_ele );
429  }
430  }
431 
432 
434  //D, E',E block: compatible connections: element-edge
435  int ele_row = ele_ac.ele_row();
436  int rows[2];
437  double local_vb[4]; // 2x2 matrix
438 
439  Neighbour *ngh;
440 
441  //DebugOut() << "adc " << print_var(this) << print_var(side_quad_.size());
442  for (unsigned int i = 0; i < ele_ac.full_iter()->n_neighs_vb; i++) {
443  // every compatible connection adds a 2x2 matrix involving
444  // current element pressure and a connected edge pressure
445  ngh= ele_ac.full_iter()->neigh_vb[i];
446  rows[0]=ele_row;
447  rows[1]=ad_->mh_dh->row_4_edge[ ngh->edge_idx() ];
448 
449 
450  assembly_local_vb(local_vb, ele_ac.full_iter(), ngh);
451 
452  ad_->lin_sys->mat_set_values(2, rows, 2, rows, local_vb);
453 
454  // update matrix for weights in BDDCML
455  if ( typeid(*ad_->lin_sys) == typeid(LinSys_BDDC) ) {
456  int ind = rows[1];
457  // there is -value on diagonal in block C!
458  double new_val = local_vb[0];
459  static_cast<LinSys_BDDC*>(ad_->lin_sys)->diagonal_weights_set_value( ind, new_val );
460  }
461  }
462  }
463 
465 
466  for (unsigned int i = 0; i < ele_ac.n_sides(); i++) {
467  Boundary* bcd = ele_ac.side(i)->cond();
468 
469  if (bcd) {
470  /*
471  DebugOut().fmt("add_flux: {} {} {} {}\n",
472  ad_->mh_dh->el_ds->myp(),
473  ele_ac.ele_global_idx(),
474  ad_->local_boundary_index,
475  ele_ac.side_row(i));
476  */
477  ad_->balance->add_flux_matrix_values(ad_->water_balance_idx, ad_->local_boundary_index,
478  {ele_ac.side_row(i)}, {1});
479  ++(ad_->local_boundary_index);
480  }
481  }
482  }
483 
484 
485 
486  // assembly volume integrals
491 
492  NeighSideValues<dim<3?dim:2> ngh_values_;
493 
494  // Interpolation of velocity into barycenters
495  QGauss<dim> velocity_interpolation_quad_;
496  FEValues<dim,3> velocity_interpolation_fv_;
497 
498  // data shared by assemblers of different dimension
499  AssemblyDataPtr ad_;
500  std::vector<unsigned int> dirichlet_edge;
501 
502  LocalSystem loc_system_;
503  std::vector<unsigned int> loc_side_dofs;
504  std::vector<unsigned int> loc_edge_dofs;
505  unsigned int loc_ele_dof;
506 
507  std::shared_ptr<MortarAssemblyBase> mortar_assembly;
508 };
509 
510 
511 #endif /* SRC_FLOW_DARCY_FLOW_ASSEMBLY_HH_ */
const arma::vec3 centre() const
Class MappingP1 implements the affine transformation of the unit cell onto the actual cell...
Shape function values.
Definition: update_flags.hh:87
double measure() const
Computes the measure of the element.
Definition: elements.cc:89
MappingP1< dim, 3 > map_
#define ASSERT_EQ_DBG(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:332
FESideValues< dim+1, 3 > fe_side_values_
std::vector< std::shared_ptr< AssemblyBase > > MultidimAssembly
Solver based on the original PETSc solver using MPIAIJ matrix and succesive Schur complement construc...
void assemble_sides(LocalElementAccessorBase< 3 > ele_ac) override
ElementAccessor< 3 > element_accessor()
virtual arma::vec3 make_element_vector(ElementFullIter ele)=0
void add_fluxes_in_balance_matrix(LocalElementAccessorBase< 3 > ele_ac)
static const unsigned int size()
void assemble(LocalElementAccessorBase< 3 > ele_ac) override
Boundary * cond() const
Definition: side_impl.hh:70
Definition: abscissa.h:25
arma::vec3 make_element_vector(ElementFullIter ele) override
Wrappers for linear systems based on MPIAIJ and MATIS format.
arma::vec3 centre() const
Definition: sides.cc:122
std::shared_ptr< DarcyMH::EqData > AssemblyDataPtr
FE_P_disc< 0, dim+1, 3 > fe_p_disc_
virtual void assemble_source_term(LocalElementAccessorBase< 3 > ele)
virtual void assemble(LocalElementAccessorBase< 3 > ele_ac)=0
Class FEValues calculates finite element data on the actual cells such as shape function values...
static constexpr bool value
Definition: json.hpp:87
Symmetric Gauss-Legendre quadrature formulae on simplices.
Assembly explicit Schur complement for the given linear system. Provides method for resolution of the...
std::shared_ptr< DarcyMH::EqData > AssemblyDataPtr
virtual void fix_velocity(LocalElementAccessorBase< 3 > ele_ac)=0
Transformed quadrature points.
FE_RT0< dim, 3 > fe_rt_
double * get_solution_array()
Definition: linsys.hh:282
void set_dofs_and_bc(LocalElementAccessorBase< 3 > ele_ac)
unsigned int edge_idx()
Definitions of basic Lagrangean finite elements with polynomial shape functions.
SideIter side()
#define xprintf(...)
Definition: system.hh:87
void assemble_sides_scale(LocalElementAccessorBase< 3 > ele_ac, double scale)
Element * element()
Definition: boundaries.cc:39
Shape function gradients.
Definition: update_flags.hh:95
virtual void update_water_content(LocalElementAccessorBase< 3 > ele)
double measure() const
Definition: sides.cc:29
QGauss< dim > quad_
Normal vectors.
unsigned int bc_ele_idx_
Definition: boundaries.h:76
Definition: system.hh:59
virtual ~AssemblyBase()
QGauss< dim > side_quad_
ElementFullIter element() const
Definition: side_impl.hh:52
FEValues< dim, 3 > fe_values_
void assembly_dim_connections(LocalElementAccessorBase< 3 > ele_ac)
#define ASSERT_DBG(expr)
Definition: asserts.hh:350
Abstract linear system class.
Definitions of particular quadrature rules on simplices.
virtual void assemble_sides(LocalElementAccessorBase< 3 > ele)=0
arma::vec::fixed< spacedim > centre() const
Definition: accessors.hh:91
void fix_velocity(LocalElementAccessorBase< 3 > ele_ac) override
unsigned int el_idx() const
Definition: side_impl.hh:81
void assembly_local_vb(double *local_vb, ElementFullIter ele, Neighbour *ngh) override
static MultidimAssembly create(typename Impl< 1 >::AssemblyDataPtr data)
void assemble_element(LocalElementAccessorBase< 3 > ele_ac)
MappingP1< dim+1, 3 > side_map_
virtual void assembly_local_vb(double *local_vb, ElementFullIter ele, Neighbour *ngh)=0
ElementFullIter full_iter()
Definitions of Raviart-Thomas finite elements.
ElementAccessor< 3 > element_accessor()
Definition: boundaries.cc:47
Solver based on Multilevel BDDC - using corresponding class of OpenFTL package.
Transformed quadrature weights.
#define ASSERT_LT_DBG(a, b)
Definition of comparative assert macro (Less Than) only for debug mode.
Definition: asserts.hh:300