Dekomposisi FFT 2D (dan fft terbalik) dengan fftw di fortran77

[edit 1] Menambahkan gambar untuk menampilkan data asli dan data yang diperoleh

[edit 2] Saya menemukan kesalahan saya, saya menggunakan fftw_measure alih-alih fftw_estimate dalam panggilan dfftw_plan_many_dft

[edit 3] memperbaiki kesalahan ketik pada kode (ganti u dengan u2d di dfftw_execute_dft_r2c )

Saya mencoba melakukan fft 2D dari sebuah array menggunakan beberapa fft 1D daripada menggunakan fungsi fft 2D yang sudah ada di perpustakaan fftw. Dan selanjutnya, saya perlu melakukan fft 2D terbalik. Alasan untuk melakukan itu adalah (di masa depan) array saya akan terlalu besar untuk dimuat sekaligus untuk melakukan fft 2D.

Draf pertama kode saya terlihat kurang lebih seperti ini saat ini:

  double precision u2d(nx,ny),u2d2(nx,ny)
  double complex qhat2d(nx/2+1,ny),qhat2d2(nx/2+1,ny)
  integer N(1)
  integer howmany, idist, odist, istride, ostride
  integer inembed(2), onembed(2)
  integer rank

  ! some function to read the data into u2d

  ! perform x-fft
  N(1) = NX
  howmany = NY
  inembed(1) = NX
  inembed(2) = NY
  istride = 1
  idist = NX
  ostride = 1
  odist = (NX/2+1)
  onembed(1) = (NX/2+1)
  onembed(2) = NY
  rank = 1
  write(*,*) 'u', u2d(1,1)
  CALL dfftw_plan_many_dft_r2c(PLAN,rank,N(1),howmany,
&                              u2d,inembed,
&                              istride,idist,
&                              qhat2d,onembed,
&                              ostride,odist,FFTW_ESTIMATE) ! 
  CALL dfftw_execute_dft_r2c(PLAN,u2d,qhat2d) ! x-fft
  CALL dfftw_destroy_plan(PLAN)


  ! perform y-fft
  N(1) = NY
  howmany = (NX/2+1)
  inembed(1) = (NX/2+1)
  inembed(2) = NY
  istride = (NX/2+1)
  idist = 1
  ostride = (NX/2+1)
  odist = 1
  onembed(1) = (NX/2+1)
  onembed(2) = NY
  rank = 1
  CALL dfftw_plan_many_dft(PLAN,rank,N(1),howmany,
&                              qhat2d,inembed,
&                              istride,idist,
&                              qhat2d2,onembed,
&                              ostride,odist,FFTW_FORWARD,
&                              FFTW_MEASURE) ! 
  CALL dfftw_execute_dft(PLAN,qhat2d,qhat2d2) ! y-fft
  CALL dfftw_destroy_plan(PLAN)

  ! normally here, perform some filtering operation
  ! but at the moment, I do nothing

  ! perform inv-y-fft
  N(1) = NY
  howmany = (NX/2+1)
  inembed(1) = (NX/2+1)
  inembed(2) = NY
  istride = (NX/2+1)
  idist = 1
  ostride = (NX/2+1)
  odist = 1
  onembed(1) = (NX/2+1)
  onembed(2) = NY
  rank = 1
  CALL dfftw_plan_many_dft(PLAN,rank,N(1),howmany,
 &                             qhat2d2,inembed,
 &                              istride,idist,
 &                              qhat2d,onembed,
 &                              ostride,odist,FFTW_BACKWARD,
 &                              FFTW_MEASURE) ! 
  CALL dfftw_execute_dft(PLAN,qhat2d2,qhat2d) ! inv-y-fft
  CALL dfftw_destroy_plan(PLAN)

  ! perform inv-x-fft
  N(1) = NX ! I'm not too sure about this value here
  howmany = NY
  inembed(1) = (NX/2+1)
  inembed(2) = NY
  istride = 1
  idist = (NX/2+1)
  ostride = 1
  odist = NX
  onembed(1) = NX
  onembed(2) = NY
  rank = 1
  CALL dfftw_plan_many_dft_c2r(PLAN,rank,N(1),howmany,
&                              qhat2d,inembed,
&                              istride,idist,
&                              u2d2,onembed,
&                              ostride,odist,FFTW_ESTIMATE) ! 
  CALL dfftw_execute_dft_c2r(PLAN,qhat2d,u2d2) ! x-fft
  CALL dfftw_destroy_plan(PLAN)
  write(*,*) 'u2d2', u2d2(1,1)

  do i=1,nx
   do j=1,ny
    u2d2(i,j) = u2d2(i,j) / (nx*ny)
   enddo
  enddo
  write(*,*) 'u2d2', u2d2(1,1) ! here the values u2d2(1,1) is different from u2d(1,1)

  ! some action to write u2d2 to file
  end

Saya mengharapkan u2d dan u2d2 sama tetapi saya mendapatkan nilai yang relatif berbeda. Apakah saya melakukan kesalahan di suatu tempat?

Asli dan hasilnya ditampilkan di bawah ini. Bentuknya terlihat serupa tetapi nilainya relatif berbeda (misalnya minimum dan maksimum).

Bidang asli

Bidang diperoleh setelah fft dan i-fft


person Anh Khoa    schedule 23.05.2016    source sumber
comment
FFTW tidak menormalkan nilai. Oleh karena itu, akan ada faktor panjang array jika Anda melakukan transformasi maju dan mundur pada data yang sama.   -  person Alexander Vogt    schedule 23.05.2016
comment
Lihat, misalnya, stackoverflow.com/questions/3721125/   -  person Alexander Vogt    schedule 23.05.2016
comment
atau stackoverflow.com/questions/4855958/normalising-fft-data-fftw   -  person Alexander Vogt    schedule 23.05.2016
comment
atau stackoverflow.com/questions/30402282/   -  person Alexander Vogt    schedule 23.05.2016
comment
Mengapa Anda melakukan DFT (_r2c) bernilai nyata pada data kompleks?   -  person Alexander Vogt    schedule 23.05.2016
comment
Selain komentar lain saya tekankan bahwa Anda harus menunjukkan apa yang salah. Anda harus menunjukkan nilai-nilai apa yang Anda dapatkan dan mengapa Anda yakin nilai-nilai itu salah.   -  person Vladimir F    schedule 24.05.2016
comment
@AlexanderVogt Data asli saya u2d adalah nyata jadi saya pikir menggunakan r2c adalah cara yang benar untuk melakukan fft pertama. Selanjutnya pada akhir saya melakukan renormalisasi data saya dengan membagi hasil 2 invers fft dengan (nx*ny).   -  person Anh Khoa    schedule 24.05.2016
comment
@roygvib Sebenarnya duplikat? stackoverflow.com/questions/36885526/ Namun, judulnya salah total.   -  person Vladimir F    schedule 24.05.2016
comment
@VladimirF Saya awalnya berpikir begitu, tetapi jika transformasi Fourier perantara tidak digunakan kembali setelahnya (bahkan disaring sebelum memasuki transformasi invers), kode tersebut tampaknya berfungsi (dengan mengasumsikan bahwa FFTW_ESTIMATE menjaga array input tetap utuh). Jadi hmm, saya tidak begitu yakin... (satu hal yang pasti adalah, saya akan menghindari pencampuran pembuatan rencana dan transformasi aktual pada saat yang bersamaan.)   -  person roygvib    schedule 24.05.2016


Jawaban (2)


Untuk menghilangkan kebingungan. Apa yang terjadi adalah rutinitas FFTW c2r dan r2c tidak menjamin pelestarian array input. Mereka bisa menimpa hasilnya dengan sampah.

Sekarang, Anda mungkin beruntung dan hanya menggunakan FFTW_ESTIMATE daripada FFTW_MEASURE, tapi itu bukan ide yang bagus.FFTW_MEASURE mencoba banyak algoritma dan oleh karena itu kemungkinan besar juga akan mencoba algoritma yang tidak mempertahankan inputnya. FFTW_ESTIMATE tidak akan mencoba menghitung apa pun dan tidak akan menimpa masukan.

Masalahnya adalah masukan Anda bisa ditimpa saat melakukan transformasi (mengeksekusi rencana). Anda hanya akan beruntung jika FFT_ESTIMATE memilih algoritme yang menyimpan masukan untuk Anda. Ini adalah lotere.

Untuk memastikan masukan dipertahankan, Anda harus menggunakan FFTW_INPUT_PRESERVE selain FFT_ESTIMATE atau FFTW_MEASURE.

Anda juga tidak dapat menggunakannya dan malah menyimpan masukan di suatu tempat. Saya pikir itu seringkali lebih baik karena FFTW_INPUT_PRESERVE dapat (sangat mungkin) memilih algoritma yang lebih lambat.

person Vladimir F    schedule 24.05.2016

Saya menemukan kesalahan saya, saya menggunakan fftw_measure alih-alih fftw_estimate dalam panggilan dfftw_plan_many_dft.

Mengoreksi itu memberi saya bidang asli yang sesuai.

person Anh Khoa    schedule 24.05.2016
comment
Ini seharusnya tidak menjadi masalah sama sekali. Yang penting adalah FFTW_PRESERVE_INPUT, tetapi hanya jika Anda tidak menyimpan masukan di tempat lain. - person Vladimir F; 24.05.2016
comment
@VladimirF Memeriksa halaman manual fftw.org/doc/Planner-Flags.html, tampaknya jika seseorang menggunakan FFTW_MEASURE, array input akan ditimpa saat membuat rencana. Antarmuka yang sangat membingungkan... - person roygvib; 24.05.2016
comment
@roygvib Ya, Anda tidak boleh hanya mengambil array input sebagai intent(in), bukan seperti itu. Bahkan selama transformasi pun tidak. Anda harus menggunakan `FFTW_PRESERVE_INPUT` kalau begitu. Saya sangat menyarankan untuk menyimpan nilai input di tempat lain jika Anda membutuhkannya nanti untuk tujuan apa pun. Tidaklah cukup menghemat hanya menggunakan FFTW_ESTIMATE seperti yang disarankan oleh jawabannya. Hal ini mungkin menyembunyikan masalah, namun dapat muncul kapan saja ketika estimasi memilih algoritma yang tidak mempertahankan masukan. Masukan tersebut kemudian akan ditimpa selama transformasi, bukan selama perencanaan. Oleh karena itu jawaban ini salah. - person Vladimir F; 24.05.2016
comment
Ya, dan secara lebih umum, saya menyarankan untuk memisahkan pembuatan rencana dan transformasi aktual. Dalam kasus saya, saya membuat modul yang menangani ini secara internal untuk pengguna. Tapi menurut saya jawabannya sendiri benar, karena gaya pengkodean adalah masalah selera (sampai batas tertentu). Namun demikian, menurut saya akan sangat berguna jika jawaban yang berbeda juga ditambahkan sebagai gaya alternatif (lebih aman)... - person roygvib; 24.05.2016
comment
@roygvib Ini tidak benar, Anda dapat menggunakan FFTW_ESTIMATE dan masukan Anda tetap ditimpa. Satu-satunya keberuntungan adalah perencana memilih algoritma yang tidak melakukan penimpaan, tapi itu murni keberuntungan. Lain kali, dengan kode yang sama pada mesin yang berbeda, bisa saja gagal lagi. - person Vladimir F; 24.05.2016
comment
Walaupun dia punya CALL dfftw_execute_dft_r2c(PLAN,u,qhat2d), kenapa tidak CALL dfftw_execute_dft_r2c(PLAN,u2d,qhat2d)? Di mana u didefinisikan? Saya menduga itu adalah tipe dan kesimpulan saya masih benar. - person Vladimir F; 24.05.2016
comment
Ah, kamu seharusnya salah ketik u2d. Kode berfungsi di komputer saya dengan modifikasi itu (sambil mengubah FFTW_MEASURE menjadi FFTW_ESTIMATE). BTW, apakah benar ada kasus di mana FFTW_ESTIMATE dapat mengubah array input? Karena saya ingin tahu lebih banyak tentang ini, saya akan sangat menghargai info tambahan apa pun... - person roygvib; 24.05.2016
comment
@roygvib tidak selama perencanaan, saya kira. Namun pada masa transformasi, hal itu bisa saja terjadi. Sulit untuk direproduksi, karena Anda tidak tahu estimasi apa yang dipilih, tetapi orang ini stackoverflow.com/questions/29322026/ memang menggunakan FFTW_ESTIMATE. Dan sebenarnya, jawaban Anda di sini stackoverflow.com/questions/36885526/ mengalami masalah yang sama, atau tidak? - person Vladimir F; 25.05.2016
comment
[@VladimirF Hai, saya akan memeriksanya lebih lanjut nanti dan kembali. (RE Q/A yang ditautkan, saya ingat saya mendapat hasil yang salah jika saya menggunakan c2r.)] - person roygvib; 25.05.2016