[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
field.cpp
1 #include <ostream>
2 
3 #include <deal.II/base/tensor.h>
4 #include <deal.II/base/symmetric_tensor.h>
5 #include <deal.II/lac/vector.h>
6 #include <deal.II/base/geometry_info.h>
7 
8 #include "field.h"
9 
10 namespace PHiLiP {
11 
12 namespace GridRefinement {
13 
14 /***** ***** Element ***** *****/
15 template <int dim, typename real>
17  const typename Element<dim,real>::VertexList& vertices)
18 {
19 
20  // example notation from 2D (for nodes and chords)
21  /* ^ chord_list[1]
22  |
23  2---+---3
24  | | |
25  +---o---+---> chord_list[0]
26  | | |
27  0---+---1
28  */
29 
30  // construcing the list of chords
32 
33  // to determine distance from face center to face center
34  // can use the difference of average node positions on each face
35  // taking average (divide by number of face nodes) after summation
36 
37  // looping over the nodes and adding either their +/- weighting to the corresponding chords
38  for(unsigned int vertex = 0; vertex < dealii::GeometryInfo<dim>::vertices_per_cell; ++vertex){
39 
40  // each vertex should have an impact on the chord of each axis
41  for(unsigned int i = 0; i < dim; ++i){
42 
43  // adding either positive or negative weighting
44  // can be determined by sign of i^th bit in vertex id binary
45  if(vertex>>i % 2 == 0){
46 
47  // lies on +ve direction of axis
48  chord_list[i] += vertices[vertex];
49 
50  }else{
51 
52  // lies on -ve face of axis
53  chord_list[i] -= vertices[vertex];
54 
55  }
56 
57  }
58 
59  }
60 
61  // applying averaging for each node position (based on number on each face)
62  for(unsigned int i = 0; i < dim; ++i)
63  chord_list[i] /= dealii::GeometryInfo<dim>::vertices_per_face;
64 
65  // chord vectors should be fully computed
66  return chord_list;
67 
68 }
69 
70 /***** ***** ElementIsotropic ***** *****/
71 
72 template <int dim, typename real>
74 {
75  return m_scale;
76 }
77 
78 template <int dim, typename real>
80  const real val)
81 {
82  m_scale = val;
83 }
84 
85 template <int dim, typename real>
87 {
88  return m_scale;
89 }
90 
91 template <int dim, typename real>
93  const std::array<real,dim>& /* ratio */)
94 {
95  assert(0); // anisotropic ratio cannot be modified
96 }
97 
98 template <int dim, typename real>
100 {
101  std::array<real,dim> anisotropic_ratio;
102 
103  for(unsigned int j = 0; j < dim; ++j)
104  anisotropic_ratio[j] = get_anisotropic_ratio(j);
105 
106  return anisotropic_ratio;
107 }
108 
109 template <int dim, typename real>
111  const unsigned int /* j */)
112 {
113  return real(1.0);
114 }
115 
116 template <int dim, typename real>
118  const std::array<dealii::Tensor<1,dim,real>,dim>& /* unit_axis */)
119 {
120  assert(0); // unit axis cannot be modified
121 }
122 
123 template <int dim, typename real>
124 std::array<dealii::Tensor<1,dim,real>,dim> ElementIsotropic<dim,real>::get_unit_axis()
125 {
126  std::array<dealii::Tensor<1,dim,real>,dim> unit_axis;
127 
128  for(unsigned int j = 0; j < dim; ++j)
129  unit_axis[j] = get_unit_axis(j);
130 
131  return unit_axis;
132 }
133 
134 template <int dim, typename real>
135 dealii::Tensor<1,dim,real> ElementIsotropic<dim,real>::get_unit_axis(
136  const unsigned int j)
137 {
138  // getting unit vector in j^th coordinate
139  dealii::Tensor<1,dim,real> u;
140  u[j] = real(1.0);
141 
142  return u;
143 }
144 
145 template <int dim, typename real>
147  const std::array<dealii::Tensor<1,dim,real>,dim>& /* axis */)
148 {
149  assert(0); // axis cannot be modified
150 }
151 
152 template <int dim, typename real>
153 std::array<dealii::Tensor<1,dim,real>,dim> ElementIsotropic<dim,real>::get_axis()
154 {
155  std::array<dealii::Tensor<1,dim,real>,dim> axis;
156 
157  for(unsigned int j = 0; j < dim; ++j)
158  axis[j] = get_axis(j);
159 
160  return axis;
161 }
162 
163 template <int dim, typename real>
164 dealii::Tensor<1,dim,real> ElementIsotropic<dim,real>::get_axis(
165  const unsigned int j)
166 {
167  return get_unit_axis(j) * get_scale();
168 }
169 
170 template <int dim, typename real>
171 dealii::Tensor<2,dim,real> ElementIsotropic<dim,real>::get_metric()
172 {
173  dealii::Tensor<2,dim,real> M;
174  for(unsigned int i = 0; i < dim; ++i)
175  M[i] = m_scale * get_unit_axis(i);
176 
177  return M;
178 }
179 
180 template <int dim, typename real>
182 {
183  // building the rotation matrix
184  dealii::Tensor<2,dim,real> R;
185  for(unsigned int i = 0; i < dim; ++i)
186  R[i] = get_unit_axis(i);
187 
188  // assuming R^-1 = R^T (orthogonal)
189  dealii::Tensor<2,dim,real> RT = transpose(R);
190 
191  // assembling the inverse metric based on
192  // M = 1/h diag(1/r_i,...) R(-\theta)
193  dealii::Tensor<2,dim,real> M;
194  for(unsigned int i = 0; i < dim; ++i)
195  M[i] = (1.0/m_scale) * RT[i];
196 
197  return M;
198 }
199 
200 template <int dim, typename real>
202  const typename Element<dim,real>::VertexList& vertices)
203 {
204  // to be consistent with anisotropic case using the average from chord lengths
205  typename Element<dim,real>::ChordList chord_list = Element<dim,real>::get_chord_list(vertices);
206 
207  // based on \Prod{L_i} = \Prod{h r_i} = h^dim \Prod{r_i}
208  // where the product of axes anisotropy should be 1.
209  real product = 1.0;
210  for(unsigned int i = 0; i < dim; ++i)
211  product *= chord_list[i].norm();
212 
213  // setting the scale from h (ignoring axes alignment)
214  m_scale = pow(product, -1.0/dim);
215 }
216 
217 template <int dim, typename real>
219  const std::array<real,dim>& /* derivative_value */,
220  const std::array<dealii::Tensor<1,dim,real>,dim>& /* derivative_direction */,
221  const unsigned int /* order */)
222 {
223  // invalid, cannot set anisotropy on isotropic cell
224  assert(0);
225 }
226 
227 template <int dim, typename real>
229  const real /* anisotropic_ratio_min */,
230  const real /* anisotropic_ratio_max */)
231 {
232  // invalid, cannot set anisotropy on isotropic cell
233  assert(0);
234 }
235 
236 /***** ***** ElementAnisotropic ***** *****/
237 
238 template <int dim, typename real>
240 {
241  // sets values to default
242  clear();
243 }
244 
245 template <int dim, typename real>
247 {
248  return m_scale;
249 }
250 
251 template <int dim, typename real>
253  const real val)
254 {
255  m_scale = val;
256 }
257 
258 template <int dim, typename real>
260 {
261  return m_scale;
262 }
263 
264 template <int dim, typename real>
266  const std::array<real,dim>& ratio)
267 {
268  m_anisotropic_ratio = ratio;
269 
270  correct_unit_axis();
271 }
272 
273 template <int dim, typename real>
275  const unsigned int j)
276 {
277  return m_anisotropic_ratio[j];
278 }
279 
280 template <int dim, typename real>
282 {
283  return m_anisotropic_ratio;
284 }
285 
286 template <int dim, typename real>
288  const std::array<dealii::Tensor<1,dim,real>,dim>& unit_axis)
289 {
290  m_unit_axis = unit_axis;
291 
292  correct_element();
293 }
294 
295 template <int dim, typename real>
296 std::array<dealii::Tensor<1,dim,real>,dim> ElementAnisotropic<dim,real>::get_unit_axis()
297 {
298  return m_unit_axis;
299 }
300 
301 template <int dim, typename real>
303  unsigned int j)
304 {
305  return m_unit_axis[j];
306 }
307 
308 template <int dim, typename real>
310  const std::array<dealii::Tensor<1,dim,real>,dim>& axis)
311 {
312  // reset length to 1 (unnormalized)
313  m_scale = 1.0;
314 
315  // copy into unit_axis, reset the aspect ratio
316  m_unit_axis = axis;
317  for(unsigned int j = 0; j < dim; ++j)
318  m_anisotropic_ratio[j] = 1.0;
319 
320  // correct and transfer values to other properties
321  correct_element();
322 }
323 
324 template <int dim, typename real>
325 dealii::Tensor<1,dim,real> ElementAnisotropic<dim,real>::get_axis(
326  unsigned int j)
327 {
328  return m_unit_axis[j] * m_anisotropic_ratio[j] * m_scale;
329 }
330 
331 template <int dim, typename real>
332 std::array<dealii::Tensor<1,dim,real>,dim> ElementAnisotropic<dim,real>::get_axis()
333 {
334  std::array<dealii::Tensor<1,dim,real>,dim> axis;
335 
336  for(unsigned int j = 0; j < dim; ++j)
337  axis[j] = get_axis(j);
338 
339  return axis;
340 }
341 
342 template <int dim, typename real>
343 dealii::Tensor<2,dim,real> ElementAnisotropic<dim,real>::get_metric()
344 {
345  dealii::Tensor<2,dim,real> M;
346 
347  for(unsigned int j = 0; j < dim; ++j)
348  M[j] = m_scale * m_anisotropic_ratio[j] * m_unit_axis[j];
349 
350  return M;
351 }
352 
353 template <int dim, typename real>
355 {
356  // building the rotation matrix
357  dealii::Tensor<2,dim,real> R;
358  for(unsigned int i = 0; i < dim; ++i)
359  R[i] = get_unit_axis(i);
360 
361  // assuming R^-1 = R^T (orthogonal)
362  dealii::Tensor<2,dim,real> RT = transpose(R);
363 
364  // assembling the inverse metric based on
365  // M = 1/h diag(1/r_i,...) R(-\theta)
366  dealii::Tensor<2,dim,real> M;
367  for(unsigned int i = 0; i < dim; ++i)
368  M[i] = (1.0)/(m_anisotropic_ratio[i]*m_scale) * RT[i];
369 
370  return M;
371 }
372 
373 template <int dim, typename real>
375 {
376  // define no element
377  m_scale = 0.0;
378 
379  for(unsigned int j = 0; j < dim; ++j){
380  // isotropic element
381  m_anisotropic_ratio[j] = 1.0;
382 
383  // setting the unit axis to e_i
384  m_unit_axis[j] = dealii::Tensor<1,dim,real>();
385  m_unit_axis[j][j] = 1.0;
386  }
387 
388 }
389 
390 template <int dim, typename real>
392 {
393  correct_unit_axis();
394  correct_anisotropic_ratio();
395 }
396 
397 template <int dim, typename real>
399 {
400  for(unsigned int j = 0; j < dim; ++j){
401  // getting the axis length
402  real length = m_unit_axis[j].norm();
403 
404  // applying change to anisotropic ratio and axis
405  m_anisotropic_ratio[j] *= length;
406  m_unit_axis[j] /= length;
407  }
408 }
409 
410 template <int dim, typename real>
412 {
413  // getting the product of the ratios
414  real product = 1.0;
415  for(unsigned int j = 0; j < dim; ++j)
416  product *= m_anisotropic_ratio[j];
417 
418  // determining the change that must be applied uniformly to each
419  real alpha = pow(product, -1.0/dim);
420 
421  // applying this change to the ratios
422  for(unsigned int j = 0; j < dim; ++j)
423  m_anisotropic_ratio[j] *= alpha;
424 
425  // scaling the length
426  m_scale *= alpha;
427 
428  // perform sorting on the anisotropic ratios
429  sort_anisotropic_ratio();
430 }
431 
432 template <int dim, typename real>
434 {
435 
436  // checking the sorting of the ansitropic ratio
437  using anisopair = std::pair< real, dealii::Tensor<1,dim,real> >;
438  std::array<anisopair, dim > sort_array;
439 
440  // storing the anisotropic ratio and their unit vectors
441  for(unsigned int j = 0; j < dim; ++j)
442  sort_array[j] = std::make_pair(
443  m_anisotropic_ratio[j],
444  m_unit_axis[j]);
445 
446  // performing the sort
447  std::sort(sort_array.begin(), sort_array.end(), [](
448  anisopair left,
449  anisopair right)
450  {
451  return left.first > right.first;
452  });
453 
454  // copying back into the corresponding array
455  for(unsigned int j = 0; j < dim; ++j){
456  m_anisotropic_ratio[j] = sort_array[j].first;
457  m_unit_axis[j] = sort_array[j].second;
458  }
459 
460 }
461 
462 template <int dim, typename real>
464  const typename Element<dim,real>::VertexList& vertices)
465 {
466  // to be consistent with anisotropic case using the average from chord lengths
467  typename Element<dim,real>::ChordList chord_list = Element<dim,real>::get_chord_list(vertices);
468 
469  // setting the axes to the chord values and correcting
470  clear();
471 
472  // overall scale is 1.0 with unit axes as the unscaled chords
473  m_scale = 1.0;
474  m_unit_axis = chord_list;
475 
476  // correcting to fix scaling issues
477  correct_element();
478 }
479 
480 template <int dim, typename real>
482  const std::array<real,dim>& derivative_value,
483  const std::array<dealii::Tensor<1,dim,real>,dim>& derivative_direction,
484  const unsigned int order)
485 {
486  // currently only implemented for dim == 2
487  assert(dim == 2);
488 
489  // std::cout << "d1 = " << derivative_value[0] << ", v1 = [" << derivative_direction[0] << "]" << std::endl;
490  // std::cout << "d2 = " << derivative_value[1] << ", v2 = [" << derivative_direction[1] << "]" << std::endl;
491  // std::cout << std::endl;
492 
493  // derivative value and direction should be an ordered set
494 
495  // computing the product of all
496  real product = 1.0;
497  for(unsigned int i = 0; i < dim; ++i)
498  product *= derivative_value[i];
499 
500  real denominator = pow(product, 1.0/dim);
501 
502  // computing anisotropy A_i/(\Prod A)^{1/dim}
503  std::array<real,dim> rho;
504  for(unsigned int i = 0; i < dim; ++i)
505  rho[i] = derivative_value[i]/denominator;
506 
507  // std::cout << "rho1 = " << rho[0] << std::endl;
508  // std::cout << "rho2 = " << rho[1] << std::endl;
509  // std::cout << std::endl;
510 
511  // anisotropy in each axis becomes \rho^{-1/(p+1)}
512  // keeping direction values as is
513  // (anisotropic ratios should be swapped, doing this by removing - sign)
514  std::array<real,dim> anisotropic_ratio;
515  for(unsigned int i = 0; i < dim; ++i)
516  anisotropic_ratio[i] = pow(rho[i], -1.0/order);
517 
518  // std::cout << "aniso1 = " << anisotropic_ratio[0] << std::endl;
519  // std::cout << "aniso2 = " << anisotropic_ratio[1] << std::endl;
520  // std::cout << std::endl;
521 
522 
523  // setting values for the cell
524  m_anisotropic_ratio = anisotropic_ratio;
525  m_unit_axis = derivative_direction;
526 
527  // correcting
528  correct_element();
529 
530 }
531 
532 template <int dim, typename real>
534  const real anisotropic_ratio_min,
535  const real anisotropic_ratio_max)
536 {
537  // boolean to keep track of if any terms have been updated
538  bool changed = false;
539 
540  // loops assume that refinements can chain together
541  // this requires that the anisotropic ratios are ordered in descending axis length
542 
543  // looping through in descending order to limit upper axes
544  for(unsigned int index = 0; index < dim; ++index){
545  // using the loop index
546  int j = index;
547 
548  if(m_anisotropic_ratio[j] > anisotropic_ratio_max){
549  // check, this should never occur on the last axis
550  assert(index != dim-1);
551 
552  // capping the value to this axis and redistributing to all subsequent axes
553  real factor = pow(m_anisotropic_ratio[j]/anisotropic_ratio_max, 1.0/(dim-1.0-index));
554  changed = true;
555 
556  // setting to the new value (the upper limit)
557  m_anisotropic_ratio[j] = anisotropic_ratio_max;
558 
559  // looping through for redistribution
560  for(unsigned int index_internal = index+1; index_internal < dim; ++index_internal){
561 
562  // getting the corresponding index (same)
563  int j_internal = index_internal;
564 
565  // applying the factor change
566  m_anisotropic_ratio[j_internal] *= factor;
567 
568  }
569 
570  }
571  }
572 
573  // looping through in ascending order to limit the lower axes
574  for(unsigned int index = 0; index < dim; ++index){
575 
576  // reversing the index
577  int j = dim-1-index;
578 
579  if(m_anisotropic_ratio[j] < anisotropic_ratio_min){
580  // check, this should never occur on the last axis
581  assert(index != dim-1);
582 
583  // capping the value to this axis and redistributing to all subsequent axes
584  real factor = pow(m_anisotropic_ratio[j]/anisotropic_ratio_min, 1.0/(dim-1.0-index));
585  changed = true;
586 
587  // setting to the new value (the upper limit)
588  m_anisotropic_ratio[j] = anisotropic_ratio_min;
589 
590  // looping through for redistribution
591  for(unsigned int index_internal = index+1; index_internal < dim; ++index_internal){
592 
593  // getting the corresponding reversed index
594  int j_internal = dim-1-index_internal;
595 
596  // applying the factor change
597  m_anisotropic_ratio[j_internal] *= factor;
598 
599  }
600 
601  }
602  }
603 
604  // if values have changed, correcting the anisotropic ratios just in case of rounding errors
605  if(changed)
606  correct_anisotropic_ratio();
607 
608 }
609 
610 /***** ***** Field ***** *****/
611 
612 template <int dim, typename real>
614  const dealii::Vector<real>& vec)
615 {
616  for(unsigned int i = 0; i < this->size(); ++i)
617  this->set_scale(i, vec[i]);
618 }
619 
620 template <int dim, typename real>
622  const std::vector<real>& vec)
623 {
624  for(unsigned int i = 0; i < this->size(); ++i)
625  this->set_scale(i, vec[i]);
626 }
627 
628 template <int dim, typename real>
629 dealii::Vector<real> Field<dim,real>::get_scale_vector_dealii() const
630 {
631  dealii::Vector<real> vec(this->size());
632 
633  for(unsigned int i = 0; i < this->size(); ++i)
634  vec[i] = this->get_scale(i);
635 
636  return vec;
637 }
638 
639 template <int dim, typename real>
640 std::vector<real> Field<dim,real>::get_scale_vector() const
641 {
642  std::vector<real> vec(this->size());
643 
644  for(unsigned int i = 0; i < this->size(); ++i)
645  vec[i] = this->get_scale(i);
646 
647  return vec;
648 }
649 
650 template <int dim, typename real>
652 {
653  dealii::Vector<real> vec(this->size());
654 
655  for(unsigned int i = 0; i < this->size(); ++i){
656  // getting the cell anisotropic ratios
657  std::array<real,dim> anisotropic_ratio = get_anisotropic_ratio(i);
658 
659  // finding the maximum value from iterators for the cell
660  vec[i] = *std::max_element(anisotropic_ratio.begin(), anisotropic_ratio.end());
661  }
662 
663  return vec;
664 }
665 
666 template <int dim, typename real>
668  const std::vector<std::array<dealii::Tensor<1,dim,real>,dim>>& vec)
669 {
670  for(unsigned int i = 0; i < this->size(); ++i)
671  this->set_axis(i, vec[i]);
672 }
673 
674 template <int dim, typename real>
675 std::vector<std::array<dealii::Tensor<1,dim,real>,dim>> Field<dim,real>::get_axis_vector()
676 {
677  std::vector<std::array<dealii::Tensor<1,dim,real>,dim>> vec(this->size());
678 
679  for(unsigned int i = 0; i < this->size(); ++i)
680  vec[i] = this->get_axis(i);
681 
682  return vec;
683 }
684 
685 template <int dim, typename real>
686 std::vector<dealii::Tensor<1,dim,real>> Field<dim,real>::get_axis_vector(
687  const unsigned int j)
688 {
689  std::vector<dealii::Tensor<1,dim,real>> vec(this->size());
690 
691  for(unsigned int i = 0; i < this->size(); ++i)
692  vec[i] = this->get_axis(i, j);
693 
694  return vec;
695 }
696 
697 template <int dim, typename real>
698 std::vector<dealii::Tensor<2,dim,real>> Field<dim,real>::get_metric_vector()
699 {
700  std::vector<dealii::Tensor<2,dim,real>> vec(this->size());
701 
702  for(unsigned int i = 0; i < this->size(); ++i){
703  // // temp
704  // std::cout << "metric[" << i << "] = "
705  // << ", alpha = " << this->get_scale(i)
706  // << ", r1 = " << this->get_anisotropic_ratio(i, 0)
707  // << ", v1 = {" << this->get_unit_axis(i, 0)
708  // << "}, r2 = " << this->get_anisotropic_ratio(i, 1)
709  // << ", v2 = {" << this->get_unit_axis(i, 1) << "}" << std::endl;
710 
711  vec[i] = this->get_metric(i);
712  }
713 
714  return vec;
715 }
716 
717 template <int dim, typename real>
718 std::vector<dealii::Tensor<2,dim,real>> Field<dim,real>::get_inverse_metric_vector()
719 {
720  std::vector<dealii::Tensor<2,dim,real>> vec(this->size());
721 
722  for(unsigned int i = 0; i < this->size(); ++i){
723  // // temp
724  // std::cout << "metric[" << i << "] = "
725  // << ", 1/alpha = " << (1.0/this->get_scale(i))
726  // << ", 1/r1 = " << (1.0/this->get_anisotropic_ratio(i, 0))
727  // << ", v1 = {" << this->get_unit_axis(i, 0)
728  // << "}, 1/r2 = " << (1.0/this->get_anisotropic_ratio(i, 1))
729  // << ", v1 = {" << this->get_unit_axis(i, 1) << "}" << std::endl;
730 
731  vec[i] = this->get_inverse_metric(i);
732  }
733 
734  return vec;
735 }
736 
737 template <int dim, typename real>
738 dealii::SymmetricTensor<2,dim,real> Field<dim,real>::get_quadratic_metric(
739  const unsigned int index)
740 {
741  dealii::SymmetricTensor<2,dim,real> quadratic_metric;
742  dealii::Tensor<2,dim,real> metric = this->get_metric(index);
743 
744  // looping over the upper triangular part
745  for(unsigned int i = 0; i < dim; ++i){
746  for(unsigned int j = i; j < dim; ++j){
747  // assigning compoennts of A = M^T M from a_ij = v_i^T v_j where M = [v_1, ..., v_n]
748  quadratic_metric[i][j] = scalar_product(metric[i], metric[j]);
749  }
750  }
751 
752  return quadratic_metric;
753 }
754 
755 template <int dim, typename real>
756 std::vector<dealii::SymmetricTensor<2,dim,real>> Field<dim,real>::get_quadratic_metric_vector()
757 {
758  std::vector<dealii::SymmetricTensor<2,dim,real>> vec(this->size());
759 
760  for(unsigned int i = 0; i < this->size(); ++i)
761  vec[i] = this->get_quadratic_metric(i);
762 
763  return vec;
764 }
765 
766 template <int dim, typename real>
767 dealii::SymmetricTensor<2,dim,real> Field<dim,real>::get_inverse_quadratic_metric(
768  const unsigned int index)
769 {
770  dealii::SymmetricTensor<2,dim,real> inverse_quadratic_metric;
771  dealii::Tensor<2,dim,real> inverse_metric = this->get_inverse_metric(index);
772 
773  // // temp
774  // std::cout << "metric[" << index << "] = "
775  // << ", 1/alpha = " << (1.0/this->get_scale(index))
776  // << ", 1/r1 = " << (1.0/this->get_anisotropic_ratio(index, 0))
777  // << ", v1 = {" << this->get_unit_axis(index, 0)
778  // << "}, 1/r2 = " << (1.0/this->get_anisotropic_ratio(index, 1))
779  // << ", v1 = {" << this->get_unit_axis(index, 1) << "}" << std::endl;
780 
781  // std::cout << "Vinv = " << inverse_metric << std::endl;
782  // std::cout << "Vinv[0] = " << inverse_metric[0] << std::endl;
783  // std::cout << "Vinv[1] = " << inverse_metric[1] << std::endl;
784 
785  // needed for proper component eval, to get the columns with inverse_metric[i] instead of the rows
786  inverse_metric = transpose(inverse_metric);
787 
788  // looping over the upper triangular part
789  for(unsigned int i = 0; i < dim; ++i){
790  for(unsigned int j = i; j < dim; ++j){
791  // assigning compoennts of A = M^T M from a_ij = v_i^T v_j where M = [v_1, ..., v_n]
792  inverse_quadratic_metric[i][j] = scalar_product(inverse_metric[i], inverse_metric[j]);
793  }
794  }
795 
796  // std::cout << "Vinv^T Vinv = " << inverse_quadratic_metric << std::endl << std::endl;
797 
798  return inverse_quadratic_metric;
799 }
800 
801 template <int dim, typename real>
802 std::vector<dealii::SymmetricTensor<2,dim,real>> Field<dim,real>::get_inverse_quadratic_metric_vector()
803 {
804  std::vector<dealii::SymmetricTensor<2,dim,real>> vec(this->size());
805 
806  for(unsigned int i = 0; i < this->size(); ++i)
807  vec[i] = this->get_inverse_quadratic_metric(i);
808 
809  return vec;
810 }
811 
812 /***** ***** FieldInternal ***** *****/
813 
814 template <int dim, typename real, typename ElementType>
816  const unsigned int size)
817 {
818  field.resize(size);
819 }
820 
821 template <int dim, typename real, typename ElementType>
823 {
824  return field.size();
825 }
826 
827 template <int dim, typename real, typename ElementType>
829  const unsigned int index)
830 {
831  return field[index].scale();
832 }
833 
834 template <int dim, typename real, typename ElementType>
836  const unsigned int index,
837  const real val)
838 {
839  field[index].set_scale(val);
840 }
841 
842 template <int dim, typename real, typename ElementType>
844  const unsigned int index) const
845 {
846  return field[index].get_scale();
847 }
848 
849 template <int dim, typename real, typename ElementType>
851  const unsigned int index,
852  const std::array<real,dim>& ratio)
853 {
854  field[index].set_anisotropic_ratio(ratio);
855 }
856 
857 template <int dim, typename real, typename ElementType>
859  const unsigned int index)
860 {
861  return field[index].get_anisotropic_ratio();
862 }
863 
864 template <int dim, typename real, typename ElementType>
866  const unsigned int index,
867  const unsigned int j)
868 {
869  return field[index].get_anisotropic_ratio(j);
870 }
871 
872 template <int dim, typename real, typename ElementType>
874  const unsigned int index,
875  const std::array<dealii::Tensor<1,dim,real>,dim>& unit_axis)
876 {
877  field[index].set_unit_axis(unit_axis);
878 }
879 
880 template <int dim, typename real, typename ElementType>
881 std::array<dealii::Tensor<1,dim,real>,dim> FieldInternal<dim,real,ElementType>::get_unit_axis(
882  const unsigned int index)
883 {
884  return field[index].get_unit_axis();
885 }
886 
887 
888 template <int dim, typename real, typename ElementType>
890  const unsigned int index,
891  const unsigned int j)
892 {
893  return field[index].get_unit_axis(j);
894 }
895 
896 template <int dim, typename real, typename ElementType>
898  const unsigned int index,
899  const std::array<dealii::Tensor<1,dim,real>,dim>& axis)
900 {
901  field[index].set_axis(axis);
902 }
903 
904 template <int dim, typename real, typename ElementType>
905 std::array<dealii::Tensor<1,dim,real>,dim> FieldInternal<dim,real,ElementType>::get_axis(
906  const unsigned int index)
907 {
908  return field[index].get_axis();
909 }
910 
911 template <int dim, typename real, typename ElementType>
913  const unsigned int index,
914  const unsigned int j)
915 {
916  return field[index].get_axis(j);
917 }
918 
919 template <int dim, typename real, typename ElementType>
921  const unsigned int index)
922 {
923  return field[index].get_metric();
924 }
925 
926 template <int dim, typename real, typename ElementType>
928  const unsigned int index)
929 {
930  return field[index].get_inverse_metric();
931 }
932 
933 template <int dim, typename real, typename ElementType>
935  const dealii::DoFHandler<dim>& dof_handler,
936  const std::vector<std::array<real,dim>>& derivative_value,
937  const std::vector<std::array<dealii::Tensor<1,dim,real>,dim>>& derivative_direction,
938  const int relative_order)
939 {
940  // sizes must match
941  assert(size() == dof_handler.get_triangulation().n_active_cells());
942  assert(size() == derivative_value.size());
943  assert(size() == derivative_direction.size());
944 
945  // looping through the cells
946  for(auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell){
947  if(!cell->is_locally_owned()) continue;
948 
949  // getting the index
950  const unsigned int index = cell->active_cell_index();
951 
952  // getting the order
953  const unsigned int order = cell->active_fe_index() + relative_order;
954 
955  // performing the call to update the anisotropy
956  field[index].set_anisotropy(
957  derivative_value[index],
958  derivative_direction[index],
959  order);
960  }
961 
962 }
963 
964 template <int dim, typename real, typename ElementType>
966  const real anisotropic_ratio_min,
967  const real anisotropic_ratio_max)
968 {
969 
970  for(unsigned int index = 0; index < this->size(); ++index)
971  field[index].apply_anisotropic_limit(
972  anisotropic_ratio_min,
973  anisotropic_ratio_max);
974 
975 }
976 
977 template <int dim, typename real, typename ElementType>
979  std::ostream& os) const
980 {
981  for(unsigned int index = 0; index < this->size(); ++index){
982  // std::cout << "writing element index = " << index << std::endl;
983  // std::cout << "with size = " << field[index].get_scale() << std::endl;
984  os << field[index] << std::endl;
985  }
986 
987  return os;
988 }
989 
990 template class Field <PHILIP_DIM, double>;
991 
992 // FieldIsotropic
994 
995 // FieldAnisotropic
997 
998 } // namespace GridRefinement
999 
1000 } // namespace PHiLiP
dealii::Tensor< 2, dim, real > get_metric() override
get metric value at index
Definition: field.cpp:343
real get_scale(const unsigned int index) const override
Gets scale for the specified element index.
Definition: field.cpp:843
void set_anisotropic_ratio(const unsigned int index, const std::array< real, dim > &ratio) override
Sets anisotropic ratio for the specified element index (if anisotropic)
Definition: field.cpp:850
std::array< dealii::Tensor< 1, dim, real >, dim > get_axis(const unsigned int index) override
Gets the frame (dim scaled axis vectors) for the specified element index.
Definition: field.cpp:905
dealii::SymmetricTensor< 2, dim, real > get_inverse_quadratic_metric(const unsigned int index)
Gets the inverse quadratic Riemannian metric used with BAMG, , for a specified element index...
Definition: field.cpp:767
void set_unit_axis(const std::array< dealii::Tensor< 1, dim, real >, dim > &unit_axis) override
setting the (unit) axis direction
Definition: field.cpp:287
void set_scale(const real val) override
Set the scale for the element.
Definition: field.cpp:79
std::array< dealii::Tensor< 1, dim, real >, dim > get_axis() override
getting frame axis j (scaled) at index (array)
Definition: field.cpp:332
void set_unit_axis(const std::array< dealii::Tensor< 1, dim, real >, dim > &unit_axis) override
Set the unit axes of the element.
Definition: field.cpp:117
dealii::Tensor< 2, dim, real > get_inverse_metric() override
Get inverse metric matrix for the reference element.
Definition: field.cpp:181
std::vector< std::array< dealii::Tensor< 1, dim, real >, dim > > get_axis_vector()
Gets the frame (dim scaled axis vectors) for each element (std::vector)
Definition: field.cpp:675
void set_scale(const unsigned int index, const real val) override
Sets scale for the specified element index.
Definition: field.cpp:835
void correct_anisotropic_ratio()
Correct the anisotropic ratio values.
Definition: field.cpp:411
Files for the baseline physics.
Definition: ADTypes.hpp:10
std::vector< dealii::SymmetricTensor< 2, dim, real > > get_quadratic_metric_vector()
Gets the quadratic Riemannian metric, , for each element (std::vector)
Definition: field.cpp:756
dealii::Vector< real > get_scale_vector_dealii() const
Gets scale for all elements from a scale vector (dealii::Vector)
Definition: field.cpp:629
void set_axis_vector(const std::vector< std::array< dealii::Tensor< 1, dim, real >, dim >> &vec)
Sets the frame (dim scaled axis vectors) for each element (std::vector)
Definition: field.cpp:667
real get_scale() const override
Get the scale for the element.
Definition: field.cpp:86
std::array< real, dim > get_anisotropic_ratio() override
Get the anisotropic ratio of each reference axis as an array.
Definition: field.cpp:99
void set_axis(const std::array< dealii::Tensor< 1, dim, real >, dim > &axis) override
setting frame axis j (scaled) at index
Definition: field.cpp:309
void set_anisotropic_ratio(const std::array< real, dim > &ratio) override
Set the anisotropic ratio for each reference axis.
Definition: field.cpp:92
std::array< dealii::Tensor< 1, dim, real >, dim > ChordList
Type alias for array of chord veectors (face center to face center) in Deal.II ordering.
Definition: field.h:103
dealii::Tensor< 2, dim, real > get_metric(const unsigned int index) override
Gets the anisotropic metric tensor, , for the specified element index.
Definition: field.cpp:920
void clear()
resets the element
Definition: field.cpp:374
void set_anisotropy(const std::array< real, dim > &derivative_value, const std::array< dealii::Tensor< 1, dim, real >, dim > &derivative_direction, const unsigned int order) override
Set anisotropy from reconstructed directional derivatives.
Definition: field.cpp:481
std::array< dealii::Tensor< 1, dim, real >, dim > get_axis() override
Get the array of axes of the local frame field .
Definition: field.cpp:153
void set_anisotropy(const std::array< real, dim > &derivative_value, const std::array< dealii::Tensor< 1, dim, real >, dim > &derivative_direction, const unsigned int order) override
Set anisotropy from reconstructed directional derivatives.
Definition: field.cpp:218
void set_scale_vector(const std::vector< real > &vec)
Sets scale for all elements from a scale vector(std::vector)
Definition: field.cpp:621
real & scale() override
Reference for element size.
Definition: field.cpp:246
unsigned int size() const
returns the internal vector size
Definition: field.cpp:822
void set_unit_axis(const unsigned int index, const std::array< dealii::Tensor< 1, dim, real >, dim > &unit_axis) override
Sets the group of dim (unit) axis directions for the specified element index.
Definition: field.cpp:873
void set_axis(const std::array< dealii::Tensor< 1, dim, real >, dim > &axis) override
Set the scaled local frame axes based on vector set (length and direction)
Definition: field.cpp:146
std::array< dealii::Tensor< 1, dim, real >, dim > get_unit_axis() override
getting the (unit) axis direction (array)
Definition: field.cpp:296
std::vector< dealii::Tensor< 2, dim, real > > get_metric_vector()
Gets the anisotropic metric tensor, , for each element (std::vector)
Definition: field.cpp:698
void set_anisotropy(const dealii::DoFHandler< dim > &dof_handler, const std::vector< std::array< real, dim >> &derivative_value, const std::vector< std::array< dealii::Tensor< 1, dim, real >, dim >> &derivative_direction, const int relative_order) override
Compute anisotropic ratio from directional derivatives.
Definition: field.cpp:934
void apply_anisotropic_limit(const real anisotropic_ratio_min, const real anisotropic_ratio_max)
Limits the anisotropic ratios to a given bandwidth.
Definition: field.cpp:533
Field element class.
Definition: field.h:452
void sort_anisotropic_ratio()
Sorts the anisotropic ratio values (and corresponding unit axis) in ascending order.
Definition: field.cpp:433
void apply_anisotropic_limit(const real anisotropic_ratio_min, const real anisotropic_ratio_max) override
Globally limit anisotropic ratio to a specified range.
Definition: field.cpp:965
void correct_element()
Corrects internal values to ensure consistent treatement.
Definition: field.cpp:391
void set_cell_internal(const typename Element< dim, real >::VertexList &vertices) override
Set element to match geometry of input vertex set.
Definition: field.cpp:201
void apply_anisotropic_limit(const real anisotropic_ratio_min, const real anisotropic_ratio_max)
Limits the anisotropic ratios to a given bandwidth.
Definition: field.cpp:228
ChordList get_chord_list(const VertexList &vertices)
Get the chord list from an input set of vertices.
Definition: field.cpp:16
std::array< real, dim > get_anisotropic_ratio(const unsigned int index) override
Gets the anisotropic ratio for the specified element index.
Definition: field.cpp:858
std::array< dealii::Tensor< 1, dim, real >, dealii::GeometryInfo< dim >::vertices_per_cell > VertexList
Type alias for array of vertex coordinates for element.
Definition: field.h:101
ElementAnisotropic()
Constructor, sets default element definition.
Definition: field.cpp:239
std::vector< dealii::SymmetricTensor< 2, dim, real > > get_inverse_quadratic_metric_vector()
Gets the inverse quadratic Riemannian metric used with BAMG, , for each element (std::vector) ...
Definition: field.cpp:802
real get_scale() const override
Get the scale for the element.
Definition: field.cpp:259
void set_anisotropic_ratio(const std::array< real, dim > &ratio) override
Set the anisotropic ratio for each reference axis.
Definition: field.cpp:265
dealii::Tensor< 2, dim, real > get_metric() override
Get metric matrix at point describing mapping from reference element.
Definition: field.cpp:171
real & scale() override
Reference for element size.
Definition: field.cpp:73
void set_cell_internal(const typename Element< dim, real >::VertexList &vertices) override
Set element to match geometry of input vertex set.
Definition: field.cpp:463
void set_axis(const unsigned int index, const std::array< dealii::Tensor< 1, dim, real >, dim > &axis) override
Sets the j^th (unit) axis direction for the specified element index.
Definition: field.cpp:897
Internal Field element class.
Definition: field.h:619
dealii::Vector< real > get_max_anisotropic_ratio_vector_dealii()
Gets the vector of largest anisotropic ratio for each element (dealii::Vector)
Definition: field.cpp:651
dealii::Tensor< 2, dim, real > get_inverse_metric(const unsigned int index) override
Gets the inverse metric tensor, , for the specified element index.
Definition: field.cpp:927
real1 norm(const dealii::Tensor< 1, dim, real1 > x)
Returns norm of dealii::Tensor<1,dim,real>
std::array< dealii::Tensor< 1, dim, real >, dim > get_unit_axis() override
Get unit axis directions as an array.
Definition: field.cpp:124
std::array< dealii::Tensor< 1, dim, real >, dim > get_unit_axis(const unsigned int index) override
Sets the group of dim (unit) axis directions for the specified element index.
Definition: field.cpp:881
std::vector< real > get_scale_vector() const
Gets scale fpr all elements from a scale vector (std::vector)
Definition: field.cpp:640
void set_scale(const real val) override
Set the scale for the element.
Definition: field.cpp:252
void reinit(const unsigned int size)
reinitialize the internal data structure
Definition: field.cpp:815
std::ostream & serialize(std::ostream &os) const override
Performs internal call for writing the field description to an ostream.
Definition: field.cpp:978
void set_scale_vector_dealii(const dealii::Vector< real > &vec)
Sets scale for all elements from a scale vector (dealii::Vector)
Definition: field.cpp:613
dealii::Tensor< 2, dim, real > get_inverse_metric() override
get inverse metric value
Definition: field.cpp:354
void correct_unit_axis()
renormalize the unit_axis
Definition: field.cpp:398
std::vector< dealii::Tensor< 2, dim, real > > get_inverse_metric_vector()
Gets the inverse metric tensor, , for each element (std::vector)
Definition: field.cpp:718
real & scale(const unsigned int index) override
reference for element size of specified element index
Definition: field.cpp:828
std::array< real, dim > get_anisotropic_ratio() override
Get the anisotropic ratio of each reference axis as an array.
Definition: field.cpp:281
dealii::SymmetricTensor< 2, dim, real > get_quadratic_metric(const unsigned int index)
Gets the quadratic Riemannian metric, , for the specified element index.
Definition: field.cpp:738