DryChem 1.0.0
A generic, compile-time C++ toolbox with no dependencies for the modern computational chemistry project.
Loading...
Searching...
No Matches
centeredDifferenceMethod.hpp
Go to the documentation of this file.
1// Copyright (c) 2020-2025 Cody R. Drisko. All rights reserved.
2// Licensed under the MIT License. See the LICENSE file in the project root for more information.
3//
4// Name: centeredDifferenceMethod.hpp
5// Author: crdrisko
6// Date: 11/13/2020-10:54:15
7// Description: Approximating the derivative of a function using the centered difference method
8
9#ifndef DRYCHEM_COMMON_UTILITIES_INCLUDE_COMMON_UTILS_MATH_CALCULUS_DIFFERENTIATION_CENTEREDDIFFERENCEMETHOD_HPP
10#define DRYCHEM_COMMON_UTILITIES_INCLUDE_COMMON_UTILS_MATH_CALCULUS_DIFFERENTIATION_CENTEREDDIFFERENCEMETHOD_HPP
11
12#include <algorithm>
13#include <cstddef>
14#include <iterator>
15#include <type_traits>
16#include <vector>
17
21
22namespace CppUtils::Math
23{
46 template<typename IteratorX, typename IteratorY = IteratorX,
47 typename Tx = typename std::iterator_traits<IteratorX>::value_type,
48 typename Ty = typename std::iterator_traits<IteratorY>::value_type,
49 typename = std::enable_if_t<std::conjunction_v<std::is_default_constructible<Tx>, std::is_default_constructible<Ty>>>>
50 constexpr auto centeredDifferenceMethod(IteratorX x_begin, IteratorX x_end, IteratorY y_begin, IteratorY y_end,
51 bool correctBoundaries = true)
52 {
53 using Ty_x = decltype(*y_begin / *x_begin);
54
55 std::ptrdiff_t x_size {x_end - x_begin}, y_size {y_end - y_begin};
56
57 if (x_size != y_size)
58 throw InputSizeMismatch {"Common-Utilities", __FILE__, __LINE__};
59
60 std::vector<Ty_x> dy_dx(x_size - 2);
61 std::vector<Ty_x> forward = forwardDifferenceMethod(x_begin, x_end, y_begin, y_end);
62 std::vector<Ty_x> backward = backwardsDifferenceMethod(x_begin, x_end, y_begin, y_end);
63
64 typename std::vector<Ty_x>::iterator forwardStart {forward.begin() + 1};
65
66 // Optionally use forward and backwards approximations on last and first elements of the derivative, respectively
67 if (correctBoundaries)
68 {
69 forward.push_back(backward.back());
70 backward.insert(backward.begin(), forward.front());
71
72 dy_dx.resize(x_size);
73
74 forwardStart = forward.begin();
75 }
76
77 typename std::vector<Ty_x>::iterator back = backward.begin();
78
79 std::transform(forwardStart, forward.end(), dy_dx.begin(), [&](auto fwd) { return (fwd + *back++) / 2; });
80
81 return dy_dx;
82 }
83
87 template<typename ContainerX, typename ContainerY = ContainerX,
88 typename = std::enable_if_t<std::conjunction_v<std::is_default_constructible<typename ContainerX::value_type>,
89 std::is_default_constructible<typename ContainerY::value_type>>>>
90 constexpr auto centeredDifferenceMethod(const ContainerX& x, const ContainerY& y, bool correctBoundaries = true)
91 {
92 return centeredDifferenceMethod(x.begin(), x.end(), y.begin(), y.end(), correctBoundaries);
93 }
94} // namespace CppUtils::Math
95
96#endif
Definition mathExceptions.hpp:25
Definition backwardsDifferenceMethod.hpp:20
constexpr auto centeredDifferenceMethod(IteratorX x_begin, IteratorX x_end, IteratorY y_begin, IteratorY y_end, bool correctBoundaries=true)
Definition centeredDifferenceMethod.hpp:50
constexpr auto forwardDifferenceMethod(IteratorX x_begin, IteratorX x_end, IteratorY y_begin, IteratorY y_end)
Definition forwardDifferenceMethod.hpp:45
constexpr auto backwardsDifferenceMethod(IteratorX x_begin, IteratorX x_end, IteratorY y_begin, IteratorY y_end)
Definition backwardsDifferenceMethod.hpp:45