Program Listing for File GridTools.cpp
↰ Return to documentation for file (src/GridTools.cpp
)
#include "crpropa/GridTools.h"
#include "crpropa/magneticField/MagneticField.h"
#include <fstream>
#include <sstream>
namespace crpropa {
void scaleGrid(ref_ptr<Grid1f> grid, double a) {
for (int ix = 0; ix < grid->getNx(); ix++)
for (int iy = 0; iy < grid->getNy(); iy++)
for (int iz = 0; iz < grid->getNz(); iz++)
grid->get(ix, iy, iz) *= a;
}
void scaleGrid(ref_ptr<Grid3f> grid, double a) {
for (int ix = 0; ix < grid->getNx(); ix++)
for (int iy = 0; iy < grid->getNy(); iy++)
for (int iz = 0; iz < grid->getNz(); iz++)
grid->get(ix, iy, iz) *= a;
}
Vector3f meanFieldVector(ref_ptr<Grid3f> grid) {
size_t Nx = grid->getNx();
size_t Ny = grid->getNy();
size_t Nz = grid->getNz();
Vector3f mean(0.);
for (int ix = 0; ix < Nx; ix++)
for (int iy = 0; iy < Ny; iy++)
for (int iz = 0; iz < Nz; iz++)
mean += grid->get(ix, iy, iz);
return mean / Nx / Ny / Nz;
}
double meanFieldStrength(ref_ptr<Grid3f> grid) {
size_t Nx = grid->getNx();
size_t Ny = grid->getNy();
size_t Nz = grid->getNz();
double mean = 0;
for (int ix = 0; ix < Nx; ix++)
for (int iy = 0; iy < Ny; iy++)
for (int iz = 0; iz < Nz; iz++)
mean += grid->get(ix, iy, iz).getR();
return mean / Nx / Ny / Nz;
}
double meanFieldStrength(ref_ptr<Grid1f> grid) {
size_t Nx = grid->getNx();
size_t Ny = grid->getNy();
size_t Nz = grid->getNz();
double mean = 0;
for (int ix = 0; ix < Nx; ix++)
for (int iy = 0; iy < Ny; iy++)
for (int iz = 0; iz < Nz; iz++)
mean += grid->get(ix, iy, iz);
return mean / Nx / Ny / Nz;
}
double rmsFieldStrength(ref_ptr<Grid3f> grid) {
size_t Nx = grid->getNx();
size_t Ny = grid->getNy();
size_t Nz = grid->getNz();
double sumV2 = 0;
for (int ix = 0; ix < Nx; ix++)
for (int iy = 0; iy < Ny; iy++)
for (int iz = 0; iz < Nz; iz++)
sumV2 += grid->get(ix, iy, iz).getR2();
return std::sqrt(sumV2 / Nx / Ny / Nz);
}
double rmsFieldStrength(ref_ptr<Grid1f> grid) {
size_t Nx = grid->getNx();
size_t Ny = grid->getNy();
size_t Nz = grid->getNz();
double sumV2 = 0;
for (int ix = 0; ix < Nx; ix++)
for (int iy = 0; iy < Ny; iy++)
for (int iz = 0; iz < Nz; iz++)
sumV2 += pow(grid->get(ix, iy, iz), 2);
return std::sqrt(sumV2 / Nx / Ny / Nz);
}
std::array<float, 3> rmsFieldStrengthPerAxis(ref_ptr<Grid3f> grid) {
size_t Nx = grid->getNx();
size_t Ny = grid->getNy();
size_t Nz = grid->getNz();
float sumV2_x = 0;
float sumV2_y = 0;
float sumV2_z = 0;
for (int ix = 0; ix < Nx; ix++)
for (int iy = 0; iy < Ny; iy++)
for (int iz = 0; iz < Nz; iz++) {
sumV2_x += pow(grid->get(ix, iy, iz).x, 2);
sumV2_y += pow(grid->get(ix, iy, iz).y, 2);
sumV2_z += pow(grid->get(ix, iy, iz).z, 2);
}
return {
std::sqrt(sumV2_x / Nx / Ny / Nz),
std::sqrt(sumV2_y / Nx / Ny / Nz),
std::sqrt(sumV2_z / Nx / Ny / Nz)
};
}
void fromMagneticField(ref_ptr<Grid3f> grid, ref_ptr<MagneticField> field) {
Vector3d origin = grid->getOrigin();
Vector3d spacing = grid->getSpacing();
size_t Nx = grid->getNx();
size_t Ny = grid->getNy();
size_t Nz = grid->getNz();
for (size_t ix = 0; ix < Nx; ix++)
for (size_t iy = 0; iy < Ny; iy++)
for (size_t iz = 0; iz < Nz; iz++) {
Vector3d pos = Vector3d(double(ix) + 0.5, double(iy) + 0.5, double(iz) + 0.5) * spacing + origin;
Vector3d B = field->getField(pos);
grid->get(ix, iy, iz) = B;
}
}
void fromMagneticFieldStrength(ref_ptr<Grid1f> grid, ref_ptr<MagneticField> field) {
Vector3d origin = grid->getOrigin();
Vector3d spacing = grid->getSpacing();
size_t Nx = grid->getNx();
size_t Ny = grid->getNy();
size_t Nz = grid->getNz();
for (size_t ix = 0; ix < Nx; ix++)
for (size_t iy = 0; iy < Ny; iy++)
for (size_t iz = 0; iz < Nz; iz++) {
Vector3d pos = Vector3d(double(ix) + 0.5, double(iy) + 0.5, double(iz) + 0.5) * spacing + origin;
double s = field->getField(pos).getR();
grid->get(ix, iy, iz) = s;
}
}
void loadGrid(ref_ptr<Grid3f> grid, std::string filename, double c) {
std::ifstream fin(filename.c_str(), std::ios::binary);
if (!fin) {
std::stringstream ss;
ss << "load Grid3f: " << filename << " not found";
throw std::runtime_error(ss.str());
}
// get length of file and compare to size of grid
fin.seekg(0, fin.end);
size_t length = fin.tellg() / sizeof(float);
fin.seekg (0, fin.beg);
size_t nx = grid->getNx();
size_t ny = grid->getNy();
size_t nz = grid->getNz();
if (length != (3 * nx * ny * nz))
throw std::runtime_error("loadGrid: file and grid size do not match");
for (int ix = 0; ix < grid->getNx(); ix++) {
for (int iy = 0; iy < grid->getNy(); iy++) {
for (int iz = 0; iz < grid->getNz(); iz++) {
Vector3f &b = grid->get(ix, iy, iz);
fin.read((char*) &(b.x), sizeof(float));
fin.read((char*) &(b.y), sizeof(float));
fin.read((char*) &(b.z), sizeof(float));
b *= c;
}
}
}
fin.close();
}
void loadGrid(ref_ptr<Grid1f> grid, std::string filename, double c) {
std::ifstream fin(filename.c_str(), std::ios::binary);
if (!fin) {
std::stringstream ss;
ss << "load Grid1f: " << filename << " not found";
throw std::runtime_error(ss.str());
}
// get length of file and compare to size of grid
fin.seekg(0, fin.end);
size_t length = fin.tellg() / sizeof(float);
fin.seekg (0, fin.beg);
size_t nx = grid->getNx();
size_t ny = grid->getNy();
size_t nz = grid->getNz();
if (length != (nx * ny * nz))
throw std::runtime_error("loadGrid: file and grid size do not match");
for (int ix = 0; ix < nx; ix++) {
for (int iy = 0; iy < ny; iy++) {
for (int iz = 0; iz < nz; iz++) {
float &b = grid->get(ix, iy, iz);
fin.read((char*) &b, sizeof(float));
b *= c;
}
}
}
fin.close();
}
void dumpGrid(ref_ptr<Grid3f> grid, std::string filename, double c) {
std::ofstream fout(filename.c_str(), std::ios::binary);
if (!fout) {
std::stringstream ss;
ss << "dump Grid3f: " << filename << " not found";
throw std::runtime_error(ss.str());
}
for (int ix = 0; ix < grid->getNx(); ix++) {
for (int iy = 0; iy < grid->getNy(); iy++) {
for (int iz = 0; iz < grid->getNz(); iz++) {
Vector3f b = grid->get(ix, iy, iz) * c;
fout.write((char*) &(b.x), sizeof(float));
fout.write((char*) &(b.y), sizeof(float));
fout.write((char*) &(b.z), sizeof(float));
}
}
}
fout.close();
}
void dumpGrid(ref_ptr<Grid1f> grid, std::string filename, double c) {
std::ofstream fout(filename.c_str(), std::ios::binary);
if (!fout) {
std::stringstream ss;
ss << "dump Grid1f: " << filename << " not found";
throw std::runtime_error(ss.str());
}
for (int ix = 0; ix < grid->getNx(); ix++) {
for (int iy = 0; iy < grid->getNy(); iy++) {
for (int iz = 0; iz < grid->getNz(); iz++) {
float b = grid->get(ix, iy, iz) * c;
fout.write((char*) &b, sizeof(float));
}
}
}
fout.close();
}
void loadGridFromTxt(ref_ptr<Grid3f> grid, std::string filename, double c) {
std::ifstream fin(filename.c_str());
if (!fin) {
std::stringstream ss;
ss << "load Grid3f: " << filename << " not found";
throw std::runtime_error(ss.str());
}
// skip header lines
while (fin.peek() == '#')
fin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
for (int ix = 0; ix < grid->getNx(); ix++) {
for (int iy = 0; iy < grid->getNy(); iy++) {
for (int iz = 0; iz < grid->getNz(); iz++) {
Vector3f &b = grid->get(ix, iy, iz);
fin >> b.x >> b.y >> b.z;
b *= c;
if (fin.eof())
throw std::runtime_error("load Grid3f: file too short");
}
}
}
fin.close();
}
void loadGridFromTxt(ref_ptr<Grid1f> grid, std::string filename, double c) {
std::ifstream fin(filename.c_str());
if (!fin) {
std::stringstream ss;
ss << "load Grid1f: " << filename << " not found";
throw std::runtime_error(ss.str());
}
// skip header lines
while (fin.peek() == '#')
fin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
for (int ix = 0; ix < grid->getNx(); ix++) {
for (int iy = 0; iy < grid->getNy(); iy++) {
for (int iz = 0; iz < grid->getNz(); iz++) {
float &b = grid->get(ix, iy, iz);
fin >> b;
b *= c;
if (fin.eof())
throw std::runtime_error("load Grid1f: file too short");
}
}
}
fin.close();
}
void dumpGridToTxt(ref_ptr<Grid3f> grid, std::string filename, double c) {
std::ofstream fout(filename.c_str());
if (!fout) {
std::stringstream ss;
ss << "dump Grid3f: " << filename << " not found";
throw std::runtime_error(ss.str());
}
for (int ix = 0; ix < grid->getNx(); ix++) {
for (int iy = 0; iy < grid->getNy(); iy++) {
for (int iz = 0; iz < grid->getNz(); iz++) {
Vector3f b = grid->get(ix, iy, iz) * c;
fout << b << "\n";
}
}
}
fout.close();
}
void dumpGridToTxt(ref_ptr<Grid1f> grid, std::string filename, double c) {
std::ofstream fout(filename.c_str());
if (!fout) {
std::stringstream ss;
ss << "dump Grid1f: " << filename << " not found";
throw std::runtime_error(ss.str());
}
for (int ix = 0; ix < grid->getNx(); ix++) {
for (int iy = 0; iy < grid->getNy(); iy++) {
for (int iz = 0; iz < grid->getNz(); iz++) {
float b = grid->get(ix, iy, iz) * c;
fout << b << "\n";
}
}
}
fout.close();
}
#ifdef CRPROPA_HAVE_FFTW3F
std::vector<std::pair<int, float>> gridPowerSpectrum(ref_ptr<Grid3f> grid) {
double rms = rmsFieldStrength(grid);
size_t n = grid->getNx(); // size of array
// arrays to hold the complex vector components of the B(k)-field
fftwf_complex *Bkx, *Bky, *Bkz;
Bkx = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * n * n * n);
Bky = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * n * n * n);
Bkz = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * n * n * n);
fftwf_complex *Bx = (fftwf_complex *)Bkx;
fftwf_complex *By = (fftwf_complex *)Bky;
fftwf_complex *Bz = (fftwf_complex *)Bkz;
// save to temp
int i;
for (size_t ix = 0; ix < n; ix++) {
for (size_t iy = 0; iy < n; iy++) {
for (size_t iz = 0; iz < n; iz++) {
i = ix * n * n + iy * n + iz;
Vector3<float> &b = grid->get(ix, iy, iz);
Bx[i][0] = b.x / rms;
By[i][0] = b.y / rms;
Bz[i][0] = b.z / rms;
}
}
}
// in-place, real to complex, inverse Fourier transformation on each component
// note that the last elements of B(x) are unused now
fftwf_plan plan_x =
fftwf_plan_dft_3d(n, n, n, Bx, Bkx, FFTW_FORWARD, FFTW_ESTIMATE);
fftwf_execute(plan_x);
fftwf_destroy_plan(plan_x);
fftwf_plan plan_y =
fftwf_plan_dft_3d(n, n, n, By, Bky, FFTW_FORWARD, FFTW_ESTIMATE);
fftwf_execute(plan_y);
fftwf_destroy_plan(plan_y);
fftwf_plan plan_z =
fftwf_plan_dft_3d(n, n, n, Bz, Bkz, FFTW_FORWARD, FFTW_ESTIMATE);
fftwf_execute(plan_z);
fftwf_destroy_plan(plan_z);
float power;
std::map<size_t, std::pair<float, int>> spectrum;
int k;
for (size_t ix = 0; ix < n; ix++) {
for (size_t iy = 0; iy < n; iy++) {
for (size_t iz = 0; iz < n; iz++) {
i = ix * n * n + iy * n + iz;
k = static_cast<int>(
std::floor(std::sqrt(ix * ix + iy * iy + iz * iz)));
if (k > n / 2. || k == 0)
continue;
power = ((Bkx[i][0] * Bkx[i][0] + Bkx[i][1] * Bkx[i][1]) +
(Bky[i][0] * Bky[i][0] + Bky[i][1] * Bky[i][1]) +
(Bkz[i][0] * Bkz[i][0] + Bkz[i][1] * Bkz[i][1]));
if (spectrum.find(k) == spectrum.end()) {
spectrum[k].first = power;
spectrum[k].second = 1;
} else {
spectrum[k].first += power;
spectrum[k].second += 1;
}
}
}
}
fftwf_free(Bkx);
fftwf_free(Bky);
fftwf_free(Bkz);
std::vector<std::pair<int, float>> points;
for (std::map<size_t, std::pair<float, int>>::iterator it = spectrum.begin();
it != spectrum.end(); ++it) {
points.push_back(
std::make_pair(it->first, (it->second).first / (it->second).second));
}
return points;
}
#endif // CRPROPA_HAVE_FFTW3F
} // namespace crpropa