CEPS  24.01
Cardiac ElectroPhysiology Simulator
LagrangeBasisFunctions.cpp
Go to the documentation of this file.
1 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2  This file is part of CEPS.
3 
4  CEPS is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  CEPS is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with CEPS (see file LICENSE at root of project).
16  If not, see <https://www.gnu.org/licenses/>.
17 
18 
19  Copyright 2019-2024 Inria, Universite de Bordeaux
20 
21  Authors, in alphabetical order:
22 
23  Pierre-Elliott BECUE, Florian CARO, Yves COUDIERE(*), Andjela DAVIDOVIC,
24  Charlie DOUANLA-LONTSI, Marc FUENTES, Mehdi JUHOOR, Michael LEGUEBE(*),
25  Pauline MIGERDITICHAN, Valentin PANNETIER(*), Nejib ZEMZEMI.
26  * : currently active authors
27 
28 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
31 
32 // void
33 // buildQuadrilateralUniformPoints(
34 // CepsUInt dim,
35 // CepsUInt numberOfPoints,
36 // CepsVector<CepsReal3D>& points,
37 // CepsVector<CepsInt>& geomCellIndex
38 // )
39 // {
40 // CepsReal h = 1.0 / (numberOfPoints - 1);
41 // CepsUInt Nx = numberOfPoints;
42 // CepsUInt Ny = (dim > 1 ? numberOfPoints : 1);
43 // CepsUInt Nz = (dim > 2 ? numberOfPoints : 1);
44 
45 // points .clear();
46 // isGeomNode.clear();
47 // points .reserve(Nx*Ny*Nz);
48 // isGeomNode.reserve(Nx*Ny*Nz);
49 // for (CepsUInt i=0; i<Nx; ++i)
50 // for (CepsUInt j=0; j<Ny; ++j)
51 // for (CepsUInt k=0; k<Nz; ++k)
52 // {
53 // points.push_back(CepsReal3D({i*h, j*h, k*h}));
54 // CepsInt toPush = -1;
55 // if ((i==0 or i==Nx-1) and (j==0 or j==Ny-1) and (k==0 or k==Nz-1))
56 // toPush = ;
57 // geomCellIndex.push_back(toPush);
58 // }
59 // return;
60 // }
61 
62 void
64  CepsUInt dim,
65  CepsUInt numberOfPoints,
66  CepsVector<CepsReal3D>& points,
67  CepsVector<CepsInt>& geomCellIndex
68 )
69 {
70  CepsReal h = 1.0 / (numberOfPoints - 1);
71  CepsUInt Nx = numberOfPoints;
72  CepsUInt Ny = (dim > 1 ? numberOfPoints : 1);
73  CepsUInt Nz = (dim > 2 ? numberOfPoints : 1);
74 
75  points .clear();
76  geomCellIndex.clear();
77  points .reserve(Nx*Ny*Nz);
78  geomCellIndex.reserve(Nx*Ny*Nz);
79  CepsInt count = -1;
80  for (CepsUInt i=0; i<Nx; ++i)
81  for (CepsUInt j=0; j<Ny; ++j)
82  for (CepsUInt k=0; k<Nz; ++k)
83  if ((i+j+k)*h <= 1.0) // x+y+z <= 1.0 for simplices
84  {
85  points.push_back(CepsReal3D({i*h, j*h, k*h}));
86  CepsInt toPush = -1;
87  if((i==0 or i==Nx-1) and (j==0 or j==Ny-1) and (k==0 or k==Nz-1))
88  {
89  toPush = geomCellIndex.size()==0 ? 0 : dim-count;
90  count ++;
91  }
92  geomCellIndex.push_back(toPush);
93  }
94 
95  return;
96 }
97 
100 {
101  CepsVector<CepsArray3<CepsInt>> expos = {};
102 
103  CepsInt Nx = numberOfPoints; // maximum degree is numberOfPoints
104  CepsInt Ny = (dim > 1 ? numberOfPoints: 1);
105  CepsInt Nz = (dim > 2 ? numberOfPoints: 1);
106 
107  for (CepsInt i=0; i<Nx; ++i)
108  for (CepsInt j=0; j<Ny; ++j)
109  for (CepsInt k=0; k<Nz; ++k)
110  if (i+j+k < (CepsInt)numberOfPoints) // maximum degree is numberOfPoints
111  expos.push_back(CepsArray3<CepsInt>({i,j,k}));
112 
113  auto compare = [] (const CepsArray3<CepsInt> &a, const CepsArray3<CepsInt> &b) -> CepsBool {
114  const CepsUInt &i =
115  (a[0] >= a[1] and a[0] >= a[2] ? 0U : (a[1] >= a[0] and a[1] >= a[2] ? 1U : 2U));
116  const CepsUInt &j =
117  (b[0] >= b[1] and b[0] >= b[2] ? 0U : (b[1] >= b[0] and b[1] >= b[2] ? 1U : 2U));
118 
119  const CepsInt &as = a[0] + a[1] + a[2];
120  const CepsInt &bs = b[0] + b[1] + b[2];
121 
122  // sum are different (eg {0, 1} <= {2,0}) -> {y <= x^2}
123  if (as != bs)
124  return as <= bs;
125  // so sum are equal here (eg {0, 2} == {1,1}) -> {x^2 ? xy}
126 
127  // the minimum value are different (eg {1,1} >= {0,2}) -> {xy <= x^2}
128  if (a[i] != b[j])
129  return a[i] <= b[j];
130  // so minimum value are equal here (eg {0, 1, 1} == {1, 1, 0}) -> {xy ? yz}
131 
132  // only ordering the index as {x}, than {y} and than {z} (eg {2, 1, 1} <= {1, 1, 2}) -> {x^2yz
133  // <= xyz^2}
134  return i <= j;
135  };
136 
137  std::sort (expos.begin(),expos.end(),compare);
138 
139  // only keep the number needed
140  return expos;
141 }
142 
143 void
145  CepsUInt dim,
146  CepsUInt order,
147  CepsVector<CepsReal3D>& points,
148  CepsVector<CepsInt>& geomCellIndex,
149  CepsVector<Polynomial<3U>>& polys,
150  void (*pointBuilder) (CepsUInt, CepsUInt, CepsVector<CepsReal3D>&, CepsVector<CepsInt>&)
151 )
152 {
153  const CepsUInt &numberOfPoints = order + 1;
154 
155  pointBuilder(dim,numberOfPoints,points,geomCellIndex);
156  const CepsUInt &np = points.size();
157 
158  CepsVector<CepsArray3<CepsInt>> exponents = buildBasisFunctionExponents(dim,numberOfPoints);
159  exponents.resize(np);
160 
161  CepsVector<Monomial<3U>> mono(np);
162  for (CepsUInt i=0; i<np; ++i)
163  mono[i].setExponents(exponents[i]);
164 
165  // mat A
166  using mat_t = Eigen::Matrix<CepsReal,-1,-1>;
167  mat_t A(np, np);
168  for (CepsUInt i=0; i<np; ++i)
169  for (CepsUInt j=0; j<np; ++j)
170  A.coeffRef(i,j) = mono[j](points[i]);
171 
172  // second member
173  mat_t I(np,np);
174  I.setIdentity();
175 
176  // solver
177  Eigen::PartialPivLU<mat_t> solver(A);
178  decltype(A) coeffs = solver.solve(I);
179 
180  // fill
181  polys.resize(np);
182  for (CepsUInt i=0; i<np; ++i)
183  {
184  polys[i].add(coeffs.col(i),exponents);
185  polys[i].pruneZeroCoeffs();
186  }
187 }
std::vector< _Type, _Alloc > CepsVector
C++ vector.
Definition: CepsTypes.hpp:155
bool CepsBool
Booleans.
Definition: CepsTypes.hpp:124
std::make_unsigned_t< CepsInt > CepsUInt
Unsigned version on CepsInt.
Definition: CepsTypes.hpp:109
float CepsReal
Need single precision floating point.
Definition: CepsTypes.hpp:100
CepsArray< _Type, 3U > CepsArray3
C++ array, 3 elements.
Definition: CepsTypes.hpp:165
CepsArray3< CepsReal > CepsReal3D
Three real scalars, used like this for compatibility in polynomials.
Definition: CepsTypes.hpp:178
int32_t CepsInt
Need 32 bit integer.
Definition: CepsTypes.hpp:106
CepsVector< CepsArray3< CepsInt > > buildBasisFunctionExponents(CepsUInt dim, CepsUInt numberOfPoints)
Constructs the list of ordered exponents for a given number of points, typically constructed x^i y^j ...
void buildPolysBasisFunction(CepsUInt dim, CepsUInt order, CepsVector< CepsReal3D > &points, CepsVector< CepsInt > &geomCellIndex, CepsVector< Polynomial< 3U >> &polys, void(*pointBuilder)(CepsUInt, CepsUInt, CepsVector< CepsReal3D > &, CepsVector< CepsInt > &))
Constructs the list of base functions in the form of Polynomials.
void buildSimplexUniformPoints(CepsUInt dim, CepsUInt numberOfPoints, CepsVector< CepsReal3D > &points, CepsVector< CepsInt > &geomCellIndex)
Constructs the list of uniform points of the simplex of given dimension.
A class to represent polynomials, as a collection of Monomial and coefficients.
void sort(CepsVector< _Type, _Alloc > &vec, _Compare compare)
Sort whole vector with specified comparator.
Definition: CepsVector.hpp:234