LCOV - code coverage report
Current view: top level - src - GridTools.cpp (source / functions) Coverage Total Hit
Test: coverage.info.cleaned Lines: 46.2 % 314 145
Test Date: 2026-06-18 09:49:19 Functions: 52.4 % 21 11

            Line data    Source code
       1              : #include "crpropa/GridTools.h"
       2              : #include "crpropa/magneticField/MagneticField.h"
       3              : 
       4              : #include <fstream>
       5              : #include <sstream>
       6              : 
       7              : namespace crpropa {
       8              : 
       9            0 : void scaleGrid(ref_ptr<Grid1f> grid, double a) {
      10            0 :         for (int ix = 0; ix < grid->getNx(); ix++)
      11            0 :                 for (int iy = 0; iy < grid->getNy(); iy++)
      12            0 :                         for (int iz = 0; iz < grid->getNz(); iz++)
      13            0 :                                 grid->get(ix, iy, iz) *= a;
      14            0 : }
      15              : 
      16           11 : void scaleGrid(ref_ptr<Grid3f> grid, double a) {
      17          654 :         for (int ix = 0; ix < grid->getNx(); ix++)
      18        41612 :                 for (int iy = 0; iy < grid->getNy(); iy++)
      19      2662436 :                         for (int iz = 0; iz < grid->getNz(); iz++)
      20      2621467 :                                 grid->get(ix, iy, iz) *= a;
      21           11 : }
      22              : 
      23            1 : Vector3f meanFieldVector(ref_ptr<Grid3f> grid) {
      24              :         size_t Nx = grid->getNx();
      25              :         size_t Ny = grid->getNy();
      26              :         size_t Nz = grid->getNz();
      27              :         Vector3f mean(0.);
      28           65 :         for (int ix = 0; ix < Nx; ix++)
      29         4160 :                 for (int iy = 0; iy < Ny; iy++)
      30       266240 :                         for (int iz = 0; iz < Nz; iz++)
      31              :                                 mean += grid->get(ix, iy, iz);
      32            1 :         return mean / Nx / Ny / Nz;
      33              : }
      34              : 
      35            0 : double meanFieldStrength(ref_ptr<Grid3f> grid) {
      36              :         size_t Nx = grid->getNx();
      37              :         size_t Ny = grid->getNy();
      38              :         size_t Nz = grid->getNz();
      39              :         double mean = 0;
      40            0 :         for (int ix = 0; ix < Nx; ix++)
      41            0 :                 for (int iy = 0; iy < Ny; iy++)
      42            0 :                         for (int iz = 0; iz < Nz; iz++)
      43            0 :                                 mean += grid->get(ix, iy, iz).getR();
      44            0 :         return mean / Nx / Ny / Nz;
      45              : }
      46              : 
      47            0 : double meanFieldStrength(ref_ptr<Grid1f> grid) {
      48              :         size_t Nx = grid->getNx();
      49              :         size_t Ny = grid->getNy();
      50              :         size_t Nz = grid->getNz();
      51              :         double mean = 0;
      52            0 :         for (int ix = 0; ix < Nx; ix++)
      53            0 :                 for (int iy = 0; iy < Ny; iy++)
      54            0 :                         for (int iz = 0; iz < Nz; iz++)
      55            0 :                                 mean += grid->get(ix, iy, iz);
      56            0 :         return mean / Nx / Ny / Nz;
      57              : }
      58              : 
      59           11 : double rmsFieldStrength(ref_ptr<Grid3f> grid) {
      60              :         size_t Nx = grid->getNx();
      61              :         size_t Ny = grid->getNy();
      62              :         size_t Nz = grid->getNz();
      63              :         double sumV2 = 0;
      64          715 :         for (int ix = 0; ix < Nx; ix++)
      65        45760 :                 for (int iy = 0; iy < Ny; iy++)
      66      2928640 :                         for (int iz = 0; iz < Nz; iz++)
      67      2883584 :                                 sumV2 += grid->get(ix, iy, iz).getR2();
      68           11 :         return std::sqrt(sumV2 / Nx / Ny / Nz);
      69              : }
      70              : 
      71            0 : double rmsFieldStrength(ref_ptr<Grid1f> grid) {
      72              :         size_t Nx = grid->getNx();
      73              :         size_t Ny = grid->getNy();
      74              :         size_t Nz = grid->getNz();
      75              :         double sumV2 = 0;
      76            0 :         for (int ix = 0; ix < Nx; ix++)
      77            0 :                 for (int iy = 0; iy < Ny; iy++)
      78            0 :                         for (int iz = 0; iz < Nz; iz++)
      79            0 :                                 sumV2 += pow(grid->get(ix, iy, iz), 2);
      80            0 :         return std::sqrt(sumV2 / Nx / Ny / Nz);
      81              : }
      82              : 
      83            0 : std::array<float, 3> rmsFieldStrengthPerAxis(ref_ptr<Grid3f> grid) {
      84              :     size_t Nx = grid->getNx();
      85              :     size_t Ny = grid->getNy();
      86              :     size_t Nz = grid->getNz();
      87              :     float sumV2_x = 0;
      88              :     float sumV2_y = 0;
      89              :     float sumV2_z = 0;
      90            0 :     for (int ix = 0; ix < Nx; ix++)
      91            0 :         for (int iy = 0; iy < Ny; iy++)
      92            0 :             for (int iz = 0; iz < Nz; iz++) {
      93            0 :                 sumV2_x += pow(grid->get(ix, iy, iz).x, 2);
      94            0 :                 sumV2_y += pow(grid->get(ix, iy, iz).y, 2);
      95            0 :                 sumV2_z += pow(grid->get(ix, iy, iz).z, 2);
      96              :             }
      97              :     return {
      98            0 :         std::sqrt(sumV2_x / Nx / Ny / Nz),
      99            0 :         std::sqrt(sumV2_y / Nx / Ny / Nz),
     100            0 :         std::sqrt(sumV2_z / Nx / Ny / Nz)
     101            0 :     };
     102              : }
     103              : 
     104            0 : void fromMagneticField(ref_ptr<Grid3f> grid, ref_ptr<MagneticField> field) {
     105              :         Vector3d origin = grid->getOrigin();
     106              :         Vector3d spacing = grid->getSpacing();
     107              :         size_t Nx = grid->getNx();
     108              :         size_t Ny = grid->getNy();
     109              :         size_t Nz = grid->getNz();
     110            0 :         for (size_t ix = 0; ix < Nx; ix++)
     111            0 :                 for (size_t iy = 0; iy < Ny; iy++)
     112            0 :                         for (size_t iz = 0; iz < Nz; iz++) {
     113            0 :                                 Vector3d pos = Vector3d(double(ix) + 0.5, double(iy) + 0.5, double(iz) + 0.5) * spacing + origin;
     114            0 :                                 Vector3d B = field->getField(pos);
     115              :                                 grid->get(ix, iy, iz) = B;
     116              :         }
     117            0 : }
     118              : 
     119            0 : void fromMagneticFieldStrength(ref_ptr<Grid1f> grid, ref_ptr<MagneticField> field) {
     120              :         Vector3d origin = grid->getOrigin();
     121              :         Vector3d spacing = grid->getSpacing();
     122              :         size_t Nx = grid->getNx();
     123              :         size_t Ny = grid->getNy();
     124              :         size_t Nz = grid->getNz();
     125            0 :         for (size_t ix = 0; ix < Nx; ix++)
     126            0 :                 for (size_t iy = 0; iy < Ny; iy++)
     127            0 :                         for (size_t iz = 0; iz < Nz; iz++) {
     128            0 :                                 Vector3d pos = Vector3d(double(ix) + 0.5, double(iy) + 0.5, double(iz) + 0.5) * spacing + origin;
     129            0 :                                 double s = field->getField(pos).getR();
     130            0 :                                 grid->get(ix, iy, iz) = s;
     131              :         }
     132            0 : }
     133              : 
     134            1 : void loadGrid(ref_ptr<Grid3f> grid, std::string filename, double c) {
     135            1 :         std::ifstream fin(filename.c_str(), std::ios::binary);
     136            1 :         if (!fin) {
     137            0 :                 std::stringstream ss;
     138            0 :                 ss << "load Grid3f: " << filename << " not found";
     139            0 :                 throw std::runtime_error(ss.str());
     140            0 :         }
     141              : 
     142              :         // get length of file and compare to size of grid
     143            1 :         fin.seekg(0, fin.end);
     144            1 :         size_t length = fin.tellg() / sizeof(float);
     145            1 :         fin.seekg (0, fin.beg);
     146              : 
     147              :         size_t nx = grid->getNx();
     148              :         size_t ny = grid->getNy();
     149              :         size_t nz = grid->getNz();
     150              : 
     151            1 :         if (length != (3 * nx * ny * nz))
     152            0 :                 throw std::runtime_error("loadGrid: file and grid size do not match");
     153              : 
     154            4 :         for (int ix = 0; ix < grid->getNx(); ix++) {
     155           12 :                 for (int iy = 0; iy < grid->getNy(); iy++) {
     156           36 :                         for (int iz = 0; iz < grid->getNz(); iz++) {
     157              :                                 Vector3f &b = grid->get(ix, iy, iz);
     158           27 :                                 fin.read((char*) &(b.x), sizeof(float));
     159           27 :                                 fin.read((char*) &(b.y), sizeof(float));
     160           27 :                                 fin.read((char*) &(b.z), sizeof(float));
     161           27 :                                 b *= c;
     162              :                         }
     163              :                 }
     164              :         }
     165            1 :         fin.close();
     166            1 : }
     167              : 
     168            0 : void loadGrid(ref_ptr<Grid1f> grid, std::string filename, double c) {
     169            0 :         std::ifstream fin(filename.c_str(), std::ios::binary);
     170            0 :         if (!fin) {
     171            0 :                 std::stringstream ss;
     172            0 :                 ss << "load Grid1f: " << filename << " not found";
     173            0 :                 throw std::runtime_error(ss.str());
     174            0 :         }
     175              : 
     176              :         // get length of file and compare to size of grid
     177            0 :         fin.seekg(0, fin.end);
     178            0 :         size_t length = fin.tellg() / sizeof(float);
     179            0 :         fin.seekg (0, fin.beg);
     180              : 
     181              :         size_t nx = grid->getNx();
     182              :         size_t ny = grid->getNy();
     183              :         size_t nz = grid->getNz();
     184              : 
     185            0 :         if (length != (nx * ny * nz))
     186            0 :                 throw std::runtime_error("loadGrid: file and grid size do not match");
     187              : 
     188            0 :         for (int ix = 0; ix < nx; ix++) {
     189            0 :                 for (int iy = 0; iy < ny; iy++) {
     190            0 :                         for (int iz = 0; iz < nz; iz++) {
     191              :                                 float &b = grid->get(ix, iy, iz);
     192            0 :                                 fin.read((char*) &b, sizeof(float));
     193            0 :                                 b *= c;
     194              :                         }
     195              :                 }
     196              :         }
     197            0 :         fin.close();
     198            0 : }
     199              : 
     200            1 : void dumpGrid(ref_ptr<Grid3f> grid, std::string filename, double c) {
     201            1 :         std::ofstream fout(filename.c_str(), std::ios::binary);
     202            1 :         if (!fout) {
     203            0 :                 std::stringstream ss;
     204            0 :                 ss << "dump Grid3f: " << filename << " not found";
     205            0 :                 throw std::runtime_error(ss.str());
     206            0 :         }
     207            4 :         for (int ix = 0; ix < grid->getNx(); ix++) {
     208           12 :                 for (int iy = 0; iy < grid->getNy(); iy++) {
     209           36 :                         for (int iz = 0; iz < grid->getNz(); iz++) {
     210           27 :                                 Vector3f b = grid->get(ix, iy, iz) * c;
     211           27 :                                 fout.write((char*) &(b.x), sizeof(float));
     212           27 :                                 fout.write((char*) &(b.y), sizeof(float));
     213           27 :                                 fout.write((char*) &(b.z), sizeof(float));
     214              :                         }
     215              :                 }
     216              :         }
     217            1 :         fout.close();
     218            1 : }
     219              : 
     220            0 : void dumpGrid(ref_ptr<Grid1f> grid, std::string filename, double c) {
     221            0 :         std::ofstream fout(filename.c_str(), std::ios::binary);
     222            0 :         if (!fout) {
     223            0 :                 std::stringstream ss;
     224            0 :                 ss << "dump Grid1f: " << filename << " not found";
     225            0 :                 throw std::runtime_error(ss.str());
     226            0 :         }
     227            0 :         for (int ix = 0; ix < grid->getNx(); ix++) {
     228            0 :                 for (int iy = 0; iy < grid->getNy(); iy++) {
     229            0 :                         for (int iz = 0; iz < grid->getNz(); iz++) {
     230            0 :                                 float b = grid->get(ix, iy, iz) * c;
     231            0 :                                 fout.write((char*) &b, sizeof(float));
     232              :                         }
     233              :                 }
     234              :         }
     235            0 :         fout.close();
     236            0 : }
     237              : 
     238            2 : void loadGridFromTxt(ref_ptr<Grid3f> grid, std::string filename, double c) {
     239            2 :         std::ifstream fin(filename.c_str());
     240            2 :         if (!fin) {
     241            0 :                 std::stringstream ss;
     242            0 :                 ss << "load Grid3f: " << filename << " not found";
     243            0 :                 throw std::runtime_error(ss.str());
     244            0 :         }
     245              :         // skip header lines
     246            3 :         while (fin.peek() == '#')
     247            1 :                 fin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
     248              : 
     249            8 :         for (int ix = 0; ix < grid->getNx(); ix++) {
     250           21 :                 for (int iy = 0; iy < grid->getNy(); iy++) {
     251           66 :                         for (int iz = 0; iz < grid->getNz(); iz++) {
     252              :                                 Vector3f &b = grid->get(ix, iy, iz);
     253           51 :                                 fin >> b.x >> b.y >> b.z;
     254           51 :                                 b *= c;
     255           51 :                                 if (fin.eof())
     256            0 :                                         throw std::runtime_error("load Grid3f: file too short");
     257              :                         }
     258              :                 }
     259              :         }
     260            2 :         fin.close();
     261            2 : }
     262              : 
     263            1 : ref_ptr<Grid3f> loadGrid3fFromTxt(std::string filename, double c) {
     264            1 :         std::ifstream fin(filename.c_str());
     265            1 :         if (!fin) {
     266            0 :                 std::stringstream ss;
     267            0 :                 ss << "load Grid3f: " << filename << " not found";
     268            0 :                 throw std::runtime_error(ss.str());
     269            0 :         }
     270              : 
     271              :         // search in header lines for GridProperties
     272            1 :         while (fin.peek() == '#') {
     273              :                 std::string line;
     274            1 :                 std::getline(fin, line);
     275              : 
     276              :                 // find gridproperties in the header 
     277            1 :                 if (line.rfind("GridProperties:") == 2) {     
     278              :                         GridProperties gp(Vector3d(0.), 1, 1, 1, 1.); // simple grid properties for default
     279            1 :                         std::stringstream ss(line); 
     280              : 
     281              :                         // skip first names and check type 
     282              :                         std::string name, type;
     283            1 :                         ss >> name >> name >> name >> type;
     284            1 :                         if (type != "Grid3f") 
     285            0 :                                 throw std::runtime_error("Tried to load Grid3f, but Gridproperties assume grid type " + type);
     286              : 
     287              :                         // grid origin
     288              :                         double x, y, z;
     289            1 :                         ss >> name >> x >> y >> z ; 
     290              :                         gp.origin = Vector3d(x, y, z);
     291              : 
     292              :                         // grid size
     293            1 :                         ss >> name >> gp.Nx >> gp.Ny >> gp.Nz;
     294              : 
     295              :                         // spacing
     296              :                         double dX, dY, dZ;
     297            1 :                         ss >> name >> dX >> dY >> dZ;
     298              :                         gp.spacing = Vector3d(dX, dY, dZ);
     299              : 
     300              :                         // reflective
     301            1 :                         ss >> name >> gp.reflective;
     302              :                         
     303              :                         // clip volume
     304              :                         bool clip; 
     305            1 :                         ss >> name >> clip;
     306            1 :                         gp.setClipVolume(clip);
     307              : 
     308              :                         // interpolation type 
     309            1 :                         ss >> name >> type;
     310            1 :                         if (type == "TRICUBIC")
     311              :                                 gp.setInterpolationType(TRICUBIC);
     312            1 :                         else if (type == "NEAREST_NEIGHBOUR")
     313              :                                 gp.setInterpolationType(NEAREST_NEIGHBOUR);
     314              :                         else 
     315              :                                 gp.setInterpolationType(TRILINEAR);
     316              : 
     317              :                         // create new grid
     318            1 :                         ref_ptr<Grid3f> grid = new Grid3f(gp);
     319            1 :                         fin.close();
     320              : 
     321              :                         // load data for grid
     322            2 :                         loadGridFromTxt(grid, filename, c); 
     323              : 
     324            1 :                         return grid;
     325            1 :                 }
     326              :         }
     327            0 :         throw std::runtime_error("could not find GridProperties in file " + filename);
     328            1 : }
     329              : 
     330              : 
     331            1 : void loadGridFromTxt(ref_ptr<Grid1f> grid, std::string filename, double c) {
     332            1 :         std::ifstream fin(filename.c_str());
     333            1 :         if (!fin) {
     334            0 :                 std::stringstream ss;
     335            0 :                 ss << "load Grid1f: " << filename << " not found";
     336            0 :                 throw std::runtime_error(ss.str());
     337            0 :         }
     338              :         
     339              :         // skip header lines
     340            2 :         while (fin.peek() == '#') 
     341            1 :                 fin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
     342              : 
     343            4 :         for (int ix = 0; ix < grid->getNx(); ix++) {
     344            9 :                 for (int iy = 0; iy < grid->getNy(); iy++) {
     345           30 :                         for (int iz = 0; iz < grid->getNz(); iz++) {
     346              :                                 float &b = grid->get(ix, iy, iz);
     347              :                                 fin >> b;
     348           24 :                                 b *= c;
     349           24 :                                 if (fin.eof())
     350            0 :                                         throw std::runtime_error("load Grid1f: file too short");
     351              :                         }
     352              :                 }
     353              :         }
     354            1 :         fin.close();
     355            1 : }
     356              : 
     357            1 : ref_ptr<Grid1f> loadGrid1fFromTxt(std::string filename, double c) {
     358            1 :         std::ifstream fin(filename.c_str());
     359            1 :         if (!fin) {
     360            0 :                 std::stringstream ss;
     361            0 :                 ss << "load Grid1f: " << filename << " not found";
     362            0 :                 throw std::runtime_error(ss.str());
     363            0 :         }
     364              : 
     365              :         // search in header lines for GridProperties
     366            1 :         while (fin.peek() == '#') {
     367              :                 std::string line;
     368            1 :                 std::getline(fin, line);
     369              : 
     370              :                 // find gridproperties in the header 
     371            1 :                 if (line.rfind("GridProperties:") == 2) {     
     372              :                         GridProperties gp(Vector3d(0.), 1, 1, 1, 1.); // simple grid properties for default
     373            1 :                         std::stringstream ss(line); 
     374              : 
     375              :                         // skip first names and check type 
     376              :                         std::string name, type;
     377            1 :                         ss >> name >> name >> name >> type;
     378            1 :                         if (type != "Grid1f") 
     379            0 :                                 throw std::runtime_error("Tried to load Grid1f, but Gridproperties assume grid type " + type);
     380              : 
     381              :                         // grid origin
     382              :                         double x, y, z;
     383            1 :                         ss >> name >> x >> y >> z ; 
     384              :                         gp.origin = Vector3d(x, y, z);
     385              : 
     386              :                         // grid size
     387            1 :                         ss >> name >> gp.Nx >> gp.Ny >> gp.Nz;
     388              : 
     389              :                         // spacing
     390              :                         double dX, dY, dZ;
     391            1 :                         ss >> name >> dX >> dY >> dZ;
     392              :                         gp.spacing = Vector3d(dX, dY, dZ);
     393              : 
     394              :                         // reflective
     395            1 :                         ss >> name >> gp.reflective;
     396              : 
     397              :                         // clip volume
     398              :                         bool clip; 
     399            1 :                         ss >> name >> clip;
     400            1 :                         gp.setClipVolume(clip);
     401              : 
     402              :                         // interpolation type 
     403            1 :                         ss >> name >> type;
     404            1 :                         if (type == "TRICUBIC")
     405              :                                 gp.setInterpolationType(TRICUBIC);
     406            0 :                         else if (type == "NEAREST_NEIGHBOUR")
     407              :                                 gp.setInterpolationType(NEAREST_NEIGHBOUR);
     408              :                         else 
     409              :                                 gp.setInterpolationType(TRILINEAR);
     410              : 
     411              :                         // create new grid
     412            1 :                         ref_ptr<Grid1f> grid = new Grid1f(gp);
     413            1 :                         fin.close();
     414              : 
     415              :                         // load data for grid
     416            2 :                         loadGridFromTxt(grid, filename, c); 
     417              : 
     418            1 :                         return grid;
     419            1 :                 }
     420              :         }
     421            0 :         throw std::runtime_error("could not find GridProperties in file " + filename);
     422            1 : }
     423              : 
     424            2 : void dumpGridToTxt(ref_ptr<Grid3f> grid, std::string filename, double c, bool saveProp) {
     425            2 :         std::ofstream fout(filename.c_str());
     426            2 :         if (!fout) {
     427            0 :                 std::stringstream ss;
     428            0 :                 ss << "dump Grid3f: " << filename << " not found";
     429            0 :                 throw std::runtime_error(ss.str());
     430            0 :         }
     431              : 
     432              :         // store the properties in the file as header information
     433            2 :         if (saveProp) {
     434              :                 fout << "# GridProperties: Type Grid3f" 
     435            1 :                         << "\t" << "origin: " << grid -> getOrigin()
     436              :                         << "\t" << "gridsize: " << grid -> getNx() << " " << grid -> getNy() << " " << grid -> getNz()
     437            2 :                         << "\t" << "spacing: " << grid -> getSpacing ()
     438              :                         << "\t" << "reflective: " << grid -> isReflective()
     439              :                         << "\t" << "clipVolume: " << grid -> getClipVolume()
     440            3 :                         << "\t" << "interpolation: " << grid -> getInterpolationTypeName() << "\n";
     441              :         }
     442              : 
     443            8 :         for (int ix = 0; ix < grid->getNx(); ix++) {
     444           21 :                 for (int iy = 0; iy < grid->getNy(); iy++) {
     445           66 :                         for (int iz = 0; iz < grid->getNz(); iz++) {
     446           51 :                                 Vector3f b = grid->get(ix, iy, iz) * c;
     447           51 :                                 fout << b << "\n";
     448              :                         }
     449              :                 }
     450              :         }
     451            2 :         fout.close();
     452            2 : }
     453              : 
     454            1 : void dumpGridToTxt(ref_ptr<Grid1f> grid, std::string filename, double c, bool saveProp) {
     455            1 :         std::ofstream fout(filename.c_str());
     456            1 :         if (!fout) {
     457            0 :                 std::stringstream ss;
     458            0 :                 ss << "dump Grid1f: " << filename << " not found";
     459            0 :                 throw std::runtime_error(ss.str());
     460            0 :         }
     461              : 
     462              :         // save properties as header information 
     463            1 :         if (saveProp) {
     464              :                 fout << "# GridProperties: Type Grid1f" 
     465            1 :                         << "\t" << "origin: " << grid -> getOrigin()
     466              :                         << "\t" << "gridsize: " << grid -> getNx() << " " << grid -> getNy() << " " << grid -> getNz()
     467            2 :                         << "\t" << "spacing: " << grid -> getSpacing ()
     468              :                         << "\t" << "reflective: " << grid -> isReflective()
     469              :                         << "\t" << "clipVolume: " << grid -> getClipVolume()
     470            3 :                         << "\t" << "interpolation: " << grid -> getInterpolationTypeName() << "\n";
     471              :         }
     472              : 
     473            4 :         for (int ix = 0; ix < grid->getNx(); ix++) {
     474            9 :                 for (int iy = 0; iy < grid->getNy(); iy++) {
     475           30 :                         for (int iz = 0; iz < grid->getNz(); iz++) {
     476           24 :                                 float b = grid->get(ix, iy, iz) * c;
     477           24 :                                 fout << b << "\n";
     478              :                         }
     479              :                 }
     480              :         }
     481            1 :         fout.close();
     482            1 : }
     483              : 
     484              : #ifdef CRPROPA_HAVE_FFTW3F
     485              : 
     486            0 : std::vector<std::pair<int, float>> gridPowerSpectrum(ref_ptr<Grid3f> grid) {
     487              : 
     488            0 :   double rms = rmsFieldStrength(grid);
     489              :   size_t n = grid->getNx(); // size of array
     490              : 
     491              :   // arrays to hold the complex vector components of the B(k)-field
     492              :   fftwf_complex *Bkx, *Bky, *Bkz;
     493            0 :   Bkx = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * n * n * n);
     494            0 :   Bky = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * n * n * n);
     495            0 :   Bkz = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * n * n * n);
     496              : 
     497              :   fftwf_complex *Bx = (fftwf_complex *)Bkx;
     498              :   fftwf_complex *By = (fftwf_complex *)Bky;
     499              :   fftwf_complex *Bz = (fftwf_complex *)Bkz;
     500              : 
     501              :   // save to temp
     502              :   int i;
     503            0 :   for (size_t ix = 0; ix < n; ix++) {
     504            0 :     for (size_t iy = 0; iy < n; iy++) {
     505            0 :       for (size_t iz = 0; iz < n; iz++) {
     506            0 :         i = ix * n * n + iy * n + iz;
     507              :         Vector3<float> &b = grid->get(ix, iy, iz);
     508            0 :         Bx[i][0] = b.x / rms;
     509            0 :         By[i][0] = b.y / rms;
     510            0 :         Bz[i][0] = b.z / rms;
     511              :       }
     512              :     }
     513              :   }
     514              : 
     515              :   // in-place, real to complex, inverse Fourier transformation on each component
     516              :   // note that the last elements of B(x) are unused now
     517              :   fftwf_plan plan_x =
     518            0 :       fftwf_plan_dft_3d(n, n, n, Bx, Bkx, FFTW_FORWARD, FFTW_ESTIMATE);
     519            0 :   fftwf_execute(plan_x);
     520            0 :   fftwf_destroy_plan(plan_x);
     521              : 
     522              :   fftwf_plan plan_y =
     523            0 :       fftwf_plan_dft_3d(n, n, n, By, Bky, FFTW_FORWARD, FFTW_ESTIMATE);
     524            0 :   fftwf_execute(plan_y);
     525            0 :   fftwf_destroy_plan(plan_y);
     526              : 
     527              :   fftwf_plan plan_z =
     528            0 :       fftwf_plan_dft_3d(n, n, n, Bz, Bkz, FFTW_FORWARD, FFTW_ESTIMATE);
     529            0 :   fftwf_execute(plan_z);
     530            0 :   fftwf_destroy_plan(plan_z);
     531              : 
     532              :   float power;
     533              :   std::map<size_t, std::pair<float, int>> spectrum;
     534              :   int k;
     535              : 
     536            0 :   for (size_t ix = 0; ix < n; ix++) {
     537            0 :     for (size_t iy = 0; iy < n; iy++) {
     538            0 :       for (size_t iz = 0; iz < n; iz++) {
     539            0 :         i = ix * n * n + iy * n + iz;
     540            0 :         k = static_cast<int>(
     541            0 :             std::floor(std::sqrt(ix * ix + iy * iy + iz * iz)));
     542            0 :         if (k > n / 2. || k == 0)
     543            0 :           continue;
     544            0 :         power = ((Bkx[i][0] * Bkx[i][0] + Bkx[i][1] * Bkx[i][1]) +
     545            0 :                  (Bky[i][0] * Bky[i][0] + Bky[i][1] * Bky[i][1]) +
     546            0 :                  (Bkz[i][0] * Bkz[i][0] + Bkz[i][1] * Bkz[i][1]));
     547            0 :         if (spectrum.find(k) == spectrum.end()) {
     548            0 :           spectrum[k].first = power;
     549            0 :           spectrum[k].second = 1;
     550              :         } else {
     551            0 :           spectrum[k].first += power;
     552            0 :           spectrum[k].second += 1;
     553              :         }
     554              :       }
     555              :     }
     556              :   }
     557              : 
     558            0 :   fftwf_free(Bkx);
     559            0 :   fftwf_free(Bky);
     560            0 :   fftwf_free(Bkz);
     561              : 
     562              :   std::vector<std::pair<int, float>> points;
     563            0 :   for (std::map<size_t, std::pair<float, int>>::iterator it = spectrum.begin();
     564            0 :        it != spectrum.end(); ++it) {
     565            0 :     points.push_back(
     566            0 :         std::make_pair(it->first, (it->second).first / (it->second).second));
     567              :   }
     568              : 
     569            0 :   return points;
     570            0 : }
     571              : 
     572              : #endif // CRPROPA_HAVE_FFTW3F
     573              : 
     574              : 
     575              : } // namespace crpropa
        

Generated by: LCOV version 2.0-1