KASKADE 7 development version
Loading...
Searching...
No Matches
barycentric.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copyright (C) 2002-2020 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef BARYCENTRIC_HH
14#define BARYCENTRIC_HH
15
16#include <cassert>
17#include <numeric> // std::accumulate, with clang++
18
19#include "dune/common/fvector.hh"
20#include "dune/common/fmatrix.hh"
21
22namespace Kaskade
23{
32 template <class CoordType, int dim>
34 {
36 zeta[dim] = 1;
37 for (int i=0; i<dim; ++i)
38 {
39 zeta[i] = x[i];
40 zeta[dim] -= x[i];
41 }
42
43 // Shape functions vanishing on the boundary will probably rely on
44 // one barycentric coordinate being exactly zero, in order not to be
45 // affected by large penalty values from Dirichlet boundary
46 // conditions. Hence we here enforce exactly zero values for very
47 // small barcyentric coordinates.
48 constexpr CoordType eps = std::numeric_limits<CoordType>::epsilon();
49 for (int i=0; i<=dim; ++i)
50 if (std::abs(zeta[i]) < 100*eps) // well, that's probably *exactly* on the boundary
51 zeta[i] = 0;
52
53 return zeta;
54 }
55
56 // ----------------------------------------------------------------------------------------------
57
62 template <class CoordType, int dim,
63 std::enable_if_t<std::is_floating_point_v<CoordType>,int> = 0>
65 {
66 constexpr CoordType eps = std::numeric_limits<CoordType>::epsilon();
67
68 auto b = barycentric(x); // This is already modified such that b>=0.
69 b /= (b.one_norm()+eps); // Now sum(b) = 1
70
71 std::copy(b.begin(),b.begin()+dim,x.begin());
72 return x;
73 }
74
75 // ----------------------------------------------------------------------------------------------
76
92 template <class CoordType, int dim>
94 {
96 zeta[0] = 1;
97 for (int i=0; i<dim; ++i) {
98 zeta[i+1] = x[i];
99 zeta[0] -= x[i];
100 }
101
102 // Shape functions vanishing on the boundary will probably rely on
103 // one barycentric coordinate being exactly zero, in order not to be
104 // affected by large penalty values from Dirichlet boundary
105 // conditions. Hence we here enforce exactly zero values for very
106 // small barcyentric coordinates.
107 constexpr CoordType eps = std::numeric_limits<CoordType>::epsilon();
108 for (int i=0; i<=dim; ++i)
109 if (std::abs(zeta[i]) < 100*eps) // well, that's probably *exactly* on the boundary
110 zeta[i] = 0;
111
112 return zeta;
113 }
114
124 template <class CoordType, int dim>
126 {
128 for (int i=0; i<dim; ++i)
129 {
130 B[0][i] = -1.0;
131 B[i+1][i] = 1.0;
132 }
133 return B;
134 }
135
136 // ----------------------------------------------------------------------------------------------
137
138
150 template <size_t dim>
151 std::array<int,dim+1> barycentric(std::array<int,dim> const& x, int bsum)
152 {
153 std::array<int,dim+1> zeta;
154 std::copy(begin(x),end(x),begin(zeta));
155 zeta[dim] = bsum - std::accumulate(begin(x),end(x),0);
156 return zeta;
157 }
158
159} /* end of namespace Kaskade */
160
161#endif
Dune::FieldVector< CoordType, dim+1 > barycentric(Dune::FieldVector< CoordType, dim > const &x)
Computes the barycentric coordinates of a point in the unit simplex.
Dune::FieldMatrix< CoordType, dim+1, dim > barycentric2Derivative(Dune::FieldVector< CoordType, dim > const &x)
Computes the derivative of the barycentric coordinates of a point in the unit simplex.
Dune::FieldVector< CoordType, dim+1 > barycentric2(Dune::FieldVector< CoordType, dim > const &x)
Computes barycentric coordinates of a point in the unit simplex.
Dune::FieldVector< CoordType, dim > projectToUnitSimplex(Dune::FieldVector< CoordType, dim > x)
Projects a vector onto the unit simplex.