1 #ifndef VTESTBED_CORE_WIND_GENERATOR_HH 2 #define VTESTBED_CORE_WIND_GENERATOR_HH 9 #include <vtestbed/base/blitz.hh> 10 #include <vtestbed/core/debug.hh> 11 #include <vtestbed/core/grid.hh> 12 #include <vtestbed/core/types.hh> 13 #include <vtestbed/core/yule_walker_solver.hh> 14 #include <vtestbed/linalg/linear_algebra.hh> 26 typedef blitz::TinyVector<int,4> shape_type;
36 _order = shape_type{4,4,4,4};
50 this->_sigma = rhs._sigma;
51 this->_grid = rhs._grid;
52 this->_order = rhs._order;
73 typedef Array<T,4> array_type;
75 typedef blitz::TinyVector<int,4> shape_type;
79 array_type _coefficients;
80 T _whitenoisevariance;
82 shape_type _order_acf;
94 inline const shape_type&
95 order()
const noexcept {
100 calculate_acf(blitz::TinyVector<int,4> shape) {
101 blitz::Array<T,4> result(shape);
102 T c1 = this->_param._c1;
104 T sigma = this->_param._sigma;
107 typedef blitz::TinyVector<int,4> index;
110 [&] (
const index& idx) {
111 T a = idx(0) * grid.
length(0) / (shape(0) - 1);
112 T b = idx(1) * grid.
length(1) / (shape(1) - 1);
113 T c = idx(2) * grid.
length(2) / (shape(2) - 1);
114 T d = idx(3) * grid.
length(3) / (shape(3) - 1);
116 sigma*sigma*exp(-c1*(a + b + c + d))
122 result(0,0,0,0) = sigma;
127 this->_param = param;
130 void calculateCoefficients() {
136 shape_type order = this->_param._order;
138 blitz::Array<T,4> acf(variance * calculate_acf(order + 1));
139 #if defined(VTB_DEBUG_WIND) 140 const auto _ = blitz::Range::all();
141 dbg::write_animated_surface(
"wind.acf", acf(0,_,_,_));
145 _coefficients.reference(gauss.
solve(acf));
147 #if defined(VTB_DEBUG_WIND) 148 std::clog <<
"_whitenoisevariance=" << _whitenoisevariance << std::endl;
156 clock_type::now().time_since_epoch().count(),
157 clock_type::rep(dev())
159 this->_prng.seed(seq);
165 array_type result(grid.
shape());
166 const auto& phi = this->_coefficients;
167 auto& buffer = this->_buffer;
168 auto& offset = this->_offset;
170 if (buffer.extent(1) != grid.
extent(1) ||
171 buffer.extent(2) != grid.
extent(2) ||
172 buffer.extent(3) != grid.
extent(3) ||
173 buffer.extent(0) < phi.extent(0) + grid.
extent(0)) {
177 phi.extent(0) + grid.
extent(0)),
186 const auto nt = grid.
extent(0);
187 if (offset + nt >= buffer.extent(0)) {
188 int shift = offset + nt - buffer.extent(0);
189 int slice_size = buffer.extent(1)*buffer.extent(2);
192 buffer.data() + shift*slice_size,
193 (offset-shift)*slice_size*
sizeof(T)
197 typedef blitz::TinyVector<int,4> index;
198 index r0{offset,0,0,0};
199 index r1{offset+grid.
extent(0), buffer.extent(1),
200 buffer.extent(2), buffer.extent(3)};
201 blitz::RectDomain<4> r{r0,r1-1};
202 this->generate_white_noise(buffer(r));
206 [&] (
const index& idx) {
208 index shape{blitz::min(idx+1, phi.shape())};
211 [&] (
const index& idx2) {
212 sum += phi(idx2) * buffer(index{idx-idx2});
228 generate_white_noise(
231 const T stdev = std::sqrt(this->_whitenoisevariance);
235 for (
auto& x : result) { x = normal(this->_prng); }
245 #endif // vim:filetype=cpp const T length(int i) const noexcept
The size of the region for dimension i.
int extent(int i) const noexcept
The number of points for dimension i.
value_type white_noise_variance() const noexcept
const int_n shape() const noexcept
The number of points for all dimensions.
array_type solve(array_type acf) override
Solve Yule—Walker system of equations.