Flow123d  JS_constraints-e651b99
op_function.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 op_function.hh
15  * @brief Store finite element reinit functions.
16  * @author David Flanderka
17  */
18 
19 #ifndef OP_FUNCTION_HH_
20 #define OP_FUNCTION_HH_
21 
22 #include "fem/patch_op.hh"
23 #include "fem/patch_fe_values.hh"
24 
25 
26 
27 namespace Op {
28 
29 /// Class used as template type for type resolution Bulk / Side
30 class BulkDomain {
31 public:
32  static ElemDomain domain() {
34  }
35 
36  static inline constexpr uint n_nodes(uint dim) {
37  return dim+1;
38  }
39 
40  /// Return number of mesh entities (in this case elements) on patch
42  return ppv.elem_dim_list_->size();
43  }
44 
45  /// Return i_n-th node of i_elm-th element stored in PatchPointValues::elem_dim_list_
46  static inline NodeAccessor<3> node(PatchPointValues<3> &ppv, unsigned int i_elm, unsigned int i_n) {
47  return (*ppv.elem_dim_list_)[i_elm].node(i_n);
48  }
49 };
50 
51 /// Class used as template type for type resolution Bulk / Side
52 class SideDomain {
53 public:
54  static ElemDomain domain() {
56  }
57 
58  static inline constexpr uint n_nodes(uint dim) {
59  return dim;
60  }
61 
62  /// Return number of mesh entities (in this case sides) on patch
64  return ppv.side_list_.size();
65  }
66 
67  /// Return i_n-th node of i_elm-th side stored in PatchPointValues::side_list_
68  static inline NodeAccessor<3> node(PatchPointValues<3> &ppv, unsigned int i_elm, unsigned int i_n) {
69  return ppv.side_list_[i_elm].node(i_n);
70  }
71 };
72 
73 
74 /**
75  * Evaluates node coordinates on Bulk (Element) / Side
76  *
77  * Template parameters:
78  * dim Dimension of operation
79  * ElDomain Target domain - data are evaluated on Bulk / Side domain
80  * Domain Source domain - operation is called from Bulk / Side domain
81  * spacedim Dimension of the solved task
82  */
83 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
84 class Coords : public PatchOp<spacedim> {
85 public:
86  /// Constructor
88  : PatchOp<spacedim>(dim, pfev, quad, {spacedim, Domain::n_nodes(dim)}) {
89  this->domain_ = Domain::domain();
90  }
91 
92  void eval() override {
94  uint n_elems = Domain::n_mesh_entities(ppv); // number of elements or sides on patch
95  this->allocate_result( n_elems, this->patch_arena() );
96  auto result = this->result_matrix();
97 
98  for (uint i_elm=0; i_elm<n_elems; ++i_elm)
99  for (uint i_col=0; i_col<Domain::n_nodes(dim); ++i_col)
100  for (uint i_row=0; i_row<spacedim; ++i_row) {
101  result(i_row, i_col)(i_elm) = ( *Domain::node(ppv, i_elm, i_col) )(i_row);
102  }
103  }
104 
105 };
106 
107 /// Evaluates Jacobians on Bulk (Element) / Side
108 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
109 class Jac : public PatchOp<spacedim> {
110 public:
111  /// Constructor
113  : PatchOp<spacedim>(dim, pfev, quad, {spacedim, Domain::n_nodes(dim)-1})
114  {
115  this->domain_ = Domain::domain();
116  this->input_ops_.push_back( pfev.template get< Op::Coords<dim, Domain, spacedim>, dim >(quad) );
117  }
118 
119  void eval() override {
120  auto jac_value = this->result_matrix();
121  auto coords_value = this->input_ops(0)->result_matrix();
122  for (unsigned int i=0; i<spacedim; i++)
123  for (unsigned int j=0; j<Domain::n_nodes(dim)-1; j++)
124  jac_value(i,j) = coords_value(i,j+1) - coords_value(i,0);
125  }
126 };
127 
128 /// Evaluates Jacobian determinants on Bulk (Element) / Side
129 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
130 class JacDet : public PatchOp<spacedim> {
131 public:
132  /// Constructor
134  : PatchOp<spacedim>(dim, pfev, quad, {1})
135  {
136  this->domain_ = Domain::domain();
137  this->input_ops_.push_back( pfev.template get< Op::Jac<dim, Domain, spacedim>, dim >(quad) );
138  }
139 
140  void eval() override {
141  auto jac_det_value = this->result_matrix();
142  auto jac_value = this->input_ops(0)->result_matrix();
143  jac_det_value(0) = eigen_arena_tools::determinant<spacedim, Domain::n_nodes(dim)-1>(jac_value).abs();
144  }
145 };
146 
147 /// Template specialization of previous: dim=1, domain=Side
148 template<>
149 class JacDet<1, Op::SideDomain, 3> : public PatchOp<3> {
150 public:
151  /// Constructor
152  JacDet(PatchFEValues<3> &pfev, const Quadrature *quad)
153  : PatchOp<3>(1, pfev, quad, {1})
154  {
156  }
157 
158  void eval() override {
159  PatchPointValues<3> &ppv = this->ppv();
160  uint n_sides = ppv.n_mesh_items();
161  this->allocate_result( n_sides, this->patch_arena() );
162  auto jac_det_value = this->result_matrix();
163  for (uint i=0;i<n_sides; ++i) {
164  jac_det_value(0,0)(i) = 1.0;
165  }
166  }
167 };
168 
169 /**
170  * Evaluates Inverse Jacobians on Bulk (Element) / Side
171  * ElDomain (target) is always Bulk
172  */
173 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
174 class InvJac : public PatchOp<spacedim> {
175 public:
176  /// Constructor
178  : PatchOp<spacedim>(dim, pfev, quad, {dim, spacedim})
179  {
180  this->domain_ = Domain::domain();
181  this->input_ops_.push_back( pfev.template get< Op::Jac<dim, Domain, spacedim>, dim >(quad) );
182  }
183 
184  void eval() override {
185  auto inv_jac_value = this->result_matrix();
186  auto jac_value = this->input_ops(0)->result_matrix();
187  inv_jac_value = eigen_arena_tools::inverse<spacedim, dim>(jac_value);
188  }
189 };
190 
191 
192 /**
193  * Holds common functionality of patch operations.
194  */
195 template<unsigned int spacedim = 3>
196 class FuncHelper {
197 public:
198  /**
199  * Copy reduced data from 'source' to 'target' ArenaVec. Mapping of reduced data is given by 'ppv' data.
200  */
202  for (uint i_el=0; i_el<ppv.n_mesh_items(); ++i_el) {
203  target( i_el ) = source( ppv.int_table_(patch_elem_on_domain)(i_el) );
204  }
205  }
206 
207  /**
208  * Copy ref_side_on_quads data from 'source' to 'target' ArenaVec. Mapping of copied data is given by 'ppv' data.
209  */
210  static void copy_ref_side_on_quads_data(PatchOp<spacedim> &op, unsigned int i_comp,
211  Eigen::Map<Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic>> &source,
212  Eigen::Map<Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic>> &target) {
213  PatchPointValues<spacedim> &ppv = op.ppv();
214  uint n_dofs = op.n_dofs();
215  uint n_sides = ppv.n_mesh_items(); // number of sides on patch
216  uint n_patch_points = n_sides * op.quad_size(); // number of points on patch
217  uint n_comp = op.shape()[0]; // number of components of result
218 
219  for (uint i_dof=0; i_dof<n_dofs; ++i_dof) {
220  for (uint i_pt=0; i_pt<n_patch_points; ++i_pt)
221  target(i_comp,i_dof)(i_pt) = source(ppv.int_table_(ref_side_on_quads)(i_pt),n_comp*i_dof+i_comp)(i_pt / n_sides);
222  }
223  }
224 
225  /**
226  * Copy ref_side_on_sides vector data from 'source' to 'target' ArenaVec. Mapping of copied data is given by 'ppv' data.
227  */
228  static void copy_ref_side_on_sides_vector_data(PatchOp<spacedim> &op, unsigned int dim,
229  Eigen::Map<Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic>> &source,
230  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> &target)
231  {
232  PatchPointValues<spacedim> &ppv = op.ppv();
233  uint n_sides = ppv.n_mesh_items();
234  for (uint i_dof=0; i_dof<op.n_dofs(); ++i_dof) {
235  for (uint i_pt=0; i_pt<op.quad_size(); ++i_pt) {
236  uint i_begin = i_pt * n_sides;
237  for (uint i_sd=0; i_sd<n_sides; ++i_sd) {
238  for (uint i_c=0; i_c<dim; ++i_c) {
239  target(i_c, i_dof)(i_begin + i_sd) = source(ppv.int_table_(ref_side_on_sides)(i_sd), i_dof*dim+i_c)(i_pt);
240  }
241  }
242  }
243  }
244  }
245 
246  /**
247  * Copy ref_side_on_sides tensor data from 'source' to 'target' ArenaVec. Mapping of copied data is given by 'ppv' data.
248  */
249  static void copy_ref_side_on_sides_tensor_data(PatchOp<spacedim> &op, unsigned int i_dof, unsigned int shape_m, unsigned int shape_n,
250  Eigen::Map<Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic>> &source,
251  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> &target)
252  {
253  PatchPointValues<spacedim> &ppv = op.ppv();
254  uint n_sides = ppv.n_mesh_items();
255  uint n_points = source(0).data_size(); // number of ref points
256 
257  for (uint i_pt=0; i_pt<n_points; ++i_pt) {
258  uint i_begin = i_pt * n_sides;
259  for (uint i_sd=0; i_sd<n_sides; ++i_sd) {
260  for (uint i_dim=0; i_dim<shape_m; ++i_dim) {
261  for (uint i_c=0; i_c<shape_n; ++i_c) {
262  target(i_dim, i_c)(i_begin + i_sd) = source(ppv.int_table_(ref_side_on_sides)(i_sd)*shape_m+i_dim, shape_n*i_dof+i_c)(i_pt);
263  }
264  }
265  }
266  }
267  }
268 
269  /**
270  * Copy patch_elem_on_domain data from 'source' to 'target' ArenaVec. Mapping of copied data is given by 'ppv' data.
271  */
272  static void copy_patch_elem_on_domain_data(PatchOp<spacedim> &op, unsigned int dim,
273  Eigen::Map<Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic>> &source,
274  Eigen::Map<Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic>> &target) {
275  PatchPointValues<spacedim> &ppv = op.ppv();
276  uint n_elems = ppv.n_mesh_items(); // number of elements on patch
277  uint n_elem_points = op.quad_size(); // number of points on element
278 
279  for (uint i_c=0; i_c<spacedim*dim; ++i_c) {
280  target(i_c) = ArenaVec<double>( n_elems*n_elem_points, op.patch_arena() );
281  for (uint i_el=0; i_el<n_elems; ++i_el)
282  for (uint i_pt=0; i_pt<n_elem_points; ++i_pt) {
283  target(i_c)( i_pt*n_elems + i_el ) = source(i_c)( ppv.int_table_(patch_elem_on_domain)(i_el) );
284  }
285  }
286  }
287 private:
288  /// Forbidden constructor
290 };
291 
292 
293 /**
294  * Reference data of PtCoords operation
295  *
296  * See note for PtCoords operation bellow.
297  * TODO need specializations for SideDomain<dim> and SideDomain<1>
298  */
299 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
300 class RefBaryCoords : public PatchOp<spacedim> {
301 public:
302  /// Constructor
304  : PatchOp<spacedim>(dim, pfev, quad, {dim+1})
305  {
306  this->domain_ = Domain::domain();
307  double n_points = quad->size();
308  this->allocate_result(n_points, pfev.asm_arena());
309  for (uint i_p=0; i_p<n_points; ++i_p) {
310  auto ref_bar_coords = RefElement<dim>::local_to_bary(quad->point<dim>(i_p));
311  for (uint i_c=0; i_c<dim+1; ++i_c)
312  this->result_(i_c)(i_p) = ref_bar_coords[i_c];
313  }
314  }
315 
316  void eval() override {}
317 };
318 
319 /**
320  * Evaluates coordinates of quadrature points
321  *
322  * Important note !!!
323  * Usage of this operation is currently in L2 error calculation in DarcyFlow output.
324  * It should not be used by any other operation. It should be unified with Field Coords in future.
325  */
326 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
327 class PtCoords : public PatchOp<spacedim> {
328 public:
329  /// Constructor
331  : PatchOp<spacedim>(dim, pfev, quad, {spacedim})
332  {
333  this->domain_ = Domain::domain();
334  this->input_ops_.push_back( pfev.template get< Op::Coords<dim, Domain, spacedim>, dim >( pfev.element_quad(dim) ) );
335  this->input_ops_.push_back( pfev.template get< Op::RefBaryCoords<dim, Domain, spacedim>, dim >(quad) );
336  }
337 
338  void eval() override {
339  auto coords_vec_elem = this->input_ops(0)->result_matrix(); // bulk: spacedim x (dim+1), side: spacedim x dim
340  auto ref_bary_vec = this->input_ops(1)->result_matrix(); // bulk: dim+1, side: dim
341 
342  // Copy coords vector of elements registered on patch, convert to ovec
344  uint n_elems = ppv.n_mesh_items();
345  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> coords_vec(spacedim, Domain::n_nodes(dim));
346  Eigen::Matrix<ArenaOVec<double>, spacedim, Domain::n_nodes(dim)> coords_ovec;
347  for (uint i=0; i<spacedim*Domain::n_nodes(dim); ++i) {
348  coords_vec(i) = ArenaVec<double>( n_elems, this->patch_arena() );
349  FuncHelper<spacedim>::fill_reduce_element_data_vec( ppv, coords_vec_elem(i), coords_vec(i) );
350  coords_ovec(i) = ArenaOVec<double>( coords_vec(i) );
351  }
352 
353  // Convert ref_bary_vec to ovec
354  Eigen::Vector<ArenaOVec<double>, Eigen::Dynamic> ref_bary_ovec(Domain::n_nodes(dim));
355  for (uint i=0; i<Domain::n_nodes(dim); ++i) {
356  ref_bary_ovec(i) = ArenaOVec<double>( ref_bary_vec(i) );
357  }
358 
359  auto result_vec = this->result_matrix();
360  Eigen::Vector<ArenaOVec<double>, Eigen::Dynamic> result_ovec = coords_ovec * ref_bary_ovec;
361  for (uint i=0; i<spacedim; ++i) {
362  result_vec(i) = result_ovec(i).get_vec();
363  }
364  }
365 };
366 
367 /**
368  * Fixed operation points weights
369  * ElDomain (target) is equivalent with Domain (source)
370  */
371 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
372 class Weights : public PatchOp<spacedim> {
373 public:
374  /// Constructor
376  : PatchOp<spacedim>(dim, pfev, quad, {1})
377  {
378  this->domain_ = Domain::domain();
379  // create result vector of weights operation in assembly arena
380  const std::vector<double> &point_weights_vec = quad->get_weights();
381  this->allocate_result(point_weights_vec.size(), pfev.asm_arena());
382  for (uint i=0; i<point_weights_vec.size(); ++i)
383  this->result_(0)(i) = point_weights_vec[i];
384  }
385 
386  void eval() override {}
387 };
388 
389 
390 /**
391  * Evaluates JxW on quadrature points
392  */
393 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
394 class JxW : public PatchOp<spacedim> {
395 public:
396  /// Constructor
398  : PatchOp<spacedim>(dim, pfev, quad, {1})
399  {
400  this->domain_ = Domain::domain();
401  this->input_ops_.push_back( pfev.template get< Op::Weights<dim, Domain, spacedim>, dim >(quad) );
402  this->input_ops_.push_back( pfev.template get< Op::JacDet<dim, Domain, spacedim>, dim >(pfev.element_quad(dim)) );
403  }
404 
405  void eval() override {
406  auto weights_value = this->input_ops(0)->result_matrix();
407  auto jac_det_value_long = this->input_ops(1)->result_matrix();
408 
409  // Copy InvJac vector of elements registered on patch
411  uint n_elems = ppv.n_mesh_items();
412  ArenaVec<double> jac_det_value( n_elems, this->patch_arena() );
413  FuncHelper<spacedim>::fill_reduce_element_data_vec(ppv, jac_det_value_long( 0 ), jac_det_value);
414 
415  ArenaOVec<double> weights_ovec( weights_value(0,0) );
416  ArenaOVec<double> jac_det_ovec( jac_det_value );
417  ArenaOVec<double> jxw_ovec = jac_det_ovec * weights_ovec;
418  this->result_(0) = jxw_ovec.get_vec();
419  }
420 };
421 
422 template<unsigned int dim, unsigned int spacedim>
423 class JxW<dim, Op::SideDomain, spacedim> : public PatchOp<spacedim> {
424 public:
425  /// Constructor
427  : PatchOp<spacedim>(dim, pfev, quad, {1})
428  {
430  this->input_ops_.push_back( pfev.template get< Op::Weights<dim, Op::SideDomain, spacedim>, dim >(quad) );
431  this->input_ops_.push_back( pfev.template get< Op::JacDet<dim, Op::SideDomain, spacedim>, dim >(pfev.element_quad(dim)) );
432  }
433 
434  void eval() override {
435  auto weights_value = this->input_ops(0)->result_matrix();
436  auto jac_det_value = this->input_ops(1)->result_matrix();
437  ArenaOVec<double> weights_ovec( weights_value(0,0) );
438  ArenaOVec<double> jac_det_ovec( jac_det_value(0,0) );
439  ArenaOVec<double> jxw_ovec = jac_det_ovec * weights_ovec;
440  this->result_(0) = jxw_ovec.get_vec();
441  }
442 };
443 
444 /// Evaluates normal vector on side quadrature points
445 template<unsigned int dim, unsigned int spacedim = 3>
446 class NormalVec : public PatchOp<spacedim> {
447 public:
448  /// Constructor
450  : PatchOp<spacedim>(dim, pfev, quad, {spacedim})
451  {
453  this->input_ops_.push_back( pfev.template get< Op::InvJac<dim, Op::BulkDomain, spacedim>, dim >(quad) );
454  }
455 
456  void eval() override {
458  auto normal_value = this->result_matrix();
459  auto inv_jac_value_elem = this->input_ops(0)->result_matrix(); // returns vector of inverse jacobians of all elements registered on patch
460 
461  // Copy InvJac vector of sides registered on patch
462  uint n_sides = ppv.n_mesh_items();
463  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> inv_jac_value(dim, spacedim);
464  for (uint i=0; i<dim*spacedim; ++i) {
465  inv_jac_value(i) = ArenaVec<double>( n_sides, this->patch_arena() );
466  }
467  for (uint i_c=0; i_c<dim*spacedim; ++i_c) {
468  FuncHelper<spacedim>::fill_reduce_element_data_vec( ppv, inv_jac_value_elem(i_c), inv_jac_value(i_c) );
469  }
470 
471  normal_value = inv_jac_value.transpose() * RefElement<dim>::normal_vector_array( ppv.int_table_(ref_side_on_sides) );
472 
473  ArenaVec<double> norm_vec( n_sides, this->patch_arena() );
474  Eigen::VectorXd A(3);
475  for (uint i=0; i<normal_value(0).data_size(); ++i) {
476  A(0) = normal_value(0)(i);
477  A(1) = normal_value(1)(i);
478  A(2) = normal_value(2)(i);
479  norm_vec(i) = A.norm();
480  }
481 
482  for (uint i=0; i<spacedim; ++i) {
483  normal_value(i) = normal_value(i) / norm_vec;
484  }
485  }
486 };
487 
488 /// Fixed operation of scalar shape reference values
489 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
490 class RefScalar : public PatchOp<spacedim> {
491 public:
492  /// Constructor
493  RefScalar(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe)
494  : PatchOp<spacedim>(dim, pfev, quad, {1}, fe->n_dofs())
495  {
496  this->domain_ = Domain::domain();
497  uint n_points = quad->size();
498 
499  this->allocate_result(n_points, pfev.asm_arena());
500  auto ref_scalar_value = this->result_matrix();
501  for (unsigned int i_p = 0; i_p < n_points; i_p++)
502  for (unsigned int i_dof = 0; i_dof < this->n_dofs_; i_dof++)
503  ref_scalar_value(i_dof)(i_p) = fe->shape_value(i_dof, quad->point<dim>(i_p));
504  }
505 
506  void eval() override {}
507 };
508 
509 /// Template specialization of previous: Domain=SideDomain
510 template<unsigned int dim, unsigned int spacedim>
511 class RefScalar<dim, Op::SideDomain, spacedim> : public PatchOp<spacedim> {
512 public:
513  /// Constructor
514  RefScalar(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe)
515  : PatchOp<spacedim>(dim, pfev, quad, {dim+1}, fe->n_dofs())
516  {
518  uint n_points = quad->size();
519 
520  this->allocate_result(n_points, pfev.asm_arena());
521  auto ref_scalar_value = this->result_matrix();
522  for (unsigned int s=0; s<dim+1; ++s) {
523  Quadrature side_q = quad->make_from_side<dim>(s);
524  for (unsigned int i_p = 0; i_p < n_points; i_p++)
525  for (unsigned int i_dof = 0; i_dof < this->n_dofs_; i_dof++)
526  ref_scalar_value(s, i_dof)(i_p) = fe->shape_value(i_dof, side_q.point<dim>(i_p));
527  }
528  }
529 
530  void eval() override {}
531 };
532 
533 /// Fixed operation of vector shape reference values
534 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
535 class RefVector : public PatchOp<spacedim> {
536 public:
537  /// Constructor
538  RefVector(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe)
539  : PatchOp<spacedim>(dim, pfev, quad, {fe->n_components()}, fe->n_dofs())
540  {
541  this->domain_ = Domain::domain();
542  uint n_points = quad->size();
543 
544  this->allocate_result(n_points, pfev.asm_arena());
545  auto ref_vector_value = this->result_matrix();
546 
547  for (uint i_dof=0; i_dof<this->n_dofs_; ++i_dof)
548  for (uint i_p=0; i_p<n_points; ++i_p)
549  for (uint c=0; c<fe->n_components(); ++c)
550  ref_vector_value(c, i_dof)(i_p) = fe->shape_value(i_dof, quad->point<dim>(i_p), c);
551  }
552 
553  void eval() override {}
554 };
555 
556 /// Template specialization of previous: Domain=SideDomain
557 template<unsigned int dim, unsigned int spacedim>
558 class RefVector<dim, Op::SideDomain, spacedim> : public PatchOp<spacedim> {
559 public:
560  /// Constructor
561  RefVector(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe)
562  : PatchOp<spacedim>(dim, pfev, quad, {dim+1, fe->n_components()}, fe->n_dofs())
563  {
565  uint n_points = quad->size();
566 
567  this->allocate_result(n_points, pfev.asm_arena());
568  auto ref_vector_value = this->result_matrix();
569 
570  for (unsigned int s=0; s<dim+1; ++s) {
571  Quadrature side_q = quad->make_from_side<dim>(s);
572  for (unsigned int i_p = 0; i_p < n_points; i_p++)
573  for (unsigned int i_dof = 0; i_dof < this->n_dofs_; i_dof++)
574  for (uint c=0; c<fe->n_components(); ++c)
575  ref_vector_value(s,fe->n_components()*i_dof+c)(i_p) = fe->shape_value(i_dof, side_q.point<dim>(i_p), c);
576  }
577  }
578 
579  void eval() override {}
580 };
581 
582 /// Fixed operation of gradient scalar reference values
583 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
584 class RefGradScalar : public PatchOp<spacedim> {
585 public:
586  /// Constructor
587  RefGradScalar(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe)
588  : PatchOp<spacedim>(dim, pfev, quad, {dim, 1}, fe->n_dofs())
589  {
590  this->domain_ = Domain::domain();
591  uint n_points = quad->size();
592 
593  this->allocate_result(n_points, pfev.asm_arena());
594  auto ref_scalar_value = this->result_matrix();
595  for (uint i_row=0; i_row<ref_scalar_value.rows(); ++i_row)
596  for (uint i_dof=0; i_dof<this->n_dofs_; ++i_dof)
597  for (uint i_p=0; i_p<n_points; ++i_p)
598  ref_scalar_value(i_row, i_dof)(i_p) = fe->shape_grad(i_dof, quad->point<dim>(i_p))[i_row];
599  }
600 
601  void eval() override {}
602 };
603 
604 /// Template specialization of previous: Domain=SideDomain
605 template<unsigned int dim, unsigned int spacedim>
606 class RefGradScalar<dim, Op::SideDomain, spacedim> : public PatchOp<spacedim> {
607 public:
608  /// Constructor
609  RefGradScalar(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe)
610  : PatchOp<spacedim>(dim, pfev, quad, {dim+1, dim}, fe->n_dofs())
611  {
613  uint n_points = quad->size();
614 
615  this->allocate_result(n_points, pfev.asm_arena());
616  auto ref_scalar_value = this->result_matrix();
617  for (unsigned int s=0; s<dim+1; ++s) {
618  Quadrature side_q = quad->make_from_side<dim>(s);
619  for (uint i_dof=0; i_dof<this->n_dofs_; ++i_dof)
620  for (uint i_p=0; i_p<n_points; ++i_p)
621  for (uint c=0; c<dim; ++c)
622  ref_scalar_value(s,dim*i_dof+c)(i_p) = fe->shape_grad(i_dof, side_q.point<dim>(i_p))[c];
623  }
624  }
625 
626  void eval() override {}
627 };
628 
629 /// Fixed operation of gradient scalar reference values
630 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
631 class RefGradVector : public PatchOp<spacedim> {
632 public:
633  /// Constructor
634  RefGradVector(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe)
635  : PatchOp<spacedim>(dim, pfev, quad, {dim, fe->n_components()}, fe->n_dofs())
636  {
637  this->domain_ = Domain::domain();
638  uint n_points = quad->size();
639  uint n_comp = fe->n_components();
640 
641  this->allocate_result(n_points, pfev.asm_arena());
642  auto ref_vector_value = this->result_matrix();
643  for (uint i_c=0; i_c<n_comp; ++i_c) {
644  for (uint i_dim=0; i_dim<dim; ++i_dim)
645  for (uint i_dof=0; i_dof<this->n_dofs_; ++i_dof)
646  for (uint i_p=0; i_p<n_points; ++i_p)
647  ref_vector_value(i_dim,n_comp*i_dof+i_c)(i_p) = fe->shape_grad(i_dof, quad->point<dim>(i_p), i_c)[i_dim];
648  }
649  }
650 
651  void eval() override {}
652 };
653 
654 /// Template specialization of previous: Domain=SideDomain
655 template<unsigned int dim, unsigned int spacedim>
656 class RefGradVector<dim, Op::SideDomain, spacedim> : public PatchOp<spacedim> {
657 public:
658  /// Constructor
659  RefGradVector(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe)
660  : PatchOp<spacedim>(dim, pfev, quad, {(dim+1)*dim, fe->n_components()}, fe->n_dofs())
661  {
663  uint n_points = quad->size();
664  uint n_sides = dim+1;
665  uint n_comp = fe->n_components();
666 
667  this->allocate_result(n_points, pfev.asm_arena());
668  auto ref_vector_value = this->result_matrix();
669  for (uint i_sd=0; i_sd<n_sides; ++i_sd) {
670  Quadrature side_q = quad->make_from_side<dim>(i_sd);
671  for (uint i_c=0; i_c<n_comp; ++i_c)
672  for (uint i_dim=0; i_dim<dim; ++i_dim)
673  for (uint i_dof=0; i_dof<this->n_dofs_; ++i_dof)
674  for (uint i_p=0; i_p<n_points; ++i_p)
675  ref_vector_value(i_sd*dim+i_dim, n_comp*i_dof+i_c)(i_p) = fe->shape_grad(i_dof, side_q.point<dim>(i_p), i_c)[i_dim];
676  }
677  }
678 
679  void eval() override {}
680 };
681 
682 /// Evaluates scalar shape values
683 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
684 class ScalarShape : public PatchOp<spacedim> {
685 public:
686  /// Constructor
687  ScalarShape(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe)
688  : PatchOp<spacedim>(dim, pfev, quad, {1}, fe->n_dofs())
689  {
690  ASSERT_EQ(fe->fe_type(), FEType::FEScalar).error("Type of FiniteElement of scalar_shape must be FEScalar!\n");
691  this->domain_ = Domain::domain();
692  this->input_ops_.push_back( pfev.template get< Op::RefScalar<dim, Domain, spacedim>, dim >(quad, fe) );
693  }
694 
695  void eval() override {
696  auto ref_vec = this->input_ops(0)->result_matrix();
697  auto result_vec = this->result_matrix();
698 
699  uint n_dofs = this->n_dofs();
700  uint n_elem = this->ppv().n_mesh_items();
701 
702  ArenaVec<double> elem_vec(n_elem, this->patch_arena());
703  for (uint i=0; i<n_elem; ++i) {
704  elem_vec(i) = 1.0;
705  }
706  ArenaOVec<double> elem_ovec(elem_vec);
707 
708  Eigen::Vector<ArenaOVec<double>, Eigen::Dynamic> ref_ovec(n_dofs);
709  for (uint i=0; i<n_dofs; ++i) {
710  ref_ovec(i) = ArenaOVec<double>( ref_vec(i) );
711  }
712 
713  Eigen::Vector<ArenaOVec<double>, Eigen::Dynamic> result_ovec = elem_ovec * ref_ovec;
714  for (uint i=0; i<n_dofs; ++i) {
715  result_vec(i) = result_ovec(i).get_vec();
716  }
717  }
718 };
719 
720 /// Template specialization of previous: Domain=SideDomain
721 template<unsigned int dim, unsigned int spacedim>
722 class ScalarShape<dim, Op::SideDomain, spacedim> : public PatchOp<spacedim> {
723 public:
724  /// Constructor
725  ScalarShape(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe)
726  : PatchOp<spacedim>(dim, pfev, quad, {1}, fe->n_dofs())
727  {
728  ASSERT_EQ(fe->fe_type(), FEType::FEScalar).error("Type of FiniteElement of scalar_shape must be FEScalar!\n");
730  this->input_ops_.push_back( pfev.template get< Op::RefScalar<dim, Op::SideDomain, spacedim>, dim >(quad, fe) );
731  }
732 
733  void eval() override {
734  uint n_patch_points = this->ppv().n_mesh_items() * this->quad_size(); // number of points on patch
735  this->allocate_result(n_patch_points, this->patch_arena());
736 
737  auto ref_vec = this->input_ops(0)->result_matrix();
738  auto result_vec = this->result_matrix();
739 
740  FuncHelper<spacedim>::copy_ref_side_on_quads_data(*this, 0, ref_vec, result_vec);
741  }
742 };
743 
744 /// Evaluates vector values (FEType == FEVector)
745 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
746 class VectorShape : public PatchOp<spacedim> {
747 public:
748  /// Constructor
749  VectorShape(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe, PatchOp<spacedim> &dispatch_op)
750  : PatchOp<spacedim>(dim, pfev, quad, {spacedim}, fe->n_dofs()), dispatch_op_(dispatch_op)
751  {
752  this->domain_ = Domain::domain();
753  this->input_ops_.push_back( pfev.template get< Op::RefVector<dim, Domain, spacedim>, dim >(quad, fe) );
754  }
755 
756  void eval() override {
757  auto ref_shape_vec = this->input_ops(0)->result_matrix();
758  auto result_vec = dispatch_op_.result_matrix();
759 
760  uint n_dofs = this->n_dofs();
761  uint n_elem = this->ppv().n_mesh_items();
762 
763  ArenaVec<double> elem_vec(n_elem, this->patch_arena());
764  for (uint i=0; i<n_elem; ++i) {
765  elem_vec(i) = 1.0;
766  }
767  ArenaOVec<double> elem_ovec(elem_vec);
768 
769  Eigen::Matrix<ArenaOVec<double>, Eigen::Dynamic, Eigen::Dynamic> ref_shape_ovec(spacedim, n_dofs);
770  for (uint c=0; c<spacedim*n_dofs; ++c) {
771  ref_shape_ovec(c) = ArenaOVec(ref_shape_vec(c));
772  }
773 
774  Eigen::Matrix<ArenaOVec<double>, Eigen::Dynamic, Eigen::Dynamic> result_ovec = elem_ovec * ref_shape_ovec;
775  for (uint c=0; c<spacedim*n_dofs; ++c)
776  result_vec(c) = result_ovec(c).get_vec();
777  }
778 
779 private:
781 };
782 
783 /// Template specialization of previous: Domain=SideDomain)
784 template<unsigned int dim, unsigned int spacedim>
785 class VectorShape<dim, Op::SideDomain, spacedim> : public PatchOp<spacedim> {
786 public:
787  /// Constructor
788  VectorShape(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe, PatchOp<spacedim> &dispatch_op)
789  : PatchOp<spacedim>(dim, pfev, quad, {spacedim}, fe->n_dofs()), dispatch_op_(dispatch_op)
790  {
792  this->input_ops_.push_back( pfev.template get< Op::RefVector<dim, Op::SideDomain, spacedim>, dim >(quad, fe) );
793  }
794 
795  void eval() override {
796  uint n_patch_points = this->ppv().n_mesh_items() * this->quad_size();
797  dispatch_op_.allocate_result(n_patch_points, this->patch_arena());
798 
799  auto ref_shape_vec = this->input_ops(0)->result_matrix(); // dim+1 x spacedim
800  auto result_vec = dispatch_op_.result_matrix(); // spacdim x 1
801 
802  for (uint c=0; c<spacedim; c++)
803  FuncHelper<spacedim>::copy_ref_side_on_quads_data(*this, c, ref_shape_vec, result_vec);
804  }
805 
806 private:
808 };
809 
810 /// Evaluates vector values (FEType == FEVectorPiola)
811 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
812 class VectorPiolaShape : public PatchOp<spacedim> {
813 public:
814  /// Constructor
815  VectorPiolaShape(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe, PatchOp<spacedim> &dispatch_op)
816  : PatchOp<spacedim>(dim, pfev, quad, {spacedim}, fe->n_dofs()), dispatch_op_(dispatch_op)
817  {
818  this->domain_ = Domain::domain();
819  this->input_ops_.push_back( pfev.template get< Op::RefVector<dim, Domain, spacedim>, dim >(quad, fe) ); // input_ops_[0] ... RefVector dim x n_dofs
820  this->input_ops_.push_back( pfev.template get< Op::Jac<dim, Domain, spacedim>, dim >(pfev.element_quad(dim)) ); // input_ops_[1] ... Jac spacedim x dim
821  this->input_ops_.push_back( pfev.template get< Op::JacDet<dim, Domain, spacedim>, dim >(pfev.element_quad(dim)) ); // input_ops_[2] ... JacDet 1
822  }
823 
824  void eval() override {
825  auto ref_shape_vec = this->input_ops(0)->result_matrix();
826  auto jac_vec_elem = this->input_ops(1)->result_matrix();
827  auto jac_det_vec_elem = this->input_ops(2)->result_matrix();
828  auto result_vec = dispatch_op_.result_matrix();
829 
830  uint n_dofs = this->n_dofs();
831 
832  // Copy Jac and JacDet vector of elements registered on patch
834  uint n_elems = ppv.n_mesh_items();
835  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> jac_vec(spacedim, dim);
836  for (uint i=0; i<spacedim*dim; ++i) {
837  jac_vec(i) = ArenaVec<double>( n_elems, this->patch_arena() );
838  }
839  for (uint i_c=0; i_c<spacedim*dim; ++i_c) {
840  FuncHelper<spacedim>::fill_reduce_element_data_vec( ppv, jac_vec_elem(i_c), jac_vec(i_c) );
841  }
842  ArenaVec<double> jac_det_vec( n_elems, this->patch_arena() );
843  FuncHelper<spacedim>::fill_reduce_element_data_vec( ppv, jac_det_vec_elem(0), jac_det_vec );
844 
845  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> jac_div_det_vec = jac_vec / jac_det_vec;
846  Eigen::Matrix<ArenaOVec<double>, spacedim, dim> jac_div_det_ovec;
847  for (uint c=0; c<spacedim*dim; ++c) {
848  jac_div_det_ovec(c) = ArenaOVec<double>(jac_div_det_vec(c));
849  }
850 
851  Eigen::Matrix<ArenaOVec<double>, Eigen::Dynamic, Eigen::Dynamic> ref_shape_ovec(dim, n_dofs);
852  for (uint c=0; c<dim*n_dofs; ++c) {
853  ref_shape_ovec(c) = ArenaOVec<double>(ref_shape_vec(c));
854  }
855 
856  Eigen::Matrix<ArenaOVec<double>, Eigen::Dynamic, Eigen::Dynamic> result_ovec = jac_div_det_ovec * ref_shape_ovec;
857  for (uint c=0; c<spacedim*n_dofs; ++c) {
858  result_vec(c) = result_ovec(c).get_vec();
859  }
860  }
861 
862 private:
864 };
865 
866 /// Template specialization of previous: Domain=SideDomain)
867 template<unsigned int dim, unsigned int spacedim>
868 class VectorPiolaShape<dim, Op::SideDomain, spacedim> : public PatchOp<spacedim> {
869 public:
870  /// Constructor
871  VectorPiolaShape(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe, PatchOp<spacedim> &dispatch_op)
872  : PatchOp<spacedim>(dim, pfev, quad, {spacedim}, fe->n_dofs()), dispatch_op_(dispatch_op)
873  {
875  this->input_ops_.push_back( pfev.template get< Op::RefVector<dim, Op::SideDomain, spacedim>, dim >(quad, fe) ); // input_ops_[0] ... dim x n_dofs
876  this->input_ops_.push_back( pfev.template get< Op::Jac<dim, Op::BulkDomain, spacedim>, dim >(pfev.element_quad(dim)) ); // input_ops_[1] ... spacedim x dim
877  this->input_ops_.push_back( pfev.template get< Op::JacDet<dim, Op::BulkDomain, spacedim>, dim >(pfev.element_quad(dim)) ); // input_ops_[2] ... 1
878  }
879 
880  void eval() override {
882  uint n_dofs = this->n_dofs();
883  uint n_sides = ppv.n_mesh_items();
884  uint n_patch_points = n_sides * this->quad_size();
885  uint n_points_per_side = this->quad_size();
886  dispatch_op_.allocate_result(n_patch_points, this->patch_arena());
887 
888  auto ref_shape_vec = this->input_ops(0)->result_matrix(); // dim+1 x n_dofs
889  auto jac_vec_elem = this->input_ops(1)->result_matrix();
890  auto jac_det_vec_elem = this->input_ops(2)->result_matrix();
891  auto result_vec = dispatch_op_.result_matrix(); // spacdim x 1
892 
893  // Copy Jac and JacDet vector of elements registered on patch
894  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> jac_vec(spacedim, dim);
895  for (uint i=0; i<spacedim*dim; ++i) {
896  jac_vec(i) = ArenaVec<double>( n_sides, this->patch_arena() );
897  }
898  for (uint i_c=0; i_c<spacedim*dim; ++i_c) {
899  FuncHelper<spacedim>::fill_reduce_element_data_vec( ppv, jac_vec_elem(i_c), jac_vec(i_c) );
900  }
901  ArenaVec<double> jac_det_vec( n_sides, this->patch_arena() );
902  FuncHelper<spacedim>::fill_reduce_element_data_vec( ppv, jac_det_vec_elem(0), jac_det_vec );
903 
904  // Computes jacobian / determinant and converts result to ArenaOVec
905  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> jac_div_det_vec = jac_vec / jac_det_vec;
906  Eigen::Matrix<ArenaOVec<double>, spacedim, dim> jac_div_det_ovec;
907  for (uint c=0; c<spacedim*dim; ++c) {
908  jac_div_det_ovec(c) = ArenaOVec(jac_div_det_vec(c));
909  }
910 
911  // Computes expand vector of previous result (jacobian / determinant)
912  ArenaVec<double> side_points_vec(n_points_per_side, this->patch_arena());
913  for (uint i=0; i<n_points_per_side; ++i) {
914  side_points_vec(i) = 1.0;
915  }
916  ArenaOVec<double> side_points_ovec(side_points_vec);
917  Eigen::Matrix<ArenaOVec<double>, Eigen::Dynamic, Eigen::Dynamic> expand_jac_div_det_ovec = jac_div_det_ovec * side_points_ovec;
918  Eigen::Matrix<ArenaVec<double>, spacedim, dim> expand_jac_div_det_vec;
919  for (uint c=0; c<spacedim*this->dim_; ++c) {
920  expand_jac_div_det_vec(c) = expand_jac_div_det_ovec(c).get_vec();
921  }
922 
923  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> expand_ref_vec(dim, n_dofs);
924  for (uint c=0; c<dim*n_dofs; c++)
925  expand_ref_vec(c) = ArenaVec<double>(n_patch_points, this->patch_arena());
926 
927  FuncHelper<spacedim>::copy_ref_side_on_sides_vector_data(*this,dim, ref_shape_vec, expand_ref_vec);
928 
929  // computes operation result
930  result_vec = expand_jac_div_det_vec * expand_ref_vec;
931  }
932 
933 private:
935 };
936 
937 // class OpVectorCovariantShape
938 // class OpVectorPiolaShape
939 
940 /// Dispatch class of vector values
941 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
942 class DispatchVectorShape : public PatchOp<spacedim> {
943 public:
944  /// Constructor
946  : PatchOp<spacedim>(dim, pfev, quad, {spacedim}, fe->n_dofs()), in_op_(nullptr)
947  {
948  this->domain_ = Domain::domain();
949  switch (fe->fe_type()) {
950  case FEVector:
951  {
952  in_op_ = new VectorShape<dim, Domain, spacedim>(pfev, quad, fe, *this);
953  break;
954  }
956  {
957  ASSERT_PERMANENT(false).error("Shape vector for FEVectorContravariant is not implemented yet!\n"); // temporary assert
958  //in_op_ = new VectorCovariantShape<dim, Domain, spacedim>(pfev, quad, fe, *this);
959  break;
960  }
961  case FEVectorPiola:
962  {
963  in_op_ = new VectorPiolaShape<dim, Domain, spacedim>(pfev, quad, fe, *this);
964  break;
965  }
966  default:
967  ASSERT(false).error("Type of FiniteElement of grad_vector_shape accessor must be FEVector, FEVectorPiola or FEVectorContravariant!\n");
968  }
969 
970  }
971 
972  void eval() override {
973  in_op_->eval();
974  }
975 
976 private:
978 };
979 
980 /// Evaluates gradient scalar values
981 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
982 class GradScalarShape : public PatchOp<spacedim> {
983 public:
984  /// Constructor
985  GradScalarShape(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe)
986  : PatchOp<spacedim>(dim, pfev, quad, {spacedim, 1}, fe->n_dofs())
987  {
988  ASSERT_EQ(fe->fe_type(), FEType::FEScalar).error("Type of FiniteElement of grad_scalar_shape must be FEScalar!\n");
989  this->domain_ = Domain::domain();
990  this->input_ops_.push_back( pfev.template get< Op::InvJac<dim, Op::BulkDomain, spacedim>, dim >(pfev.element_quad(dim)) );
991  this->input_ops_.push_back( pfev.template get< Op::RefGradScalar<dim, Domain, spacedim>, dim >(quad, fe) );
992  }
993 
994  void eval() override {
995  auto inv_jac_vec_elem = this->input_ops(0)->result_matrix(); // dim x spacedim=3
996  auto ref_grads_vec = this->input_ops(1)->result_matrix(); // dim x n_dofs
997 
998  uint n_dofs = this->n_dofs();
999 
1000  // Copy InvJac vector of elements registered on patch
1001  PatchPointValues<spacedim> &ppv = this->ppv();
1002  uint n_elems = ppv.n_mesh_items();
1003  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> inv_jac_vec(dim, spacedim);
1004  for (uint i=0; i<dim*spacedim; ++i) {
1005  inv_jac_vec(i) = ArenaVec<double>( n_elems, this->patch_arena() );
1006  }
1007  for (uint i_c=0; i_c<dim*spacedim; ++i_c) {
1008  FuncHelper<spacedim>::fill_reduce_element_data_vec( ppv, inv_jac_vec_elem(i_c), inv_jac_vec(i_c) );
1009  }
1010 
1011  Eigen::Matrix<ArenaOVec<double>, Eigen::Dynamic, Eigen::Dynamic> ref_grads_ovec(this->dim_, n_dofs);
1012  for (uint i=0; i<this->dim_*n_dofs; ++i) {
1013  ref_grads_ovec(i) = ArenaOVec(ref_grads_vec(i));
1014  }
1015 
1016  Eigen::Matrix<ArenaOVec<double>, dim, 3> inv_jac_ovec;
1017  for (uint i=0; i<this->dim_*spacedim; ++i) {
1018  inv_jac_ovec(i) = ArenaOVec(inv_jac_vec(i));
1019  }
1020 
1021  auto result_vec = this->result_matrix();
1022  Eigen::Matrix<ArenaOVec<double>, Eigen::Dynamic, Eigen::Dynamic> result_ovec = inv_jac_ovec.transpose() * ref_grads_ovec;
1023  for (uint i=0; i<spacedim*n_dofs; ++i) {
1024  result_vec(i) = result_ovec(i).get_vec();
1025  }
1026  }
1027 };
1028 
1029 /// Template specialization of previous: Domain=SideDomain
1030 template<unsigned int dim, unsigned int spacedim>
1031 class GradScalarShape<dim, Op::SideDomain, spacedim> : public PatchOp<spacedim> {
1032 public:
1033  /// Constructor
1035  : PatchOp<spacedim>(dim, pfev, quad, {spacedim, 1}, fe->n_dofs())
1036  {
1037  ASSERT_EQ(fe->fe_type(), FEType::FEScalar).error("Type of FiniteElement of grad_scalar_shape must be FEScalar!\n");
1038  this->domain_ = Op::SideDomain::domain();
1039  this->input_ops_.push_back( pfev.template get< Op::InvJac<dim, Op::BulkDomain, spacedim>, dim >(pfev.element_quad(dim)) );
1040  this->input_ops_.push_back( pfev.template get< Op::RefGradScalar<dim, Op::SideDomain, spacedim>, dim >(quad, fe) );
1041  }
1042 
1043  void eval() override {
1044  PatchPointValues<spacedim> &ppv = this->ppv();
1045  auto ref_shape_grads = this->input_ops(1)->result_matrix();
1046  auto grad_scalar_shape_value = this->result_matrix();
1047 
1048  uint n_dofs = this->n_dofs();
1049  uint n_sides = ppv.n_mesh_items();
1050  uint n_patch_points = n_sides * this->quad_size();
1051 
1052  this->allocate_result(n_patch_points, this->patch_arena());
1053 
1054  // Expands inverse jacobian to inv_jac_expd_value
1055  auto inv_jac_value = this->input_ops(0)->result_matrix();
1056  Eigen::Matrix<ArenaVec<double>, dim, spacedim> inv_jac_expd_value;
1057  Eigen::Map<Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic>> inv_jac_expd_map(inv_jac_expd_value.data(), dim, spacedim);
1058  FuncHelper<spacedim>::copy_patch_elem_on_domain_data(*this, dim, inv_jac_value, inv_jac_expd_map);
1059 
1060  // Fill ref shape gradients by q_point. DOF and side_idx
1061  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> ref_shape_grads_expd(dim, n_dofs);
1062  for (uint i=0; i<dim*n_dofs; ++i) {
1063  ref_shape_grads_expd(i) = ArenaVec<double>( n_patch_points, this->patch_arena() );
1064  }
1065  FuncHelper<spacedim>::copy_ref_side_on_sides_vector_data(*this, dim, ref_shape_grads, ref_shape_grads_expd);
1066 
1067  // computes operation result
1068  grad_scalar_shape_value = inv_jac_expd_value.transpose() * ref_shape_grads_expd;
1069  }
1070 };
1071 
1072 /// Evaluates vector values (FEType == FEVector)
1073 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
1074 class GradVectorShape : public PatchOp<spacedim> {
1075 public:
1076  /// Constructor
1077  GradVectorShape(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe, PatchOp<spacedim> &dispatch_op)
1078  : PatchOp<spacedim>(dim, pfev, quad, {spacedim, spacedim}, fe->n_dofs()), dispatch_op_(dispatch_op)
1079  {
1080  this->domain_ = Domain::domain();
1081  this->input_ops_.push_back( pfev.template get< Op::InvJac<dim, Op::BulkDomain, spacedim>, dim >(pfev.element_quad(dim)) );
1082  this->input_ops_.push_back( pfev.template get< Op::RefGradVector<dim, Domain, spacedim>, dim >(quad, fe) );
1083  }
1084 
1085  void eval() override {
1086  auto inv_jac_vec_elem = this->input_ops(0)->result_matrix(); // dim x spacedim
1087  auto ref_grads_vec = this->input_ops(1)->result_matrix(); // dim x spacedim
1088  auto result_vec = dispatch_op_.result_matrix(); // spacedim x spacedim
1089 
1090  uint n_dofs = this->n_dofs();
1091 
1092  // Copy InvJac vector of elements registered on patch
1093  PatchPointValues<spacedim> &ppv = this->ppv();
1094  uint n_elems = ppv.n_mesh_items();
1095  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> inv_jac_vec(dim, spacedim);
1096  for (uint i=0; i<dim*spacedim; ++i) {
1097  inv_jac_vec(i) = ArenaVec<double>( n_elems, this->patch_arena() );
1098  }
1099  for (uint i_c=0; i_c<dim*spacedim; ++i_c) {
1100  FuncHelper<spacedim>::fill_reduce_element_data_vec( ppv, inv_jac_vec_elem(i_c), inv_jac_vec(i_c) );
1101  }
1102 
1103  Eigen::Matrix<ArenaOVec<double>, dim, 3> inv_jac_ovec;
1104  for (uint i=0; i<dim*spacedim; ++i) {
1105  inv_jac_ovec(i) = ArenaOVec(inv_jac_vec(i));
1106  }
1107 
1108  Eigen::Matrix<ArenaOVec<double>, dim, spacedim> ref_grads_ovec;
1109  for (uint i_dof=0; i_dof<n_dofs; ++i_dof) {
1110  for (uint i=0; i<spacedim*dim; ++i) {
1111  ref_grads_ovec(i) = ArenaOVec(ref_grads_vec(i_dof*3*dim + i));
1112  }
1113 
1114  Eigen::Matrix<ArenaOVec<double>, spacedim, spacedim> result_ovec = inv_jac_ovec.transpose() * ref_grads_ovec;
1115  for (uint i=0; i<spacedim; ++i) {
1116  for (uint j=0; j<spacedim; ++j) {
1117  result_vec(j,i+spacedim*i_dof) = result_ovec(i,j).get_vec();
1118  }
1119  }
1120  }
1121  }
1122 
1123 private:
1125 };
1126 
1127 /// Template specialization of previous: Domain=SideDomain)
1128 template<unsigned int dim, unsigned int spacedim>
1129 class GradVectorShape<dim, Op::SideDomain, spacedim> : public PatchOp<spacedim> {
1130 public:
1131  /// Constructor
1132  GradVectorShape(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe, PatchOp<spacedim> &dispatch_op)
1133  : PatchOp<spacedim>(dim, pfev, quad, {spacedim, spacedim}, fe->n_dofs()), dispatch_op_(dispatch_op)
1134  {
1135  this->domain_ = Op::SideDomain::domain();
1136  this->input_ops_.push_back( pfev.template get< Op::InvJac<dim, Op::BulkDomain, spacedim>, dim >(pfev.element_quad(dim)) );
1137  this->input_ops_.push_back( pfev.template get< Op::RefGradVector<dim, Op::SideDomain, spacedim>, dim >(quad, fe) );
1138  }
1139 
1140  void eval() override {
1141  PatchPointValues<spacedim> &ppv = this->ppv();
1142  auto inv_jac_value = this->input_ops(0)->result_matrix(); // dim x spacedim
1143  auto ref_vector_grad = this->input_ops(1)->result_matrix(); // n_sides*dim x spacedim
1144 
1145  uint n_dofs = this->n_dofs();
1146  uint n_patch_sides = ppv.n_mesh_items();
1147  uint n_patch_points = n_patch_sides * this->quad_size();
1148 
1149  // Expands inverse jacobian to inv_jac_expd_value
1150  Eigen::Matrix<ArenaVec<double>, dim, spacedim> inv_jac_expd_value;
1151  Eigen::Map<Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic>> inv_jac_expd_map(inv_jac_expd_value.data(), dim, spacedim);
1152  FuncHelper<spacedim>::copy_patch_elem_on_domain_data(*this, dim, inv_jac_value, inv_jac_expd_map);
1153 
1154  // Fill ref shape gradients by q_point. DOF and side_idx
1155  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> ref_shape_grads_expd(dim, spacedim);
1156  for (uint i=0; i<spacedim*dim; ++i) {
1157  ref_shape_grads_expd(i) = ArenaVec<double>( n_patch_points, this->patch_arena() );
1158  }
1159  for (uint i_dof=0; i_dof<n_dofs; ++i_dof) {
1160  // prepare copy of reference data by indices of sides on elements
1161  FuncHelper<spacedim>::copy_ref_side_on_sides_tensor_data(*this, i_dof, dim, spacedim, ref_vector_grad, ref_shape_grads_expd);
1162 
1163  // computes operation result
1164  Eigen::Map< Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> > res_submat = dispatch_op_.result_sub_matrix(i_dof);
1165  res_submat = (inv_jac_expd_value.transpose() * ref_shape_grads_expd).transpose();
1166  }
1167  }
1168 
1169 private:
1171 };
1172 
1173 /// Evaluates vector values (FEType == FEVectorPiola)
1174 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
1175 class GradVectorPiolaShape : public PatchOp<spacedim> {
1176 public:
1177  /// Constructor
1178  GradVectorPiolaShape(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe, PatchOp<spacedim> &dispatch_op)
1179  : PatchOp<spacedim>(dim, pfev, quad, {spacedim, spacedim}, fe->n_dofs()), dispatch_op_(dispatch_op)
1180  {
1181  this->domain_ = Domain::domain();
1182  this->input_ops_.push_back( pfev.template get< Op::InvJac<dim, Op::BulkDomain, spacedim>, dim >(pfev.element_quad(dim)) );
1183  this->input_ops_.push_back( pfev.template get< Op::RefGradVector<dim, Domain, spacedim>, dim >(quad, fe) );
1184  this->input_ops_.push_back( pfev.template get< Op::Jac<dim, Op::BulkDomain, spacedim>, dim >(pfev.element_quad(dim)) );
1185  this->input_ops_.push_back( pfev.template get< Op::JacDet<dim, Op::BulkDomain, spacedim>, dim >(pfev.element_quad(dim)) );
1186  }
1187 
1188  void eval() override {
1189  auto inv_jac_vec_elem = this->input_ops(0)->result_matrix(); // dim x spacedim
1190  auto ref_grads_vec = this->input_ops(1)->result_matrix(); // dim x dim
1191  auto jac_vec_elem = this->input_ops(2)->result_matrix(); // spacedim x dim
1192  auto jac_det_vec_elem = this->input_ops(3)->result_matrix(); // 1
1193  auto result_vec = dispatch_op_.result_matrix(); // spacedim x spacedim
1194 
1195  PatchPointValues<spacedim> &ppv = this->ppv();
1196  uint n_elems = ppv.n_mesh_items();
1197  uint n_dofs = this->n_dofs();
1198 
1199  // Copy InvJac and JacDet vector of elements registered on patch
1200  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> inv_jac_vec(dim, spacedim);
1201  for (uint i=0; i<dim*spacedim; ++i) {
1202  inv_jac_vec(i) = ArenaVec<double>( n_elems, this->patch_arena() );
1203  }
1204  for (uint i_c=0; i_c<spacedim*dim; ++i_c) {
1205  FuncHelper<spacedim>::fill_reduce_element_data_vec( ppv, inv_jac_vec_elem(i_c), inv_jac_vec(i_c) );
1206  }
1207  ArenaVec<double> jac_det_vec( n_elems, this->patch_arena() );
1208  FuncHelper<spacedim>::fill_reduce_element_data_vec( ppv, jac_det_vec_elem(0), jac_det_vec );
1209 
1210  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> inv_jac_div_det_vec = inv_jac_vec / jac_det_vec;
1211  Eigen::Matrix<ArenaOVec<double>, dim, spacedim> inv_jac_div_det_ovec;
1212  for (uint c=0; c<dim*spacedim; ++c) {
1213  inv_jac_div_det_ovec(c) = ArenaOVec<double>(inv_jac_div_det_vec(c));
1214  }
1215 
1216  Eigen::Matrix<ArenaVec<double>, spacedim, dim> jac_vec;
1217  Eigen::Map<Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic>> jac_vec_map(jac_vec.data(), spacedim, dim);
1218  FuncHelper<spacedim>::copy_patch_elem_on_domain_data(*this, dim, jac_vec_elem, jac_vec_map);
1219 
1220  Eigen::Matrix<ArenaOVec<double>, Eigen::Dynamic, Eigen::Dynamic> ref_grads_ovec(dim, dim);
1221  for (uint i_dof=0; i_dof<n_dofs; ++i_dof) {
1222  for (uint i=0; i<dim*dim; ++i) {
1223  ref_grads_ovec(i) = ArenaOVec(ref_grads_vec(i_dof*dim*dim + i));
1224  }
1225 
1226  Eigen::Matrix<ArenaOVec<double>, spacedim, dim> inv_jac_multi_ref_ovec = inv_jac_div_det_ovec.transpose() * ref_grads_ovec;
1227  Eigen::Matrix<ArenaVec<double>, spacedim, dim> inv_jac_multi_ref_vec; // converts components ArenaOVec to ArenaVec
1228  for (uint i=0; i<spacedim*dim; ++i) {
1229  inv_jac_multi_ref_vec(i) = inv_jac_multi_ref_ovec(i);
1230  }
1231 
1232  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> sub_result_vec = inv_jac_multi_ref_vec * jac_vec.transpose();
1233  for (uint i=0; i<spacedim; ++i) {
1234  for (uint j=0; j<spacedim; ++j) {
1235  result_vec(j,i+spacedim*i_dof) = sub_result_vec(i,j);
1236  }
1237  }
1238  }
1239  }
1240 
1241 private:
1243 };
1244 
1245 /// Template specialization of previous: Domain=SideDomain)
1246 template<unsigned int dim, unsigned int spacedim>
1247 class GradVectorPiolaShape<dim, Op::SideDomain, spacedim> : public PatchOp<spacedim> {
1248 public:
1249  /// Constructor
1250  GradVectorPiolaShape(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe, PatchOp<spacedim> &dispatch_op)
1251  : PatchOp<spacedim>(dim, pfev, quad, {spacedim, spacedim}, fe->n_dofs()), dispatch_op_(dispatch_op)
1252  {
1253  this->domain_ = Op::SideDomain::domain();
1254  this->input_ops_.push_back( pfev.template get< Op::InvJac<dim, Op::BulkDomain, spacedim>, dim >(pfev.element_quad(dim)) );
1255  this->input_ops_.push_back( pfev.template get< Op::RefGradVector<dim, Op::SideDomain, spacedim>, dim >(quad, fe) );
1256  this->input_ops_.push_back( pfev.template get< Op::Jac<dim, Op::BulkDomain, spacedim>, dim >(pfev.element_quad(dim)) );
1257  this->input_ops_.push_back( pfev.template get< Op::JacDet<dim, Op::BulkDomain, spacedim>, dim >(pfev.element_quad(dim)) );
1258  }
1259 
1260  void eval() override {
1261  auto inv_jac_vec_elem = this->input_ops(0)->result_matrix(); // dim x spacedim
1262  auto ref_grads_vec = this->input_ops(1)->result_matrix(); // dim x dim
1263  auto jac_vec_elem = this->input_ops(2)->result_matrix(); // spacedim x dim
1264  auto jac_det_vec_elem = this->input_ops(3)->result_matrix(); // 1
1265 
1266  PatchPointValues<spacedim> &ppv = this->ppv();
1267  uint n_sides = ppv.n_mesh_items();
1268  uint n_dofs = this->n_dofs();
1269  uint n_patch_points = n_sides * this->quad_size();
1270  uint n_points_per_side = this->quad_size();
1271 
1272  // Copy InvJac, Jac and JacDet vector of elements registered on patch
1273  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> inv_jac_vec(dim, spacedim);
1274  for (uint i_c=0; i_c<dim*spacedim; ++i_c) {
1275  inv_jac_vec(i_c) = ArenaVec<double>( n_sides, this->patch_arena() );
1276  FuncHelper<spacedim>::fill_reduce_element_data_vec( ppv, inv_jac_vec_elem(i_c), inv_jac_vec(i_c) );
1277  }
1278  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> jac_vec(spacedim, dim);
1279  Eigen::Matrix<ArenaOVec<double>, spacedim, dim> jac_ovec;
1280  for (uint i_c=0; i_c<spacedim*dim; ++i_c) {
1281  jac_vec(i_c) = ArenaVec<double>( n_sides, this->patch_arena() );
1282  FuncHelper<spacedim>::fill_reduce_element_data_vec( ppv, jac_vec_elem(i_c), jac_vec(i_c) );
1283  jac_ovec(i_c) = ArenaOVec<double>(jac_vec(i_c));
1284  }
1285  ArenaVec<double> jac_det_vec( n_sides, this->patch_arena() );
1286  FuncHelper<spacedim>::fill_reduce_element_data_vec( ppv, jac_det_vec_elem(0), jac_det_vec );
1287 
1288  // Compute InvJac / Determinant, convert to ArenaOvec
1289  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> inv_jac_div_det_vec = inv_jac_vec / jac_det_vec;
1290  Eigen::Matrix<ArenaOVec<double>, dim, spacedim> inv_jac_div_det_ovec;
1291  for (uint c=0; c<dim*spacedim; ++c) {
1292  inv_jac_div_det_ovec(c) = ArenaOVec<double>(inv_jac_div_det_vec(c));
1293  }
1294 
1295  // Computes expand vector of previous result (inv_jac / determinant) and expand vector of Jacobian
1296  ArenaVec<double> side_points_vec(n_points_per_side, this->patch_arena());
1297  for (uint i=0; i<n_points_per_side; ++i) {
1298  side_points_vec(i) = 1.0;
1299  }
1300  ArenaOVec<double> side_points_ovec(side_points_vec);
1301  Eigen::Matrix<ArenaOVec<double>, Eigen::Dynamic, Eigen::Dynamic> expand_inv_jac_div_det_ovec = inv_jac_div_det_ovec * side_points_ovec;
1302  Eigen::Matrix<ArenaVec<double>, dim, spacedim> expand_inv_jac_div_det_vec;
1303  for (uint c=0; c<spacedim*dim; ++c) {
1304  expand_inv_jac_div_det_vec(c) = expand_inv_jac_div_det_ovec(c).get_vec();
1305  }
1306  Eigen::Matrix<ArenaOVec<double>, Eigen::Dynamic, Eigen::Dynamic> expand_jac_ovec = jac_ovec * side_points_ovec;
1307  Eigen::Matrix<ArenaVec<double>, spacedim, dim> expand_jac_vec;
1308  for (uint c=0; c<spacedim*dim; ++c) {
1309  expand_jac_vec(c) = expand_jac_ovec(c).get_vec();
1310  }
1311 
1312  Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> expand_ref_vec(dim, dim);
1313  for (uint c=0; c<dim*dim; c++)
1314  expand_ref_vec(c) = ArenaVec<double>(n_patch_points, this->patch_arena());
1315 
1316  for (uint i_dof=0; i_dof<n_dofs; ++i_dof) {
1317  // prepare copy of reference data by indices of sides on elements
1318  FuncHelper<spacedim>::copy_ref_side_on_sides_tensor_data(*this, i_dof, dim, dim, ref_grads_vec, expand_ref_vec);
1319 
1320  // computes operation result
1321  Eigen::Map< Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> > res_submat = dispatch_op_.result_sub_matrix(i_dof);
1322  res_submat = expand_inv_jac_div_det_vec.transpose() * expand_ref_vec * expand_jac_vec.transpose();
1323  }
1324  }
1325 
1326 private:
1328 };
1329 
1330 // class OpGradVectorCovariantShape
1331 
1332 /// Dispatch class of vector values
1333 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
1334 class DispatchGradVectorShape : public PatchOp<spacedim> {
1335 public:
1336  /// Constructor
1338  : PatchOp<spacedim>(dim, pfev, quad, {spacedim, spacedim}, fe->n_dofs()), in_op_(nullptr)
1339  {
1340  this->domain_ = Domain::domain();
1341  switch (fe->fe_type()) {
1342  case FEVector:
1343  {
1344  in_op_ = new GradVectorShape<dim, Domain, spacedim>(pfev, quad, fe, *this);
1345  break;
1346  }
1347  case FEVectorContravariant:
1348  {
1349  ASSERT_PERMANENT(false).error("Shape vector for FEVectorContravariant is not implemented yet!\n"); // temporary assert
1350  //in_op_ = new GradVectorCovariantShape<dim, Domain, spacedim>(pfev, quad, fe, *this);
1351  break;
1352  }
1353  case FEVectorPiola:
1354  {
1355  in_op_ = new GradVectorPiolaShape<dim, Domain, spacedim>(pfev, quad, fe, *this);
1356  break;
1357  }
1358  default:
1359  ASSERT(false).error("Type of FiniteElement of grad_vector_shape accessor must be FEVector, FEVectorPiola or FEVectorContravariant!\n");
1360  }
1361 
1362  }
1363 
1364  void eval() override {
1365  in_op_->eval();
1366  }
1367 
1368 private:
1370 };
1371 
1372 /// Evaluates vector symmetric gradients
1373 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
1374 class VectorSymGrad : public PatchOp<spacedim> {
1375 public:
1376  /// Constructor
1377  VectorSymGrad(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe)
1378  : PatchOp<spacedim>(dim, pfev, quad, {spacedim, spacedim}, fe->n_dofs())
1379  {
1380  this->domain_ = Domain::domain();
1381  this->input_ops_.push_back( pfev.template get< DispatchGradVectorShape<dim, Domain, spacedim>, dim >(quad, fe) );
1382  }
1383 
1384  void eval() override {
1385  for (uint i_dof=0; i_dof<this->n_dofs(); ++i_dof) {
1386  Eigen::Map< Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> > grad_vector_dof = this->input_ops(0)->result_sub_matrix(i_dof);
1387  Eigen::Map< Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> > sym_grad_dof = this->result_sub_matrix(i_dof);
1388  sym_grad_dof = 0.5 * (grad_vector_dof.transpose() + grad_vector_dof);
1389  }
1390  }
1391 };
1392 
1393 /// Evaluates vector vector divergence
1394 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
1395 class VectorDivergence : public PatchOp<spacedim> {
1396 public:
1397  /// Constructor
1399  : PatchOp<spacedim>(dim, pfev, quad, {1}, fe->n_dofs())
1400  {
1401  this->domain_ = Domain::domain();
1402  this->input_ops_.push_back( pfev.template get< DispatchGradVectorShape<dim, Domain, spacedim>, dim >(quad, fe) );
1403  }
1404 
1405  void eval() override {
1406  auto divergence_value = this->result_matrix();
1407 
1408  for (uint i_dof=0; i_dof<this->n_dofs(); ++i_dof) {
1409  Eigen::Map< Eigen::Matrix<ArenaVec<double>, Eigen::Dynamic, Eigen::Dynamic> > grad_vector_dof = this->input_ops(0)->result_sub_matrix(i_dof);
1410  divergence_value(i_dof) = grad_vector_dof(0,0) + grad_vector_dof(1,1) + grad_vector_dof(2,2);
1411  }
1412  }
1413 };
1414 
1415 /// Class represents zero operation of Join quantities.
1416 template<unsigned int dim, class Domain, unsigned int spacedim = 3>
1417 class OpZero : public PatchOp<spacedim> {
1418 public:
1419  /// Constructor
1420  OpZero(PatchFEValues<spacedim> &pfev, const Quadrature *quad, std::shared_ptr<FiniteElement<dim>> fe)
1421  : PatchOp<spacedim>(dim, pfev, quad, {spacedim, spacedim}, fe->n_dofs())
1422  {
1423  this->domain_ = Domain::domain();
1424  this->allocate_const_result( this->patch_fe_->patch_fe_data().zero_vec_ );
1425  }
1426 
1427  void eval() override {}
1428 };
1429 
1430 } // end of namespace Op
1431 
1432 
1433 #endif /* OP_FUNCTION_HH_ */
#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
ArenaVec< T > get_vec() const
Convert ArenaOVec to ArenaVec and its.
Definition: arena_vec.hh:329
Abstract class for the description of a general finite element on a reference simplex in dim dimensio...
Class used as template type for type resolution Bulk / Side.
Definition: op_function.hh:30
static ElemDomain domain()
Definition: op_function.hh:32
static constexpr uint n_nodes(uint dim)
Definition: op_function.hh:36
static NodeAccessor< 3 > node(PatchPointValues< 3 > &ppv, unsigned int i_elm, unsigned int i_n)
Return i_n-th node of i_elm-th element stored in PatchPointValues::elem_dim_list_.
Definition: op_function.hh:46
static uint n_mesh_entities(PatchPointValues< 3 > &ppv)
Return number of mesh entities (in this case elements) on patch.
Definition: op_function.hh:41
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:92
Coords(PatchFEValues< spacedim > &pfev, const Quadrature *quad)
Constructor.
Definition: op_function.hh:87
Dispatch class of vector values.
PatchOp< spacedim > * in_op_
void eval() override
Reinit function of operation. Implementation in descendants.
DispatchGradVectorShape(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
Dispatch class of vector values.
Definition: op_function.hh:942
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:972
PatchOp< spacedim > * in_op_
Definition: op_function.hh:977
DispatchVectorShape(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
Definition: op_function.hh:945
static void copy_ref_side_on_quads_data(PatchOp< spacedim > &op, unsigned int i_comp, Eigen::Map< Eigen::Matrix< ArenaVec< double >, Eigen::Dynamic, Eigen::Dynamic >> &source, Eigen::Map< Eigen::Matrix< ArenaVec< double >, Eigen::Dynamic, Eigen::Dynamic >> &target)
Definition: op_function.hh:210
FuncHelper()
Forbidden constructor.
Definition: op_function.hh:289
static void copy_patch_elem_on_domain_data(PatchOp< spacedim > &op, unsigned int dim, Eigen::Map< Eigen::Matrix< ArenaVec< double >, Eigen::Dynamic, Eigen::Dynamic >> &source, Eigen::Map< Eigen::Matrix< ArenaVec< double >, Eigen::Dynamic, Eigen::Dynamic >> &target)
Definition: op_function.hh:272
static void copy_ref_side_on_sides_vector_data(PatchOp< spacedim > &op, unsigned int dim, Eigen::Map< Eigen::Matrix< ArenaVec< double >, Eigen::Dynamic, Eigen::Dynamic >> &source, Eigen::Matrix< ArenaVec< double >, Eigen::Dynamic, Eigen::Dynamic > &target)
Definition: op_function.hh:228
static void fill_reduce_element_data_vec(PatchPointValues< spacedim > &ppv, ArenaVec< double > &source, ArenaVec< double > &target)
Definition: op_function.hh:201
static void copy_ref_side_on_sides_tensor_data(PatchOp< spacedim > &op, unsigned int i_dof, unsigned int shape_m, unsigned int shape_n, Eigen::Map< Eigen::Matrix< ArenaVec< double >, Eigen::Dynamic, Eigen::Dynamic >> &source, Eigen::Matrix< ArenaVec< double >, Eigen::Dynamic, Eigen::Dynamic > &target)
Definition: op_function.hh:249
void eval() override
Reinit function of operation. Implementation in descendants.
GradScalarShape(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
Evaluates gradient scalar values.
Definition: op_function.hh:982
GradScalarShape(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
Definition: op_function.hh:985
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:994
void eval() override
Reinit function of operation. Implementation in descendants.
GradVectorPiolaShape(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe, PatchOp< spacedim > &dispatch_op)
Constructor.
Evaluates vector values (FEType == FEVectorPiola)
void eval() override
Reinit function of operation. Implementation in descendants.
GradVectorPiolaShape(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe, PatchOp< spacedim > &dispatch_op)
Constructor.
PatchOp< spacedim > & dispatch_op_
void eval() override
Reinit function of operation. Implementation in descendants.
GradVectorShape(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe, PatchOp< spacedim > &dispatch_op)
Constructor.
Evaluates vector values (FEType == FEVector)
GradVectorShape(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe, PatchOp< spacedim > &dispatch_op)
Constructor.
PatchOp< spacedim > & dispatch_op_
void eval() override
Reinit function of operation. Implementation in descendants.
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:184
InvJac(PatchFEValues< spacedim > &pfev, const Quadrature *quad)
Constructor.
Definition: op_function.hh:177
JacDet(PatchFEValues< 3 > &pfev, const Quadrature *quad)
Constructor.
Definition: op_function.hh:152
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:158
Evaluates Jacobian determinants on Bulk (Element) / Side.
Definition: op_function.hh:130
JacDet(PatchFEValues< spacedim > &pfev, const Quadrature *quad)
Constructor.
Definition: op_function.hh:133
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:140
Evaluates Jacobians on Bulk (Element) / Side.
Definition: op_function.hh:109
Jac(PatchFEValues< spacedim > &pfev, const Quadrature *quad)
Constructor.
Definition: op_function.hh:112
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:119
JxW(PatchFEValues< spacedim > &pfev, const Quadrature *quad)
Constructor.
Definition: op_function.hh:426
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:434
JxW(PatchFEValues< spacedim > &pfev, const Quadrature *quad)
Constructor.
Definition: op_function.hh:397
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:405
Evaluates normal vector on side quadrature points.
Definition: op_function.hh:446
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:456
NormalVec(PatchFEValues< spacedim > &pfev, const Quadrature *quad)
Constructor.
Definition: op_function.hh:449
Class represents zero operation of Join quantities.
void eval() override
Reinit function of operation. Implementation in descendants.
OpZero(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
PtCoords(PatchFEValues< spacedim > &pfev, const Quadrature *quad)
Constructor.
Definition: op_function.hh:330
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:338
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:316
RefBaryCoords(PatchFEValues< spacedim > &pfev, const Quadrature *quad)
Constructor.
Definition: op_function.hh:303
Template specialization of previous: Domain=SideDomain.
Definition: op_function.hh:606
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:626
RefGradScalar(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
Definition: op_function.hh:609
Fixed operation of gradient scalar reference values.
Definition: op_function.hh:584
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:601
RefGradScalar(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
Definition: op_function.hh:587
Template specialization of previous: Domain=SideDomain.
Definition: op_function.hh:656
RefGradVector(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
Definition: op_function.hh:659
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:679
Fixed operation of gradient scalar reference values.
Definition: op_function.hh:631
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:651
RefGradVector(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
Definition: op_function.hh:634
Template specialization of previous: Domain=SideDomain.
Definition: op_function.hh:511
RefScalar(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
Definition: op_function.hh:514
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:530
Fixed operation of scalar shape reference values.
Definition: op_function.hh:490
RefScalar(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
Definition: op_function.hh:493
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:506
Template specialization of previous: Domain=SideDomain.
Definition: op_function.hh:558
RefVector(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
Definition: op_function.hh:561
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:579
Fixed operation of vector shape reference values.
Definition: op_function.hh:535
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:553
RefVector(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
Definition: op_function.hh:538
ScalarShape(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
Definition: op_function.hh:725
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:733
Evaluates scalar shape values.
Definition: op_function.hh:684
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:695
ScalarShape(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
Definition: op_function.hh:687
Class used as template type for type resolution Bulk / Side.
Definition: op_function.hh:52
static constexpr uint n_nodes(uint dim)
Definition: op_function.hh:58
static uint n_mesh_entities(PatchPointValues< 3 > &ppv)
Return number of mesh entities (in this case sides) on patch.
Definition: op_function.hh:63
static ElemDomain domain()
Definition: op_function.hh:54
static NodeAccessor< 3 > node(PatchPointValues< 3 > &ppv, unsigned int i_elm, unsigned int i_n)
Return i_n-th node of i_elm-th side stored in PatchPointValues::side_list_.
Definition: op_function.hh:68
Evaluates vector vector divergence.
void eval() override
Reinit function of operation. Implementation in descendants.
VectorDivergence(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:880
VectorPiolaShape(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe, PatchOp< spacedim > &dispatch_op)
Constructor.
Definition: op_function.hh:871
Evaluates vector values (FEType == FEVectorPiola)
Definition: op_function.hh:812
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:824
VectorPiolaShape(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe, PatchOp< spacedim > &dispatch_op)
Constructor.
Definition: op_function.hh:815
PatchOp< spacedim > & dispatch_op_
Definition: op_function.hh:863
VectorShape(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe, PatchOp< spacedim > &dispatch_op)
Constructor.
Definition: op_function.hh:788
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:795
Evaluates vector values (FEType == FEVector)
Definition: op_function.hh:746
PatchOp< spacedim > & dispatch_op_
Definition: op_function.hh:780
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:756
VectorShape(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe, PatchOp< spacedim > &dispatch_op)
Constructor.
Definition: op_function.hh:749
Evaluates vector symmetric gradients.
void eval() override
Reinit function of operation. Implementation in descendants.
VectorSymGrad(PatchFEValues< spacedim > &pfev, const Quadrature *quad, std::shared_ptr< FiniteElement< dim >> fe)
Constructor.
Weights(PatchFEValues< spacedim > &pfev, const Quadrature *quad)
Constructor.
Definition: op_function.hh:375
void eval() override
Reinit function of operation. Implementation in descendants.
Definition: op_function.hh:386
Class represents element or FE operations.
Definition: patch_op.hh:45
Eigen::Vector< ArenaVec< double >, Eigen::Dynamic > result_
Result matrix of operation.
Definition: patch_op.hh:189
Eigen::Map< Eigen::Matrix< ArenaVec< double >, Eigen::Dynamic, Eigen::Dynamic > > result_sub_matrix(uint i_dof)
Return map referenced result of DOF values as Eigen::Matrix.
Definition: patch_op.hh:133
uint n_dofs() const
Getter for n_dofs_.
Definition: patch_op.hh:92
uint n_comp() const
Definition: patch_op.hh:77
std::vector< PatchOp< spacedim > * > input_ops_
Indices of operations in PatchPointValues::operations_ vector on which PatchOp is depended.
Definition: patch_op.hh:190
PatchOp< spacedim > * input_ops(uint i_op) const
Return pointer to operation of i_op index in input operation vector.
Definition: patch_op.hh:97
uint dim_
Dimension.
Definition: patch_op.hh:186
const std::vector< uint > & shape() const
Getter for shape_.
Definition: patch_op.hh:102
Eigen::Map< Eigen::Matrix< ArenaVec< double >, Eigen::Dynamic, Eigen::Dynamic > > result_matrix()
Return map referenced result as Eigen::Vector.
Definition: patch_op.hh:128
void allocate_const_result(ArenaVec< double > &value_vec)
Definition: patch_op.hh:122
ElemDomain domain_
Flag: BulkOp = 0, SideOp = 1.
Definition: patch_op.hh:187
void allocate_result(size_t data_size, PatchArena &arena)
Definition: patch_op.hh:117
unsigned int quad_size() const
Return size of quadrature.
Definition: patch_op.hh:175
PatchPointValues< spacedim > & ppv() const
Return reference of PatchPointValues.
Definition: patch_op.hh:150
PatchArena & patch_arena() const
return reference to patch arena
Definition: patch_op.hh:180
virtual void eval()=0
Reinit function of operation. Implementation in descendants.
uint n_dofs_
Number of DOFs of FE operations (or 1 in case of element operations)
Definition: patch_op.hh:191
PatchFEValues< spacedim > * patch_fe_
Pointer to PatchFEValues object.
Definition: patch_op.hh:192
uint n_mesh_items() const
Getter for n_mesh_items__.
ElemDimList< spacedim > * elem_dim_list_
Number and list of elements on patch.
IntTableArena int_table_
std::vector< Side > side_list_
List of sides on patch.
Base class for quadrature rules on simplices in arbitrary dimensions.
Definition: quadrature.hh:48
Quadrature make_from_side(unsigned int sid) const
Definition: quadrature.cc:47
Armor::ArmaVec< double, point_dim > point(unsigned int i) const
Returns the ith quadrature point.
Definition: quadrature.hh:151
static BaryPoint local_to_bary(const LocalPoint &lp)
Converts from local to barycentric coordinates.
Definition: ref_element.cc:188
static Eigen::Matrix< ArenaVec< double >, dim, 1 > normal_vector_array(ArenaVec< uint > loc_side_idx_vec)
Definition: ref_element.cc:280
@ FEScalar
@ FEVectorPiola
@ FEVectorContravariant
@ FEVector
unsigned int uint
ArenaVec< double > determinant(const Eigen::Matrix< ArenaVec< double >, m, n > &A)
Calculates determinant of a rectangular matrix.
Class FEValues calculates finite element data on the actual cells such as shape function values,...
Base class of FE operations.
ElemDomain
Distinguishes bulk and side domain.
Definition: patch_op.hh:35
@ domain_side
Definition: patch_op.hh:37
@ domain_bulk
Definition: patch_op.hh:36
@ patch_elem_on_domain
Index of patch element for each bulk element or side.
@ ref_side_on_sides
Ref index of side in element for each side in patch.
@ ref_side_on_quads
Ref index of side in element for each quadrature point in patch.