Virtual Testbed
Ship dynamics simulator for extreme conditions
arma.hh
1 #ifndef VTESTBED_CORE_ARMA_HH
2 #define VTESTBED_CORE_ARMA_HH
3 
4 #include <complex>
5 #include <random>
6 
7 #include <vtestbed/base/blitz.hh>
8 #include <vtestbed/core/fourier_transform.hh>
9 #include <vtestbed/core/wavy_surface_generator.hh>
10 #include <vtestbed/core/yule_walker_solver.hh>
11 
12 namespace vtb {
13 
14  namespace core {
15 
16  template <class T>
17  inline std::unique_ptr<T>
18  copy(const std::unique_ptr<T>& ptr) {
19  return std::unique_ptr<T>(ptr ? ptr->copy() : nullptr);
20  }
21 
23 
24  private:
25  int _nbadroots = 0;
26 
27  public:
28 
29  inline explicit
30  Invalid_ARMA_process(int nbadroots):
31  _nbadroots(nbadroots) {}
32 
33  inline int
34  num_bad_roots() const noexcept {
35  return this->_nbadroots;
36  }
37 
38  const char*
39  what() const noexcept override {
40  return "AR/MA process is not stationary/invertible: "
41  "some roots lie inside unit disk.";
42  }
43 
44  };
45 
47  template <class T, int N>
48  void
49  validate_process(blitz::Array<T,N> phi);
50 
77  template <class T, int N>
78  blitz::Array<T,N>
79  auto_covariance(const blitz::Array<T,N>& rhs);
80 
81  template <class T, int N>
82  blitz::Array<T,N>
83  covariance(
84  blitz::Array<T,N> lhs,
85  blitz::Array<T,N> rhs,
87  );
88 
89  template <class T, int N>
90  inline blitz::Array<T,N>
91  covariance(blitz::Array<T,N> lhs, blitz::Array<T,N> rhs) {
92  Chirp_Z_transform<std::complex<T>,N> fft(rhs.shape());
93  return covariance<T,N>(lhs, rhs, fft);
94  }
95 
96  template <class T, int N>
97  inline blitz::Array<T,N>
98  correlation(
99  blitz::Array<T,N> lhs,
100  blitz::Array<T,N> rhs,
101  Chirp_Z_transform<std::complex<T>,N>& fft
102  ) {
103  const auto& lhs_stat = statistics(lhs);
104  const auto& rhs_stat = statistics(rhs);
105  blitz::Array<T,N> result(covariance<T,N>(
106  blitz::Array<T,N>(lhs - lhs_stat.mean()),
107  blitz::Array<T,N>(rhs - rhs_stat.mean()),
108  fft
109  ));
110  const T denominator = lhs_stat.variance() * rhs_stat.variance();
111  if (denominator > 0) {
112  result /= std::sqrt(denominator);
113  }
114  return result;
115  }
116 
117  template <class T, int N>
118  inline blitz::Array<T,N>
119  correlation(blitz::Array<T,N> lhs, blitz::Array<T,N> rhs) {
120  Chirp_Z_transform<std::complex<T>,N> fft(rhs.shape());
121  return correlation<T,N>(lhs, rhs, fft);
122  }
123 
124  template <class T, int N>
126  public Wavy_surface_generator<T,N> {
127 
128  private:
130 
131  public:
132  using typename base_type::array_type;
133  using typename base_type::grid_type;
134 
135  public:
136  typedef std::mt19937 prng_type;
141  typedef blitz::TinyVector<T,N> vec3;
142  typedef blitz::RectDomain<N> rect3;
143 
144  private:
145  array_type _acf;
146  generator_ptr _acf_generator;
147  array_type _coefficients;
148  T _whitenoisevariance{0};
149  prng_type _prng;
150  solver_ptr _solver;
151  vec3 _alpha{0,0,0.01};
152 
153  public:
154 
156 
157  virtual
159 
160  inline explicit
161  ARMA_wavy_surface_generator_base(array_type acf_in) {
162  this->acf(acf_in);
163  }
164 
165  inline bool
166  has_coefficients() const {
167  return this->_coefficients.size() > 0;
168  }
169 
170  inline bool
171  has_acf() const {
172  return this->_acf.size() > 0;
173  }
174 
175  inline bool
176  has_acf_generator() const {
177  return static_cast<bool>(this->_acf_generator);
178  }
179 
180  inline void
181  acf_generator(generator_ptr ptr) {
182  this->_acf_generator = std::move(ptr);
183  this->_acf.free();
184  }
185 
186  inline const generator_ptr&
187  acf_generator() const {
188  return this->_acf_generator;
189  }
190 
191  inline void
192  acf(array_type acf_in) {
193  this->_acf.reference(acf_in);
194  this->_acf_generator = nullptr;
195  }
196 
197  inline const array_type&
198  acf() const noexcept {
199  return this->_acf;
200  }
201 
202  inline const array_type&
203  coefficients() const noexcept {
204  return this->_coefficients;
205  }
206 
207  inline T
208  white_noise_variance() const noexcept {
209  return this->_whitenoisevariance;
210  }
211 
212  inline T
213  variance() const noexcept {
214  return *this->_acf.data();
215  }
216 
217  void
218  seed();
219 
220  template <class SeedSequence>
221  inline void
222  seed(SeedSequence& seq) {
223  this->_prng.seed(seq);
224  }
225 
226  inline void
227  coefficient_solver(solver_ptr&& ptr) {
228  this->_solver = std::move(ptr);
229  }
230 
231  inline const solver_type*
232  coefficient_solver() const noexcept {
233  return this->_solver.get();
234  }
235 
236  inline solver_type*
237  coefficient_solver() noexcept {
238  return this->_solver.get();
239  }
240 
241  inline void
242  decay(const vec3& rhs) {
243  this->_alpha = rhs;
244  }
245 
246  inline const vec3&
247  decay() const noexcept {
248  return this->_alpha;
249  }
250 
251  void
252  calculate_coefficients();
253 
254  protected:
255 
256  void
257  generate_white_noise(array_type result);
258 
259  };
260 
266  template <class T, int N>
269 
270  private:
272 
273  public:
274  using typename base_type::array_type;
275  using typename base_type::grid_type;
276  using typename base_type::solver_ptr;
277 
278  private:
279  array_type _buffer;
280  int _offset = 0;
281 
282  public:
283 
284  inline
285  AR_wavy_surface_generator() = default;
286 
287  virtual
288  ~AR_wavy_surface_generator() = default;
289 
290  void
291  generate(const grid_type& grid, array_type& result) override;
292 
293  };
294 
300  template <class T, int N>
303 
304  private:
306 
307  public:
312 
313  public:
314  using typename base_type::array_type;
315  using typename base_type::grid_type;
316 
317  public:
318 
319  inline
321  this->coefficient_solver(
323  );
324  }
325 
327 
329  operator=(const MA_wavy_surface_generator&) = default;
330 
331  void
332  generate(const grid_type& grid, array_type& result) override;
333 
334  };
335 
336  }
337 
338 }
339 
340 #endif // vim:filetype=cpp
T copy(T... args)
Based on autoregerssive model.
Definition: arma.hh:267
void validate_process(blitz::Array< T, N > phi)
Check AR (MA) process stationarity (invertibility).
Definition: arma.cc:64
blitz::Array< T, N > auto_covariance(const blitz::Array< T, N > &rhs)
Computes autocovariance function of three-dimensional field.
Definition: arma.cc:83
A region defined by start and end index and lower and upper bound for each dimension.
Definition: core/grid.hh:25
Multi-dimensional solver that determines MA model coefficients from ACF.
Main namespace.
Definition: convert.hh:9
Based on moving-average model.
Definition: arma.hh:301
Base class for wavy surface generators.
Definition: core/types.hh:50