C++ Library containing some ODE and PDE solvers
LSS supports three types of boundary conditions: Dirichlet, Neumann and Robin. All solvers except for specific ones (so far only Heston type) allow any combination of these.
In what follows represents a solution of an ODE and represents a point in which we evaluate a boundary condition. Let us consider following simple 2nd order ODE
LSS assumes Dirichlet boundary of following form
Specifically, if we have following Dirichlet boundary:
then in code we write:
#include <lss/boundary/dirichlet_1d.hpp>
auto const dirichlet = 3.1415;
// build boundary conditions from above function:
auto const &boundary_ptr = lss::dirichlet_1d_builder().value(dirichlet).build();
LSS assumes Neumann boundary of following form
Specifically, if we have following Neumann boundary:
then in code we write:
#include <lss/boundary/neumann_1d.hpp>
auto const neumann = -1.0;
// build boundary conditions from above function:
auto const &boundary_ptr = lss::neumann_1d_builder().value(neumann).build();
Note -1.0 rather then 1.0. We must pay attention to the aforementioned convention or we get completely different solution.
LSS assumes Robin boundary of following form
Specifically, if we have following Robin boundary:
then in code we write:
#include <lss/boundary/robin_1d.hpp>
auto const robin_first = 2.0;
auto const robin_second = 0.0;
// build boundary conditions from above function:
auto const &boundary_ptr = lss::robin_1d_builder()
.values(robin_first,robin_second)
.build();
In what follows represents a solution of 1D PDE and represents a point in which we evaluate a boundary condition and represents a time at which we evaluate an initial/terminal condition. Let us consider following 1D PDE (heat equation)
LSS assumes Dirichlet boundary of following form
Specifically, if we have following Dirichlet boundary:
then in code we write:
#include <lss/boundary/dirichlet_1d.hpp>
auto const &dirichlet = [](double t) { return 2*t; };
// build boundary conditions from above function:
auto const &boundary_ptr = lss::dirichlet_1d_builder().value(dirichlet).build();
LSS assumes Neumann boundary of following form
Specifically, if we have following Neumann boundary:
then in code we write:
#include <lss/boundary/neumann_1d.hpp>
auto const neumann = [](double t) { return -2.0*t; };
// build boundary conditions from above function:
auto const &boundary_ptr = lss::neumann_1d_builder().value(neumann).build();
Note -2.0t rather then 2.0t. We must pay attention to the aforementioned convention or we get completely different solution.
LSS assumes Robin boundary of following form
Specifically, if we have following Robin boundary:
then in code we write:
#include <lss/boundary/robin_1d.hpp>
auto const robin_first = [](double t) { return 2*t; };
auto const robin_second = [](double t) { return 0.0; };
// build boundary conditions from above function:
auto const &boundary_ptr = lss::robin_1d_builder()
.values(robin_first,robin_second)
.build();
Initial/terminal condition follows similar pattern.
which for
translates into C++ code
#include <lss/pde/configs/heat_initial_data_config_1d.hpp>
// strike
auto const strike = 20.0;
// terminal condition function (payoff of call):
auto terminal_condition = [=](double x) { return std::max<double>(0.0, x - strike); };
// build initial data config:
auto const &heat_init_data_ptr =
lss::heat_initial_data_config_1d_builder().condition(terminal_condition).build();
Note that builder lss::heat_initial_data_config_1d_builder() is used for either initial or terminal condition.
In case we have two initial/terminal conditions (as in case of wave type equations)
we will have for
C++ code
#include <lss/pde/configs/wave_initial_data_config_1d.hpp>
// initial condition:
auto first_condition = [](double x) { return std::sin(pi() * x); };
auto second_condition = [](double x) { return 0.0; };
auto const wave_init_data_ptr = std::make_shared<wave_initial_data_config_1d>(initial_condition, second_condition);