b2api
B2000++ API Reference Manual, VERSION 4.6
 
Loading...
Searching...
No Matches
b2splines.H
1//------------------------------------------------------------------------
2// b2splines.H --
3//
4//
5// written by Mathias Doreille
6//
7// Copyright (c) 2007-2012 SMR Engineering & Development SA
8// 2502 Bienne, Switzerland
9//
10// All Rights Reserved. Proprietary source code. The contents of
11// this file may not be disclosed to third parties, copied or
12// duplicated in any form, in whole or in part, without the prior
13// written permission of SMR.
14//----------------------------------------------------------------------*/
15
16#ifndef __B2SPLINES_H__
17#define __B2SPLINES_H__
18
19#include <vector>
20
21#include "utils/b2exception.H"
22
23namespace b2000 {
24
25class CubicSpline {
26public:
27 CubicSpline() {}
28
29 template <typename T1, typename T2>
30 CubicSpline(
31 T1 x_begin, T1 x_end, T2 y_begin, T2 y_end, bool natural, double yp1 = 0, double ypn = 0)
32 : xa(x_begin, x_end), ya(y_begin, y_end) {
33 compute_y2a(natural, yp1, ypn);
34 }
35
36 template <typename T1>
37 CubicSpline(T1 xy_begin, T1 xy_end, bool natural, double yp1 = 0, double ypn = 0) {
38 size_t s = (xy_end - xy_begin) / 2;
39 xa.reserve(s);
40 ya.reserve(s);
41 while (xy_begin != xy_end) {
42 xa.push_back(*xy_begin);
43 ++xy_begin;
44 ya.push_back(*xy_begin);
45 ++xy_begin;
46 }
47 compute_y2a(natural, yp1, ypn);
48 }
49
50 template <typename T1, typename T2>
51 CubicSpline(
52 size_t s, std::pair<T1, T2> xy_begin, std::pair<T1, T2> xy_end, bool natural,
53 double yp1 = 0, double ypn = 0) {
54 xa.reserve(s);
55 ya.reserve(s);
56 while (xy_begin != xy_end) {
57 xa.push_back(xy_begin->first);
58 ya.push_back(xy_begin->second);
59 ++xy_begin;
60 }
61 compute_y2a(natural, yp1, ypn);
62 }
63
64 void add_point(double x, double y) {
65 xa.push_back(x);
66 ya.push_back(y);
67 }
68
69 void finalise(bool natural, double yp1 = 0, double ypn = 0) { compute_y2a(natural, yp1, ypn); }
70
71 double operator()(double x) const {
72 if (x < xa.front()) { return ya.front(); }
73 if (x > xa.back()) { return ya.back(); }
74 size_t klo = 0;
75 size_t khi = xa.size() - 1;
76 {
77 size_t k;
78 while (khi - klo > 1) {
79 k = (khi + klo) / 2;
80 if (xa[k] > x) {
81 khi = k;
82 } else {
83 klo = k;
84 }
85 }
86 }
87 const double h = xa[khi] - xa[klo];
88 if (h == 0) { Exception() << THROW; }
89 const double a = (xa[khi] - x) / h;
90 const double b = (x - xa[klo]) / h;
91 return a * ya[klo] + b * ya[khi]
92 + ((a * a * a - a) * y2a[klo] + (b * b * b - b) * y2a[khi]) * (h * h) / 6.0;
93 }
94
95 void get_value_and_derivative(double x, double& v, double& dv) const {
96 if (x < xa.front()) {
97 v = ya.front();
98 dv = 0;
99 return;
100 }
101 if (x > xa.back()) {
102 v = ya.back();
103 dv = 0;
104 return;
105 }
106 size_t klo = 0;
107 size_t khi = xa.size() - 1;
108 {
109 size_t k;
110 while (khi - klo > 1) {
111 k = (khi + klo) / 2;
112 if (xa[k] > x) {
113 khi = k;
114 } else {
115 klo = k;
116 }
117 }
118 }
119 const double h = xa[khi] - xa[klo];
120 if (h == 0) { Exception() << THROW; }
121 const double a = (xa[khi] - x) / h;
122 const double b = (x - xa[klo]) / h;
123 v = a * ya[klo] + b * ya[khi]
124 + ((a * a * a - a) * y2a[klo] + (b * b * b - b) * y2a[khi]) * (h * h) / 6.0;
125 dv = (-ya[klo] + ya[khi]) / h
126 + ((1 - 3 * a * a) * y2a[klo] + (3 * b * b - 1) * y2a[khi]) * h / 6.0;
127 }
128
129private:
130 void compute_y2a(bool natural, double yp1 = 0, double ypn = 0) {
131 std::vector<double> u(xa.size() - 1);
132 y2a.resize(xa.size());
133 if (natural) {
134 y2a[0] = u[0] = 0.0;
135 } else {
136 y2a[0] = -0.5;
137 u[0] = (3.0 / (xa[1] - xa[0])) * ((ya[1] - ya[0]) / (xa[1] - xa[0]) - yp1);
138 }
139 const size_t i_max = xa.size() - 1;
140 for (size_t i = 1; i != i_max; ++i) {
141 const double sig = (xa[i] - xa[i - 1]) / (xa[i + 1] - xa[i - 1]);
142 const double p = sig * y2a[i - 1] + 2.0;
143 y2a[i] = (sig - 1.0) / p;
144 u[i] = (ya[i + 1] - ya[i]) / (xa[i + 1] - xa[i])
145 - (ya[i] - ya[i - 1]) / (xa[i] - xa[i - 1]);
146 u[i] = (6.0 * u[i] / (xa[i + 1] - xa[i - 1]) - sig * u[i - 1]) / p;
147 }
148 {
149 double qn, un;
150 size_t n = xa.size();
151 if (natural) {
152 qn = un = 0.0;
153 } else {
154 qn = 0.5;
155 un = (3.0 / (xa[n - 1] - xa[n - 2]))
156 * (ypn - (ya[n - 1] - ya[n - 2]) / (xa[n - 1] - xa[n - 2]));
157 }
158 y2a[n - 1] = (un - qn * u[n - 2]) / (qn * y2a[n - 2] + 1.0);
159 }
160 for (size_t i = xa.size() - 1; i > 0; --i) { y2a[i - 1] = y2a[i - 1] * y2a[i] + u[i - 1]; }
161 }
162
163 std::vector<double> xa;
164 std::vector<double> ya;
165 std::vector<double> y2a;
166};
167
168} // namespace b2000
169
170#endif
#define THROW
Definition b2exception.H:198
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32