protected unsafe override void OnLoad( EventArgs e ) { base.OnLoad( e ); using ( fftwlib.FFT2D FFT = new fftwlib.FFT2D( 256, 256 ) ) { // Build the source data // FillInput( FFT.Input ); { const double Lx = 400.0; const double Lz = Lx; const double WindAngle = 45.0 * Math.PI / 180.0; const double WindVelocity = 20.0; double Wx = Math.Cos( WindAngle ); double Wz = Math.Sin( WindAngle ); double U1, U2, fX, fZ; Random RNG = new Random( 1 ); FFT.FillInputFrequency( ( int Fx, int Fy, out float r, out float i ) => { double kx = (2.0 * Math.PI / Lx) * Fx; double kz = (2.0 * Math.PI / Lz) * Fy; // Build white gaussian noise // (source: http://www.dspguru.com/dsp/howtos/how-to-generate-white-gaussian-noise) U1 = 1e-10 + RNG.NextDouble(); U2 = RNG.NextDouble(); fX = Math.Sqrt(-2.0 * Math.Log( U1 )) * Math.Sin( 2.0 * Math.PI * U2 ); U1 = 1e-10 + RNG.NextDouble(); U2 = RNG.NextDouble(); fZ = Math.Sqrt(-2.0 * Math.Log( U1 )) * Math.Sin( 2.0 * Math.PI * U2 ); fX = fZ = 1.0; // Build Phillips spectrum double SqrtPhillips = Math.Sqrt( Phillips( kx, kz, WindVelocity, Wx, Wz ) ); r = (float) (1.0 / Math.Sqrt( 2.0 ) * fX * SqrtPhillips); i = (float) (1.0 / Math.Sqrt( 2.0 ) * fZ * SqrtPhillips); r = (float) (U1);// * Math.Exp( -0.001 * Math.Abs( Fx ) )); i = 0.0f;//(float) U2; // r = 0.0; // for ( int j=1; j < 100; j++ ) // r += 0.25 * Math.Cos( 2.0 * Math.PI * -j * (X+2*Y) / 256.0 ) / j; // i = 0.0; // r = Math.Exp( -0.1 * kx ); // i = Math.Exp( -0.1 * kz ); } ); } // Fill in bitmap outputPanelFrequency.FillBitmap( ( int _X, int _Y, int _Width, int _Height ) => { int X = 256 * _X / _Width; int Y = 256 * _Y / _Height; byte R = (byte) (255 * Math.Min( 1.0, Math.Abs( FFT.Input[2*(256*Y+X)+0] ))); byte I = (byte) (255 * Math.Min( 1.0, Math.Abs( FFT.Input[2*(256*Y+X)+1] ))); return 0xFF000000 | (uint) ((R << 16) | (I << 8)); } ); // Inverse FFT FFT.InputIsSpatial = false; // We fed frequencies and need an inverse transform FFT.Execute( fftwlib.FFT2D.Normalization.SQUARE_ROOT_OF_DIMENSIONS_PRODUCT ); // DEBUG: Test we get back what we fed! // FFT.SwapInputOutput(); // FFT.InputIsSpatial = false; // FFT.Execute( fftwlib.FFT2D.Normalization.SQUARE_ROOT_OF_DIMENSIONS_PRODUCT ); // Retrieve results outputPanelSpatial.FillBitmap( ( int _X, int _Y, int _Width, int _Height ) => { int X = 256 * _X / _Width; int Y = 256 * _Y / _Height; byte R = (byte) (255 * Math.Min( 1.0f, Math.Abs( FFT.Output[2*(256*Y+X)+0] ))); byte I = (byte) (255 * Math.Min( 1.0f, Math.Abs( FFT.Output[2*(256*Y+X)+1] ))); // byte R = (byte) (255 * Math.Min( 1.0f, 1.0e6 * Math.Abs( FFT.Output[2*(256*Y+X)+0] ) )); // byte I = (byte) (255 * Math.Min( 1.0f, 1.0e6 * Math.Abs( FFT.Output[2*(256*Y+X)+1] ) )); return 0xFF000000 | (uint) ((R << 16) | (I << 8)); } ); ////////////////////////////////////////////////////////////////////////// // Save the results System.IO.FileInfo F = new System.IO.FileInfo( @".\Water0_256x256.complex" ); System.IO.FileStream S = F.Create(); System.IO.BinaryWriter Writer = new System.IO.BinaryWriter( S ); for ( int Y=0; Y < 256; Y++ ) for ( int X=0; X < 256; X++ ) { Writer.Write( FFT.Output[2*(256*Y+X)+0] ); Writer.Write( FFT.Output[2*(256*Y+X)+1] ); } Writer.Close(); S.Close(); } }
void TestTransform1D(double _time) { // Build the input signal Array.Clear(m_signalSource, 0, m_signalSource.Length); switch (m_signalType1D) { case SIGNAL_TYPE.SQUARE: for (int i = 0; i < SIGNAL_SIZE; i++) { m_signalSource[i].r = 0.5 * Math.Sin(_time) + ((i + 50.0 * _time) % (SIGNAL_SIZE / 2.0) < (SIGNAL_SIZE / 4.0) ? 0.5 : -0.5); } break; case SIGNAL_TYPE.SINE: for (int i = 0; i < SIGNAL_SIZE; i++) { // m_signalSource[i].r = Math.Cos( 2.0 * Math.PI * i / SIGNAL_SIZE + _time ); m_signalSource[i].r = Math.Cos((4.0 * (1.0 + Math.Sin(_time))) * 2.0 * Math.PI * i / SIGNAL_SIZE); } break; case SIGNAL_TYPE.SAW: for (int i = 0; i < SIGNAL_SIZE; i++) { m_signalSource[i].r = 0.5 * Math.Sin(_time) + ((((i + 50.0 * _time) / 128.0) % 1.0) - 0.5); } break; case SIGNAL_TYPE.SINC: for (int i = 0; i < SIGNAL_SIZE; i++) { // double a = 4.0 * (1.0 + Math.Sin( _time )) * 2.0 * Math.PI * (1+i) / SIGNAL_SIZE; // Asymmetrical double a = 4.0 * (1.0 + Math.Sin(_time)) * 2.0 * Math.PI * (i - SIGNAL_SIZE / 2.0) * 2.0 / SIGNAL_SIZE; // Symmetrical m_signalSource[i].r = Math.Abs(a) > 0.0 ? Math.Sin(a) / a : 1.0; } break; case SIGNAL_TYPE.RANDOM: for (int i = 0; i < SIGNAL_SIZE; i++) { m_signalSource[i].r = SimpleRNG.GetUniform(); } // m_signalSource[i].r = SimpleRNG.GetExponential(); // m_signalSource[i].r = SimpleRNG.GetBeta( 0.5, 1 ); // m_signalSource[i].r = SimpleRNG.GetGamma( 1.0, 0.1 ); // m_signalSource[i].r = SimpleRNG.GetCauchy( 0.0, 1.0 ); // m_signalSource[i].r = SimpleRNG.GetChiSquare( 1.0 ); // m_signalSource[i].r = SimpleRNG.GetNormal( 0.0, 0.1 ); // m_signalSource[i].r = SimpleRNG.GetLaplace( 0.0, 0.1 ); // m_signalSource[i].r = SimpleRNG.GetStudentT( 2.0 ); break; } // Transform if (m_FFTW_1D != null && checkBoxUseFFTW.Checked) { m_FFTW_1D.FillInputSpatial((int x, int y, out float r, out float i) => { r = (float)m_signalSource[x].r; i = (float)m_signalSource[x].i; }); m_FFTW_1D.Execute(fftwlib.FFT2D.Normalization.DIMENSIONS_PRODUCT); m_FFTW_1D.GetOutput((int x, int y, float r, float i) => { m_spectrum[x].Set(r, i); }); } else { // DFT1D.DFT_Forward( m_signalSource, m_spectrum ); FFT1D.FFT_Forward(m_signalSource, m_spectrum); } // Try the GPU version m_FFT1D_GPU.FFT_Forward(m_signalSource, m_spectrumGPU); // m_FFT1D_GPU.FFT_Forward( m_signalSource, m_spectrum ); double sumSqDiffR = 0.0; double sumSqDiffI = 0.0; for (int i = 0; i < m_spectrum.Length; i++) { Complex diff = m_spectrum[i] - m_spectrumGPU[i]; sumSqDiffR += diff.r * diff.r; sumSqDiffI += diff.i * diff.i; } labelDiff.Text = "SqDiff = " + sumSqDiffR.ToString("G3") + " , " + sumSqDiffI.ToString("G3"); if (m_FFTW_1D == null && checkBoxUseFFTW.Checked) { labelDiff.Text += "\r\nERROR: Can't use FFTW because of an initialization error!"; } if (checkBoxInvertFilter.Checked) { for (int i = 0; i < m_spectrum.Length; i++) { m_spectrum[i] = m_spectrumGPU[i]; } } // else // for ( int i=0; i < m_spectrum.Length; i++ ) // m_spectrum[i] *= 2.0; // Filter FilterDelegate filter = null; switch (m_filter1D) { case FILTER_TYPE.CUT_LARGE: filter = (int i, int frequency) => { return(Math.Abs(frequency) > 256 ? 0 : 1.0); }; // Cut break; case FILTER_TYPE.CUT_MEDIUM: filter = (int i, int frequency) => { return(Math.Abs(frequency) > 128 ? 0 : 1.0); }; // Cut break; case FILTER_TYPE.CUT_SHORT: filter = (int i, int frequency) => { return(Math.Abs(frequency) > 64 ? 0 : 1.0); }; // Cut break; case FILTER_TYPE.EXP: filter = (int i, int frequency) => { return(Math.Exp(-0.01f * Math.Abs(frequency))); }; // Exponential break; case FILTER_TYPE.GAUSSIAN: filter = (int i, int frequency) => { return(Math.Exp(-0.005f * frequency * frequency)); }; // Gaussian break; case FILTER_TYPE.INVERSE: filter = (int i, int frequency) => { return(Math.Min(1.0, 4.0 / (1 + Math.Abs(frequency)))); }; // Inverse break; // case FILTER_TYPE.SINUS: // filter = ( int i, int frequency ) => { return Math.Sin( -2.0f * Math.PI * frequency / 32 ); }; // Gni ? // break; } if (filter != null) { int size = m_spectrum.Length; int halfSize = size >> 1; if (!checkBoxInvertFilter.Checked) { for (int i = 0; i < size; i++) { int frequency = ((i + halfSize) % size) - halfSize; double filterValue = filter(i, frequency); m_spectrum[i] *= filterValue; } } else { for (int i = 0; i < size; i++) { int frequency = ((size - i) % size) - halfSize; double filterValue = filter(i, frequency); m_spectrum[i] *= filterValue; } } } // Inverse Transform if (m_FFTW_1D != null && checkBoxUseFFTW.Checked) { m_FFTW_1D.FillInputFrequency((int x, int y, out float r, out float i) => { r = (float)m_spectrum[x].r; i = (float)m_spectrum[x].i; }); m_FFTW_1D.Execute(fftwlib.FFT2D.Normalization.NONE); m_FFTW_1D.GetOutput((int x, int y, float r, float i) => { m_signalReconstructed[x].Set(r, i); }); } else { // DFT1D.DFT_Inverse( m_spectrum, m_signalReconstructed ); FFT1D.FFT_Inverse(m_spectrum, m_signalReconstructed); } }
protected unsafe override void OnLoad(EventArgs e) { base.OnLoad(e); using (fftwlib.FFT2D FFT = new fftwlib.FFT2D(256, 256)) { // Build the source data // FillInput( FFT.Input ); { const double Lx = 400.0; const double Lz = Lx; const double WindAngle = 45.0 * Math.PI / 180.0; const double WindVelocity = 20.0; double Wx = Math.Cos(WindAngle); double Wz = Math.Sin(WindAngle); double U1, U2, fX, fZ; Random RNG = new Random(1); FFT.FillInputFrequency((int Fx, int Fy, out float r, out float i) => { double kx = (2.0 * Math.PI / Lx) * Fx; double kz = (2.0 * Math.PI / Lz) * Fy; // Build white gaussian noise // (source: http://www.dspguru.com/dsp/howtos/how-to-generate-white-gaussian-noise) U1 = 1e-10 + RNG.NextDouble(); U2 = RNG.NextDouble(); fX = Math.Sqrt(-2.0 * Math.Log(U1)) * Math.Sin(2.0 * Math.PI * U2); U1 = 1e-10 + RNG.NextDouble(); U2 = RNG.NextDouble(); fZ = Math.Sqrt(-2.0 * Math.Log(U1)) * Math.Sin(2.0 * Math.PI * U2); fX = fZ = 1.0; // Build Phillips spectrum double SqrtPhillips = Math.Sqrt(Phillips(kx, kz, WindVelocity, Wx, Wz)); r = (float)(1.0 / Math.Sqrt(2.0) * fX * SqrtPhillips); i = (float)(1.0 / Math.Sqrt(2.0) * fZ * SqrtPhillips); r = (float)(U1); // * Math.Exp( -0.001 * Math.Abs( Fx ) )); i = 0.0f; //(float) U2; // r = 0.0; // for ( int j=1; j < 100; j++ ) // r += 0.25 * Math.Cos( 2.0 * Math.PI * -j * (X+2*Y) / 256.0 ) / j; // i = 0.0; // r = Math.Exp( -0.1 * kx ); // i = Math.Exp( -0.1 * kz ); }); } // Fill in bitmap outputPanelFrequency.FillBitmap((int _X, int _Y, int _Width, int _Height) => { int X = 256 * _X / _Width; int Y = 256 * _Y / _Height; byte R = (byte)(255 * Math.Min(1.0, Math.Abs(FFT.Input[2 * (256 * Y + X) + 0]))); byte I = (byte)(255 * Math.Min(1.0, Math.Abs(FFT.Input[2 * (256 * Y + X) + 1]))); return(0xFF000000 | (uint)((R << 16) | (I << 8))); }); // Inverse FFT FFT.InputIsSpatial = false; // We fed frequencies and need an inverse transform FFT.Execute(fftwlib.FFT2D.Normalization.SQUARE_ROOT_OF_DIMENSIONS_PRODUCT); // DEBUG: Test we get back what we fed! // FFT.SwapInputOutput(); // FFT.InputIsSpatial = false; // FFT.Execute( fftwlib.FFT2D.Normalization.SQUARE_ROOT_OF_DIMENSIONS_PRODUCT ); // Retrieve results outputPanelSpatial.FillBitmap((int _X, int _Y, int _Width, int _Height) => { int X = 256 * _X / _Width; int Y = 256 * _Y / _Height; byte R = (byte)(255 * Math.Min(1.0f, Math.Abs(FFT.Output[2 * (256 * Y + X) + 0]))); byte I = (byte)(255 * Math.Min(1.0f, Math.Abs(FFT.Output[2 * (256 * Y + X) + 1]))); // byte R = (byte) (255 * Math.Min( 1.0f, 1.0e6 * Math.Abs( FFT.Output[2*(256*Y+X)+0] ) )); // byte I = (byte) (255 * Math.Min( 1.0f, 1.0e6 * Math.Abs( FFT.Output[2*(256*Y+X)+1] ) )); return(0xFF000000 | (uint)((R << 16) | (I << 8))); }); ////////////////////////////////////////////////////////////////////////// // Save the results System.IO.FileInfo F = new System.IO.FileInfo(@".\Water0_256x256.complex"); System.IO.FileStream S = F.Create(); System.IO.BinaryWriter Writer = new System.IO.BinaryWriter(S); for (int Y = 0; Y < 256; Y++) { for (int X = 0; X < 256; X++) { Writer.Write(FFT.Output[2 * (256 * Y + X) + 0]); Writer.Write(FFT.Output[2 * (256 * Y + X) + 1]); } } Writer.Close(); S.Close(); } }