BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
Convolve.h
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Device/Resolution/Convolve.h
6 //! @brief Defines class Math::Convolve.
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
15 #ifdef SWIG
16 #error no need to expose this header to Swig
17 #endif
18 
19 #ifndef USER_API
20 #ifndef BORNAGAIN_DEVICE_RESOLUTION_CONVOLVE_H
21 #define BORNAGAIN_DEVICE_RESOLUTION_CONVOLVE_H
22 
23 #include <fftw3.h>
24 #include <vector>
25 
26 //! Convolution of two real vectors (in 1D or 2D) using Fast Fourier Transform.
27 //!
28 //! Usage:
29 //! std::vector<double> signal, kernel, result;
30 //! Convolve cv;
31 //! cv.fftconvolve(signal, kernel, result)
32 //!
33 //! Given code rely on code from Jeremy Fix page, http://jeremy.fix.free.fr/spip.php?article15,
34 //! see also "Efficient convolution using the Fast Fourier Transform, Application in C++"
35 //! by Jeremy Fix, May 30, 2011
36 class Convolve {
37 public:
38  //! definition of 1d vector of double
39  using double1d_t = std::vector<double>;
40 
41  //! definition of 2d vector of double
42  using double2d_t = std::vector<double1d_t>;
43 
44  Convolve();
45 
46  //! convolution modes
47  //! use LINEAR_SAME or CIRCULAR_SAME_SHIFTED for maximum performance
56  };
57 
58  //! convolution in 1D
59  void fftconvolve(const double1d_t& source, const double1d_t& kernel, double1d_t& result);
60 
61  //! convolution in 2D
62  void fftconvolve(const double2d_t& source, const double2d_t& kernel, double2d_t& result);
63 
64  //! prepare arrays for 2D convolution of given vectors
65  void init(int h_src, int w_src, int h_kernel, int w_kernel);
66 
67  //! Sets convolution mode
68  void setMode(EConvolutionMode mode) { m_mode = mode; }
69 
70 private:
71  //! compute circual convolution of source and kernel using fast Fourier transformation
72  void fftw_circular_convolution(const double2d_t& src, const double2d_t& kernel);
73 
74  //! find closest number X>n that can be factorized according to fftw3 favorite factorization
75  int find_closest_factor(int n);
76 
77  //! if a number can be factorized using only favorite fftw3 factors
78  bool is_optimal(int n);
79 
80  //! Workspace for Fourier convolution.
81 
82  //! Workspace contains input (source and kernel), intermediate and output
83  //! arrays to run convolution via fft; 'source' it is our signal, 'kernel'
84  //! it is our resolution function.
85  //! Sizes of input arrays are adjusted; output arrays are alocated via
86  //! fftw3 allocation for maximum performance.
87  class Workspace {
88  public:
89  Workspace() = default;
90  ~Workspace();
91  void clear();
92  friend class Convolve;
93 
94  private:
95  int h_src{0}, w_src{0}; // size of original 'source' array in 2 dimensions
96  int h_kernel{0}, w_kernel{0}; // size of original 'kernel' array in 2 dimensions
97  // size of adjusted source and kernel arrays (in_src, out_src, in_kernel, out_kernel)
98  int w_fftw{0}, h_fftw{0};
99  //! adjusted input 'source' array
100  double* in_src{nullptr};
101  //! result of Fourier transformation of source
102  double* out_src{nullptr};
103  //! adjusted input 'kernel' array
104  double* in_kernel{nullptr};
105  //! result of Fourier transformation of kernel
106  double* out_kernel{nullptr};
107  //! result of product of FFT(source) and FFT(kernel)
108  double* dst_fft{nullptr};
109  int h_dst{0}, w_dst{0}; // size of resulting array
110  int h_offset{0}, w_offset{0}; // offsets to copy result into output arrays
111  fftw_plan p_forw_src{nullptr};
112  fftw_plan p_forw_kernel{nullptr};
113  fftw_plan p_back{nullptr};
114  };
115 
116  //! input and output data for fftw3
118  //! convolution mode
120  std::vector<size_t> m_implemented_factors; // favorite factorization terms of fftw3
121 };
122 
123 #endif // BORNAGAIN_DEVICE_RESOLUTION_CONVOLVE_H
124 #endif // USER_API
Workspace for Fourier convolution.
Definition: Convolve.h:87
double * out_src
result of Fourier transformation of source
Definition: Convolve.h:102
fftw_plan p_back
Definition: Convolve.h:113
double * in_src
adjusted input 'source' array
Definition: Convolve.h:100
double * in_kernel
adjusted input 'kernel' array
Definition: Convolve.h:104
double * dst_fft
result of product of FFT(source) and FFT(kernel)
Definition: Convolve.h:108
fftw_plan p_forw_src
Definition: Convolve.h:111
fftw_plan p_forw_kernel
Definition: Convolve.h:112
double * out_kernel
result of Fourier transformation of kernel
Definition: Convolve.h:106
Convolution of two real vectors (in 1D or 2D) using Fast Fourier Transform.
Definition: Convolve.h:36
EConvolutionMode m_mode
convolution mode
Definition: Convolve.h:119
Workspace ws
input and output data for fftw3
Definition: Convolve.h:117
std::vector< double > double1d_t
definition of 1d vector of double
Definition: Convolve.h:39
std::vector< size_t > m_implemented_factors
Definition: Convolve.h:120
Convolve()
Definition: Convolve.cpp:20
EConvolutionMode
convolution modes use LINEAR_SAME or CIRCULAR_SAME_SHIFTED for maximum performance
Definition: Convolve.h:48
@ FFTW_LINEAR_FULL
Definition: Convolve.h:49
@ FFTW_CIRCULAR_SAME_SHIFTED
Definition: Convolve.h:54
@ FFTW_LINEAR_VALID
Definition: Convolve.h:52
@ FFTW_UNDEFINED
Definition: Convolve.h:55
@ FFTW_LINEAR_SAME_UNPADDED
Definition: Convolve.h:50
@ FFTW_CIRCULAR_SAME
Definition: Convolve.h:53
@ FFTW_LINEAR_SAME
Definition: Convolve.h:51
std::vector< double1d_t > double2d_t
definition of 2d vector of double
Definition: Convolve.h:42
void fftw_circular_convolution(const double2d_t &src, const double2d_t &kernel)
compute circual convolution of source and kernel using fast Fourier transformation
Definition: Convolve.cpp:250
void init(int h_src, int w_src, int h_kernel, int w_kernel)
prepare arrays for 2D convolution of given vectors
Definition: Convolve.cpp:132
void setMode(EConvolutionMode mode)
Sets convolution mode.
Definition: Convolve.h:68
void fftconvolve(const double1d_t &source, const double1d_t &kernel, double1d_t &result)
convolution in 1D
Definition: Convolve.cpp:115
bool is_optimal(int n)
if a number can be factorized using only favorite fftw3 factors
Definition: Convolve.cpp:317
int find_closest_factor(int n)
find closest number X>n that can be factorized according to fftw3 favorite factorization
Definition: Convolve.cpp:304