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