HAL Id: hal-01361291
https://hal.archives-ouvertes.fr/hal-01361291v9
Submitted on 19 Jun 2020
HAL is a multi-disciplinary open access archive for the deposit and dissemination of sci-entific research documents, whether they are pub-lished or not. The documents may come from teaching and research institutions in France or abroad, or from public or private research centers.
L’archive ouverte pluridisciplinaire HAL, est destinée au dépôt et à la diffusion de documents scientifiques de niveau recherche, publiés ou non, émanant des établissements d’enseignement et de recherche français ou étrangers, des laboratoires publics ou privés.
STochastic OPTimization library in C++
Hugo Gevret, Nicolas Langrené, Jérôme Lelong, Rafael Lobato, Thomas
Ouillon, Xavier Warin, Aditya Maheshwari
To cite this version:
Hugo Gevret, Nicolas Langrené, Jérôme Lelong, Rafael Lobato, Thomas Ouillon, et al.. STochastic OPTimization library in C++. [Research Report] EDF Lab. 2018. �hal-01361291v9�
STochastic OPTimization library in C++
Hugo Gevret
1Nicolas Langren´
e
2Jerome Lelong
3Rafael D. Lobato
4Thomas Ouillon
5Xavier Warin
6Aditya Maheshwari
71EDF R&D, Hugo.Gevret@edf.fr
2data61 CSIRO, locked bag 38004 docklands vic 8012 Australia,
Nicolas.Langrene@data61.csiro.au
3Ensimag, Laboratoire Jean Kuntzmann, 700 avenue Centrale Domaine Universitaire - 38401
St Martin d’Hres
4Department of Computer Science, University of Pisa, Italy, Rafael.Lobato@di.unipi.it
5EDF R&D, Thomas.Ouillon@edf.fr
6EDF R&D & FiME, Laboratoire de Finance des March´es de l’Energie, ANR PROJECT
CAE-SARS, Xavier.Warin@edf.fr
Contents
I
Introduction
6
1 General context 7
2 General mathematical setting 10
II
Useful tools for stochastic control
13
3 The grids and their interpolators 14
3.1 Linear grids . . . 18
3.1.1 Definition and C++ API . . . 18
3.1.2 The python API . . . 20
3.2 Legendre grids . . . 21
3.2.1 Approximation of a function in 1 dimension . . . 22
3.2.2 Extension in dimension d . . . 25
3.2.3 Troncature . . . 26
3.2.4 The C++ API . . . 27
3.2.5 The python API . . . 29
3.3 Sparse grids . . . 30
3.3.1 The sparse linear grid method . . . 30
3.4 High order sparse grid methods . . . 34
3.5 Anisotropy . . . 36
3.6 Adaptation . . . 37
3.7 C++ API . . . 38
3.8 Python API . . . 43
4 Introducing regression resolution 46 4.1 C++ global API . . . 47
4.2 Adapted local polynomial basis with same probability . . . 52
4.2.1 Description of the method . . . 52
4.2.2 C++ API . . . 53
4.2.3 Python API . . . 56
4.3 Adapted local basis by K-Means clustering methods . . . 56
4.3.1 C++ API . . . 58
4.3.2 Python api . . . 59
4.4.1 C++ API . . . 59
4.4.2 An example in the linear case . . . 60
4.4.3 Python API . . . 61
4.5 Sparse grid regressor . . . 61
4.5.1 C++ API . . . 61
4.5.2 Python API . . . 62
4.6 Global polynomial basis . . . 62
4.6.1 Description of the method . . . 62
4.6.2 C++ API . . . 63
4.6.3 Python API . . . 64
4.7 Kernel regression with Epanechnikov kernel . . . 64
4.7.1 The univariate case . . . 65
4.7.2 The multivariate case . . . 66
4.7.3 C++ API . . . 71
4.7.4 Python API . . . 71
4.8 Kernel regression with Laplacian kernels . . . 72
4.8.1 Reducing the problem to empiral CDF calculations . . . 72
4.8.2 Effective ECDF calculations . . . 73
4.8.3 Divide and conquere approach . . . 76
4.8.4 C++ API for fast summation method . . . 76
4.8.5 Python API for fast summation method . . . 77
4.8.6 C++ API for exact divid and conquer method . . . 77
4.8.7 Python API for exact divid and conquer method . . . 78
5 Calculating conditional expectation by trees 79 5.0.1 C++ API . . . 80
6 Continuation values objects and similar ones 82 6.1 Continuation values objects with regression methods . . . 82
6.1.1 Continuation values object . . . 82
6.1.2 The GridAndRegressedValue object . . . 86
6.1.3 The continuation cut object . . . 87
6.2 Continuation objects and associated with trees . . . 91
6.2.1 Continuation object . . . 91
6.2.2 GridTreeValues . . . 93
6.2.3 Continuation Cut with trees . . . 93
III
Solving optimization problems with dynamic programming
methods
96
7 Creating simulators 97 7.1 Simulators for regression methods . . . 978 Using conditional expectation to solve simple problems 103
8.1 American option by regression . . . 103
8.1.1 The American option valuing by Longstaff–Schwartz . . . 103
8.2 American options by tree . . . 105
8.2.1 The American option by tree . . . 105
8.2.2 Python API . . . 105
9 Using the general framework to manage stock problems 107 9.1 General requirement about business object . . . 108
9.2 Solving the problem using conditional expectation calculated by regressions . 110 9.2.1 Requirement to use the framework . . . 110
9.2.2 Classical regression . . . 111
9.2.3 Regressions and cuts for linear continuous transition problems with some concavity, convexity features . . . 123
9.3 Solving the problem for X2x,t stochastic . . . 130
9.3.1 Requirement to use the framework . . . 130
9.3.2 The framework in optimization . . . 132
9.3.3 The framework in simulation . . . 135
9.4 Solving stock problems with trees . . . 135
9.4.1 Solving dynamic programming problems with control discretization . 135 9.4.2 Solving Dynamic Programming by solving LP problems . . . 141
10 The Python API 148 10.1 Mapping to the framework . . . 148
10.2 Special python binding . . . 153
10.2.1 A first binding to use the framework . . . 153
10.2.2 Binding to store/read a regressor and some two dimensional array . . 156
11 Using the C++ framework to solve some hedging problem 158 11.1 The problem . . . 158
11.2 Theoretical algorithm . . . 159
11.3 Practical algorithm based on Algorithm 10 . . . 162
IV
Semi-Lagrangian methods
165
12 Theoretical background 167 12.1 Notation and regularity results . . . 16712.2 Time discretization for HJB equation . . . 168
12.3 Space interpolation . . . 168
13 C++ API 170 13.1 PDE resolution . . . 176
V
An example with both dynamic programming with
regres-sion and PDE
184
13.3 The dynamic programming with regression approach . . . 186
13.4 The PDE approach . . . 189
VI
Stochastic Dual Dynamic Programming
192
14 SDDP algorithm 193 14.1 Some general points about SDDP . . . 19314.2 A method, different algorithms . . . 195
14.2.1 The basic case . . . 195
14.2.2 Dependence of the random quantities . . . 197
14.2.3 Non-convexity and conditional cuts . . . 199
14.3 C++ API . . . 205
14.3.1 Inputs . . . 205
14.3.2 Architecture . . . 210
14.3.3 Implement your problem . . . 210
14.3.4 Set of parameters . . . 215
14.3.5 The black box . . . 217
14.3.6 Outputs . . . 217
14.4 Python API (only for regression based methods) . . . 218
VII
Nesting Monte Carlo for general non linear PDEs
223
VIII
Some test cases description
229
15 Some test cases description in C++ 230 15.1 American option . . . 230 15.1.1 testAmerican . . . 230 15.1.2 testAmericanConvex . . . 232 15.1.3 testAmericanForSparse . . . 233 15.1.4 testAmericanOptionCorrel . . . 233 15.1.5 testAmericanOptionTree . . . 233 15.2 testSwingOption . . . 234 15.2.1 testSwingOption2D . . . 234 15.2.2 testSwingOption3 . . . 235 15.2.3 testSwingOptimSimu / testSwingOptimSimuMpi . . . 235 15.2.4 testSwingOptimSimuWithHedge . . . 235 15.2.5 testSwingOptimSimuND / testSwingOptimSimuNDMpi . . . 23515.3 Gas Storage . . . 236 15.3.1 testGasStorage / testGasStorageMpi . . . 236 15.3.2 testGasStorageCut / testGasStorageCutMpi . . . 237 15.3.3 testGasStorageTree/testGasStorageTreeMpi . . . 237 15.3.4 testGasStorageTreeCut/testGasStorageTreeCutMpi . . . 237 15.3.5 testGasStorageKernel . . . 238 15.3.6 testGasStorageLaplacianLinearKernel . . . 238 15.3.7 testGasStorageLaplacianConstKernel . . . 238 15.3.8 testGasStorageLaplacianGridKernel . . . 238 15.3.9 testGasStorageVaryingCavity . . . 239 15.3.10 testGasStorageSwitchingCostMpi . . . 239 15.3.11 testGasStorageSDDP . . . 239 15.3.12 testGasStorageSDDPTree . . . 240 15.4 testLake / testLakeMpi . . . 240 15.5 testOptionNIGL2 . . . 241 15.6 testDemandSDDP . . . 241
15.7 Reservoir variations with SDDP . . . 241
15.7.1 testReservoirWithInflowsSDDP . . . 241 15.7.2 testStorageWithInflowsSDDP . . . 242 15.7.3 testStorageWithInflowsAndMarketSDDP . . . 243 15.8 Semi-Lagrangian . . . 244 15.8.1 testSemiLagrangCase1/testSemiLagrangCase1 . . . 244 15.8.2 testSemiLagrangCase2/testSemiLagrangCase2 . . . 244 15.8.3 testSemiLagrangCase2/testSemiLagrangCase2 . . . 245
15.9 Non emimissive test case . . . 245
15.9.1 testDPNonEmissive . . . 245
15.9.2 testSLNonEmissive . . . 245
15.10Nesting for Non Linear PDE’s . . . 246
15.10.1 Some HJB test . . . 246
15.10.2 Some Toy example: testUD2UTou . . . 246
15.10.3 Some Portfolio optimization . . . 247
16 Some python test cases description 249 16.1 Microgrid Management . . . 249
16.1.1 testMicrogridBangBang . . . 249
16.1.2 testMicrogrid . . . 249
16.2 Dynamic Emulation Algorithm (DEA) . . . 250
Part I
Chapter 1
General context
Optimizing while dealing with uncertainties is a shared goal by many sectors in the industry. For example in the banking system:
• Some options such as American options need, in order to be valuated, to find an optimal exercise strategy to maximize the gain on average.
• When dealing with assets management, a fund manager may want to find a strategy to optimize his gains by investing in different assets while trying to satisfy some risk constraints.
• When dealing with credit risk in the case of option selling, some CVA modelization necessitates to solve some high dimensional problem in order to evaluate the option value.
In the energy financial sector, many problems involve stochastic optimization:
• some options, known as swing options, permit the owner to get some energy at some chosen dates with constraints on volumes. The price paid is either deterministic such as in the electricity market or can be an index which is an average of some commodity prices such as in the gas market.
• When some batteries are installed on a network, the battery has to be filled in or discharged optimally in order to avoid the use of some expensive thermal units. • The optimal management of certain gas storage or certain thermal assets taking into
account the prices of raw materials is a goal shared by all asset owners in the sector. • Even in regulated energy market, when water is used to generate electricity, a common
target consists in finding an optimal water management in order to maximize the profit on average.
A goal shared by many industries is the problem of risk management: which financial assets to buy to guarantee a given gain by immunizing a financial portfolio against certain uncertainties.
• either to resolve certain PDEs when the control must be evaluated continuously, • or to calculate a certain conditional expectation in the event that control must be
taken on certain discrete dates. The problem is then solved by a dynamic programming method.
The STochastic OPTimization library (StOpt) https://gitlab.com/stochastic-control/StOpt
aims to provide tools to solve certain stochastic optimization problems encountered in finance or in industry. This library is a toolbox used to facilitate the work of developers whishing to solve certain stochastic optimization problems by providing a general framework and some objects commonly used in stochastic programming. Many effective methods are implemented and the toolkit must be flexible enough to use the library at different levels being either an expert or only whishing to use the general framework.
The python interface allows you to use the library at a low level. The test cases are either in C++ , or in python or in the both language.
The user is invited to consult the different test cases proposed in order to have global view of the resolution methods. All the test cases are described in the last section of the documentation and deal with problems encountered in the banking system or the energy sector.
• The American options are solved by a part of dynamic programming III in python or C++ using regression (section 4) or using a scenario tree 5.
Regression are achieved:
1. either by local polynomials or with base support of the same size (subsection 4.4) or with an adapted size of the support (subsection 4.2) ,
2. either by global polynomials (section 4.6)
3. either by sparse grid regression (section 4.5) useful in high dimension 4. or by kernel regression (section4.7)
In the test, a trinomial tree is developed as an example and the valorisation of an American option for the Black-Scholes model is given using this tree.
• Gas storage problems are solved
– either by dynamic programming (part III) in python or C++ using regression (section 4) or tree (section 5) and stock interpolation ( chapter 3).
Regression are achieved:
1. either by Local polynomials with an adapted size of the support (subsection 4.2) ,
2. either by global polynomials (section 4.6) 3. or kernel regression (section 4.7)
As before the trinomial tree developed in tests is used in the tree methods. The interpolation between stock points is either linear or quadratic.
– either by the SDDP method (chapter 14) in C++ using both regression and tree methods.
• The swing options are solved by dynamic programming (part III) in python or C++ using regression with local polynomials with a suitable size of the support (subsection 4.2)
• The optimal management of a lake with stochastic inflows is solved by dynamic pro-gramming (part III) in python or C++ using local polynomials with an adapted sup-port size (subsection 4.2)
• The optimal hedging of an option using a average variance criterion of the hedged portfolio is resolved in C++ by dynamic programming (part III) using the methodology in chapter 11.
• A certain management of the reservoirs is solved by the SDDP method (chapter 14) in C++ trying to minimize the cost of the energy supply to satisfy a given demand with the possibility of buying energy at a price that can be stochastic.
• The continuous optimization of a portfolio made up of a few assets following a Heston model is achieved by solving C++ the corresponding PDE with the Monte Carlo nesting method (part VII).
• Some microgrid problems in the energy sector are solved using the python interface by dynamic programming methods (part III) using grids with linear interpolation (sub-section 3.1.1) to discretize the energy level in the battery and the different regressors using:
1. either local polynomials with an suitable support size (subsection 4.2) , 2. either global polynomials (section 4.6)
Chapter 2
General mathematical setting
In a continuous frame, the controlled state is given by a stochastic differential equation dXx,t
s = ba(t, Xsx,t)ds + σa(s, Xsx,t)dWs
Xtx,t = x
where
• Wt is a dthree-dimensional Brownian motion on a probability space (Ω, F , P) endowed
with the natural (complete and continuous line) filtration F = (Ft)t≤T generated by
W up to a fixed time horizon T > 0,
• σa is a Lipschitz continuous function of (t, x, a) defined on [0, T ] × Rd× Rnand taking
values in the set of d-dimensional square matrices,
• ba is a Lipschitz continuous function of (t, x, a) defined on [0, T ] × Rd× Rn and taking
values in Rd,
• a a control adapted to the filtration taking values in Rn.
Suppose we want to minimize a cost function J (t, x, a) = E[RT
t fa(s, X x,t s )e Rs t ca(u,X x,t u )duds + eRtTca(u,X x,t u )g(Xx,t
T )] compared to the a control. It is well known [16] that the optimal value
ˆ
J (t, x) = infaJ (T − t, x, a) is a viscosity solution of the equation
∂v ∂t(t, x) − a∈Ainf 1 2tr(σa(t, x)σa(t, x) TD2v(t, x)) + b a(t, x)Dv(t, x) +ca(t, x)v(t, x) + fa(t, x) = 0 in Rd v(0, x) = g(x) in Rd (2.1)
According to certain classical hypotheses on the coefficients [16], the previous equation known as the Hamilton Jacobi Bellman equation admits a solution of unique viscosity ([25]). Solving the previous equation is quite difficult, especially in dimensions larger than 3 or 4. The library provides tools to solve this equation and simplified versions of it.
• a first method supposes that Xx,t s = (X x,t 1,s, X x,t 2,s) where X x,t 1,s is not controlled dXx,t 1,s = b(t, X x,t 1,s)ds + σ(s, X1,sx,t)dWs X1,tx,t = x (2.2)
and X2,sx,t has no diffusion term
dXx,t
2,s = ba(t, X2,sx,t)ds
X2,tx,t = x
In this case, we can use Monte Carlo methods based on regression to solve the problem. The method is based on the principle of dynamic programming and can be used even if the uncontrolled SDE is controlled by a general Levy process. This method can be used even if the controlled state takes only a few discrete values.
A second approach based on dynamic programming uses scenario trees: in this case, the uncertainties evolve on a tree taking only discrete values.
• The second case is a special case of the previous one when the problem to be solved is linear and the controlled state takes values at continuous intervals. The value function must be convex or concave with respect to the controlled variables. This method, the SDDP method, is used when the dimension of the controlled state is large, which prevents the use of the dynamic programming method. As before, the uncertainties can be described either by scenarios or by a scenario tree.
Remark 1 The use of this method requires other assumptions which will be described in the dedicated chapter.
• A third method solves the Monte Carlo problem when a process is controlled but by an uncontrolled process. this is generally the optimization of a portfolio:
– The value of the portfolio is deterministically controlled and discretized on a network,
– The evolution of the portfolio is driven by an uncontrolled exogenous process: market prices.
• In the fourth method, we will assume that the state takes continuous values, we will solve equation (2.1) using semi-Lagrangian methods discretizing the Brownian motion with two values and using some interpolations on grids.
• Finally, we present a general pure Monte Carlo method based on automatic differen-tiation and randomization of the time step to solve general non-linear equations and which can be used to solve certain control problems.
In what follows, we assume that a temporal discretization is given for the resolution of the optimization problem. We assume that the step discretization is constant and equal to h such that ti = ih. First, we describe some useful tools developed in the library for stochastic
control. Then, we explain how to solve certain optimization problems using these developed tools.
Remark 2 In the library, we rely a lot on the Eigen library: ArrayXdwhich represents a double vector, ArrayXXd for a double matrix and ArrayXi for a vector of integer.
Part II
Chapter 3
The grids and their interpolators
In this chapter we develop the tools used to interpolate a discretized function on a given grid. A grid is a set of point in Rd defining meshes which can be used to interpolate a function on an open set in Rd. These tools are used to interpolate a given function, for example at
certain stock points, when it comes to storage. These are also useful for semi-Lagrangian methods, which require efficient interpolation methods. In StOpt four types of grids are currently available:
• the first and second are grids used to interpolate a function linearly on a grid;
• the third type of grid, starting from a regular grid, makes it possible to interpolate on a grid at Gauss - Lobatto points on each mesh;
• the last grid allows to interpolate a function in high dimension using the sparse grid-method. The approximation is linear, quadratic, or cubic in each direction.
Each type of grid is associated with iterators. An iterator on a grid makes it possible to iterate on all the points of the grids. All iterators derive from abstract class GridIterator
1 // C o p y r i g h t ( C ) 2 0 1 6 EDF
2 // All R i g h t s R e s e r v e d
3 // T h i s c o d e is p u b l i s h e d u n d e r the GNU L e s s e r G e n e r a l P u b l i c L i c e n s e ( GNU L G P L )
4 # i f n d e f G R I D I T E R A T O R _ H 5 # d e f i n e G R I D I T E R A T O R _ H 6 # i n c l u d e < E i g e n / Dense > 7 8 /* * \ f i l e G r i d I t e r a t o r . h 9 * \ b r i e f D e f i n e s an i t e r a t o r on the p o i n t s of a g r i d 10 * \ a u t h o r X a v i e r W a r i n 11 */ 12 n a m e s p a c e S t O p t 13 { 14 15 // / \ c l a s s G r i d I t e r a t o r G r i d I t e r a t o r . h 16 // / I t e r a t o r on a g i v e n g r i d 17 c l a s s G r i d I t e r a t o r 18 { 19 20 p u b l i c : 21 22 // / \ b r i e f C o n s t r u c t o r 23 G r i d I t e r a t o r () {} 24 25 // / \ b r i e f D e s t r u c t o r
26 v i r t u a l ~ G r i d I t e r a t o r () {} 27 28 // / \ b r i e f get c u r r e n t c o o r d i n a t e s 29 v i r t u a l E i g e n :: A r r a y X d g e t C o o r d i n a t e () c o n s t = 0 ; 30 31 // / \ b r i e f C h e c k if the i t e r a t o r is v a l i d 32 v i r t u a l b o o l i s V a l i d (v o i d) c o n s t = 0; 33 34 // / \ b r i e f i t e r a t e on p o i n t 35 v i r t u a l v o i d n e x t () = 0; 36 37 // / \ b r i e f i t e r a t e j u m p i n g s o m e p o i n t 38 // / \ p a r a m p _ i n c r i n c r e m e n t in the j u m p 39 v i r t u a l v o i d n e x t I n c (c o n s t int & p _ i n c r ) = 0; 40
41 // / \ b r i e f get c o u n t e r : the i n t e g e r a s s o c i a t e d the c u r r e n t p o i n t
42 v i r t u a l int g e t C o u n t () c o n s t = 0;
43
44 // / \ b r i e f P e r m i t s to j u m p to a g i v e n p l a c e g i v e n the n u m b e r of p r o c e s s o r s ( p e r m i t s to
use MPI and o p e n m p )
45 // / \ p a r a m p _ r a n k p r o c e s s o r r a n k
46 // / \ p a r a m p _ n b P r o c n u m b e r of p r o c e s s o r
47 // / \ p a r a m p _ j u m p i n c r e m e n t j u m p for i t e r a t o r
48 v i r t u a l v o i d j u m p T o A n d I n c (c o n s t int & p_rank , c o n s t int & p _ n b P r o c , c o n s t int & p _ j u m p ) = 0; 49 50 // / \ b r i e f r e t u r n r e l a t i v e p o s i t i o n 51 v i r t u a l int g e t R e l a t i v e P o s i t i o n () c o n s t = 0 ; 52 53 // / \ b r i e f r e t u r n n u m b e r of p o i n t s t r e a t e d 54 v i r t u a l int g e t N b P o i n t R e l a t i v e () c o n s t = 0 ; 55 56 // / \ b r i e f R e s e t the i n t e r p o l a t o r 57 v i r t u a l v o i d r e s e t () = 0 ; 58 59 }; 60 } 61 # e n d i f /* G R I D I T E R A T O R _ H */
All iterators share some common characteristics:
• the getCount method provides the number associated with the current grid point, • the next method allows you to go to the next point, while the nextInc method allows
you to go to the pointp incr,
• the isValid method checks that we are still on a grid point,
• the getNbPointRelative allows to get the number of points on which a given iterator can iterate,
• the getRelativePosition retrieves the number of points already iterated by the it-erator.
In addition, we can go directly to a given point: this functionality is useful for ”mpi” when some calculations on the grid are distributed on some processors and threads. This possibility is given by the method jumpToAndInc.
Using a grid regGrid the following source code makes it possible to iterate over the points of the grids and obtain coordinates. For each coordinate, a function f is used to fill an array of values. As mentioned earlier, each type of grid has its own grid iterator which can be obtained by the getGridIterator method.
1 A r r a y X d d a t a ( r e g G r i d . g e t N b P o i n t s () ) ; // c r e a t e an a r r a y to s t o r e the v a l u e s of the f u n c t i o n f 2 s h a r e d _ p t r < G r i d I t e r a t o r > i t e r R e g G r i d = r e g G r i d . g e t G r i d I t e r a t o r () ; 3 w h i l e ( i t e r R e g G r i d - > i s V a l i d () ) 4 { 5 A r r a y X d p o i n t C o o r d = i t e r R e g G r i d - > g e t C o o r d i n a t e () ; // s t o r e the c o o r d i n a t e s of the p o i n t 6 d a t a ( i t e r R e g G r i d - > g e t C o u n t () ) = f ( p o i n t C o o r d ) ; // the v a l u e is s t o r e d in d a t a at p l a c e i t e r R e g G r i d - > g e t C o u n t () 7 i t e r R e g G r i d - > n e x t () ; // go to n e x t p o i n t 8 }
It is also possible to “skip” certain points and repeat for the ”p” points afterwards. This possibility is useful for multithreaded tasks on points.
For each type of grid, an interpolator is provided to interpolate a given function on a grid. Note that the interpolator is created for a given point where we want to interpolate. All interpolators (which are not spectral interpolators) derive from Interpolator whose source code is given below.
1 // C o p y r i g h t ( C ) 2 0 1 6 EDF
2 // All R i g h t s R e s e r v e d
3 // T h i s c o d e is p u b l i s h e d u n d e r the GNU L e s s e r G e n e r a l P u b l i c L i c e n s e ( GNU L G P L )
4 # i f n d e f I N T E R P O L A T O R _ H 5 # d e f i n e I N T E R P O L A T O R _ H 6 # i n c l u d e < vector > 7 # i n c l u d e < E i g e n / Dense > 8 /* * \ f i l e I n t e r p o l a t o r . h 9 * \ b r i e f D e f i n e s a i n t e r p o l a t o r on a f u l l g r i d 10 * \ a u t h o r X a v i e r W a r i n 11 */ 12 n a m e s p a c e S t O p t 13 { 14 15 // / \ c l a s s I n t e r p o l a t o r I n t e r p o l a t o r . h 16 // / I n t e r p o l a t i o n b a s e c l a s s 17 c l a s s I n t e r p o l a t o r 18 { 19 p u b l i c : 20 21 // / \ b r i e f D e f a u l t c o n s t r u c t o r 22 I n t e r p o l a t o r () {} 23 24 // / \ b r i e f D e f a u l t D e s t r u c t o r 25 v i r t u a l ~ I n t e r p o l a t o r () {} 26 27 /* * \ b r i e f i n t e r p o l a t e 28 * \ p a r a m p _ d a t a V a l u e s V a l u e s of the d a t a on the g r i d 29 * \ r e t u r n i n t e r p o l a t e d v a l u e 30 */ 31 v i r t u a l d o u b l e a p p l y (c o n s t E i g e n :: Ref < c o n s t E i g e n :: A r r a y X d > & p _ d a t a V a l u e s ) c o n s t = 0; 32 33 /* * \ b r i e f i n t e r p o l a t e and use v e c t o r i z a t i o n
34 * \ p a r a m p _ d a t a V a l u e s V a l u e s of the d a t a on the g r i d . I n t e r p o l a t i o n is a c h i e v e d for
all v a l u e s in the f i r s t d i m e n s i o n
35 * \ r e t u r n i n t e r p o l a t e d v a l u e
36 */
37 v i r t u a l E i g e n :: A r r a y X d a p p l y V e c (c o n s t E i g e n :: A r r a y X X d & p _ d a t a V a l u e s ) c o n s t = 0;
38
39 /* * \ b r i e f S a m e as a b o v e but a v o i d s c o p y for N u m p y e i g e n m a p p i n g due to s t o r a g e
c o n v e n t i o n s
40 * \ p a r a m p _ d a t a V a l u e s V a l u e s of the d a t a on the g r i d . I n t e r p o l a t i o n is a c h i e v e d
for all v a l u e s in the f i r s t d i m e n s i o n
41 * \ r e t u r n i n t e r p o l a t e d v a l u e
43 v i r t u a l E i g e n :: A r r a y X d a p p l y V e c P y ( E i g e n :: Ref < E i g e n :: A r r a y X X d , 0 , E i g e n :: Stride < E i g e n :: Dynamic , E i g e n :: Dynamic > > p _ d a t a V a l u e s ) c o n s t = 0; 44 45 }; 46 } 47 # e n d i f
All interpolators provide a constructor specifying the point where the interpolation is car-ried out and the two functions apply and applyVec interpolating either a function (and returning a value) or an array of functions returning an array of interpolated values.
All grid classes derive from an abstract class SpaceGrid below allowing to retrieve an iterator associated with the points of the grid (with possible jumps) and to create an inter-polator associated with the grid.
1 // C o p y r i g h t ( C ) 2 0 1 6 EDF
2 // All R i g h t s R e s e r v e d
3 // T h i s c o d e is p u b l i s h e d u n d e r the GNU L e s s e r G e n e r a l P u b l i c L i c e n s e ( GNU L G P L )
4 # i f n d e f S P A C E G R I D _ H 5 # d e f i n e S P A C E G R I D _ H 6 # i n c l u d e < array > 7 # i n c l u d e < memory > 8 # i n c l u d e < E i g e n / Dense > 9 # i n c l u d e " S t O p t / c o r e / g r i d s / G r i d I t e r a t o r . h " 10 # i n c l u d e " S t O p t / c o r e / g r i d s / I n t e r p o l a t o r . h " 11 # i n c l u d e " S t O p t / c o r e / g r i d s / I n t e r p o l a t o r S p e c t r a l . h " 12 13 /* * \ f i l e S p a c e G r i d . h
14 * \ b r i e f D e f i n e s a b a s e c l a s s for all the g r i d s
15 * \ a u t h o r X a v i e r W a r i n 16 */ 17 n a m e s p a c e S t O p t 18 { 19 20 // / \ c l a s s S p a c e G r i d S p a c e G r i d . h 21 // / D e f i n e s a b a s e c l a s s for g r i d s 22 c l a s s S p a c e G r i d 23 { 24 p u b l i c : 25 // / \ b r i e f D e f a u l t c o n s t r u c t o r 26 S p a c e G r i d () {} 27 28 // / \ b r i e f D e f a u l t d e s t r u c t o r 29 v i r t u a l ~ S p a c e G r i d () {} 30 31 // / \ b r i e f N u m b e r of p o i n t s of the g r i d 32 v i r t u a l s i z e _ t g e t N b P o i n t s () c o n s t = 0; 33 34 // / \ b r i e f get b a c k i t e r a t o r a s s o c i a t e d to the g r i d 35 v i r t u a l std :: s h a r e d _ p t r < G r i d I t e r a t o r > g e t G r i d I t e r a t o r () c o n s t = 0; 36 37 // / \ b r i e f get b a c k i t e r a t o r a s s o c i a t e d to the g r i d ( m u l t i t h r e a d ) 38 v i r t u a l std :: s h a r e d _ p t r < G r i d I t e r a t o r > g e t G r i d I t e r a t o r I n c (c o n s t int & p _ i T h r e a d ) c o n s t = 0; 39 40 // / \ b r i e f Get b a c k i n t e r p o l a t o r at a p o i n t I n t e r p o l a t e on the g r i d 41 // / \ p a r a m p _ c o o r d c o o r d i n a t e of the p o i n t for i n t e r p o l a t i o n 42 // / \ r e t u r n i n t e r p o l a t o r at the p o i n t c o o r d i n a t e s on the g r i d 43 v i r t u a l std :: s h a r e d _ p t r < I n t e r p o l a t o r > c r e a t e I n t e r p o l a t o r (c o n s t E i g e n :: A r r a y X d & p _ c o o r d ) c o n s t = 0; 44 45 // / \ b r i e f Get b a c k a s p e c t r a l o p e r a t o r a s s o c i a t e d to a w h o l e f u n c t i o n 46 // / \ p a r a m p _ v a l u e s F u n c t i o n v a l u e at the g r i d s p o i n t s 47 // / \ r e t u r n the w h o l e i n t e r p o l a t e d v a l u e f u n c t i o n 48 v i r t u a l std :: s h a r e d _ p t r < I n t e r p o l a t o r S p e c t r a l > c r e a t e I n t e r p o l a t o r S p e c t r a l (c o n s t E i g e n :: A r r a y X d & p _ v a l u e s ) c o n s t = 0;
49
50 // / \ b r i e f D i m e n s i o n of the g r i d
51 v i r t u a l int g e t D i m e n s i o n () c o n s t = 0 ;
52
53 // / \ b r i e f get b a c k b o u n d s a s s o c i a t e d to the g r i d
54 // / \ r e t u r n in e a c h d i m e n s i o n g i v e the e x t r e m e v a l u e s ( min , max ) of the d o m a i n
55 v i r t u a l std :: v e c t o r < std :: array < double, 2 > > g e t E x t r e m e V a l u e s () c o n s t = 0; 56 57 // / \ b r i e f t e s t if the p o i n t is s t r i c t l y i n s i d e the d o m a i n 58 // / \ p a r a m p _ p o i n t p o i n t to t e s t 59 // / \ r e t u r n t r u e if the p o i n t is s t r i c t l y i n s i d e the o p e n d o m a i n 60 v i r t u a l b o o l i s S t r i c t l y I n s i d e (c o n s t E i g e n :: A r r a y X d & p _ p o i n t ) c o n s t = 0 ; 61 62 // / \ b r i e f t e s t if a p o i n t is i n s i d e the g r i d ( b o u n d a r y i n c l u d e ) 63 // / \ p a r a m p _ p o i n t p o i n t to t e s t 64 // / \ r e t u r n t r u e if the p o i n t is i n s i d e the o p e n d o m a i n 65 v i r t u a l b o o l i s I n s i d e (c o n s t E i g e n :: A r r a y X d & p _ p o i n t ) c o n s t = 0 ; 66 67 // / \ b r i e f t r u n c a t e a p o i n t so t h a t it s t a y s i n s i d e the d o m a i n 68 // / \ p a r a m p _ p o i n t p o i n t to t r u n c a t e 69 v i r t u a l v o i d t r u n c a t e P o i n t ( E i g e n :: A r r a y X d & p _ p o i n t ) c o n s t = 0 ; 70 71 }; 72 } 73 # e n d i f /* S P A C E G R I D . H */
All the grids objects, interpolators and iterators on grids point are in StOpt/core/grids
Grid objects are mapped to python, giving the possibility of retrieving the iterators and interpolators associated with a grid. Examples of Python can be found in
test/python/unit/grids
3.1
Linear grids
3.1.1
Definition and C++ API
Two kinds of grids are developed:
• the first one is the GeneralSpaceGrid with Constructor
1 G e n e r a l S p a c e G r i d (c o n s t std :: vector < s h a r e d _ p t r < E i g e n :: ArrayXd > > & p _ m e s h P e r D i m e n s i o n )
where std::vector<shared ptr<Eigen::ArrayXd>> is a vector of (pointer to) arrays defining the grid points in each dimension. In this case the grid is not regular and the mesh varies in space (see figure 3.1).
• the second one is the RegularSpaceGrid with Constructor
1 R e g u l a r S p a c e G r i d (c o n s t E i g e n :: A r r a y X d & p _ l o w V a l u e s , c o n s t E i g e n :: A r r a y X d & p_step ,
c o n s t E i g e n :: A r r a y X i & p _ n b S t e p )
The p lowValues corresponds to the bottom of the grid, p step the size of each mesh, p nbStep the number of steps in each direction (see figure 3.2)
Figure 3.1: 2D general grid
Figure 3.2: 2D regular grid
For each grid, a linear interpolator can be generated by calling the createInterpolator method or by directly creating the interpolator:
1 /* * \ b r i e f C o n s t r u c t o r
2 * \ p a r a m p _ g r i d is the g r i d u s e d to i n t e r p o l a t e
3 * \ p a r a m p _ p o i n t is the c o o r d i n a t e s of the p o i n t s u s e d for i n t e r p o l a t i o n
4 */
5 L i n e a r I n t e r p o l a t o r ( c o n s t F u l l G r i d * p _ g r i d , c o n s t E i g e n :: A r r a y X d & p _ p o i n t ) :
Its construction from a grid (regLin) and from an array data containing the values of the function at the points of the grid is given below (taking an example above for fill in the table data) 1 A r r a y X d d a t a ( r e g G r i d . g e t N b P o i n t s () ) ; // c r e a t e an a r r a y to s t o r e the v a l u e s of the f u n c t i o n f 2 s h a r e d _ p t r < G r i d I t e r a t o r > i t e r R e g G r i d = r e g G r i d . g e t G r i d I t e r a t o r () ; 3 w h i l e ( i t e r R e g G r i d - > i s V a l i d () ) 4 { 5 A r r a y X d p o i n t C o o r d = i t e r R e g G r i d - > g e t C o o r d i n a t e () ; // s t o r e the c o o r d i n a t e of the p o i n t 6 d a t a ( i t e r R e g G r i d - > g e t C o u n t () ) = f ( p o i n t C o o r d ) ; // the v a l u e is s t o r e d in the d a t a at l o c a t i o n i t e r R e g G r i d - > g e t C o u n t () 7 i t e r R e g G r i d - > n e x t () ; // go to n e x t p o i n t 8 } 9 // p o i n t w h e r e to i n t e r p o l a t e 10 A r r a y X d p o i n t = A r r a y X d :: C o n s t a n t ( nDim , 1. / 3.) ; 11 // c r e a t e the i n t e r p o l a t o r 12 L i n e a r I n t e r p o l a t o r r e g L i n (& regGrid , p o i n t ) ; 13 // get b a c k the i n t e r p o l a t e d v a l u e 14 d o u b l e i n t e r p R e g = r e g L i n . a p p l y ( d a t a ) ;
Let I1,∆X be the linear interpolator where the mesh is ∆x = (∆x1, . . . , ∆xd). We obtain for a function f in Ck+1(Rd) with k ≤ 1 ||f − I1,∆xf ||∞≤ c d X i=1 ∆xk+1i sup x∈[−1,1]d |∂ k+1f ∂xk+1i | (3.1)
In particular if f is only Lipschitz
||f − I1,∆xf ||∞≤ K sup i
∆xi.
3.1.2
The python API
The python API allows you to use grids with a syntax similar to the C++ API. Here, we give an example with a regular grid
1 # C o p y r i g h t ( C ) 2 0 1 6 EDF
2 # All R i g h t s R e s e r v e d
3 # T h i s c o d e is p u b l i s h e d u n d e r the GNU L e s s e r G e n e r a l P u b l i c L i c e n s e ( GNU L G P L )
4 i m p o r t n u m p y as np 5 i m p o r t u n i t t e s t 6 i m p o r t r a n d o m 7 i m p o r t m a t h 8 i m p o r t S t O p t G r i d s 9 10 # u n i t t e s t for r e g u l a r g r i d s 11 # # # # # # # # # # # # # # # # # # # # # # # # # # # # 12 13 c l a s s t e s t G r i d s ( u n i t t e s t . T e s t C a s e ) : 14 15 # 3 d i m e n s i o n a l t e s t for l i n e a r i n t e r p o l a t i o n on r e g u l a r g r i d s 16 def t e s t R e g u l a r G r i d s ( s e l f ) :
17 # low v a l u e for the m e s h e s
18 l o w V a l u e s = np . a r r a y ([1. ,2. ,3.] , d t y p e = np .f l o a t) 19 # s i z e of the m e s h e s 20 s t e p = np . a r r a y ([ 0 . 7 , 2. 3 , 1 . 9] , d t y p e = np .f l o a t) 21 # n u m b e r of s t e p s 22 n b S t e p = np . a r r a y ([4 ,5 ,6] , d t y p e = np . i n t 3 2 ) 23 # c r e a t e the r e g u l a r g r i d 24 g r i d = S t O p t G r i d s . R e g u l a r S p a c e G r i d ( l o w V a l u e s , step , n b S t e p ) 25 i t e r G r i d = g r i d . g e t G r i d I t e r a t o r () 26 # a r r a y to s t o r e 27 d a t a = np . e m p t y ( g r i d . g e t N b P o i n t s () ) 28 # i t e r a t e s on p o i n t s and s t o r e v a l u e s 29 w h i l e( i t e r G r i d . i s V a l i d () ) : 30 # get c o o r d i n a t e s of the p o i n t 31 p o i n t C o o r d = i t e r G r i d . g e t C o o r d i n a t e () 32 d a t a [ i t e r G r i d . g e t C o u n t () ] = m a t h . log (1. + p o i n t C o o r d .sum() ) 33 i t e r G r i d .n e x t() 34 # get b a c k an i n t e r p o l a t o r 35 p t I n t e r p = np . a r r a y ( [ 2 .3 , 3 . 2 , 5 . 9 ] , d t y p e = np .f l o a t) 36 i n t e r p o l = g r i d . c r e a t e I n t e r p o l a t o r ( p t I n t e r p ) 37 # c a l c u l a t e i n t e r p o l a t e d v a l u e 38 i n t e r p V a l u e = i n t e r p o l .a p p l y( d a t a ) 39 p r i n t((" I n t e r p o l a t e d v a l u e " , i n t e r p V a l u e ) ) 40 # t e s t g r i d s f u n c t i o n 41 i D i m = g r i d . g e t D i m e n s i o n () 42 pt = g r i d . g e t E x t r e m e V a l u e s () 43 44 if _ _ n a m e _ _ == ’ _ _ m a i n _ _ ’: 45 u n i t t e s t . m a i n ()
1 # C o p y r i g h t ( C ) 2 0 1 7 EDF
2 # All R i g h t s R e s e r v e d
3 # T h i s c o d e is p u b l i s h e d u n d e r the GNU L e s s e r G e n e r a l P u b l i c L i c e n s e ( GNU L G P L )
4 i m p o r t n u m p y as np 5 i m p o r t u n i t t e s t 6 i m p o r t r a n d o m 7 i m p o r t m a t h 8 i m p o r t S t O p t G r i d s 9 10 # u n i t t e s t for g e n e r a l g r i d s 11 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 12 13 c l a s s t e s t G r i d s ( u n i t t e s t . T e s t C a s e ) : 14 15 16 # t e s t g e n e r a l g r i d s 17 def t e s t G e n e r a l G r i d s ( s e l f ) :
18 # low v a l u e for the m e s h
19 l o w V a l u e s = np . a r r a y ([1. ,2. ,3.] , d t y p e = np .f l o a t) 20 # s i z e of the m e s h 21 s t e p = np . a r r a y ([ 0 . 7 , 2. 3 , 1 . 9] , d t y p e = np .f l o a t) 22 # n u m b e r of s t e p 23 n b S t e p = np . a r r a y ([4 ,5 ,6] , d t y p e = np . i n t 3 2 ) 24 # d e g r e e of the p o l y n o m i a l in e a c h d i r e c t i o n 25 d e g r e e = np . a r r a y ([2 ,1 ,3] , d t y p e = np . i n t 3 2 ) 26 27 # l i s t of m e s h 28 m e s h 1 = np . a r r a y ( [ 1 . + 0 . 7 * i for i in np . a r a n g e (5) ] , d t y p e = np .f l o a t) 29 m e s h 2 = np . a r r a y ( [ 2 . + 2 . 3 * i for i in np . a r a n g e (6) ] , d t y p e = np .f l o a t) 30 m e s h 3 = np . a r r a y ( [ 3 . + 1 . 9 * i for i in np . a r a n g e (7) ] , d t y p e = np .f l o a t) 31 32 # c r e a t e the g e n e r a l g r i d 33 g r i d = S t O p t G r i d s . G e n e r a l S p a c e G r i d ([ mesh1 , mesh2 , m e s h 3 ] ) 34 35 i t e r G r i d = g r i d . g e t G r i d I t e r a t o r () 36 # a r r a y to s t o r e 37 d a t a = np . e m p t y ( g r i d . g e t N b P o i n t s () ) 38 # i t e r a t e s on p o i n t 39 w h i l e( i t e r G r i d . i s V a l i d () ) : 40 # get c o o r d i n a t e s of the p o i n t 41 p o i n t C o o r d = i t e r G r i d . g e t C o o r d i n a t e () 42 d a t a [ i t e r G r i d . g e t C o u n t () ] = m a t h . log (1. + p o i n t C o o r d .sum() ) 43 i t e r G r i d .n e x t() 44 # get b a c k an i n t e r p o l a t o r 45 p t I n t e r p = np . a r r a y ( [ 2 .3 , 3 . 2 , 5 . 9 ] , d t y p e = np .f l o a t) 46 i n t e r p o l = g r i d . c r e a t e I n t e r p o l a t o r ( p t I n t e r p ) 47 # c a l c u l a t e i n t e r p o l a t e d v a l u e 48 i n t e r p V a l u e = i n t e r p o l .a p p l y( d a t a ) 49 # t e s t g r i d s f u n c t i o n 50 i D i m = g r i d . g e t D i m e n s i o n () 51 pt = g r i d . g e t E x t r e m e V a l u e s () 52 53 54 if _ _ n a m e _ _ == ’ _ _ m a i n _ _ ’: 55 u n i t t e s t . m a i n ()
3.2
Legendre grids
With linear interpolation, to obtain a precise solution, it is necessary to refine the mesh so that ∆x goes to zero. Another approach consists in trying to fit a polynomial on each mesh using a high degree interpolator.
3.2.1
Approximation of a function in 1 dimension
From now on, by resizing we assume that we want to interpolate a function f on [−1, 1]. All the following results can be extended by tensorization in dimension greater than 1. PN is
the set of polynomials of total degree less than or equal to N . The minmax approximation of f of degree N is the polynomial PN∗(f ) such that:
||f − PN∗(f )||∞= min p∈PN
||f − p||∞
We call IX
N interpolator from f on a grid of N + 1 points of [−1, 1] X = (x0, . . . , xN), the
unique polynomial of degree N such that
INX(f )(xi) = f (xi), 0 ≤ i ≤ N
This polynomial can be expressed in terms of the Lagrange polynomial lX
i , 0 ≤ i ≤ N
associated with the grid (lXi is the unique polynomial of degree N taking a value equal to 1 at the point i and 0 at the other interpolation points).
INX(f )(x) =
N
X
i=0
f (xi)lXi (x)
The interpolation error can be expressed in terms of interpolation points: ||INX(f )(x) − f ||∞≤ (1 + λN(X))||f − PN∗(f )||∞
where λN(X) is the Lebesgue constant associated with the Lagrange quadrature on the grid:
λN(X) = max x∈[−1,1] N X i=0 |lX i (x)|.
We have the following bound ||IX
N(f )(x)||∞ ≤ λN(X)supxi∈X|f (xi)| ≤ λN(X)||f ||∞
and the Erd¨os theorem states that λN(X) >
2
Πlog(N + 1) − C
It is well–known that the use of a uniform grid Xu is not optimal, because like N −→ ∞,
the Lebesgue constant satisfies
λN(Xu) '
2N +1 eN ln N
and the quadrature error in L∞ increases a lot with N . Its use brings some
oscilla-tions giving the Runge effect. On Figures 3.3a, 3.3b, 3.3c, 3.3d, we trace the function Runge 1+25x1 2 against its interpolation with polynomial with equidistant interpolation. We
(a) (b)
(c) (d)
Figure 3.3: Runge function 1+25x1 2 and its polynomial interpolations at degrees 3, 4, 8, and
18.
Gauss–Chebyshev interpolation points (corresponding to the 0 of the polynomial TN +1(x) =
cos((N + 1) arccos(x)) give a Lebesgue constant λN(XGC) equal to
λN(XGC) '
2
Πln(N + 1)
For our problem, we want to interpolate a function on meshes with great precision on the mesh while respecting the continuity of the function between the meshes. In order to ensure this continuity we want the extreme points of the resized mesh [−1, −1] (therefore −1, 1) to be on the interpolation grid. This leads to the Gauss–Lobatto–Chebyshev interpolation grid.
In the library we choose to use the Gauss–Lobatto–Legendre interpolation grids which are as efficient as the Gauss–Lobatto–Chebyshev grids (in term of Lebesgue constant) but less costly in calculation due to the absence of trigonometric function. We recall that the Leg-endre polynomial satisfies the recurrence
(N + 1)LN +1(x) = (2N + 1)xLN(x) − N LN −1(x)
with L0 = 1, L1(x) = x.
These polynomials are orthogonal with the scalar product (f, g) = R−11 f (x)g(x)dx. We are interested in the derivatives of these polynomials L0N which satisfy the recurrence
These polynomials are orthogonal with the scalar product (f, g) =R−11 f (x)g(x)(1 − x2)dx.
The Gauss–Lobatto–Legendre grids points for a grid with N +1 points are η1 = −1, ηN +1= 1
and the ηi (i = 2, . . . , N ) zeros of L
0
N. The ηi (i = 2, . . . , N ) are eigenvalues of the matrix P
P = 0 γ1 . . . 0 0 γ1 0 . . . 0 0 .. . ... . .. ... ... 0 0 . . . 0 γN −2 0 0 . . . γN −2 0 , γn = 1 2 s n(n + 2) (n + 12)(n + 32), 1 ≤ n ≤ N − 2,
The interpolation IN(f ) is expressed in terms of Legendre polynomials by
IN(f ) = N X k=0 ˜ fkLk(x), ˜ fk = 1 γk N X i=0 ρif (ηi)Lk(ηi), γk = N X i=0 Lk(ηi)2ρi,
and the weights satisfy
ρi =
2.
(M + 1)M L2
M(ηi)
, 1 ≤ i ≤ N + 1.
More details can be found in [2]. In the figure 3.4, we give the interpolation obtained with the Gauss–Lobatto–Legendre quadrature with two degrees of approximation.
Figure 3.4: Interpolation with Gauss–Legendre–Lobatto grids
• When the function is not regular we introduce a weaker notion than the notion of derivative. We denote w(f, δ) The modulus of continuityon [−1, 1] of a function f as
w(f, δ) = sup
x1, x2 ∈ [−1, 1]
|x1− x2| < δ
The modulus of continuity makes it possible to express the best approximation of a function by a polynomial with the Jackson theorem:
Theorem 1 For a continuous function f on [−1, 1] ||f − PN∗(f )||∞ ≤ Kw(f,
1 N) and we deduce that for an interpolation gridX
||IX
N(f )(x) − f ||∞ ≤ M (N )
M (N ) ' Kw(f, 1
N)λN(X)
a function is Dini–Lipschitz continues if w(f, δ)log(δ) −→ 0 as δ −→ 0. It is clear that the functions of Lipschitz are Dini–Lipschitz continuously because w(f, δ)log(δ) ≤ Klog(δ)δ.
• When the solution is more regular, we can express the interpolation error as a function of its derivatives and we obtain the following Cauchy theorem for an interpolation grid X (see [41])
Theorem 2 If f is CN +1, and X an interpolation grid with N + 1 points, the inter-polation error checks
E(x) = f (x) − INX(f )(x) = f
N +1(η)
(N + 1)!W
X
N +1(x) (3.2)
where η ∈ [−1, 1] and WN +1X (x) is the nodal polynomial of degree N + 1 (the polynomial with the monomial of the highest degree with coefficient 1 being zero at all points N + 1 of X)
If we partition a domain I = [a, b] into a few meshes of size h and we use a Lagrange interpolator for the function f ∈ Ck+1 , k ≤ N we obtain
||f − IX
N,∆xf ||∞≤ chk+1||f(k+1)||∞
3.2.2
Extension in dimension d
In the dimension d, we denote PN∗ the best multivariate polynomial approximation of f of total degree less than N on [−1, 1]d. On a d multidimensional grid X = XNd, we define the
multivariate interpolator as the composition of one-dimensional interpolator IX
N(f )(x) = IXN,1 N × I XN,2 N · · · × I XN,d N (f )(x) where I XN,i
N represents for the interpolator in dimension i.
We get the following interpolation error ||IX
The error associated with the min max approximation is given by Feinerman and Newman [15], Soardi [44] ||f − PN∗(f )||∞ ≤ (1 + π2 4 √ d)w(f, 1 N + 2) We deduce that if f is only Lipschitz
||IX N(f )(x) − f ||∞ ≤ C √ d(1 + λN(X)) d N + 2 If the function is regular (in Ck+1([−1, 1]d), k < N ) we get
||f − PN∗(f )||∞ ≤ Ck Nk d X i=1 sup x∈[−1,1]d |∂ k+1f ∂xk+1i |
If we partition the domain I = [a1, b1]×· · ·×[ad, bd] in meshes of size ∆x = (∆x1, ∆x2, . . . , ∆xd)
and use a Lagrange interpolation on each mesh we obtain
||f − IX N,∆xf ||∞≤ c (1 + λN(X))d Nk d X i=1 ∆xk+1i sup x∈[−1,1]d |∂ k+1f ∂xk+1i |
On figure 3.5 we give the Gauss–Legendre–Lobatto points in 2D for 2 × 2 meshes and a polynomial of degree 8 in each direction
Figure 3.5: Gauss–Legendre–Lobatto points on 2 × 2 meshes.
3.2.3
Troncature
In order to avoid oscillations during the interpolation, a truncation is used on each mesh so that the modified interpolator ˆIX
N,∆x checks: ˆ IN,∆xX f (x) = min xi∈M f (xi) ∧ IN,∆xX f (x) ∨ max xi∈M f (xi) (3.3)
where the xi are the interpolation points on the mesh M containing the point x. For all the
3.2.4
The C++ API
The grid using Gauss–Legendre–Lobatto points can be created using this constructor:
1 R e g u l a r L e g e n d r e G r i d (c o n s t E i g e n :: A r r a y X d & p _ l o w V a l u e s , c o n s t E i g e n :: A r r a y X d & p_step ,
c o n s t E i g e n :: A r r a y X i & p _ n b S t e p , c o n s t E i g e n :: A r r a y X i & p _ p o l y ) ;
The p lowValues corresponds to the bottom of the grid, p step the size of each mesh, p nbStep the number of steps in each direction (see figure 3.2). On each mesh the polynomial approximation in each dimension is specified by the table p poly.
Remark 3 If we take a polynomial of degree 1 in each direction this interpolator is equiv-alent to the linear interpolator. Its sort of less efficient than the linear interpolator on a Regular grid described in the section above.
We illustrate the use of the grid, its iterator and its interpolator used to draw the figures 3.4. 1 2 A r r a y X d l o w V a l u e s = A r r a y X d :: C o n s t a n t (1 , -1.) ; // c o r n e r p o i n t 3 A r r a y X d s t e p = A r r a y X d :: C o n s t a n t (1 ,2.) ; // m e s h s i z e 4 A r r a y X i n b S t e p = A r r a y X i :: C o n s t a n t (1 ,1) ; // n u m b e r of m e s h e s in e a c h d i r e c t i o n 5 A r r a y X i n P o l = A r r a y X i :: C o n s t a n t (1 , p _ n P o l ) ; // p o l y n o m i a l a p p r o x i m a t i o n 6 // r e g u l a r L e g e n d r e 7 R e g u l a r L e g e n d r e G r i d r e g G r i d ( l o w V a l u e s , step , nbStep , n P o l ) ; 8 9 // D a t a t a b l e to s t o r e v a l u e s on the g r i d p o i n t s 10 A r r a y X d d a t a ( r e g G r i d . g e t N b P o i n t s () ) ; 11 s h a r e d _ p t r < G r i d I t e r a t o r > i t e r R e g G r i d = r e g G r i d . g e t G r i d I t e r a t o r () ; 12 w h i l e ( i t e r R e g G r i d - > i s V a l i d () ) 13 { 14 A r r a y X d p o i n t C o o r d = i t e r R e g G r i d - > g e t C o o r d i n a t e () ; 15 d a t a ( i t e r R e g G r i d - > g e t C o u n t () ) = 1 . / ( 1 . + 2 5 * p o i n t C o o r d (0) * p o i n t C o o r d (0) ) ; // r u n g e s t o r a g e f u n c t i o n 16 i t e r R e g G r i d - > n e x t () ; 17 } 18 // p o i n t 19 A r r a y X d p o i n t (1) ; 20 int nbp = 1 0 0 0 ; 21 d o u b l e dx = 2./ nbp ; 22 for (int ip =0; ip <= nbp ; ++ ip ) 23 { 24 p o i n t (0) = -1+ ip * dx ; 25 // c r e a t e i n t e r p o l a t o r 26 s h a r e d _ p t r < I n t e r p o l a t o r > i n t e r p = r e g G r i d . c r e a t e I n t e r p o l a t o r ( p o i n t ) ; 27 d o u b l e i n t e r p R e g = interp - > a p p l y ( d a t a ) ; // i n t e r p o l a t e d v a l u e 28 }
The operator defined above is more efficient when we interpolate several functions at the same point. Its is the case for example for the valuation of a storage with regression where one wishes to interpolate all the simulations at the same level of stock.
In some cases it is more practical to build an interpolator acting on a global function. This is the case when you have only one function and you want to interpolate at several points for this function. In this specific case an interpolator deriving from the class Inter polatorSpectral can be constructed:
1 // C o p y r i g h t ( C ) 2 0 1 6 EDF
2 // All R i g h t s R e s e r v e d
3 // T h i s c o d e is p u b l i s h e d u n d e r the GNU L e s s e r G e n e r a l P u b l i c L i c e n s e ( GNU L G P L )
5 # d e f i n e I N T E R P O L A T O R S P E C T R A L _ H 6 # i n c l u d e < E i g e n / Dense > 7 // # i n c l u d e " S t O p t / c o r e / g r i d s / S p a c e G r i d . h " 8 9 /* * \ f i l e I n t e r p o l a t o r S p e c t r a l . h 10 * \ b r i e f D e f i n e s an i n t e r p o l a t o r for a g r i d : h e r e is a g l o b a l i n t e r p o l a t o r , s t o r i n g the r e p r e s e n t a t i o n of the f u n c t i o n 11 * to i n t e r p o l a t e : t h i s i n t e r p o l a t i o n is e f f e c t i v e w h e n i n t e r p o l a t i n g the s a m e f u n c t i o n m a n y t i m e s at d i f f e r e n t p o i n t s 12 * H e r e it is an a b s t r a c t c l a s s 13 * \ a u t h o r X a v i e r W a r i n 14 */ 15 n a m e s p a c e S t O p t 16 { 17 18 // / f o r w a r d d e c l a r a t i o n 19 c l a s s S p a c e G r i d ; 20 21 // / \ c l a s s I n t e r p o l a t o r S p e c t r a l I n t e r p o l a t o r S p e c t r a l . h 22 // / A b s t r a c t c l a s s for s p e c t r a l o p e r a t o r 23 c l a s s I n t e r p o l a t o r S p e c t r a l 24 { 25 26 p u b l i c : 27 v i r t u a l ~ I n t e r p o l a t o r S p e c t r a l () {} 28 29 /* * \ b r i e f i n t e r p o l a t e 30 * \ p a r a m p _ p o i n t c o o r d i n a t e s of the p o i n t for i n t e r p o l a t i o n 31 * \ r e t u r n i n t e r p o l a t e d v a l u e 32 */ 33 v i r t u a l d o u b l e a p p l y (c o n s t E i g e n :: A r r a y X d & p _ p o i n t ) c o n s t = 0; 34 35 36 /* * \ b r i e f A f f e c t the g r i d 37 * \ p a r a m p _ g r i d the g r i d to a f f e c t 38 */ 39 v i r t u a l v o i d s e t G r i d (c o n s t S t O p t :: S p a c e G r i d * p _ g r i d ) = 0 ; 40 41 /* * \ b r i e f Get b a c k g r i d a s s o c i a t e d to o p e r a t o r 42 */ 43 v i r t u a l c o n s t S t O p t :: S p a c e G r i d * g e t G r i d () = 0; 44 }; 45 } 46 # e n d i f
Its constructor is given by:
1 /* * \ b r i e f C o n s t r u c t o r t a k i n g v a l u e s on the g r i d
2 * \ p a r a m p _ g r i d is the g r i d u s e d to i n t e r p o l a t e
3 * \ p a r a m p _ v a l u e s V a l u e of the f u n c t i o n at the p o i n t s of the g r i d .
4 */
5 L e g e n d r e I n t e r p o l a t o r S p e c t r a l (c o n s t s h a r e d _ p t r < R e g u l a r L e g e n d r e G r i d > & p _ g r i d , c o n s t
E i g e n :: A r r a y X d & p _ v a l u e s ) ;
This class has a member allowing to interpolate at a given point:
1 /* * \ b r i e f i n t e r p o l a t e
2 * \ p a r a m p _ p o i n t c o o r d i n a t e s of the p o i n t for i n t e r p o l a t i o n
3 * \ r e t u r n i n t e r p o l a t e d v a l u e
4 */
5 i n l i n e d o u b l e a p p l y (c o n s t E i g e n :: A r r a y X d & p _ p o i n t ) c o n s t
We give an example of using this class, by interpolating a function f function in dimension 2.
1 A r r a y X d l o w V a l u e s = A r r a y X d :: C o n s t a n t (2 ,1.) ; // b o t t o m of the d o m a i n
2 A r r a y X d s t e p = A r r a y X d :: C o n s t a n t (2 ,1.) ; // m e s h s i z e
4 A r r a y X i n P o l = A r r a y X i :: C o n s t a n t (2 ,2) ; // p o l y n o m i a l of d e g r e e 2 in e a c h d i r e c t i o n
5 // r e g u l a r
6 s h a r e d _ p t r < R e g u l a r L e g e n d r e G r i d > r e g G r i d (new R e g u l a r L e g e n d r e G r i d ( l o w V a l u e s , step , nbStep , n P o l ) ) ; 7 A r r a y X d d a t a ( regGrid - > g e t N b P o i n t s () ) ; // D a t a t a b l e 8 s h a r e d _ p t r < G r i d I t e r a t o r > i t e r R e g G r i d = regGrid - > g e t G r i d I t e r a t o r () ; // i t e r a t o r on the g r i d p o i n t s 9 w h i l e ( i t e r R e g G r i d - > i s V a l i d () ) 10 { 11 A r r a y X d p o i n t C o o r d = i t e r R e g G r i d - > g e t C o o r d i n a t e () ; 12 d a t a ( i t e r R e g G r i d - > g e t C o u n t () ) = f ( p o i n t C o o r d ) ; 13 i t e r R e g G r i d - > n e x t () ; 14 } 15 16 // s p e c t r a l i n t e r p o l a t o r 17 L e g e n d r e I n t e r p o l a t o r S p e c t r a l i n t e r p o l a t o r ( regGrid , d a t a ) ; 18 // i n t e r p o l a t i o n p o i n t 19 A r r a y X d p o i n t C o o r d (2 , 5 . 2 ) ; 20 // i n t e r p o l a t e d v a l u e 21 d o u b l e v I n t e r p = i n t e r p o l a t o r . a p p l y ( p o i n t C o o r d ) ;
3.2.5
The python API
Here is an example using Legendre grids:
1 # C o p y r i g h t ( C ) 2 0 1 6 EDF
2 # All R i g h t s R e s e r v e d
3 # T h i s c o d e is p u b l i s h e d u n d e r the GNU L e s s e r G e n e r a l P u b l i c L i c e n s e ( GNU L G P L )
4 i m p o r t n u m p y as np 5 i m p o r t u n i t t e s t 6 i m p o r t r a n d o m 7 i m p o r t m a t h 8 i m p o r t S t O p t G r i d s 9 10 # u n i t t e s t for L e g e n d r e g r i d s 11 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 12 13 c l a s s t e s t G r i d s ( u n i t t e s t . T e s t C a s e ) : 14 15 16 # t e s t L e g e n d r e g r i d s 17 def t e s t L e g e n d r e G r i d s ( s e l f ) :
18 # low v a l u e for the m e s h
19 l o w V a l u e s = np . a r r a y ([1. ,2. ,3.] , d t y p e = np .f l o a t) 20 # s i z e of the m e s h 21 s t e p = np . a r r a y ([ 0 . 7 , 2. 3 , 1 . 9] , d t y p e = np .f l o a t) 22 # n u m b e r of s t e p 23 n b S t e p = np . a r r a y ([4 ,5 ,6] , d t y p e = np . i n t 3 2 ) 24 # d e g r e e of the p o l y n o m i a l in e a c h d i r e c t i o n 25 d e g r e e = np . a r r a y ([2 ,1 ,3] , d t y p e = np . i n t 3 2 ) 26 # c r e a t e the L e g e n d r e g r i d 27 g r i d = S t O p t G r i d s . R e g u l a r L e g e n d r e G r i d ( l o w V a l u e s , step , nbStep , d e g r e e ) 28 i t e r G r i d = g r i d . g e t G r i d I t e r a t o r () 29 # a r r a y to s t o r e 30 d a t a = np . e m p t y ( g r i d . g e t N b P o i n t s () ) 31 # i t e r a t e s on p o i n t 32 w h i l e( i t e r G r i d . i s V a l i d () ) : 33 # get c o o r d i n a t e s of the p o i n t 34 p o i n t C o o r d = i t e r G r i d . g e t C o o r d i n a t e () 35 d a t a [ i t e r G r i d . g e t C o u n t () ] = m a t h . log (1. + p o i n t C o o r d .sum() ) 36 i t e r G r i d .n e x t() 37 # get b a c k an i n t e r p o l a t o r 38 p t I n t e r p = np . a r r a y ( [ 2 .3 , 3 . 2 , 5 . 9 ] , d t y p e = np .f l o a t) 39 i n t e r p o l = g r i d . c r e a t e I n t e r p o l a t o r ( p t I n t e r p ) 40 # c a l c u l a t e i n t e r p o l a t e d v a l u e 41 i n t e r p V a l u e = i n t e r p o l .a p p l y( d a t a )
42 p r i n t((" I n t e r p o l a t e d v a l u e L e g e n d r e " , i n t e r p V a l u e ) ) 43 # t e s t g r i d s f u n c t i o n 44 i D i m = g r i d . g e t D i m e n s i o n () 45 pt = g r i d . g e t E x t r e m e V a l u e s () 46 47 48 if _ _ n a m e _ _ == ’ _ _ m a i n _ _ ’: 49 u n i t t e s t . m a i n ()
3.3
Sparse grids
A representation of a function of dimension d for d small (less than 4) is obtained by tensorization in the preceding methods of interpolation. When the function is smooth and its cross derivatives are bounded, the function can be represented using the sparse grid methods. This method makes it possible to represent the function with much less points than the traditional one without losing too much by interpolating. The sparse grid method was used for the first time by assuming that the function f to be represented is zero at the boundary Γ of the domain. This assumption is important because it makes it possible to limit the explosion of the number of points to the dimension of the problem. In many application this assumption is not realistic or it is impossible to work on f − f|Γ. In this library we
will assume that the function is not zero at the borderand provide grid object, iterators and interpolators to interpolate certain functions depicted on the sparse grid. However, for the sake of clarity of presentation, we will start with the case of a function disappearing on the border.
3.3.1
The sparse linear grid method
We recall some classic results on sparse grids which can be found in [40]. We first assume that the function we are interpolating is zero at the border. By a change of coordinates a hyper-cube domain can be changed to a domain ω = [0, 1]d. By Introducing the hat function φ(L)(x) = max(1 − |x|, 0) (where (L) means linear), we obtain the followingl one-dimensional
local hat function by translation and dilation
φ(L)l,i (x) = φ(L)(2lx − i)
according to the level l and the index i, 0 < i < 2l. The grid points used for the interpolation
are noted xl,i = 2−li. In the dimension d, we introduce the basic functions
φ(L)l,i (x) = d Y j=1 φ(L)l j,ij(xj)
via a tensorial approach for a point x = (x1, . . . , xd), a multi-level l := (l1, . . . , ld) and
a multi-index i := (i1, . . . , id). The grid points used for interpolation are noted xl,i :=
(xl1,i1, . . . , xld,id).
We then present the index set
Bl :=i : 1 ≤ ij ≤ 2lj − 1, ij odd , 1 ≤ j ≤ d
and the hierarchical base space.
Wl(L) := spannφ(L)l,i (x) : i ∈ Bl
o
A representation of the space Wl(L) is given in dimension 1 on the figure 3.6. The sparse
Figure 3.6: One dimensional W(L) spaces: W(L) 1 , W (L) 2 , W (L) 3 , W (L)
4 and the nodal
represen-tation W4(L,N )
mesh space is defined as follows:
Vn = ⊕
|l|1≤n+d−1
Wl(L) (3.4)
Remark 4 The conventional full grid space is defined as VF
n = ⊕ |l|∞≤n
Wl(L).
At hierarchical increment space Wl(L) corresponds to a nodal function space Wl(L,N ) such that
Wl(L,N ) := spannφ(L)l,i (x) : i ∈ BNl o
with
BlN :=i : 1 ≤ ij ≤ 2lj− 1, 1 ≤ j ≤ d .
In the figure 3.6 the one-dimensional nodal base W4(L,N ) is generated by W4(L)and the dotted
base function. The space Vn can be represented as the space spawn by the W
(L,N ) l such that |l|1 = n + d − 1: Vn = span n φ(L)l,i (x) : i ∈ BlN, |l|1 = n + d − 1 o (3.5) A function f is interpolated on the hierarchical basis like
I(L)(f ) = X
|l|1≤n+d−1,i∈Bl
α(L)l,i φ(L)l,i
where α(L)l,i are called the surplus (we give on the figure 3.7 a representation of these coeffi-cients). These surpluses associated with a function f are calculated in the one-dimensional
Figure 3.7: Example of hierarchical coefficients
case for a node m = xl,i as the difference of the value of the function at the node and the
linear representation of the calculated function with neighboring nodes. For example in figure 3.8, the hierarchical value is given by the relation:
α(L)(m) := αl,i(L)= f (m) − 0.5(f (e(m)) + f (w(m)))
where e(m) is the east neighbor of m and w(m) the west one. The procedure is generalized in dimension d by successive hierarchy in all directions. On figure 3.9, we give a representation
Figure 3.8: Node involved in the linear, quadratic and cubic representation of a function at the node m and n
of the subspace W for l ≤ 3 in dimension 2.
In order to deal with functions non-zero at the boundary, two more basis are added to the
Figure 3.9: The two-dimensional subspace Wl(L) up to l = 3 in each dimension. Additional hierarchical functions corresponding to an approximation on the complete grid are indicated by dotted lines.
Figure 3.10: One dimensional W(L) spaces with linear functions with “exact” boundary
(left) and “modified” boundary (right): W1(L), W2(L), W3(L), W4(L)
without the border. As indicated in [40] for n =5, in dimension 8 have almost 2.8 million points in this approximation but only 6401 inside the domain. On the figure 3.11 we give the points of the grids including boundary points in dimension 2 and 3 for a level 5 of the sparse grid.
Figure 3.11: Sparse grid in dimension 2 and 3 with boundary points
If the boundary conditions are not important (infinite truncated domain in finance for example) the hat functions near the borders are modified by extrapolation (see figure 3.10) as explained in [40]. At level 1, we have only one degree of freedom assuming that the function is constant on the domain. At all the other levels, we extrapolate linearly towards the boundary the basic functions left and right, the other functions remaining unchanged. So the new function base in 1D ˜φ becomes
˜ φ(L)l,i (x) = 1 if l = 1 and i = 1 2 − 2lx if x ∈ [0, 2−l+1] 0 else if l > 1 and i = 1 2l(x − 1) + 2 if x ∈ [1 − 2−l+1, 1] 0 else if l > 1 and i = 2l− 1 φ(L)l,i (x) otherwise
On the figure 3.12 we give the grid points by eliminating the boundary points in dimension 2 and 3 for a level 5 of the sparse grid.
Figure 3.12: Sparse grid in dimensions 2 and 3 without boundary points
The interpolation error associated with the linear operator I1 := I(L) is related to the
regularity of the crossed derivatives of the function [10, 11, 12]. If f is zero at the boundary and admits derivatives such as ||∂x∂22du
1...∂x2d
||∞ < ∞ then
||f − I1(f )||
∞= O(N−2log(N )d−1), (3.6)
with N the number of points per dimension.
3.4
High order sparse grid methods
Changing the interpolator allows us to obtain a higher convergence rate mainly in the region where the solution is smooth. By following [11] and [12], it is possible to obtain higher order interpolators. Using a quadratic interpolator, the reconstruction on the nodal base gives a quadratic function on the support of the hat function previously defined and a continuous function of the whole domain. The polynomial quadratic base is defined on [2−l(i − 1), 2−l(i + 1)] by
φ(Q)l,i (x) = φ(Q)(2lx − i) with φ(Q)(x) = 1 − x2.
The hierarchical surplus (coefficient on the basis) in a dimension is the difference between the value function at the node and the quadratic representation of the function using nodes available at the previous level. With the notation of figure 3.8
α(m)(Q) = f (m) − (3 8f (w(m)) + 3 4f (e(m)) − 1 8f (ee(m))) = α(m)(L)(m) − 1 4α(m) (L)(e(m)) = α(m)(L)(m) − 1 4α(m) (L)(df (m))
where df (m) is the direct father of the node m in the tree structure.
Once again, the quadratic surplus of dimension d is obtained by successive hierarchization in the different dimensions.
added at the first level (see figure 3.13).
A version with modified boundary conditions can be derived for example by using linear interpolation at the boundary so that
˜ φ(Q)l,i (x) = ( ˜ φ(L)l,i if i = 1 or i = 2l− 1, φ(Q)l,i (x) otherwise
In the case of the cubic representation, on figure 3.8 we need 4 points to define a function
Figure 3.13: One dimensional W(Q) spaces with quadratic with “exact” boundary (left) and
“modified” boundary (right): W1(Q), W2(Q), W3(Q), W4(Q)
basis. In order to keep the same data structure, we use a cubic function base at node m with value 1 at this node and 0 at the node e(m), w(m) and ee(m) and we keep only the basic function between w(m) and e(m) [11].
Note that there are two basic types of function depending on the position in the tree. The basic functions are given on [2−l+1i, 2−l+1(i + 1)] by
φ(C)l,2i+1(x) = φ(C),1(2lx − (2i + 1)), if i even = φ(C),2(2lx − (2i + 1)), if i odd
with φ(C),1(x) = (x2−1)(x−3) 3 , φ
(C),2(x) = (1−x2)(x+3) 3 .
The surplus coefficient can be defined as above as the difference between the value function at the node and the cubic representation of the function at the parent node. Due to the two basic functions involved there are two types of cubic coefficient.
• For a node m = xl,8i+1 or m = xl,8i+7 , α(C)(m) = α(C,1)(m), with
α(C,1)(m) = α(Q)(m) − 1 8α
(Q)
(df (m))
• For a node m = xl,8i+3 or m = xl,8i+5 , α(C)(m) = α(C,2)(m), with
α(C,2)(m) = α(Q)(m) + 1 8α
Note that a cubic representation is not available for l = 1 so a quadratic approximation is used. As before, the boundary conditions are treated by adding two linear basis functions at the first level and a modified version is available. We choose the following basic functions as defined in figure 3.14: ˜ φ(C)l,i (x) = ( ˜ φ(Q)l,i if i ∈ {1, 3, 2l− 3, 2l− 1}, φ(C)l,i (x) otherwise
Figure 3.14: One dimensional W(C) spaces with cubic and “exact” boundary (left) and
“modified” boundary (right): W1(C), W2(C), W3(C), W4(C)
According to [10, 11, 12], if the function f is zero at the boundary and admits derivatives such as supα i∈{2,...,p+1} n ||∂α1+···+αdu ∂xα11 ...∂xαdd ||∞ o
< ∞ then the interpolation error can be generalized for I2 := I(Q), I3 := I(C) by:
||f − Ip(f )||
∞= O(N−(p+1)log(N )d−1), p = 2, 3
with N the number of points per dimension.
3.5
Anisotropy
In many situations, there is no point in refining as much in each direction. For example, when we process multidimensional storage, we expect the mesh to be the same order in each direction. When the different storages have very different sizes, we want to further refine the storage with the largest capacity. In order to treat this anisotropy, an extension of the sparse grids can be obtained by defining the weight w in each direction. The definition 3.4 is replaced by:
Vn = ⊕
Pd
i=1liw(i)≤n+d−1