Reference documentation for deal.II version 8.5.1
fe_enriched.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2016 - 2017 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #include <deal.II/fe/fe_enriched.h>
18 
19 #ifdef DEAL_II_WITH_CXX14
20 
21 #include <deal.II/fe/fe_tools.h>
22 
23 DEAL_II_NAMESPACE_OPEN
24 
25 namespace
26 {
30  template <typename T>
31  std::vector<unsigned int>
32  build_multiplicities(const std::vector<std::vector<T > > &functions )
33  {
34  std::vector<unsigned int> multiplicities;
35  multiplicities.push_back(1); // the first one is non-enriched FE
36  for (unsigned int i = 0; i < functions.size(); i++)
37  multiplicities.push_back(functions[i].size());
38 
39  return multiplicities;
40  }
41 
42 
46  template <int dim, int spacedim>
47  std::vector< const FiniteElement< dim, spacedim > * >
48  build_fes(const FiniteElement<dim,spacedim> *fe_base,
49  const std::vector<const FiniteElement<dim,spacedim> * > &fe_enriched)
50  {
51  std::vector< const FiniteElement< dim, spacedim > * > fes;
52  fes.push_back(fe_base);
53  for (unsigned int i = 0; i < fe_enriched.size(); i++)
54  fes.push_back(fe_enriched[i]);
55 
56  return fes;
57  }
58 
59 
64  template <int dim, int spacedim>
65  bool
66  consistency_check (const std::vector< const FiniteElement< dim, spacedim > * > &fes,
67  const std::vector< unsigned int > &multiplicities,
68  const std::vector<std::vector<std::function<const Function<spacedim> *(const typename Triangulation<dim, spacedim>::cell_iterator &) > > > &functions)
69  {
70  AssertThrow(fes.size() > 0,
71  ExcMessage("FEs size should be >=1"));
72  AssertThrow(fes.size() == multiplicities.size(),
73  ExcMessage("FEs and multiplicities should have the same size"));
74 
75  AssertThrow (functions.size() == fes.size() - 1,
76  ExcDimensionMismatch(functions.size(), fes.size()-1));
77 
78  AssertThrow(multiplicities[0] == 1,
79  ExcMessage("First multiplicity should be 1"));
80 
81  const unsigned int n_comp_base = fes[0]->n_components();
82 
83  // start from fe=1 as 0th is always non-enriched FE.
84  for (unsigned int fe=1; fe < fes.size(); fe++)
85  {
86  const FE_Nothing<dim> *fe_nothing = dynamic_cast<const FE_Nothing<dim>*>(fes[fe]);
87  if (fe_nothing)
88  AssertThrow (fe_nothing->is_dominating(),
89  ExcMessage("Only dominating FE_Nothing can be used in FE_Enriched"));
90 
91  AssertThrow (fes[fe]->n_components() == n_comp_base,
92  ExcMessage("All elements must have the same number of components"));
93  }
94  return true;
95  }
96 
97 
101  template <int dim, int spacedim>
102  bool
103  check_if_enriched (const std::vector< const FiniteElement< dim, spacedim > * > &fes)
104  {
105  // start from fe=1 as 0th is always non-enriched FE.
106  for (unsigned int fe=1; fe < fes.size(); fe++)
107  if (dynamic_cast<const FE_Nothing<dim>*>(fes[fe]) == 0)
108  // this is not FE_Nothing => there will be enrichment
109  return true;
110 
111  return false;
112  }
113 }
114 
115 
116 template <int dim, int spacedim>
118  :
119  FE_Enriched<dim,spacedim>(fe_base,
120  FE_Nothing<dim,spacedim>(fe_base.n_components(),true),
121  NULL)
122 {
123 }
124 
125 
126 template <int dim, int spacedim>
128  const FiniteElement<dim,spacedim> &fe_enriched,
129  const Function<spacedim> *enrichment_function)
130  :
131  FE_Enriched<dim,spacedim>
132  (&fe_base,
133  std::vector<const FiniteElement<dim,spacedim>*>(1, &fe_enriched),
134  std::vector<std::vector<std::function<const Function<spacedim> *(const typename Triangulation<dim, spacedim>::cell_iterator &) > > >
135  (1,
136  std::vector<std::function<const Function<spacedim> *(const typename Triangulation<dim, spacedim>::cell_iterator &) > >
137  (1,
138  [=] (const typename Triangulation<dim, spacedim>::cell_iterator &) -> const Function<spacedim> *
139 {
140  return enrichment_function;
141 })
142  )
143 )
144 {}
145 
146 
147 template <int dim, int spacedim>
149  const std::vector<const FiniteElement<dim,spacedim> * > &fe_enriched,
150  const std::vector<std::vector<std::function<const Function<spacedim> *(const typename Triangulation<dim, spacedim>::cell_iterator &) > > > &functions)
151  :
152  FE_Enriched<dim,spacedim> (build_fes(fe_base,fe_enriched),
153  build_multiplicities(functions),
154  functions)
155 {}
156 
157 
158 template <int dim, int spacedim>
160  const std::vector< unsigned int > &multiplicities,
161  const std::vector<std::vector<std::function<const Function<spacedim> *(const typename Triangulation<dim, spacedim>::cell_iterator &) > > > &functions)
162  :
163  FiniteElement<dim,spacedim> (FETools::Compositing::multiply_dof_numbers(fes,multiplicities,false),
164  FETools::Compositing::compute_restriction_is_additive_flags(fes,multiplicities),
165  FETools::Compositing::compute_nonzero_components(fes,multiplicities,false)),
166  enrichments(functions),
167  is_enriched(check_if_enriched(fes)),
168  fe_system(fes,multiplicities)
169 {
170  // descriptive error are thrown within the function.
171  Assert(consistency_check(fes,multiplicities,functions),
172  ExcInternalError());
173 
174  initialize(fes, multiplicities);
175 
176  // resize to be consistent with all FEs used to construct the FE_Enriched,
177  // even though we will never use the 0th element.
178  base_no_mult_local_enriched_dofs.resize(fes.size());
179  for (unsigned int fe=1; fe < fes.size(); fe++)
180  base_no_mult_local_enriched_dofs[fe].resize(multiplicities[fe]);
181 
184  this->n_base_elements()));
185 
186  // build the map: (base_no, base_m) -> vector of local element DoFs
187  for (unsigned int system_index=0; system_index<this->dofs_per_cell;
188  ++system_index)
189  {
190  const unsigned int base_no = this->system_to_base_table[system_index].first.first;
191  if (base_no == 0) // 0th is always non-enriched FE
192  continue;
193 
194  const unsigned int base_m = this->system_to_base_table[system_index].first.second;
195 
196  Assert (base_m < base_no_mult_local_enriched_dofs[base_no].size(),
197  ExcMessage("Size mismatch for base_no_mult_local_enriched_dofs: "
198  "base_index = " + std::to_string(this->system_to_base_table[system_index].second) +
199  "; base_no = " + std::to_string(base_no) +
200  "; base_m = " + std::to_string(base_m) +
201  "; system_index = " + std::to_string(system_index)));
202 
203  Assert (base_m < base_no_mult_local_enriched_dofs[base_no].size(),
204  ExcDimensionMismatch(base_m,
205  base_no_mult_local_enriched_dofs[base_no].size()));
206 
207  base_no_mult_local_enriched_dofs[base_no][base_m].push_back(system_index);
208  }
209 
210  // make sure that local_enriched_dofs.size() is correct, that is equals to DoFs
211  // per cell of the corresponding FE.
212  for (unsigned int base_no = 1; base_no < base_no_mult_local_enriched_dofs.size(); base_no++)
213  {
214  for (unsigned int m=0; m < base_no_mult_local_enriched_dofs[base_no].size(); m++)
215  Assert ( base_no_mult_local_enriched_dofs[base_no][m].size() == fes[base_no]->dofs_per_cell,
217  fes[base_no]->dofs_per_cell));
218  }
219 }
220 
221 
222 template <int dim, int spacedim>
223 const std::vector<std::vector<std::function<const Function<spacedim> *(const typename Triangulation<dim, spacedim>::cell_iterator &) > > >
225 {
226  return enrichments;
227 }
228 
229 
230 template <int dim, int spacedim>
231 double
233  const Point< dim > &p) const
234 {
235  Assert(!is_enriched, ExcMessage("For enriched finite elements shape_value() can not be defined on the reference element."));
236  return fe_system.shape_value(i,p);
237 }
238 
239 
240 template <int dim, int spacedim>
243 {
244  std::vector< const FiniteElement< dim, spacedim > * > fes;
245  std::vector< unsigned int > multiplicities;
246 
247  for (unsigned int i=0; i<this->n_base_elements(); i++)
248  {
249  fes.push_back( & base_element(i) );
250  multiplicities.push_back(this->element_multiplicity(i) );
251  }
252 
253  return new FE_Enriched<dim,spacedim>(fes, multiplicities, get_enrichments());
254 }
255 
256 
257 template <int dim, int spacedim>
260 {
261  UpdateFlags out = fe_system.requires_update_flags(flags);
262 
263  if (is_enriched)
264  {
265  // if we ask for values or gradients, then we would need quadrature points
266  if (flags & (update_values | update_gradients))
268 
269  // if need gradients, add update_values due to product rule
270  if (out & update_gradients)
271  out |= update_values;
272  }
273 
274  Assert (!(flags & update_3rd_derivatives),
276 
277  return out;
278 }
279 
280 
281 template <int dim, int spacedim>
282 template <int dim_1>
285  const UpdateFlags flags,
286  const Quadrature<dim_1> &quadrature) const
287 {
288  Assert ((dynamic_cast<typename FESystem<dim,spacedim>::InternalData *> (fes_data.get()) != NULL),
289  ExcInternalError());
290  typename FESystem<dim,spacedim>::InternalData *data_fesystem =
291  static_cast<typename FESystem<dim,spacedim>::InternalData *> (fes_data.get());
292 
293  // FESystem::InternalData will be aggregated (owned) by
294  // our InternalData.
295  fes_data.release();
296  InternalData *data = new InternalData(std::unique_ptr<typename FESystem<dim,spacedim>::InternalData>(data_fesystem));
297 
298  // copy update_each from FESystem data:
299  data->update_each = data_fesystem->update_each;
300 
301  // resize cache array according to requested flags
302  data->enrichment.resize(this->n_base_elements());
303 
304  const unsigned int n_q_points = quadrature.size();
305 
306  for (unsigned int base=0; base < this->n_base_elements(); ++base)
307  {
308  data->enrichment[base].resize(this->element_multiplicity(base));
309  for (unsigned int m = 0; m < this->element_multiplicity(base); ++m)
310  {
311  if (flags & update_values)
312  data->enrichment[base][m].values.resize(n_q_points);
313 
314  if (flags & update_gradients)
315  data->enrichment[base][m].gradients.resize(n_q_points);
316 
317  if (flags & update_hessians)
318  data->enrichment[base][m].hessians.resize(n_q_points);
319  }
320  }
321 
322  return data;
323 }
324 
325 
326 template <int dim, int spacedim>
329  const Mapping<dim,spacedim> &mapping,
330  const Quadrature<dim-1> &quadrature,
332 {
333  return setup_data(std::unique_ptr<typename FiniteElement<dim,spacedim>::InternalDataBase>(fe_system.get_face_data(update_flags,mapping,quadrature,output_data)),
334  update_flags,
335  quadrature);
336 }
337 
338 
339 template <int dim, int spacedim>
342  const Mapping<dim,spacedim> &mapping,
343  const Quadrature<dim-1> &quadrature,
345 {
346  return setup_data(std::unique_ptr<typename FiniteElement<dim,spacedim>::InternalDataBase>(fe_system.get_subface_data(update_flags,mapping,quadrature,output_data)),
347  update_flags,
348  quadrature);
349 }
350 
351 
352 template <int dim, int spacedim>
355  const Mapping<dim,spacedim> &mapping,
356  const Quadrature<dim> &quadrature,
358 {
359  return setup_data(std::unique_ptr<typename FiniteElement<dim,spacedim>::InternalDataBase>(fe_system.get_data(flags,mapping,quadrature,output_data)),
360  flags,
361  quadrature);
362 }
363 
364 
365 template <int dim, int spacedim>
367  const std::vector<unsigned int> &multiplicities)
368 {
369  Assert (fes.size() == multiplicities.size(),
370  ExcDimensionMismatch (fes.size(), multiplicities.size()) );
371 
372  // Note that we need to skip every fe with multiplicity 0 in the following block of code
373  this->base_to_block_indices.reinit(0, 0);
374 
375  for (unsigned int i=0; i<fes.size(); i++)
376  if (multiplicities[i]>0)
377  this->base_to_block_indices.push_back( multiplicities[i] );
378 
379  {
380  // If the system is not primitive, these have not been initialized by
381  // FiniteElement
382  this->system_to_component_table.resize(this->dofs_per_cell);
383  this->face_system_to_component_table.resize(this->dofs_per_face);
384 
385  FETools::Compositing::build_cell_tables(this->system_to_base_table,
386  this->system_to_component_table,
387  this->component_to_base_table,
388  *this,
389  false);
390 
391  FETools::Compositing::build_face_tables(this->face_system_to_base_table,
392  this->face_system_to_component_table,
393  *this,
394  false);
395  }
396 
397  // restriction and prolongation matrices are built on demand
398 
399  // now set up the interface constraints for h-refinement.
400  // take them from fe_system:
401  this->interface_constraints = fe_system.interface_constraints;
402 
403  // if we just wrap another FE (i.e. use FE_Nothing as a second FE)
404  // then it makes sense to have support points.
405  // However, functions like interpolate_boundary_values() need all FEs inside
406  // FECollection to be able to provide support points irrespectively whether
407  // this FE sits on the boundary or not. Thus for moment just copy support
408  // points from fe system:
409  {
410  this->unit_support_points = fe_system.unit_support_points;
411  this->unit_face_support_points = fe_system.unit_face_support_points;
412  }
413 
414  // take adjust_quad_dof_index_for_face_orientation_table from FESystem:
415  {
416  this->adjust_line_dof_index_for_line_orientation_table = fe_system.adjust_line_dof_index_for_line_orientation_table;
417  }
418 }
419 
420 
421 template <int dim, int spacedim>
422 std::string
424 {
425  std::ostringstream namebuf;
426 
427  namebuf << "FE_Enriched<"
428  << Utilities::dim_string(dim,spacedim)
429  << ">[";
430  for (unsigned int i=0; i< this->n_base_elements(); ++i)
431  {
432  namebuf << base_element(i).get_name();
433  if (this->element_multiplicity(i) != 1)
434  namebuf << '^' << this->element_multiplicity(i);
435  if (i != this->n_base_elements()-1)
436  namebuf << '-';
437  }
438  namebuf << ']';
439 
440  return namebuf.str();
441 }
442 
443 
444 template <int dim, int spacedim>
446 FE_Enriched<dim,spacedim>::base_element (const unsigned int index) const
447 {
448  return fe_system.base_element(index);
449 }
450 
451 
452 template <int dim, int spacedim>
453 void
455  const CellSimilarity::Similarity cell_similarity,
456  const Quadrature< dim > &quadrature,
457  const Mapping< dim, spacedim > &mapping,
458  const typename Mapping< dim, spacedim >::InternalDataBase &mapping_internal,
459  const ::internal::FEValues::MappingRelatedData< dim, spacedim > &mapping_data,
460  const typename FiniteElement<dim,spacedim>::InternalDataBase &fe_internal,
462  ) const
463 {
464  Assert (dynamic_cast<const InternalData *> (&fe_internal) != NULL,
465  ExcInternalError());
466  const InternalData &fe_data = static_cast<const InternalData &> (fe_internal);
467 
468  // call FESystem's method to fill everything without enrichment function
469  fe_system.fill_fe_values(cell,
470  cell_similarity,
471  quadrature,
472  mapping,
473  mapping_internal,
474  mapping_data,
475  *fe_data.fesystem_data,
476  output_data);
477 
478  if (is_enriched)
479  multiply_by_enrichment(quadrature,
480  fe_data,
481  mapping_data,
482  cell,
483  output_data);
484 }
485 
486 
487 template <int dim, int spacedim>
488 void
491  const unsigned int face_no,
492  const Quadrature< dim-1 > &quadrature,
493  const Mapping< dim, spacedim > &mapping,
494  const typename Mapping< dim, spacedim >::InternalDataBase &mapping_internal,
495  const ::internal::FEValues::MappingRelatedData< dim, spacedim > &mapping_data,
496  const typename FiniteElement<dim,spacedim>::InternalDataBase &fe_internal,
498 ) const
499 {
500  Assert (dynamic_cast<const InternalData *> (&fe_internal) != NULL,
501  ExcInternalError());
502  const InternalData &fe_data = static_cast<const InternalData &> (fe_internal);
503 
504  // call FESystem's method to fill everything without enrichment function
505  fe_system.fill_fe_face_values(cell,
506  face_no,
507  quadrature,
508  mapping,
509  mapping_internal,
510  mapping_data,
511  *fe_data.fesystem_data,
512  output_data);
513 
514  if (is_enriched)
515  multiply_by_enrichment(quadrature,
516  fe_data,
517  mapping_data,
518  cell,
519  output_data);
520 }
521 
522 
523 template <int dim, int spacedim>
524 void
527  const unsigned int face_no,
528  const unsigned int sub_no,
529  const Quadrature< dim-1 > &quadrature,
530  const Mapping< dim, spacedim > &mapping,
531  const typename Mapping< dim, spacedim >::InternalDataBase &mapping_internal,
532  const ::internal::FEValues::MappingRelatedData< dim, spacedim > &mapping_data,
533  const typename FiniteElement<dim,spacedim>::InternalDataBase &fe_internal,
535 ) const
536 {
537  Assert (dynamic_cast<const InternalData *> (&fe_internal) != NULL,
538  ExcInternalError());
539  const InternalData &fe_data = static_cast<const InternalData &> (fe_internal);
540 
541  // call FESystem's method to fill everything without enrichment function
542  fe_system.fill_fe_subface_values(cell,
543  face_no,
544  sub_no,
545  quadrature,
546  mapping,
547  mapping_internal,
548  mapping_data,
549  *fe_data.fesystem_data,
550  output_data);
551 
552  if (is_enriched)
553  multiply_by_enrichment(quadrature,
554  fe_data,
555  mapping_data,
556  cell,
557  output_data);
558 
559 }
560 
561 
562 template <int dim, int spacedim>
563 template <int dim_1>
564 void
566 (const Quadrature<dim_1> &quadrature,
567  const InternalData &fe_data,
571 {
572  // mapping_data will contain quadrature points on the real element.
573  // fe_internal is needed to get update flags
574  // finally, output_data should store all the results we need.
575 
576  // Either dim_1==dim
577  // (fill_fe_values) or dim_1==dim-1
578  // (fill_fe_(sub)face_values)
579  Assert(dim_1==dim || dim_1==dim-1, ExcInternalError());
580  const UpdateFlags flags = fe_data.update_each;
581 
582  const unsigned int n_q_points = quadrature.size();
583 
584  // First, populate output_data object (that shall hold everything requested such
585  // as shape value, gradients, hessians, etc) from each base element.
586  // That is almost identical to FESystem::compute_fill_one_base(),
587  // the difference being that we do it irrespectively of cell_similarity
588  // and use base_fe_data.update_flags
589 
590  // TODO: do we need it only for dim_1 == dim (i.e. fill_fe_values)?
591  if (dim_1 == dim)
592  for (unsigned int base_no = 1; base_no < this->n_base_elements(); base_no++)
593  {
595  base_fe = base_element(base_no);
597  base_fe_data = fe_data.get_fe_data(base_no);
599  base_data = fe_data.get_fe_output_object(base_no);
600 
601  const UpdateFlags base_flags = base_fe_data.update_each;
602 
603  for (unsigned int system_index=0; system_index<this->dofs_per_cell;
604  ++system_index)
605  if (this->system_to_base_table[system_index].first.first == base_no)
606  {
607  const unsigned int
608  base_index = this->system_to_base_table[system_index].second;
609  Assert (base_index<base_fe.dofs_per_cell, ExcInternalError());
610 
611  // now copy. if the shape function is primitive, then there
612  // is only one value to be copied, but for non-primitive
613  // elements, there might be more values to be copied
614  //
615  // so, find out from which index to take this one value, and
616  // to which index to put
617  unsigned int out_index = 0;
618  for (unsigned int i=0; i<system_index; ++i)
619  out_index += this->n_nonzero_components(i);
620  unsigned int in_index = 0;
621  for (unsigned int i=0; i<base_index; ++i)
622  in_index += base_fe.n_nonzero_components(i);
623 
624  // then loop over the number of components to be copied
625  Assert (this->n_nonzero_components(system_index) ==
626  base_fe.n_nonzero_components(base_index),
627  ExcInternalError());
628  for (unsigned int s=0; s<this->n_nonzero_components(system_index); ++s)
629  {
630  if (base_flags & update_values)
631  for (unsigned int q=0; q<n_q_points; ++q)
632  output_data.shape_values[out_index+s][q] =
633  base_data.shape_values(in_index+s,q);
634 
635  if (base_flags & update_gradients)
636  for (unsigned int q=0; q<n_q_points; ++q)
637  output_data.shape_gradients[out_index+s][q] =
638  base_data.shape_gradients[in_index+s][q];
639 
640  if (base_flags & update_hessians)
641  for (unsigned int q=0; q<n_q_points; ++q)
642  output_data.shape_hessians[out_index+s][q] =
643  base_data.shape_hessians[in_index+s][q];
644  }
645  }
646  }
647 
648  Assert (base_no_mult_local_enriched_dofs.size() == fe_data.enrichment.size(),
649  ExcDimensionMismatch(base_no_mult_local_enriched_dofs.size(),
650  fe_data.enrichment.size()));
651  // calculate hessians, gradients and values for each function
652  for (unsigned int base_no = 1; base_no < this->n_base_elements(); base_no++)
653  {
654  Assert (base_no_mult_local_enriched_dofs[base_no].size() == fe_data.enrichment[base_no].size(),
655  ExcDimensionMismatch(base_no_mult_local_enriched_dofs[base_no].size(),
656  fe_data.enrichment[base_no].size()));
657  for (unsigned int m=0; m < base_no_mult_local_enriched_dofs[base_no].size(); m++)
658  {
659  Assert (enrichments[base_no-1][m](cell) !=NULL,
660  ExcMessage("The pointer to the enrichment function is NULL"));
661 
662  Assert (enrichments[base_no-1][m](cell)->n_components == 1,
663  ExcMessage("Only scalar-valued enrichment functions are allowed"));
664 
665  if (flags & update_hessians)
666  {
667  Assert (fe_data.enrichment[base_no][m].hessians.size() == n_q_points,
668  ExcDimensionMismatch(fe_data.enrichment[base_no][m].hessians.size(),
669  n_q_points));
670  for (unsigned int q=0; q<n_q_points; q++)
671  fe_data.enrichment[base_no][m].hessians[q] = enrichments[base_no-1][m](cell)->hessian (mapping_data.quadrature_points[q]);
672  }
673 
674  if (flags & update_gradients)
675  {
676  Assert (fe_data.enrichment[base_no][m].gradients.size() == n_q_points,
677  ExcDimensionMismatch(fe_data.enrichment[base_no][m].gradients.size(),
678  n_q_points));
679  for (unsigned int q=0; q<n_q_points; q++)
680  fe_data.enrichment[base_no][m].gradients[q] = enrichments[base_no-1][m](cell)->gradient(mapping_data.quadrature_points[q]);
681  }
682 
683  if (flags & update_values)
684  {
685  Assert (fe_data.enrichment[base_no][m].values.size() == n_q_points,
686  ExcDimensionMismatch(fe_data.enrichment[base_no][m].values.size(),
687  n_q_points));
688  for (unsigned int q=0; q<n_q_points; q++)
689  fe_data.enrichment[base_no][m].values[q] = enrichments[base_no-1][m](cell)->value (mapping_data.quadrature_points[q]);
690  }
691  }
692  }
693 
694  // Finally, update the standard data stored in output_data
695  // by expanding the product rule for enrichment function.
696  // note that the order if important, namely
697  // output_data.shape_XYZ contains values of standard FEM and we overwrite
698  // it with the updated one in the following order: hessians -> gradients -> values
699  if (flags & update_hessians)
700  {
701  for (unsigned int base_no = 1; base_no < this->n_base_elements(); base_no++)
702  {
703  for (unsigned int m=0; m < base_no_mult_local_enriched_dofs[base_no].size(); m++)
704  for (unsigned int i=0; i < base_no_mult_local_enriched_dofs[base_no][m].size(); i++)
705  {
706  const unsigned int enriched_dof = base_no_mult_local_enriched_dofs[base_no][m][i];
707  for (unsigned int q=0; q<n_q_points; ++q)
708  {
709  const Tensor<2, spacedim> grad_grad = outer_product(output_data.shape_gradients[enriched_dof][q],
710  fe_data.enrichment[base_no][m].gradients[q]);
711  const Tensor<2,spacedim,double> sym_grad_grad = symmetrize (grad_grad) * 2.0; // symmetrize does [s+s^T]/2
712 
713  output_data.shape_hessians [enriched_dof][q]*= fe_data.enrichment[base_no][m].values[q];
714  output_data.shape_hessians [enriched_dof][q]+=
715  sym_grad_grad +
716  output_data.shape_values [enriched_dof][q] * fe_data.enrichment[base_no][m].hessians[q];
717  }
718  }
719  }
720  }
721 
722  if (flags & update_gradients)
723  for (unsigned int base_no = 1; base_no < this->n_base_elements(); base_no++)
724  {
725  for (unsigned int m=0; m < base_no_mult_local_enriched_dofs[base_no].size(); m++)
726  for (unsigned int i=0; i < base_no_mult_local_enriched_dofs[base_no][m].size(); i++)
727  {
728  const unsigned int enriched_dof = base_no_mult_local_enriched_dofs[base_no][m][i];
729  for (unsigned int q=0; q<n_q_points; ++q)
730  {
731  output_data.shape_gradients[enriched_dof][q]*= fe_data.enrichment[base_no][m].values[q];
732  output_data.shape_gradients[enriched_dof][q]+=
733  output_data.shape_values [enriched_dof][q] * fe_data.enrichment[base_no][m].gradients[q];
734  }
735  }
736  }
737 
738  if (flags & update_values)
739  for (unsigned int base_no = 1; base_no < this->n_base_elements(); base_no++)
740  {
741  for (unsigned int m=0; m < base_no_mult_local_enriched_dofs[base_no].size(); m++)
742  for (unsigned int i=0; i < base_no_mult_local_enriched_dofs[base_no][m].size(); i++)
743  {
744  const unsigned int enriched_dof = base_no_mult_local_enriched_dofs[base_no][m][i];
745  for (unsigned int q=0; q<n_q_points; ++q)
746  {
747  output_data.shape_values[enriched_dof][q] *= fe_data.enrichment[base_no][m].values[q];
748  }
749  }
750  }
751 }
752 
753 
754 template <int dim, int spacedim>
758 {
759  return fe_system;
760 }
761 
762 
763 template <int dim, int spacedim>
764 bool
767 {
768  return true;
769 }
770 
771 
772 template <int dim, int spacedim>
773 void
776  FullMatrix<double> &matrix) const
777 {
778  if (const FE_Enriched<dim,spacedim> *fe_enr_other
779  = dynamic_cast<const FE_Enriched<dim,spacedim>*>(&source))
780  {
781  fe_system.get_face_interpolation_matrix(fe_enr_other->get_fe_system(),
782  matrix);
783  }
784  else
785  {
786  typedef FiniteElement<dim,spacedim> FEL;
787  AssertThrow(false,typename FEL::ExcInterpolationNotImplemented());
788  }
789 }
790 
791 
792 template <int dim, int spacedim>
793 void
796  const unsigned int subface,
797  FullMatrix<double> &matrix) const
798 {
799  if (const FE_Enriched<dim,spacedim> *fe_enr_other
800  = dynamic_cast<const FE_Enriched<dim,spacedim>*>(&source))
801  {
802  fe_system.get_subface_interpolation_matrix(fe_enr_other->get_fe_system(),
803  subface,
804  matrix);
805  }
806  else
807  {
808  typedef FiniteElement<dim,spacedim> FEL;
809  AssertThrow(false,typename FEL::ExcInterpolationNotImplemented());
810  }
811 }
812 
813 
814 template <int dim, int spacedim>
815 std::vector<std::pair<unsigned int, unsigned int> >
818 {
819  if (const FE_Enriched<dim,spacedim> *fe_enr_other
820  = dynamic_cast<const FE_Enriched<dim,spacedim>*>(&fe_other))
821  {
822  return fe_system.hp_vertex_dof_identities(fe_enr_other->get_fe_system());
823  }
824  else
825  {
826  Assert (false, ExcNotImplemented());
827  return std::vector<std::pair<unsigned int, unsigned int> >();
828  }
829 }
830 
831 
832 template <int dim, int spacedim>
833 std::vector<std::pair<unsigned int, unsigned int> >
836 {
837  if (const FE_Enriched<dim,spacedim> *fe_enr_other
838  = dynamic_cast<const FE_Enriched<dim,spacedim>*>(&fe_other))
839  {
840  return fe_system.hp_line_dof_identities(fe_enr_other->get_fe_system());
841  }
842  else
843  {
844  Assert (false, ExcNotImplemented());
845  return std::vector<std::pair<unsigned int, unsigned int> >();
846  }
847 }
848 
849 
850 template <int dim, int spacedim>
851 std::vector<std::pair<unsigned int, unsigned int> >
854 {
855  if (const FE_Enriched<dim,spacedim> *fe_enr_other
856  = dynamic_cast<const FE_Enriched<dim,spacedim>*>(&fe_other))
857  {
858  return fe_system.hp_quad_dof_identities(fe_enr_other->get_fe_system());
859  }
860  else
861  {
862  Assert (false, ExcNotImplemented());
863  return std::vector<std::pair<unsigned int, unsigned int> >();
864  }
865 }
866 
867 
868 template <int dim, int spacedim>
872 {
873  // need to decide which element constrain another.
874  // for example Q(2) dominate Q(4) and thus some DoFs of Q(4) will be constrained.
875  // If we have Q(2) and Q(4)+POU, then it's clear that Q(2) dominates,
876  // namely our DoFs will be constrained to make field continuous.
877  // However, we need to check for situations like Q(4) vs Q(2)+POU.
878  // In that case the domination for the underlying FEs should be the other way,
879  // but this implies that we can't constrain POU dofs to make the field continuous.
880  // In that case, through an error
881 
882  // if it's also enriched, do domination based on each one's FESystem
883  if (const FE_Enriched<dim,spacedim> *fe_enr_other
884  = dynamic_cast<const FE_Enriched<dim,spacedim>*>(&fe_other))
885  {
886  return fe_system.compare_for_face_domination(fe_enr_other->get_fe_system());
887  }
888  else
889  {
890  Assert (false, ExcNotImplemented());
892  }
893 }
894 
895 template <int dim, int spacedim>
896 const FullMatrix<double> &
898  const RefinementCase<dim> &refinement_case) const
899 {
900  return fe_system.get_prolongation_matrix(child, refinement_case);
901 }
902 
903 
904 template <int dim, int spacedim>
905 const FullMatrix<double> &
907  const RefinementCase<dim> &refinement_case) const
908 {
909  return fe_system.get_restriction_matrix(child, refinement_case);
910 }
911 
912 
913 /* ----------------------- FESystem::InternalData ------------------- */
914 
915 
916 template <int dim, int spacedim>
918  :
919  fesystem_data(std::move(fesystem_data))
920 {}
921 
922 
923 template <int dim, int spacedim>
926 InternalData::get_fe_data (const unsigned int base_no) const
927 {
928  return fesystem_data->get_fe_data(base_no);
929 }
930 
931 
932 template <int dim, int spacedim>
935 InternalData::get_fe_output_object (const unsigned int base_no) const
936 {
937  return fesystem_data->get_fe_output_object(base_no);
938 }
939 
940 
941 // explicit instantiations
942 #include "fe_enriched.inst"
943 
944 DEAL_II_NAMESPACE_CLOSE
945 
946 #endif // CXX14
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_line_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const
Definition: fe_enriched.cc:835
Shape function values.
bool is_dominating() const
Definition: fe_nothing.cc:165
Definition: tria.h:67
InternalData(std::unique_ptr< typename FESystem< dim, spacedim >::InternalData > fesystem_data)
Definition: fe_enriched.cc:917
unsigned int n_nonzero_components(const unsigned int i) const
Definition: fe.h:3023
FE_Enriched(const FiniteElement< dim, spacedim > &fe_base, const FiniteElement< dim, spacedim > &fe_enriched, const Function< spacedim > *enrichment_function)
Definition: fe_enriched.cc:127
void initialize(const std::vector< const FiniteElement< dim, spacedim > *> &fes, const std::vector< unsigned int > &multiplicities)
Definition: fe_enriched.cc:366
SymmetricTensor< 2, dim, Number > symmetrize(const Tensor< 2, dim, Number > &t)
void build_face_tables(std::vector< std::pair< std::pair< unsigned int, unsigned int >, unsigned int > > &face_system_to_base_table, std::vector< std::pair< unsigned int, unsigned int > > &face_system_to_component_table, const FiniteElement< dim, spacedim > &finite_element, const bool do_tensor_product=true)
Definition: fe_tools.cc:776
virtual void get_subface_interpolation_matrix(const FiniteElement< dim, spacedim > &source, const unsigned int subface, FullMatrix< double > &matrix) const
Definition: fe_enriched.cc:795
std::vector< std::vector< EnrichmentValues > > enrichment
Definition: fe_enriched.h:518
STL namespace.
Transformed quadrature points.
#define AssertThrow(cond, exc)
Definition: exceptions.h:369
virtual const FiniteElement< dim, spacedim > & base_element(const unsigned int index) const
Definition: fe_enriched.cc:446
const FESystem< dim, spacedim > & get_fe_system() const
Definition: fe_enriched.cc:757
virtual UpdateFlags requires_update_flags(const UpdateFlags update_flags) const
Definition: fe_enriched.cc:259
static ::ExceptionBase & ExcMessage(std::string arg1)
virtual bool hp_constraints_are_implemented() const
Definition: fe_enriched.cc:766
virtual double shape_value(const unsigned int i, const Point< dim > &p) const
Definition: fe_enriched.cc:232
Third derivatives of shape functions.
#define Assert(cond, exc)
Definition: exceptions.h:313
UpdateFlags
internal::FEValues::FiniteElementRelatedData< dim, spacedim > & get_fe_output_object(const unsigned int base_no) const
Definition: fe_enriched.cc:935
virtual const FullMatrix< double > & get_prolongation_matrix(const unsigned int child, const RefinementCase< dim > &refinement_case=RefinementCase< dim >::isotropic_refinement) const
Definition: fe_enriched.cc:897
FiniteElement< dim, spacedim >::InternalDataBase & get_fe_data(const unsigned int base_no) const
Definition: fe_enriched.cc:926
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
Abstract base class for mapping classes.
Definition: dof_tools.h:46
virtual std::string get_name() const
Definition: fe_enriched.cc:423
Definition: fe.h:33
void multiply_by_enrichment(const Quadrature< dim_1 > &quadrature, const InternalData &fe_data, const internal::FEValues::MappingRelatedData< dim, spacedim > &mapping_data, const typename Triangulation< dim, spacedim >::cell_iterator &cell, internal::FEValues::FiniteElementRelatedData< dim, spacedim > &output_data) const
Definition: fe_enriched.cc:566
SymmetricTensor< 4, dim, Number > outer_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, Number > &t2)
Second derivatives of shape functions.
std::string dim_string(const int dim, const int spacedim)
Definition: utilities.cc:161
FiniteElement< dim, spacedim >::InternalDataBase * setup_data(std::unique_ptr< typename FiniteElement< dim, spacedim >::InternalDataBase > fes_data, const UpdateFlags flags, const Quadrature< dim_1 > &quadrature) const
Definition: fe_enriched.cc:284
virtual FiniteElement< dim, spacedim >::InternalDataBase * get_data(const UpdateFlags flags, const Mapping< dim, spacedim > &mapping, const Quadrature< dim > &quadrature, ::internal::FEValues::FiniteElementRelatedData< dim, spacedim > &output_data) const
Definition: fe_enriched.cc:354
unsigned int size() const
const unsigned int dofs_per_cell
Definition: fe_base.h:295
virtual FiniteElement< dim, spacedim >::InternalDataBase * get_face_data(const UpdateFlags update_flags, const Mapping< dim, spacedim > &mapping, const Quadrature< dim-1 > &quadrature, ::internal::FEValues::FiniteElementRelatedData< dim, spacedim > &output_data) const
Definition: fe_enriched.cc:328
virtual FiniteElement< dim, spacedim >::InternalDataBase * get_subface_data(const UpdateFlags update_flags, const Mapping< dim, spacedim > &mapping, const Quadrature< dim-1 > &quadrature, ::internal::FEValues::FiniteElementRelatedData< dim, spacedim > &output_data) const
Definition: fe_enriched.cc:341
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_quad_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const
Definition: fe_enriched.cc:853
Shape function gradients.
std::vector< std::vector< std::vector< unsigned int > > > base_no_mult_local_enriched_dofs
Definition: fe_enriched.h:527
std::vector< Point< spacedim > > quadrature_points
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_vertex_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const
Definition: fe_enriched.cc:817
void build_cell_tables(std::vector< std::pair< std::pair< unsigned int, unsigned int >, unsigned int > > &system_to_base_table, std::vector< std::pair< unsigned int, unsigned int > > &system_to_component_table, std::vector< std::pair< std::pair< unsigned int, unsigned int >, unsigned int > > &component_to_base_table, const FiniteElement< dim, spacedim > &finite_element, const bool do_tensor_product=true)
Definition: fe_tools.cc:581
virtual void get_face_interpolation_matrix(const FiniteElement< dim, spacedim > &source, FullMatrix< double > &matrix) const
Definition: fe_enriched.cc:775
static ::ExceptionBase & ExcNotImplemented()
virtual FiniteElement< dim, spacedim > * clone() const
Definition: fe_enriched.cc:242
unsigned int n_components(const DoFHandler< dim, spacedim > &dh)
unsigned int n_base_elements() const
Definition: fe.h:2853
virtual const FullMatrix< double > & get_restriction_matrix(const unsigned int child, const RefinementCase< dim > &refinement_case=RefinementCase< dim >::isotropic_refinement) const
Definition: fe_enriched.cc:906
virtual FiniteElementDomination::Domination compare_for_face_domination(const FiniteElement< dim, spacedim > &fe_other) const
Definition: fe_enriched.cc:871
UpdateFlags update_each
Definition: fe.h:638
std::vector< std::pair< std::pair< unsigned int, unsigned int >, unsigned int > > system_to_base_table
Definition: fe.h:2309
static ::ExceptionBase & ExcInternalError()