STEM4U: Added numerical integration

git-svn-id: svn://ultimatepp.org/upp/trunk@14953 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
koldo 2020-09-01 07:52:09 +00:00
parent eff0bc3b8d
commit 3ccbaa6c81
5 changed files with 164 additions and 55 deletions

View file

@ -1,43 +0,0 @@
#include <Core/Core.h>
#include <Functions4U/Functions4U.h>
#include <plugin/Eigen/Eigen.h>
#include "Integral.h"
namespace Upp {
using namespace Eigen;
double Integral(VectorXd &y, const VectorXd &x) {
ASSERT(x.size() == y.size());
double ret = 0;
Eigen::Index n = x.size();
for (int i = 1; i < n; ++i)
ret += Avg(y(i), y(i-1))*(x(i) - x(i-1));
return ret;
}
double Integral(VectorXd &y, double dx, IntegralType type) {
Eigen::Index n = y.size();
if (n <= 1)
return 0;
else if (n == 2)
return Avg(y(0), y(1))*dx;
else if (type == TRAPEZOIDAL) {
double ret2 = (y.segment(1, n-2).sum() + y(0)/2 + y(n-1)/2)*dx;
return ret2;
} else {
double ret = 0;
if ((n-1)%2) {
ret = Avg(y(n-1), y(n-2))*dx;
--n;
}
ret = ret + dx/3*(y(0) + 2*(Map<VectorXd, 0, InnerStride<2>>(y.data()+1, n/2).sum() +
y.block(1, 0, n-2, 1).sum()) + y(n-1));
return ret;
}
}
}

View file

@ -3,10 +3,109 @@
namespace Upp {
enum IntegralType {TRAPEZOIDAL, SIMPSON_1_3};
enum IntegralType {TRAPEZOIDAL, SIMPSON_1_3, SIMPSON_3_8, HERMITE_3, HERMITE_5};
double Integral(Eigen::VectorXd &y, const Eigen::VectorXd &x);
double Integral(Eigen::VectorXd &y, double dx, IntegralType type = TRAPEZOIDAL);
template <class Range, class T>
T Integral(const Range &y, const Range &x, IntegralType type = TRAPEZOIDAL) {
ASSERT(x.size() == y.size());
ASSERT(x.size() > 1);
T ret = 0;
size_t n = x.size();
if (type == TRAPEZOIDAL) {
for (int i = 1; i < n; ++i)
ret += Avg(y(i), y(i-1))*(x(i) - x(i-1));
} else if (type == SIMPSON_1_3) {
if (n < 3)
return Null;
int i;
for (i = 2; i < n; i += 2)
ret += (x[i] - x[i-2])/6.*(y[i-2] + 4*y[i-1] + y[i]);
if (i == n)
ret += Avg(y(n-1), y(n-2))*(x(n-1) - x(n-2));
} else if (type == SIMPSON_3_8) {
if (n < 4)
return Null;
int i;
for (i = 3; i < n; i += 3)
ret += (x[i] - x[i-3])/8.*(y[i-3] + 3*y[i-2] + 3*y[i-1] + y[i]);
if (i == n)
ret += (x[n-1] - x[n-3])/6.*(y[n-3] + 4*y[n-2] + y[n-1]);
else if (i == n+1)
ret += Avg(y(n-1), y(n-2))*(x(n-1) - x(n-2));
} else
NEVER();
return ret;
}
template <class Range, class T>
inline T Calc1_3(const Range &y, T dx, size_t n) {
T ret = y[0] + y[n-1];
for (int i = 1; i < n-1; i++)
ret += 2*y[i];
for (int i = 1; i < n-1; i += 2)
ret += 2*y[i];
ret *= dx/3.;
return ret;
}
inline double Calc1_3(Eigen::VectorXd &y, double dx, size_t n) {
return dx/3*(y(0) + 2*(Eigen::Map<Eigen::VectorXd, 0, Eigen::InnerStride<2>>(y.data()+1, n/2).sum() +
y.block(1, 0, n-2, 1).sum()) + y(n-1));
}
template <class Range, class T>
T Integral(Range &y, T dx, IntegralType type = TRAPEZOIDAL) {
ASSERT(y.size() > 1);
Eigen::Index n = y.size();
if (type == TRAPEZOIDAL)
return (y.segment(1, n-2).sum() + (y(0) + y(n-1))/2)*dx;
else if (type == SIMPSON_1_3) {
if (n < 3)
return Null;
T ret0 = 0;
if ((n-1)%2) {
ret0 = Avg(y(n-1), y(n-2))*dx;
--n;
}
return ret0 + Calc1_3(y, dx, n);
} else if (type == SIMPSON_3_8) {
if (n < 4)
return Null;
T ret0 = 0;
int rem = (n-1)%3;
if (rem == 2) {
ret0 = (y[n-3] + 4*y[n-2] + y[n-1])/3.*dx;
n -= 2;
} else if (rem == 1) {
ret0 = Avg(y[n-2], y[n-1])*dx;
n--;
}
T ret = y[0] + y[n-1];
for (int i = 1; i < n-1; ++i)
ret += 2*y[i];
for (int i = 1; i < n-1; ++i) {
ret += y[i++];
ret += y[i++];
}
return ret0 + ret*dx*3./8;
} else if (type == HERMITE_3) {
if (n < 3)
return Null;
return (y.segment(1, n-2).sum() + (y(0) + y(n-1))/2)*dx
+ dx/24.*(3*y[0] - 4*y[1] + y[2] + y[n-3] - 4*y[n-2] + 3*y[n-1]);
} else if (type == HERMITE_5) {
if (n < 5)
return Null;
return (y.segment(1, n-2).sum() + (y(0) + y(n-1))/2)*dx
- dx/144.*(25*(y[0] - y[n-1]) - 48*(y[1] - y[n-2]) + 36*(y[2] - y[n-3])
- 16*(y[3] - y[n-4]) + 3*(y[4] - y[n-5]));
} else
NEVER();
return Null;
}
}

View file

@ -12,9 +12,8 @@ file
Rational.h,
IntInf.h,
Polynomial.h,
Integral.cpp,
Integral.h,
Sundials.cpp,
Integral.h,
Sundials.h,
Financial.cpp,
Financial.h,

View file

@ -76,12 +76,10 @@ T TSP_NearestNeighbor(const Vector<T> &distances, int sz, Vector<int> &order) {
}
void OrderToConnections(const Vector<int> &order, Vector<int> &left, Vector<int> &right) {
left.SetCount(order.size()-1);
right.SetCount(order.size()-1);
for (int i = 0; i < left.size(); ++i) {
left[i] = order[i];
right[i] = order[i+1];
}
left = clone(order);
left.Remove(left.size()-1);
right = clone(order);
right.Remove(0);
}
void ConnectionsToOrder(const Vector<int> &left, const Vector<int> &right, Vector<int> &order) {
@ -118,7 +116,7 @@ T TSP_2_Opt(const Vector<T> &distances, int sz, Vector<int> &order) {
T bestSaving = 0;
for (int i = 0; i < order.size()-1 && idchange < 0; ++i) {
for (int j = 0; j < order.size()-1; ++j) {
for (int j = i+1; j < order.size()-1; ++j) {
if (i != j && order[i] != order[j] && order[i] != order[j+1]
&& order[i+1] != order[j] && order[i+1] != order[j+1]) {
T saving = distances[ind(order[i], order[i+1])]

View file

@ -0,0 +1,56 @@
topic "Numerical Integration";
[H6;0 $$1,0#05600065144404261032431302351956:begin]
[i448;a25;kKO9;2 $$2,0#37138531426314131252341829483370:codeitem]
[l288;2 $$3,0#27521748481378242620020725143825:desc]
[0 $$4,0#96390100711032703541132217272105:end]
[ $$0,0#00000000000000000000000000000000:Default]
[{_}%EN-US
[ {{10000@3 [s0; [*@7;4 Integral]]}}&]
[s1;%- &]
[s0;%- &]
[s0; [2 Numerical integration of a series of points.]&]
[s0; [2 Integration schemes included are:]&]
[s0;2 &]
[ {{2098:7902<288;h1; [s0;%- [*2 TRAPEZOIDAL]]
:: [s0;%- [2 Trapezoidal integration]]
:: [s0;%- [*2 SIMPSON`_1`_3]]
:: [s0;%- [2 Simpson`'s 1/3 rule with a correction if the number of points
is even.]]
:: [s0;%- [*2 SIMPSON`_3`_8]]
:: [s0;%- [2 Simpson`'s 3/8 rule with a correction if the number of points
is not a multiple of three.]]
:: [s0;%- [*2 HERMITE`_3]]
:: [s0;%- [2 Hermite`'s rule with a three points difference scheme to
approximate endpoints derivatives.]]
:: [s0;%- [*2 HERMITE`_5]]
:: [s0;%- [2 Hermite`'s rule with a five points difference scheme to approximate
endpoints derivatives.]]}}&]
[s0;2 &]
[s2; References:&]
[s3;i150;O0; [^https`:`/`/en`.wikipedia`.org`/wiki`/Simpson`%27s`_rule^ Wikipedia]&]
[s3;i150;O0; [^https`:`/`/epubs`.siam`.org`/doi`/pdf`/10`.1137`/S0036144502416308^ `"An
Invitation to Hermites Integration and Summation: A Comparison
between Hermites and Simpsons Rules`", V. Lampret. SIAM
REVIEW Vol. 46, No. 2, pp. 311328 (2004)]&]
[s3;i150;O0;%- [^https`:`/`/www`.semanticscholar`.org`/paper`/Hermite`-versus`-Simpson`-`%3A`-the`-Geometry`-of`-Numerical`-Long`-Long`/9f1d1ccfafc604428397ffbe6855a1686bba7a41^ `"
Hermite versus Simpson: the Geometry of Numerical Integration`",
Andy Long and Cliff Long., (2010)]&]
[s0;^https`:`/`/en`.wikipedia`.org`/wiki`/Simpson`%27s`_rule^ &]
[s1;%- &]
[s2;:Upp`:`:Integral`(const Range`&`,const Range`&`,IntegralType`):%- [@(0.0.255) templ
ate]_<[@(0.0.255) class]_[*@4 Range], [@(0.0.255) class]_[*@4 T]>_[*@4 T]_[* Integral]([@(0.0.255) c
onst]_[*@4 Range]_`&[*@3 y], [@(0.0.255) const]_[*@4 Range]_`&[*@3 x],
IntegralType_[*@3 type]_`=_TRAPEZOIDAL)&]
[s3; Obtains the numerical integration of data series defined by
points ([%-*@3 x], [%-*@3 y]), using the integration schema defined
with [%-*@3 type].&]
[s4; &]
[s1;%- &]
[s2;:Upp`:`:Integral`(Range`&`,T`,IntegralType`):%- [@(0.0.255) template]_<[@(0.0.255) cl
ass]_[*@4 Range], [@(0.0.255) class]_[*@4 T]>_[*@4 T]_[* Integral]([*@4 Range]_`&[*@3 y],
[*@4 T]_[*@3 dx], IntegralType_[*@3 type]_`=_TRAPEZOIDAL)&]
[s3; Obtains the numerical integration of data series defined by
points [%-*@3 y], separated [%-*@3 dx] between them, using the integration
schema defined with [%-*@3 type].&]
[s4; &]
[s0; ]]