Coverage Report

Created: 2026-06-23 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/experimental/finitedifferences/fdmextendedornsteinuhlenbeckop.cpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2011 Klaus Spanderen
5
6
 This file is part of QuantLib, a free-software/open-source library
7
 for financial quantitative analysts and developers - http://quantlib.org/
8
9
 QuantLib is free software: you can redistribute it and/or modify it
10
 under the terms of the QuantLib license.  You should have received a
11
 copy of the license along with this program; if not, please email
12
 <quantlib-dev@lists.sf.net>. The license is also available online at
13
 <https://www.quantlib.org/license.shtml>.
14
15
 This program is distributed in the hope that it will be useful, but WITHOUT
16
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
 FOR A PARTICULAR PURPOSE.  See the license for more details.
18
*/
19
20
/*! \file fdmextendedornsteinuhlenbeckop.cpp
21
*/
22
23
#include <ql/experimental/finitedifferences/fdmextendedornsteinuhlenbeckop.hpp>
24
#include <ql/experimental/processes/extendedornsteinuhlenbeckprocess.hpp>
25
#include <ql/math/functional.hpp>
26
#include <ql/math/interpolations/linearinterpolation.hpp>
27
#include <ql/methods/finitedifferences/meshers/fdmmesher.hpp>
28
#include <ql/methods/finitedifferences/operators/fdmlinearoplayout.hpp>
29
#include <ql/methods/finitedifferences/operators/secondderivativeop.hpp>
30
#include <ql/termstructures/yieldtermstructure.hpp>
31
#include <utility>
32
33
namespace QuantLib {
34
35
    FdmExtendedOrnsteinUhlenbeckOp::FdmExtendedOrnsteinUhlenbeckOp(
36
        const ext::shared_ptr<FdmMesher>& mesher,
37
        ext::shared_ptr<ExtendedOrnsteinUhlenbeckProcess> process,
38
        ext::shared_ptr<YieldTermStructure> rTS,
39
        FdmBoundaryConditionSet bcSet,
40
        Size direction)
41
0
    : mesher_(mesher), process_(std::move(process)), rTS_(std::move(rTS)), bcSet_(std::move(bcSet)),
42
0
      direction_(direction), x_(mesher->locations(direction)), dxMap_(direction, mesher),
43
0
      dxxMap_(SecondDerivativeOp(direction, mesher)
44
0
                  .mult(0.5 * squared(process_->volatility()) *
45
0
                        Array(mesher->layout()->size(), 1.))),
46
0
      mapX_(direction, mesher) {}
47
48
0
    Size FdmExtendedOrnsteinUhlenbeckOp::size() const {
49
0
        return mesher_->layout()->dim().size();;
50
0
    }
51
52
0
    void FdmExtendedOrnsteinUhlenbeckOp::setTime(Time t1, Time t2) {
53
0
        const Rate r = rTS_->forwardRate(t1, t2, Continuous).rate();
54
55
0
        Array drift(mesher_->layout()->size());
56
0
        for (const auto& iter : *mesher_->layout()) {
57
0
            const Size i = iter.index();
58
0
            drift[i] = process_->drift(0.5*(t1+t2), x_[i]);
59
0
        }
60
0
        mapX_.axpyb(drift, dxMap_, dxxMap_, Array(1, -r));
61
0
    }
62
63
0
    Array FdmExtendedOrnsteinUhlenbeckOp::apply(const Array& r) const {
64
0
        return mapX_.apply(r);
65
0
    }
66
67
0
    Array FdmExtendedOrnsteinUhlenbeckOp::apply_mixed(const Array& r) const {
68
0
        return Array(r.size(), 0.0);
69
0
    }
70
71
    Array FdmExtendedOrnsteinUhlenbeckOp::apply_direction(
72
0
                                    Size direction, const Array& r) const {
73
0
        if (direction == direction_) {
74
0
            return mapX_.apply(r);
75
0
        }
76
0
        else {
77
0
            return Array(r.size(), 0.0);
78
0
        }
79
0
    }
80
81
    Array FdmExtendedOrnsteinUhlenbeckOp::solve_splitting(
82
0
                            Size direction, const Array& r, Real a) const {
83
0
        if (direction == direction_) {
84
0
            return mapX_.solve_splitting(r, a, 1.0);
85
0
        }
86
0
        else {
87
0
            return r;
88
0
        }
89
0
    }
90
91
    Array FdmExtendedOrnsteinUhlenbeckOp::preconditioner(
92
0
                                            const Array& r, Real dt) const {
93
0
        return solve_splitting(direction_, r, dt);
94
0
    }
95
96
0
    std::vector<SparseMatrix> FdmExtendedOrnsteinUhlenbeckOp::toMatrixDecomp() const {
97
0
        return std::vector<SparseMatrix>(1, mapX_.toMatrix());
98
0
    }
99
100
}