1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
#include "Tensor"
#include "fftw3.h"
#include <complex>
#include <array>
#include <iostream>
#include <iomanip>
static const int nx = 8;
static const int ny = 6;
static const int nz = 8;
using namespace std;
using namespace Eigen;
double SpatialMesh3DTrans(
double dx,
double dy,
double dz,
double zlow,
double zupp,
Tensor<double, 3>& xarr,
Tensor<double, 3>& yarr,
Tensor<double, 3>& zarr)
{
for (int x = 0; x < nx; x++)
{
for (int y = 0; y < ny; y++)
{
for(int z = 0; z < nz+1; z++)
{
xarr(z,x,y) = x*dx;
yarr(z,x,y) = y*dy;
zarr(z,x,y) = 1. * cos(((z) * EIGEN_PI) / nz);
zarr(z,x,y) = (1./2)*(((zupp-zlow)*zarr(z,x,y) ) + (zupp+zlow));
}
}
}
if (dx < dy){
return 1/(2*dx);
}else {
return 1/(2*dy);
}
}
int main()
{
double const Lx = 6.;
double const zlow = 0.;
double const zupp = 6.;
double const Ly = 6.;
double const Lz = zupp - zlow;
double const dx = Lx / nx;
double const dy = Ly / ny;
double const dz = Lz / nz;
Tensor<double, 3> eXX(nz + 1, nx, ny);
Tensor<double, 3> eYY(nz + 1, nx, ny);
Tensor<double, 3> eZZ(nz + 1, nx, ny);
Tensor<double, 3> uFun(nz + 1, nx, ny);
Tensor<std::complex<double>, 3> uFunk(nz + 1, nx, ny);
Tensor<double, 3> out(nz + 1, nx, ny);
int fft_size[] { ny, nx }; // NOTE(mbozzi): Indices are in reverse order because the tensor is column-major.
fftw_plan fft_through_each_zx_slice = fftw_plan_many_dft_r2c(
2, // int rank,
fft_size, // const int *n,
ny, // int howmany,
uFun.data(), // double *in,
nullptr, // const int *inembed,
1, // int istride, // adjacent elements within the same zx-slice are adjacent in memory
(nz + 1) * ny, // int idist, // adjacent elements within separate zx-slices are separate in memory.
reinterpret_cast<fftw_complex*>(uFunk.data()), // fftw_complex *out,
nullptr, // const int *onembed,
1, // int ostride,
(nz + 1) * ny, // int odist,
FFTW_ESTIMATE // unsigned flags
);
fftw_plan inverse_fft_through_each_zx_slice = fftw_plan_many_dft_c2r(
2, // int rank,
fft_size, // const int *n,
ny, // int howmany,
reinterpret_cast<fftw_complex*>(uFunk.data()), // fftw_complex *in,
nullptr, // const int *inembed,
1, // int istride, // adjacent elements within the same zx-slice are adjacent in memory
(nz + 1) * ny, // int idist, // adjacent elements within separate zx-slices are separate in memory.
out.data(), // fftw_complex *out,
nullptr, // const int *onembed,
1, // int ostride,
(nz + 1) * ny, // int odist,
FFTW_ESTIMATE // unsigned flags
);
double const kmax = SpatialMesh3DTrans(dx,dy,dz,zlow,zupp,eXX,eYY,eZZ);
double const A = 2*EIGEN_PI / Lx;
double const A1 = 2*EIGEN_PI / Ly;
for (int x = 0; x < nx; x++)
{
for (int y = 0; y < ny; y++)
{
for (int z = 0; z < nz + 1; z++)
{
uFun(z,x,y) = (eZZ(z,x,y)-zlow) * (eZZ(z,x,y)-zupp) * sin(A*eXX(z,x,y)) * sin(A1 *eYY(z,x,y));
}
}
}
std::cout << std::setprecision(2) << std::fixed;
std::cout << uFun.slice(std::array{0, 0, 1}, std::array{nz + 1, nx, 1}).reshape(std::array{nz + 1, nx}) << "\n\n";
fftw_execute(fft_through_each_zx_slice); // uFun --> uFunk
fftw_execute(inverse_fft_through_each_zx_slice); // uFunk --> out
out = (1.0 / (nx * ny)) * out; // normalize
std::cout << out.slice(std::array{0, 0, 1}, std::array{nz + 1, nx, 1}).reshape(std::array{nz + 1, nx}) << '\n';
}
| |