Flow123d  DF_patch_fe_mechanics-ccea6e4
assembly_elasticity.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_elasticity.hh
15  * @brief
16  */
17 
18 #ifndef ASSEMBLY_ELASTICITY_HH_
19 #define ASSEMBLY_ELASTICITY_HH_
20 
23 #include "mechanics/elasticity.hh"
24 #include "fem/fe_p.hh"
25 #include "fem/fe_values.hh"
27 #include "coupling/balance.hh"
29 
30 
31 /**
32  * Auxiliary container class for Finite element and related objects of given dimension.
33  */
34 template <unsigned int dim>
36 {
37 public:
38  typedef typename Elasticity::EqFields EqFields;
39  typedef typename Elasticity::EqData EqData;
40 
41  static constexpr const char * name() { return "StiffnessAssemblyElasticity"; }
42 
43  /// Constructor.
44  StiffnessAssemblyElasticity(EqFields *eq_fields, EqData *eq_data, PatchFEValues<3> *fe_values)
45  : AssemblyBasePatch<dim>(fe_values), eq_fields_(eq_fields), eq_data_(eq_data), // quad_order = 1
46  JxW_( this->bulk_values().JxW() ),
47  JxW_side_( this->side_values().JxW() ),
48  normal_( this->side_values().normal_vector() ),
49  ref_vals_( this->bulk_values().ref_vector() ),
50  ref_vals_side_( this->side_values().ref_vector() ),
51  grad_ref_vals_( this->bulk_values().ref_vector_grad() ),
52  grad_ref_vals_side_( this->side_values().ref_vector_grad() ),
53  deform_side_( this->side_values().vector_shape() ),
54  grad_deform_( this->bulk_values().grad_vector_shape() ),
55  sym_grad_deform_( this->bulk_values().vector_sym_grad() ),
56  div_deform_( this->bulk_values().vector_divergence() ),
57  deform_join_( this->join_values().vector_join_shape() ),
58  deform_join_grad_( this->join_values().gradient_vector_join_shape() ) {
66  }
67 
68  /// Destructor.
70 
71  /// Initialize auxiliary vectors and other data members
72  void initialize(ElementCacheMap *element_cache_map) {
73  //this->balance_ = eq_data_->balance_;
74  this->element_cache_map_ = element_cache_map;
75 
76  shared_ptr<FE_P<dim-1>> fe_p_low = std::make_shared< FE_P<dim-1> >(1);
77  shared_ptr<FiniteElement<dim-1>> fe_low = std::make_shared<FESystem<dim-1>>(fe_p_low, FEVector, 3);
78  this->fe_values_->template initialize<dim>(*this->quad_);
79  this->fe_values_->template initialize<dim>(*this->quad_low_);
80 
81  n_dofs_ = this->n_dofs();
82  n_dofs_sub_ = fe_low->n_dofs();
84  dof_indices_.resize(n_dofs_);
85  side_dof_indices_.resize(2*n_dofs_);
86  local_matrix_.resize(4*n_dofs_*n_dofs_);
87  }
88 
89 
90  /// Assemble integral over element
91  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
92  {
93  if (cell.dim() != dim) return;
94 
95  // Fracture stiffness is assembled in dimjoin_integral.
96  if (cell.elm()->n_neighs_vb() > 0) return;
97 
99 
100  // assemble the local stiffness matrix
101  for (unsigned int i=0; i<n_dofs_; i++)
102  for (unsigned int j=0; j<n_dofs_; j++)
103  local_matrix_[i*n_dofs_+j] = 0;
104 
105  for (auto p : this->bulk_points(element_patch_idx) )
106  {
107  for (unsigned int i=0; i<n_dofs_; i++)
108  {
109  for (unsigned int j=0; j<n_dofs_; j++)
111  arma::dot(eq_fields_->stress_tensor(p,sym_grad_deform_.shape(j)(p)), sym_grad_deform_.shape(i)(p))
112  )*JxW_(p);
113  }
114  }
116  }
117 
118  /// Assembles boundary integral.
119  inline void boundary_side_integral(DHCellSide cell_side)
120  {
121  ASSERT_EQ(cell_side.dim(), dim).error("Dimension of element mismatch!");
122  if (!cell_side.cell().is_own()) return;
123 
124  Side side = cell_side.side();
125  const DHCellAccessor &dh_cell = cell_side.cell();
126  dh_cell.get_dof_indices(dof_indices_);
127 
128  for (unsigned int i=0; i<n_dofs_; i++)
129  for (unsigned int j=0; j<n_dofs_; j++)
130  local_matrix_[i*n_dofs_+j] = 0;
131 
132  auto p_side = *( this->boundary_points(cell_side).begin() );
133  auto p_bdr = p_side.point_bdr( side.cond().element_accessor() );
134  unsigned int bc_type = eq_fields_->bc_type(p_bdr);
135  double side_measure = cell_side.measure();
136  if (bc_type == EqFields::bc_type_displacement)
137  {
138  for (auto p : this->boundary_points(cell_side) ) {
139  for (unsigned int i=0; i<n_dofs_; i++)
140  for (unsigned int j=0; j<n_dofs_; j++)
141  local_matrix_[i*n_dofs_+j] += (eq_fields_->dirichlet_penalty(p) / side_measure) *
142  arma::dot(deform_side_.shape(i)(p),deform_side_.shape(j)(p)) * JxW_side_(p);
143  }
144  }
145  else if (bc_type == EqFields::bc_type_displacement_normal)
146  {
147  for (auto p : this->boundary_points(cell_side) ) {
148  for (unsigned int i=0; i<n_dofs_; i++)
149  for (unsigned int j=0; j<n_dofs_; j++)
150  local_matrix_[i*n_dofs_+j] += (eq_fields_->dirichlet_penalty(p) / side_measure) *
151  arma::dot(deform_side_.shape(i)(p), normal_(p)) *
152  arma::dot(deform_side_.shape(j)(p), normal_(p)) * JxW_side_(p);
153  }
154  }
155 
157  }
158 
159 
160  /// Assembles between elements of different dimensions.
161  inline void dimjoin_intergral(DHCellAccessor cell_lower_dim, DHCellSide neighb_side) {
162  if (dim == 1) return;
163  ASSERT_EQ(cell_lower_dim.dim(), dim-1).error("Dimension of element mismatch!");
164 
165  unsigned int n_indices = cell_lower_dim.get_dof_indices(dof_indices_);
166  for(unsigned int i=0; i<n_indices; ++i) {
168  }
169 
170  DHCellAccessor cell_higher_dim = eq_data_->dh_->cell_accessor_from_element( neighb_side.element().idx() );
171  n_indices = cell_higher_dim.get_dof_indices(dof_indices_);
172  for(unsigned int i=0; i<n_indices; ++i) {
174  }
175 
176  // Element id's for testing if they belong to local partition.
177  bool own_element_id[2];
178  own_element_id[0] = cell_lower_dim.is_own();
179  own_element_id[1] = cell_higher_dim.is_own();
180 
181  unsigned int n_neighs = cell_lower_dim.elm()->n_neighs_vb();
182 
183  for (unsigned int i=0; i<n_dofs_ngh_[0]+n_dofs_ngh_[1]; i++)
184  for (unsigned int j=0; j<n_dofs_ngh_[0]+n_dofs_ngh_[1]; j++)
185  local_matrix_[i*(n_dofs_ngh_[0]+n_dofs_ngh_[1])+j] = 0;
186 
187  // set transmission conditions
188  for (auto p_high : this->coupling_points(neighb_side) )
189  {
190  auto p_low = p_high.lower_dim(cell_lower_dim);
191  arma::vec3 nv = normal_(p_high);
192 
193  for (uint i=0; i<deform_join_.n_dofs_both(); ++i) {
194  uint is_high_i = deform_join_.is_high_dim(i);
195  if (!own_element_id[is_high_i]) continue;
196  arma::vec3 diff_deform_i = deform_join_.shape(i)(p_low) - deform_join_.shape(i)(p_high);
197  arma::mat33 grad_deform_i = deform_join_grad_.shape(i)(p_low); // low dim element
198  arma::mat33 semi_grad_i = grad_deform_i + n_neighs/eq_fields_->cross_section(p_low)*arma::kron(diff_deform_i,nv.t());
199  arma::mat33 semi_sym_grad_i = 0.5*(semi_grad_i + semi_grad_i.t());
200 
201  for (uint j=0; j<deform_join_.n_dofs_both(); ++j) {
202  arma::vec3 deform_j_high = deform_join_.shape(j)(p_high);
203  arma::vec3 diff_deform_j = deform_join_.shape(j)(p_low) - deform_j_high;
204  arma::mat33 grad_deform_j = deform_join_grad_.shape(j)(p_low); // low dim element
205  arma::mat33 semi_grad_j = grad_deform_j + n_neighs/eq_fields_->cross_section(p_low)*arma::kron(diff_deform_j,nv.t());
206  arma::mat33 semi_sym_grad_j = 0.5*(semi_grad_j + semi_grad_j.t());
207 
208  local_matrix_[i * (n_dofs_ngh_[0]+n_dofs_ngh_[1]) + j] +=
209  (
210  eq_fields_->fracture_sigma(p_low)*eq_fields_->cross_section(p_low) / n_neighs
211  * arma::dot(semi_sym_grad_i, eq_fields_->stress_tensor(p_low,semi_sym_grad_j))
212 
213  // This term corrects the tangential part of the above product so that there is no
214  // dependence on fracture_sigma.
215  // TODO: Fracture_sigma should be possibly removed and replaced by anisotropic elasticity.
216  + (1-eq_fields_->fracture_sigma(p_low))*eq_fields_->cross_section(p_low) / n_neighs
217  * arma::dot(0.5*(grad_deform_i+grad_deform_i.t()), eq_fields_->stress_tensor(p_low,0.5*(grad_deform_j+grad_deform_j.t())))
218  )*JxW_side_(p_high);
219  }
220  }
221 
222  }
223 
225  }
226 
227 
228 
229 private:
230  inline arma::mat33 mat_t(const arma::mat33 &m, const arma::vec3 &n)
231  {
232  arma::mat33 mt = m - m*arma::kron(n,n.t());
233  return mt;
234  }
235 
236 
237  /// Data objects shared with Elasticity
240 
241  /// Sub field set contains fields used in calculation.
243 
244  unsigned int n_dofs_; ///< Number of dofs
245  unsigned int n_dofs_sub_; ///< Number of dofs (on lower dim element)
246  std::vector<unsigned int> n_dofs_ngh_; ///< Number of dofs on lower and higher dimension element (vector of 2 items)
247 
248  vector<LongIdx> dof_indices_; ///< Vector of global DOF indices
249  vector<LongIdx> side_dof_indices_; ///< vector of DOF indices in neighbour calculation.
250  vector<PetscScalar> local_matrix_; ///< Auxiliary vector for assemble methods
251 
252  /// Following data members represent Element quantities and FE quantities
266 
267  template < template<IntDim...> class DimAssembly>
268  friend class GenericAssembly;
269 
270 };
271 
272 
273 template <unsigned int dim>
275 {
276 public:
277  typedef typename Elasticity::EqFields EqFields;
278  typedef typename Elasticity::EqData EqData;
279 
280  static constexpr const char * name() { return "RhsAssemblyElasticity"; }
281 
282  /// Constructor.
283  RhsAssemblyElasticity(EqFields *eq_fields, EqData *eq_data, PatchFEValues<3> *fe_values)
284  : AssemblyBasePatch<dim>(fe_values), eq_fields_(eq_fields), eq_data_(eq_data),
285  JxW_( this->bulk_values().JxW() ),
286  JxW_side_( this->side_values().JxW() ),
287  normal_( this->side_values().normal_vector() ),
288  ref_vals_( this->bulk_values().ref_vector() ),
289  ref_vals_side_( this->side_values().ref_vector() ),
290  grad_ref_vals_( this->bulk_values().ref_vector_grad() ),
291  grad_ref_vals_side_( this->side_values().ref_vector_grad() ),
292  deform_( this->bulk_values().vector_shape() ),
293  deform_side_( this->side_values().vector_shape() ),
294  grad_deform_( this->bulk_values().grad_vector_shape() ),
295  div_deform_( this->bulk_values().vector_divergence() ),
296  deform_join_( this->join_values().vector_join_shape() ) {
299  this->used_fields_ += eq_fields_->load;
304  this->used_fields_ += eq_fields_->bc_type;
309  }
310 
311  /// Destructor.
313 
314  /// Initialize auxiliary vectors and other data members
315  void initialize(ElementCacheMap *element_cache_map) {
316  //this->balance_ = eq_data_->balance_;
317  this->element_cache_map_ = element_cache_map;
318 
319  shared_ptr<FE_P<dim-1>> fe_p_low = std::make_shared< FE_P<dim-1> >(1);
320  shared_ptr<FiniteElement<dim-1>> fe_low = std::make_shared<FESystem<dim-1>>(fe_p_low, FEVector, 3);
321  this->fe_values_->template initialize<dim>(*this->quad_);
322  this->fe_values_->template initialize<dim>(*this->quad_low_);
323 
324  n_dofs_ = this->n_dofs();
325  n_dofs_sub_ = fe_low->n_dofs();
327  dof_indices_.resize(n_dofs_);
329  local_rhs_.resize(2*n_dofs_);
330  }
331 
332 
333  /// Assemble integral over element
334  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
335  {
336  if (cell.dim() != dim) return;
337  if (!cell.is_own()) return;
338 
340 
341  // assemble the local stiffness matrix
342  fill_n(&(local_rhs_[0]), n_dofs_, 0);
343  //local_source_balance_vector.assign(n_dofs_, 0);
344  //local_source_balance_rhs.assign(n_dofs_, 0);
345 
346  // compute sources
347  for (auto p : this->bulk_points(element_patch_idx) )
348  {
349  for (unsigned int i=0; i<n_dofs_; i++)
350  local_rhs_[i] += (
351  arma::dot(eq_fields_->load(p), deform_.shape(i)(p))
353  -arma::dot(eq_fields_->initial_stress(p), grad_deform_.shape(i)(p))
354  )*eq_fields_->cross_section(p)*JxW_(p);
355  }
357 
358 // for (unsigned int i=0; i<n_dofs_; i++)
359 // {
360 // for (unsigned int k=0; k<qsize_; k++) // point range
361 // local_source_balance_vector[i] -= 0;//sources_sigma[k]*fe_vals_[vec_view_].value(i,k)*JxW_(k);
362 //
363 // local_source_balance_rhs[i] += local_rhs_[i];
364 // }
365 // balance_->add_source_matrix_values(subst_idx, elm_acc.region().bulk_idx(), dof_indices_, local_source_balance_vector);
366 // balance_->add_source_vec_values(subst_idx, elm_acc.region().bulk_idx(), dof_indices_, local_source_balance_rhs);
367  }
368 
369  /// Assembles boundary integral.
370  inline void boundary_side_integral(DHCellSide cell_side)
371  {
372  ASSERT_EQ(cell_side.dim(), dim).error("Dimension of element mismatch!");
373  if (!cell_side.cell().is_own()) return;
374 
375  const DHCellAccessor &dh_cell = cell_side.cell();
376  dh_cell.get_dof_indices(dof_indices_);
377 
378  auto p_side = *( this->boundary_points(cell_side).begin() );
379  auto p_bdr = p_side.point_bdr( cell_side.cond().element_accessor() );
380  unsigned int bc_type = eq_fields_->bc_type(p_bdr);
381 
382  fill_n(&(local_rhs_[0]), n_dofs_, 0);
383  // local_flux_balance_vector.assign(n_dofs_, 0);
384  // local_flux_balance_rhs = 0;
385 
386  // addtion from initial stress
387  for (auto p : this->boundary_points(cell_side) )
388  {
389  for (unsigned int i=0; i<n_dofs_; i++)
391  arma::dot(( eq_fields_->initial_stress(p) * normal_(p)),
392  deform_side_.shape(i)(p)) *
393  JxW_side_(p);
394  }
395 
396  if (bc_type == EqFields::bc_type_displacement)
397  {
398  double side_measure = cell_side.measure();
399  for (auto p : this->boundary_points(cell_side) )
400  {
401  auto p_bdr = p.point_bdr( cell_side.cond().element_accessor() );
402  for (unsigned int i=0; i<n_dofs_; i++)
403  local_rhs_[i] += (eq_fields_->dirichlet_penalty(p) / side_measure) *
404  arma::dot(eq_fields_->bc_displacement(p_bdr), deform_side_.shape(i)(p)) *
405  JxW_side_(p);
406  }
407  }
408  else if (bc_type == EqFields::bc_type_displacement_normal)
409  {
410  double side_measure = cell_side.measure();
411  for (auto p : this->boundary_points(cell_side) )
412  {
413  auto p_bdr = p.point_bdr( cell_side.cond().element_accessor() );
414  for (unsigned int i=0; i<n_dofs_; i++)
415  local_rhs_[i] += (eq_fields_->dirichlet_penalty(p) / side_measure) *
416  arma::dot(eq_fields_->bc_displacement(p_bdr), normal_(p)) *
417  arma::dot(deform_side_.shape(i)(p), normal_(p)) *
418  JxW_side_(p);
419  }
420  }
421  else if (bc_type == EqFields::bc_type_traction)
422  {
423  for (auto p : this->boundary_points(cell_side) )
424  {
425  auto p_bdr = p.point_bdr( cell_side.cond().element_accessor() );
426  for (unsigned int i=0; i<n_dofs_; i++)
428  arma::dot(deform_side_.shape(i)(p), eq_fields_->bc_traction(p_bdr) + eq_fields_->ref_potential_load(p) * normal_(p)) *
429  JxW_side_(p);
430  }
431  }
432  else if (bc_type == EqFields::bc_type_stress)
433  {
434  for (auto p : this->boundary_points(cell_side) )
435  {
436  auto p_bdr = p.point_bdr( cell_side.cond().element_accessor() );
437  for (unsigned int i=0; i<n_dofs_; i++)
438  // stress is multiplied by inward normal to obtain traction
440  arma::dot(deform_side_.shape(i)(p), -eq_fields_->bc_stress(p_bdr)*normal_(p)
442  * JxW_side_(p);
443  }
444  }
446 
447 
448 // balance_->add_flux_matrix_values(subst_idx, loc_b, side_dof_indices, local_flux_balance_vector);
449 // balance_->add_flux_vec_value(subst_idx, loc_b, local_flux_balance_rhs);
450  // ++loc_b;
451  }
452 
453 
454  /// Assembles between elements of different dimensions.
455  inline void dimjoin_intergral(DHCellAccessor cell_lower_dim, DHCellSide neighb_side) {
456  if (dim == 1) return;
457  ASSERT_EQ(cell_lower_dim.dim(), dim-1).error("Dimension of element mismatch!");
458 
459  unsigned int n_indices = cell_lower_dim.get_dof_indices(dof_indices_);
460  for(unsigned int i=0; i<n_indices; ++i) {
462  }
463 
464  DHCellAccessor cell_higher_dim = eq_data_->dh_->cell_accessor_from_element( neighb_side.element().idx() );
465  n_indices = cell_higher_dim.get_dof_indices(dof_indices_);
466  for(unsigned int i=0; i<n_indices; ++i) {
468  }
469 
470  // Element id's for testing if they belong to local partition.
471  bool own_element_id[2];
472  own_element_id[0] = cell_lower_dim.is_own();
473  own_element_id[1] = cell_higher_dim.is_own();
474 
475  for (unsigned int i=0; i<2*n_dofs_; i++)
476  local_rhs_[i] = 0;
477 
478  // set transmission conditions
479  for (auto p_high : this->coupling_points(neighb_side) )
480  {
481  auto p_low = p_high.lower_dim(cell_lower_dim);
482  arma::vec3 nv = normal_(p_high);
483 
484  for (uint i=0; i<deform_join_.n_dofs_both(); ++i) {
485  uint is_high_i = deform_join_.is_high_dim(i);
486  if (!own_element_id[is_high_i]) continue;
487 
488  arma::vec3 vi = deform_join_.shape(i)(p_high);
489  arma::vec3 vf = deform_join_.shape(i)(p_low);
490 
491  local_rhs_[i] -= eq_fields_->fracture_sigma(p_low) * eq_fields_->cross_section(p_high) *
492  arma::dot(vf-vi, eq_fields_->potential_load(p_high) * nv) * JxW_side_(p_high);
493  }
494  }
495 
497  }
498 
499 
500 
501 private:
502  /// Data objects shared with Elasticity
505 
506  /// Sub field set contains fields used in calculation.
508 
509  unsigned int n_dofs_; ///< Number of dofs
510  unsigned int n_dofs_sub_; ///< Number of dofs (on lower dim element)
511  std::vector<unsigned int> n_dofs_ngh_; ///< Number of dofs on lower and higher dimension element (vector of 2 items)
512 
513  vector<LongIdx> dof_indices_; ///< Vector of global DOF indices
514  vector<LongIdx> side_dof_indices_; ///< 2 items vector of DOF indices in neighbour calculation.
515  vector<PetscScalar> local_rhs_; ///< Auxiliary vector for assemble methods
516 
517  /// Following data members represent Element quantities and FE quantities
530 
531 
532  template < template<IntDim...> class DimAssembly>
533  friend class GenericAssembly;
534 
535 };
536 
537 template <unsigned int dim>
539 {
540 public:
541  typedef typename Elasticity::EqFields EqFields;
543 
544  static constexpr const char * name() { return "OutpuFieldsAssemblyElasticity"; }
545 
546  /// Constructor.
548  : AssemblyBasePatch<dim>(fe_values), eq_fields_(eq_fields), eq_data_(eq_data),
549  normal_( this->side_values().normal_vector() ),
550  ref_vals_side_( this->side_values().ref_vector() ),
551  grad_ref_vals_( this->bulk_values().ref_vector_grad() ),
552  deform_side_( this->side_values().vector_shape() ),
553  grad_deform_( this->bulk_values().grad_vector_shape() ),
554  sym_grad_deform_( this->bulk_values().vector_sym_grad() ),
555  div_deform_( this->bulk_values().vector_divergence() ) {
558  this->used_fields_ += eq_fields_->lame_mu;
561  }
562 
563  /// Destructor.
565 
566  /// Initialize auxiliary vectors and other data members
567  void initialize(ElementCacheMap *element_cache_map) {
568  //this->balance_ = eq_data_->balance_;
569  this->element_cache_map_ = element_cache_map;
570 
571  this->fe_values_->template initialize<dim>(*this->quad_);
572  this->fe_values_->template initialize<dim>(*this->quad_low_);
573 
574  n_dofs_ = this->n_dofs();
575 
582  }
583 
584 
585  /// Assemble integral over element
586  inline void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
587  {
588  if (cell.dim() != dim) return;
589  if (!cell.is_own()) return;
590  DHCellAccessor cell_tensor = cell.cell_with_other_dh(eq_data_->dh_tensor_.get());
591  DHCellAccessor cell_scalar = cell.cell_with_other_dh(eq_data_->dh_scalar_.get());
592 
596 
597  auto p = *( this->bulk_points(element_patch_idx).begin() );
598 
600  double div = 0;
601  for (unsigned int i=0; i<n_dofs_; i++)
602  {
603  stress += eq_fields_->stress_tensor(p,sym_grad_deform_.shape(i)(p))
605  div += div_deform_.shape(i)(p)*output_vec_.get(dof_indices_[i]);
606  }
607 
608  arma::mat33 stress_dev = stress - arma::trace(stress)/3*arma::eye(3,3);
609  double von_mises_stress = sqrt(1.5*arma::dot(stress_dev, stress_dev));
610  double mean_stress = arma::trace(stress) / 3;
612 
613  for (unsigned int i=0; i<3; i++)
614  for (unsigned int j=0; j<3; j++)
615  output_stress_vec_.add( dof_indices_tensor_[i*3+j], stress(i,j) );
616  output_von_mises_stress_vec_.set( dof_indices_scalar_[0], von_mises_stress );
618 
620  }
621 
622 
623  /// Assembles between elements of different dimensions.
624  inline void dimjoin_intergral(DHCellAccessor cell_lower_dim, DHCellSide neighb_side) {
625  if (dim == 1) return;
626  ASSERT_EQ(cell_lower_dim.dim(), dim-1).error("Dimension of element mismatch!");
627 
629  normal_stress_.zeros();
630 
631  DHCellAccessor cell_higher_dim = neighb_side.cell();
632  DHCellAccessor cell_tensor = cell_lower_dim.cell_with_other_dh(eq_data_->dh_tensor_.get());
633  DHCellAccessor cell_scalar = cell_lower_dim.cell_with_other_dh(eq_data_->dh_scalar_.get());
634 
635  dof_indices_ = cell_higher_dim.get_loc_dof_indices();
636  auto p_high = *( this->coupling_points(neighb_side).begin() );
637  auto p_low = p_high.lower_dim(cell_lower_dim);
638 
639  for (unsigned int i=0; i<n_dofs_; i++)
640  {
641  normal_displacement_ -= arma::dot(deform_side_.shape(i)(p_high)*output_vec_.get(dof_indices_[i]), normal_(p_high));
642  arma::mat33 grad = -arma::kron(deform_side_.shape(i)(p_high)*output_vec_.get(dof_indices_[i]), normal_(p_high).t()) / eq_fields_->cross_section(p_low);
643  normal_stress_ += eq_fields_->stress_tensor(p_low, 0.5*(grad+grad.t()));
644  }
645 
648  for (unsigned int i=0; i<3; i++)
649  for (unsigned int j=0; j<3; j++)
653  }
654 
655 
656 
657 private:
658  /// Data objects shared with Elasticity
661 
662  /// Sub field set contains fields used in calculation.
664 
665  unsigned int n_dofs_; ///< Number of dofs
666  LocDofVec dof_indices_; ///< Vector of local DOF indices of vector fields
667  LocDofVec dof_indices_scalar_; ///< Vector of local DOF indices of scalar fields
668  LocDofVec dof_indices_tensor_; ///< Vector of local DOF indices of tensor fields
669 
670  double normal_displacement_; ///< Holds constributions of normal displacement.
671  arma::mat33 normal_stress_; ///< Holds constributions of normal stress.
672 
673  /// Following data members represent Element quantities and FE quantities
681 
682  /// Data vectors of output fields (FieldFE).
689 
690  template < template<IntDim...> class DimAssembly>
691  friend class GenericAssembly;
692 
693 };
694 
695 
696 
697 /**
698  * Container class for assembly of constraint matrix for contact condition.
699  */
700 template <unsigned int dim>
702 {
703 public:
704  typedef typename Elasticity::EqFields EqFields;
705  typedef typename Elasticity::EqData EqData;
706 
707  static constexpr const char * name() { return "ConstraintAssemblyElasticity"; }
708 
709  /// Constructor.
711  : AssemblyBasePatch<dim>(fe_values), eq_fields_(eq_fields), eq_data_(eq_data),
712  JxW_side_( this->side_values().JxW() ),
713  normal_( this->side_values().normal_vector() ),
714  ref_vals_side_( this->side_values().ref_vector() ),
715  deform_side_( this->side_values().vector_shape() ) {
719  }
720 
721  /// Destructor.
723 
724  /// Initialize auxiliary vectors and other data members
725  void initialize(ElementCacheMap *element_cache_map) {
726  this->element_cache_map_ = element_cache_map;
727 
728  this->fe_values_->template initialize<dim>(*this->quad_);
729  this->fe_values_->template initialize<dim>(*this->quad_low_);
730 
731  n_dofs_ = this->n_dofs();
732  dof_indices_.resize(n_dofs_);
733  local_matrix_.resize(n_dofs_*n_dofs_);
734  }
735 
736 
737  /// Assembles between elements of different dimensions.
738  inline void dimjoin_intergral(DHCellAccessor cell_lower_dim, DHCellSide neighb_side) {
739  if (dim == 1) return;
740  if (!cell_lower_dim.is_own()) return;
741 
742  ASSERT_EQ(cell_lower_dim.dim(), dim-1).error("Dimension of element mismatch!");
743 
744  DHCellAccessor cell_higher_dim = eq_data_->dh_->cell_accessor_from_element( neighb_side.element().idx() );
745  cell_higher_dim.get_dof_indices(dof_indices_);
746 
747  for (unsigned int i=0; i<n_dofs_; i++)
748  local_matrix_[i] = 0;
749 
750  // Assemble matrix and vector for contact conditions in the form B*x <= c,
751  // where B*x is the average jump of normal displacements and c is the average cross-section on element.
752  // Positive value means that the fracture closes.
753  double local_vector = 0;
754  for (auto p_high : this->coupling_points(neighb_side) )
755  {
756  auto p_low = p_high.lower_dim(cell_lower_dim);
757  arma::vec3 nv = normal_(p_high);
758 
759  local_vector += (eq_fields_->cross_section(p_low) - eq_fields_->cross_section_min(p_low))*JxW_side_(p_high) / cell_lower_dim.elm().measure() / cell_lower_dim.elm()->n_neighs_vb();
760 
761  for (unsigned int i=0; i<n_dofs_; i++)
762  {
763  local_matrix_[i] += eq_fields_->cross_section(p_high)*arma::dot(deform_side_.shape(i)(p_high), nv)*JxW_side_(p_high) / cell_lower_dim.elm().measure();
764  }
765  }
766 
767  int arow[1] = { eq_data_->constraint_idx[cell_lower_dim.elm_idx()] };
768  MatSetValues(eq_data_->constraint_matrix, 1, arow, n_dofs_, dof_indices_.data(), &(local_matrix_[0]), ADD_VALUES);
769  VecSetValue(eq_data_->constraint_vec, arow[0], local_vector, ADD_VALUES);
770  }
771 
772 
773 
774 private:
775 
776 
777  /// Data objects shared with Elasticity
780 
781  /// Sub field set contains fields used in calculation.
783 
784  unsigned int n_dofs_; ///< Number of dofs
785  vector<LongIdx> dof_indices_; ///< Vector of global DOF indices
786  vector<vector<LongIdx> > side_dof_indices_; ///< 2 items vector of DOF indices in neighbour calculation.
787  vector<PetscScalar> local_matrix_; ///< Auxiliary vector for assemble methods
788 
789  /// Following data members represent Element quantities and FE quantities
794 
795 
796  template < template<IntDim...> class DimAssembly>
797  friend class GenericAssembly;
798 
799 };
800 
801 
802 #endif /* ASSEMBLY_ELASTICITY_HH_ */
803 
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:333
JoinValues< dim > join_values()
Return JoinValues object.
PatchFEValues< 3 > * fe_values_
Common FEValues object over all dimensions.
BulkValues< dim > bulk_values()
Return BulkValues object.
unsigned int n_dofs()
Return BulkValues object.
SideValues< dim > side_values()
Return SideValues object.
Range< BulkPoint > bulk_points(unsigned int element_patch_idx) const
Return BulkPoint range of appropriate dimension.
Quadrature * quad_
Quadrature used in assembling methods.
Quadrature * quad_low_
Quadrature used in assembling methods (dim-1).
Range< CouplingPoint > coupling_points(const DHCellSide &cell_side) const
Return CouplingPoint range of appropriate dimension.
int active_integrals_
Holds mask of active integrals.
Range< BoundaryPoint > boundary_points(const DHCellSide &cell_side) const
Return BoundaryPoint range of appropriate dimension.
ElementCacheMap * element_cache_map_
ElementCacheMap shared with GenericAssembly object.
ElementAccessor< 3 > element_accessor()
EqFields * eq_fields_
Data objects shared with Elasticity.
ConstraintAssemblyElasticity(EqFields *eq_fields, EqData *eq_data, PatchFEValues< 3 > *fe_values)
Constructor.
void dimjoin_intergral(DHCellAccessor cell_lower_dim, DHCellSide neighb_side)
Assembles between elements of different dimensions.
static constexpr const char * name()
vector< vector< LongIdx > > side_dof_indices_
2 items vector of DOF indices in neighbour calculation.
vector< PetscScalar > local_matrix_
Auxiliary vector for assemble methods.
unsigned int n_dofs_
Number of dofs.
FeQ< Scalar > JxW_side_
Following data members represent Element quantities and FE quantities.
vector< LongIdx > dof_indices_
Vector of global DOF indices.
void initialize(ElementCacheMap *element_cache_map)
Initialize auxiliary vectors and other data members.
FieldSet used_fields_
Sub field set contains fields used in calculation.
Cell accessor allow iterate over DOF handler cells.
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 get_dof_indices(std::vector< LongIdx > &indices) const
Fill vector of the global indices of dofs associated to the cell.
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_.
Side accessor allows to iterate over sides of DOF handler cell.
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
ElementAccessor< 3 > element() const
Data of equation parameters.
Definition: elasticity.hh:114
LinSys * ls
Linear algebraic system.
Definition: elasticity.hh:141
std::shared_ptr< DOFHandlerMultiDim > dh_
Objects for distribution of dofs.
Definition: elasticity.hh:135
std::map< LongIdx, LongIdx > constraint_idx
Definition: elasticity.hh:147
Field< 3, FieldValue< 3 >::Scalar > potential_load
Potential of an additional (external) load.
Definition: elasticity.hh:81
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::TensorFixed > > output_stress_ptr
Definition: elasticity.hh:103
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > output_von_mises_stress_ptr
Definition: elasticity.hh:104
Field< 3, FieldValue< 3 >::Scalar > cross_section_min
Definition: elasticity.hh:80
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > output_cross_section_ptr
Definition: elasticity.hh:106
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::VectorFixed > > output_field_ptr
Definition: elasticity.hh:102
BCField< 3, FieldValue< 3 >::Enum > bc_type
Definition: elasticity.hh:68
Field< 3, FieldValue< 3 >::Scalar > lame_lambda
Definition: elasticity.hh:97
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > output_div_ptr
Definition: elasticity.hh:107
BCField< 3, FieldValue< 3 >::VectorFixed > bc_displacement
Definition: elasticity.hh:69
Field< 3, FieldValue< 3 >::TensorFixed > initial_stress
Definition: elasticity.hh:76
BCField< 3, FieldValue< 3 >::VectorFixed > bc_traction
Definition: elasticity.hh:70
Field< 3, FieldValue< 3 >::Scalar > ref_potential_load
Potential of reference external load on boundary. TODO: Switch to BCField when possible.
Definition: elasticity.hh:82
Field< 3, FieldValue< 3 >::VectorFixed > load
Definition: elasticity.hh:72
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > output_mean_stress_ptr
Definition: elasticity.hh:105
arma::mat33 stress_tensor(BulkPoint &p, const arma::mat33 &strain_tensor)
Definition: elasticity.cc:113
Field< 3, FieldValue< 3 >::Scalar > fracture_sigma
Transition parameter for diffusive transfer on fractures.
Definition: elasticity.hh:75
Field< 3, FieldValue< 3 >::Scalar > dirichlet_penalty
Definition: elasticity.hh:98
Field< 3, FieldValue< 3 >::Scalar > cross_section
Pointer to DarcyFlow field cross_section.
Definition: elasticity.hh:79
BCField< 3, FieldValue< 3 >::TensorFixed > bc_stress
Definition: elasticity.hh:71
Field< 3, FieldValue< 3 >::Scalar > lame_mu
Definition: elasticity.hh:96
Data of output parameters.
Definition: elasticity.hh:158
std::shared_ptr< DOFHandlerMultiDim > dh_scalar_
Objects for distribution of dofs.
Definition: elasticity.hh:175
std::shared_ptr< DOFHandlerMultiDim > dh_tensor_
Definition: elasticity.hh:176
double measure() const
Computes the measure of the element.
unsigned int idx() const
We need this method after replacing Region by RegionIdx, and movinf RegionDB instance into particular...
Definition: accessors.hh:215
Directing class of FieldValueCache.
unsigned int n_neighs_vb() const
Return number of neighbours.
Definition: elements.h:65
Compound finite element on dim dimensional simplex.
Definition: fe_system.hh:102
Conforming Lagrangean finite element on dim dimensional simplex.
Definition: fe_p.hh:86
FeQ< ValueType > shape(unsigned int i_shape_fn_idx) const
Container for various descendants of FieldCommonBase.
Definition: field_set.hh:159
Abstract class for the description of a general finite element on a reference simplex in dim dimensio...
Generic class of assemblation.
virtual void rhs_set_values(int nrow, int *rows, double *vals)=0
virtual void mat_set_values(int nrow, int *rows, int ncol, int *cols, double *vals)=0
LocDofVec dof_indices_scalar_
Vector of local DOF indices of scalar fields.
VectorMPI output_vec_
Data vectors of output fields (FieldFE).
unsigned int n_dofs_
Number of dofs.
FieldSet used_fields_
Sub field set contains fields used in calculation.
static constexpr const char * name()
LocDofVec dof_indices_
Vector of local DOF indices of vector fields.
LocDofVec dof_indices_tensor_
Vector of local DOF indices of tensor fields.
EqFields * eq_fields_
Data objects shared with Elasticity.
arma::mat33 normal_stress_
Holds constributions of normal stress.
void initialize(ElementCacheMap *element_cache_map)
Initialize auxiliary vectors and other data members.
void dimjoin_intergral(DHCellAccessor cell_lower_dim, DHCellSide neighb_side)
Assembles between elements of different dimensions.
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
Assemble integral over element.
double normal_displacement_
Holds constributions of normal displacement.
ElQ< Vector > normal_
Following data members represent Element quantities and FE quantities.
OutpuFieldsAssemblyElasticity(EqFields *eq_fields, EqData *eq_data, PatchFEValues< 3 > *fe_values)
Constructor.
Elasticity::OutputEqData EqData
vector< LongIdx > side_dof_indices_
2 items vector of DOF indices in neighbour calculation.
void dimjoin_intergral(DHCellAccessor cell_lower_dim, DHCellSide neighb_side)
Assembles between elements of different dimensions.
vector< LongIdx > dof_indices_
Vector of global DOF indices.
FeQArray< Vector > ref_vals_
FeQArray< Vector > deform_
EqFields * eq_fields_
Data objects shared with Elasticity.
Elasticity::EqFields EqFields
FeQArray< Scalar > div_deform_
void initialize(ElementCacheMap *element_cache_map)
Initialize auxiliary vectors and other data members.
FeQ< Scalar > JxW_
Following data members represent Element quantities and FE quantities.
std::vector< unsigned int > n_dofs_ngh_
Number of dofs on lower and higher dimension element (vector of 2 items)
Elasticity::EqData EqData
FeQArray< Tensor > grad_ref_vals_
FeQArray< Tensor > grad_deform_
RhsAssemblyElasticity(EqFields *eq_fields, EqData *eq_data, PatchFEValues< 3 > *fe_values)
Constructor.
unsigned int n_dofs_sub_
Number of dofs (on lower dim element)
vector< PetscScalar > local_rhs_
Auxiliary vector for assemble methods.
unsigned int n_dofs_
Number of dofs.
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
Assemble integral over element.
static constexpr const char * name()
void boundary_side_integral(DHCellSide cell_side)
Assembles boundary integral.
FeQArray< Tensor > grad_ref_vals_side_
FieldSet used_fields_
Sub field set contains fields used in calculation.
FeQArray< Vector > ref_vals_side_
FeQArray< Vector > deform_side_
FeQJoin< Vector > deform_join_
Boundary cond() const
void dimjoin_intergral(DHCellAccessor cell_lower_dim, DHCellSide neighb_side)
Assembles between elements of different dimensions.
arma::mat33 mat_t(const arma::mat33 &m, const arma::vec3 &n)
FieldSet used_fields_
Sub field set contains fields used in calculation.
FeQArray< Tensor > grad_ref_vals_side_
vector< LongIdx > side_dof_indices_
vector of DOF indices in neighbour calculation.
static constexpr const char * name()
vector< PetscScalar > local_matrix_
Auxiliary vector for assemble methods.
vector< LongIdx > dof_indices_
Vector of global DOF indices.
EqFields * eq_fields_
Data objects shared with Elasticity.
unsigned int n_dofs_sub_
Number of dofs (on lower dim element)
FeQ< Scalar > JxW_
Following data members represent Element quantities and FE quantities.
unsigned int n_dofs_
Number of dofs.
StiffnessAssemblyElasticity(EqFields *eq_fields, EqData *eq_data, PatchFEValues< 3 > *fe_values)
Constructor.
std::vector< unsigned int > n_dofs_ngh_
Number of dofs on lower and higher dimension element (vector of 2 items)
void initialize(ElementCacheMap *element_cache_map)
Initialize auxiliary vectors and other data members.
void cell_integral(DHCellAccessor cell, unsigned int element_patch_idx)
Assemble integral over element.
void boundary_side_integral(DHCellSide cell_side)
Assembles boundary integral.
double get(unsigned int pos) const
Return value on given position.
Definition: vector_mpi.hh:105
void set(unsigned int pos, double val)
Set value on given position.
Definition: vector_mpi.hh:111
void add(unsigned int pos, double val)
Add value to item on given position.
Definition: vector_mpi.hh:125
FEM for linear elasticity.
Definitions of basic Lagrangean finite elements with polynomial shape functions.
Class FEValues calculates finite element data on the actual cells such as shape function values,...
@ FEVector
@ coupling
@ boundary
@ bulk
arma::Col< IntIdx > LocDofVec
Definition: index_types.hh:28
unsigned int uint
unsigned int IntDim
A dimension index type.
Definition: mixed.hh:19
Definitions of particular quadrature rules on simplices.