Я пытаюсь решить уравнение Яда с граничным условием Дирихле для четырех сторон вычислительной области. Как известно, я должен использовать FFTW_RODFT00 для выполнения условия. Однако результат неверен. Не могли бы вы мне помочь?fftw3 для пуассонов с граничным условием дирихле для всей стороны вычислительной области
#include <stdio.h>
#include <math.h>
#include <cmath>
#include <fftw3.h>
#include <iostream>
#include <vector>
using namespace std;
int main() {
int N1=100;
int N2=100;
double pi = 3.141592653589793;
double L1 = 2.0;
double dx = L1/(double)(N1-1);
double L2= 2.0;
double dy=L2/(double)(N2-1);
double invL1s=1.0/(L1*L1);
double invL2s=1.0/(L2*L2);
std::vector<double> in1(N1*N2,0.0);
std::vector<double> in2(N1*N2,0.0);
std::vector<double> out1(N1*N2,0.0);
std::vector<double> out2(N1*N2,0.0);
std::vector<double> X(N1,0.0);
std::vector<double> Y(N2,0.0);
fftw_plan p, q;
int i,j;
p = fftw_plan_r2r_2d(N1,N2, in1.data(), out1.data(), FFTW_RODFT00, FFTW_RODFT00, FFTW_EXHAUSTIVE);
q = fftw_plan_r2r_2d(N1,N2, in2.data(), out2.data(), FFTW_RODFT00, FFTW_RODFT00, FFTW_EXHAUSTIVE);
int l=-1;
for(i = 0;i <N1;i++){
X[i] =-1.0+(double)i*dx ;
for(j = 0;j<N2;j++){
l=l+1;
Y[j] =-1.0+ (double)j*dy ;
in1[l]= sin(pi*X[i]) + sin(pi*Y[j]) ; // row major ordering
}
}
fftw_execute(p);
l=-1;
for (i = 0; i < N1; i++){ // f = g/(kx² + ky²)
for(j = 0; j < N2; j++){
l=l+1;
double fact=0;
in2[l]=0;
if(2*i<N1){
fact=((double)i*i)*invL1s;;
}else{
fact=((double)(N1-i)*(N1-i))*invL1s;
}
if(2*j<N2){
fact+=((double)j*j)*invL2s;
}else{
fact+=((double)(N2-j)*(N2-j))*invL2s;
}
if(fact!=0){
in2[l] = out1[l]/fact;
}else{
in2[l] = 0.0;
}
}
}
fftw_execute(q);
l=-1;
double erl1 = 0.;
for (i = 0; i < N1; i++) {
for(j = 0; j < N2; j++){
l=l+1;
erl1 +=1.0/pi/pi*fabs(in1[l]- 0.25*out2[l]/((double)(N1-1))/((double)(N2-1)));
printf("%3d %10.5f %10.5f\n", l, in1[l], 0.25*out2[l]/((double)(N1-1))/((double)(N2-1)));
}
}
cout<<"error=" <<erl1 <<endl ;
fftw_destroy_plan(p); fftw_destroy_plan(q); fftw_cleanup();
return 0;
}
Большое спасибо. Ваш отредактированный код работает отлично, и ваше объяснение очень ясно и подробно. Однако я просто путаю разницу частоты f_k типа I между DST и DCT. Разница здесь равна +1 по частоте DST. Равномерно, я изменяю расчет частоты DST в вашем модифицированном коде, таком как DCT-код, и получаю тот же результат. Не могли бы вы указать на этот аспект? –
Боюсь, я не мог понять ваш комментарий. Если я заменю 'fact = pi * pi * ((double) (i + 1) * (i + 1)) * invL1s;' по частоте DCT 'fact = pi * pi * ((double) (i) * (i)) * invL1s; 'и масштабирование'/((double) (N1 + 1))/((double) (N2 + 1))); 'by' ((double) (N1-1))/((double) (N2-1))); ', ошибка переходит от 7.3e-5 до 0.87 ... Если вы только что изменили высокие частоты (i> N/2), результат немного изменен, поскольку DST предлагаемого источника источника не характеризуется высокой величиной в диапазоне высоких частот. Другой тестовый пример (например, sin ((70pi x/L1) .sin (70pi y/l2)) поможет выбрать правильный! – francis
Прошу прощения за мой неясный вопрос. Не могли бы вы объяснить принципы расчета частота DCT, DST в вашем коде? Я прочитал все ваши ссылки, упомянутые выше, однако я не нашел способ его рассчитать. Большое спасибо за ваш энтузиазм. –