diff --git a/src/map_2d.cpp b/src/map_2d.cpp index 13a280c..2650acb 100644 --- a/src/map_2d.cpp +++ b/src/map_2d.cpp @@ -1,248 +1,246 @@ /** * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "map_2d.hh" #include #include #include #include /* -------------------------------------------------------------------------- */ #define TIMER #include "surface_timer.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ template void Map2d::rescaleHeights(Real C){ /* compute actual RMS */ for (UInt i = 0 ; i < n[0] ; ++i) for (UInt j = 0 ; j < n[1] ; ++j){ this->at(i,j) *= C; } } /* -------------------------------------------------------------------------- */ template void Map2d::setGridSize(UInt n0, UInt n1){ n[0] = n0; n[1] = n1; data.resize(n[0]*n[1]); data.assign(n[0]*n[1],T(0.)); } /* -------------------------------------------------------------------------- */ template void Map2d::setGridSize(const UInt n[2]){ setGridSize(n[0],n[1]); } /* -------------------------------------------------------------------------- */ template void Map2d::operator=(const T & e){ for (UInt i = 0 ; i < n[0]*n[1] ; ++i){ this->at(i) = e; } } /* -------------------------------------------------------------------------- */ template Map2d::Map2d(UInt n0, UInt n1, Real L0, Real L1) { setGridSize(n0,n1); this->L[0] = L0; this->L[1] = L1; this->plan = NULL; generateFFTPlan(); } /* -------------------------------------------------------------------------- */ template Map2d::Map2d(const UInt * n, const Real *L) { setGridSize(n[0],n[1]); this->L[0] = L[0]; this->L[1] = L[1]; this->plan = NULL; generateFFTPlan(); } /* -------------------------------------------------------------------------- */ template Map2d::~Map2d() { destroyFFTPlan(); } /* -------------------------------------------------------------------------- */ template void Map2d::generateFFTPlan() { // this should not do anything } /* -------------------------------------------------------------------------- */ template <> void Map2d::generateFFTPlan() { fftw_complex * in = (fftw_complex*) &data[0]; this->plan = fftw_plan_dft_2d(n[0], n[1], in, in, FFTW_FORWARD, FFTW_ESTIMATE); } /* -------------------------------------------------------------------------- */ template void Map2d::destroyFFTPlan() { if (this->plan) { fftw_destroy_plan(this->plan); this->plan = NULL; } } /* -------------------------------------------------------------------------- */ template void Map2d::FFTTransform(int nthreads){ SURFACE_FATAL("impossible situation"); throw; } /* -------------------------------------------------------------------------- */ template void Map2d::FFTTransform(Map2d > & output, int nthreads)const{ output = *this; output.FFTTransform(nthreads); } /* -------------------------------------------------------------------------- */ template void Map2d::FFTITransform(Map2d > & output, int nthreads)const{ output = *this; output.FFTITransform(nthreads); } /* -------------------------------------------------------------------------- */ template void Map2d::FFTITransform(Map2d & output, int nthreads) const{ const UInt * n = this->sizes(); const Real * Ls = this->getLs(); Map2d > _output(n,Ls); - // _output = *static_cast< >(this); - const Map2d & tmp = *this; - _output.copy(tmp); + _output = *this; _output.FFTITransform(nthreads); for (UInt i = 0; i < n[0]*n[1]; i++) { output(i) = _output(i).real(); } } /* -------------------------------------------------------------------------- */ template <> void Map2d::FFTTransform(int nthreads){ STARTTIMER("FFTW"); fftw_execute(this->plan); STOPTIMER("FFTW"); } /* -------------------------------------------------------------------------- */ template void Map2d::FFTITransform(int nthreads){ SURFACE_FATAL("impossible situation"); throw; } /* -------------------------------------------------------------------------- */ template <> void Map2d::FFTITransform(int nthreads){ #pragma omp parallel for for (UInt i = 0; i < n[0]*n[1]; ++i) { data[i] = std::conj(data[i]); } FFTTransform(nthreads); #pragma omp parallel for for (UInt i = 0; i < n[0]*n[1]; ++i) { data[i] = std::conj(data[i]); data[i] *= 1./(n[0]*n[1]); } } /* -------------------------------------------------------------------------- */ template void Map2d::dumpToTextFile(std::string filename) { UInt n1 = this->size(0); UInt n2 = this->size(1); std::cout << "Writing surface file " << filename << std::endl; std::ofstream file(filename.c_str()); if (!file.is_open()) SURFACE_FATAL("cannot open file " << filename); file.precision(15); for (UInt i = 0; i < n1; i++) { for (UInt j=0; j< n2; j++) { file << i << " " << j << " "; this->writeValue(file,this->at(i,j)); file << std::endl; } file << std::endl; } file.close(); } /* -------------------------------------------------------------------------- */ template void Map2d::writeValue(std::ostream & os, const T & val) { os << val; } /* -------------------------------------------------------------------------- */ template <> void Map2d::writeValue(std::ostream & os, const complex & val) { os << std::scientific << val.real(); os << " " << val.imag(); } /* -------------------------------------------------------------------------- */ template class Map2d; template class Map2d; template class Map2d; template class Map2d; template class Map2d; template class Map2d; __END_TAMAAS__ diff --git a/src/map_2d.hh b/src/map_2d.hh index 93ed787..6dd4270 100644 --- a/src/map_2d.hh +++ b/src/map_2d.hh @@ -1,577 +1,591 @@ /** * * @author Guillaume Anciaux * * @section LICENSE * * Copyright (©) 2016 EPFL (Ecole Polytechnique Fédérale de * Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des * Solides) * * Tamaas is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Tamaas. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __MAP_2D_HH__ #define __MAP_2D_HH__ /* -------------------------------------------------------------------------- */ #include #include #include #include "tamaas.hh" #include #include "my_vector.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ template class Map2d { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ // class iterator; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Map2d(UInt n1, UInt n2, Real L0 = 1., Real L1 = 1.); Map2d(const UInt * n, const Real * L); virtual ~Map2d(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: template std::vector > getNeighborIndexes(UInt i, UInt j); template std::vector > getNeighborIndexes(std::pair i); // //! return an iterator over the neighbors // iterator beginNeighborhood(); // //! return the end iterator over the neighbors // iterator endNeighborhood(); //! generate fft plan void generateFFTPlan(); //! destroy fft plan void destroyFFTPlan(); //! perform fft transform void FFTTransform(Map2d > & output,int nthreads = 1) const; //! perform inverse fft transform void FFTITransform(Map2d > & output, int nthreads = 1) const; //! perform inverse fft transform void FFTITransform(Map2d & output, int nthreads = 1) const; //! perform fft transform void FFTTransform(int nthreads = 1); // //! inverse fft transform void FFTITransform(int nthreads = 1); //compute compute component by component product and put result in object template void fullProduct(Map2d & s1,Map2d &s2); //! set the grid size void setGridSize(const UInt n[2]); //! set the grid size void setGridSize(UInt n0,UInt n1); //! rescale height profile void rescaleHeights(Real factor); //! Write heights array to text file usable with plot programs void dumpToTextFile(std::string filename); //! copy method template class surf, typename T2> void copy(const surf & s); // set all the members of the map to a given value void operator=(const T & e); // multiply the map by scalar template void operator*=(const T2 & e); // divide the map by scalar template void operator/=(const T2 & e); // multiply the map by scalar void operator*=(const T & e); // divide the map by scalar void operator/=(const T & e); // multiply the map with another map, component by component template class surf, typename T2> void operator*=(const surf & e); // divide the map with another map, component by component template class surf, typename T2> void operator/=(const surf & e); // copy the map passed as parameter template class surf, typename T2> void operator=(const surf & s); + // temporary hack + void operator=(const Map2d & s); + // copy the map passed as const parameter template class surf, typename T2> void operator=(surf & s); /* -------------------------------------------------------------------------- */ private: //! write an entry to a stringstream void writeValue(std::ostream & os, const T & val); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: // access to the i,j-th value in the surface inline void operator+=(const Map2d & s); // access to the i,j-th value in the surface inline void operator+=(const T & val); // access to the i,j-th value in the surface inline void operator-=(const T & val); // access to the i,j-th value in the surface inline T & operator()(UInt i,UInt j); // access to the i,j-th value in the surface inline T & operator()(std::pair i); // access to the i,j-th value in the surface inline const T & operator()(UInt i,UInt j)const; // access to the i,j-th value in the surface inline const T & operator()(std::pair i)const; // access to the i,j-th value in the surface inline T & at(UInt i,UInt j); // access to the i-th value in the array inline T & at(UInt i); // access to the i,j-th value in the surface inline T & at(std::pair i); // access to the i,j-th value in the surface inline const T & at(UInt i,UInt j) const; // access to the i,j-th value in the surface inline const T & at(std::pair i) const; // access to the i,j-th value in the surface inline const T & at(UInt i) const; // access to the i-th value in the array inline T & operator()(int i); // access to the i-th value in the array // inline T & operator[](std::pair i); // access to the i-th value in the array inline const T & operator()(int i) const; //! get lateral number of discretization points inline UInt size(UInt dir)const {return n[dir];}; //! get both lateral number of discretization points inline const UInt* sizes()const {return n;}; //! get the lateral size of the sample inline const Real * getLs() const {return L;}; //! get the lateral size of the sample inline Real getL(UInt dir) const {return L[dir];}; //! get the lateral size of the sample inline void setL(Real L[2]){this->L[0] = L[0];this->L[1] = L[1];}; //! get the lateral size of the sample inline void setL(Real L0,Real L1){this->L[0] = L0;this->L[1] = L1;}; const T * getInternalData() const{return data.getPtr();}; //! Write heights array to text file usable with plot programs template void dumpToTextFile(std::string filename) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: //! number of points in each direction UInt n[2]; //! size in each direction Real L[2]; //! internal storage of data MyVector data; //! fftw plan fftw_plan plan; }; /* -------------------------------------------------------------------------- */ //#define _at(I,J,N) I+J*N[1] #define _at(I,J,N) I*N[1]+J /* -------------------------------------------------------------------------- */ template inline T & Map2d::at(UInt i,UInt j){ if (_at(i,j,n) >= n[0]*n[1]) SURFACE_FATAL("out of bound access " << i << " " << j << " " << n[0] << " " << n[1] << " " << _at(i,j,n)); return data[_at(i,j,n)]; } /* -------------------------------------------------------------------------- */ template inline const T & Map2d::at(UInt i,UInt j)const { if (_at(i,j,n) >= n[0]*n[1]) SURFACE_FATAL("out of bound access " << i << " " << j << " " << n[0] << " " << n[1] << " " << _at(i,j,n)); return data[_at(i,j,n)]; } /* -------------------------------------------------------------------------- */ #undef _at /* -------------------------------------------------------------------------- */ template inline T & Map2d::at(UInt i){ return data[i]; } /* -------------------------------------------------------------------------- */ template inline const T & Map2d::at(UInt i) const{ return data[i]; } /* -------------------------------------------------------------------------- */ template inline T & Map2d::operator()(UInt i,UInt j){ return this->at(i,j); } /* -------------------------------------------------------------------------- */ template inline T & Map2d::at(std::pair i){ return this->at(i.first,i.second); } /* -------------------------------------------------------------------------- */ template inline const T & Map2d::at(std::pair i)const { return this->at(i.first,i.second); } /* -------------------------------------------------------------------------- */ template inline T & Map2d::operator()(std::pair i){ return this->at(i.first,i.second); } /* -------------------------------------------------------------------------- */ template inline const T & Map2d::operator()(UInt i,UInt j)const{ return this->at(i,j); } /* -------------------------------------------------------------------------- */ template inline const T & Map2d::operator()(std::pair i)const { return this->at(i.first,i.second); } /* -------------------------------------------------------------------------- */ template inline T & Map2d::operator()(int i){ return data[i]; } /* -------------------------------------------------------------------------- */ template inline const T & Map2d::operator()(int i) const{ return data[i]; } /* -------------------------------------------------------------------------- */ // template // inline T & Map2d::operator[](std::pair c){ // return this->at(c.first,c.second); // } // /* -------------------------------------------------------------------------- */ template void Map2d::operator-=(const T & e){ for (UInt i = 0 ; i < n[0]*n[1] ; ++i){ this->at(i) -= e; } } /* -------------------------------------------------------------------------- */ template void Map2d::operator+=(const T & e){ for (UInt i = 0 ; i < n[0]*n[1] ; ++i){ this->at(i) += e; } } /* -------------------------------------------------------------------------- */ template void Map2d::operator+=(const Map2d & s){ for (UInt i = 0 ; i < n[0]*n[1] ; ++i){ this->at(i) += s.at(i); } } /* -------------------------------------------------------------------------- */ template template std::vector > Map2d::getNeighborIndexes(UInt i, UInt j){ std::vector > vres; std::pair res; for (int ii = -1; ii < 2; ++ii) { res.first = ii+static_cast(i); if (res.first < 0 && !periodic) continue; if (res.first >= (int)n[0] && !periodic) continue; if (res.first < 0 && periodic) res.first += n[0]; if (res.first >= (int)n[0] && periodic) res.first -= n[0]; for (int jj = -1; jj < 2; ++jj) { res.second = jj+static_cast(j); if (res.second < 0 && !periodic) continue; if (res.second >= (int)n[1] && !periodic) continue; if (res.second < 0 && periodic) res.second += n[1]; if (res.second >= (int)n[1] && periodic) res.second -= n[1]; if (ii == 0 && jj == 0) continue; { UInt i = res.first; UInt j = res.second; if (i+j*n[0] >= n[0]*n[1]) SURFACE_FATAL("out of bound access " << i << " " << j << " " << n[0] << " " << n[1] << " " << i+j*n[0]); } vres.push_back(res); } } return vres; } /* -------------------------------------------------------------------------- */ template template std::vector > Map2d ::getNeighborIndexes(std::pair i){ return this->getNeighborIndexes(i.first,i.second); } /* -------------------------------------------------------------------------- */ template template void Map2d::fullProduct(Map2d & s1,Map2d & s2){ auto n1 = s1.sizes(); auto n2 = s2.sizes(); if (n1[0] != n2[0] || n1[1] != n2[1]) SURFACE_FATAL("fullproduct of non compatible matrices"); if (n[0] != n1[0] || n[1] != n1[1]) SURFACE_FATAL("fullproduct of non compatible matrices") for (UInt i = 0 ; i < n[0] ; ++i) for (UInt j = 0 ; j < n[1] ; ++j){ this->at(i,j) = s1(i,j)* s2(i,j); } } /* -------------------------------------------------------------------------- */ template template void Map2d::dumpToTextFile(std::string filename) const { UInt m = this->n[0]; UInt n = this->n[1]; std::cout << "Writing surface file " << filename << std::endl; std::ofstream file(filename.c_str()); if (!file.is_open()) SURFACE_FATAL("cannot open file " << filename); file.precision(15); for (UInt i = 0; i < m; i++) { for (UInt j=0; j< n; j++) { if (!consider_zeros && std::norm(this->at(i,j)) < zero_threshold*zero_threshold) continue; file << i << " " << j << " "; file << std::scientific << this->at(i,j); file << std::endl; } file << std::endl; } file.close(); } // template // class Map2d::iterator { // public: // iterator(std::vector & data, // std::queue > & indices): // data(data),indices(indices){ // } // inline void operator++(){ // indices.pop(); // } // inline T & operator *(){ // return data[indices.front]; // } // bool operator != (Map2d::iterator & it){ // return (indices.front == it.indices.front); // } // private: // std::vector & data; // std::queue > indices; // bool finished; // }; /* -------------------------------------------------------------------------- */ template template class surf, typename T2> void Map2d::copy(const surf & s){ this->setGridSize(s.sizes()); UInt m = this->sizes()[0]; UInt n = this->sizes()[1]; #pragma omp parallel for for (UInt i = 0; i < m*n; i++) { this->at(i) = s(i); } } /* -------------------------------------------------------------------------- */ template template class surf, typename T2> void Map2d::operator=(surf & s){ this->copy(s); } /* -------------------------------------------------------------------------- */ template template class surf, typename T2> void Map2d::operator=(const surf & s){ this->copy(s); } +/* -------------------------------------------------------------------------- */ + +template +void Map2d::operator=(const Map2d & s){ + SURFACE_FATAL("Cannot copy a complex surface into incompatible type"); +} +template <> +inline void Map2d::operator=(const Map2d & s){ + this->copy(s); +} + /* -------------------------------------------------------------------------- */ template template void Map2d::operator*=(const T2 & e){ UInt sz = this->n[0]*this->n[1]; #pragma omp parallel for for (unsigned int i = 0; i < sz; ++i) { this->at(i) *= e; } } /* -------------------------------------------------------------------------- */ template template void Map2d::operator/=(const T2 & e){ UInt sz = this->n[0]*this->n[1]; #pragma omp parallel for for (unsigned int i = 0; i < sz; ++i) { this->at(i) /= e; } } /* -------------------------------------------------------------------------- */ template void Map2d::operator*=(const T & e){ UInt sz = this->n[0]*this->n[1]; #pragma omp parallel for for (unsigned int i = 0; i < sz; ++i) { this->at(i) *= e; } } /* -------------------------------------------------------------------------- */ template void Map2d::operator/=(const T & e){ UInt sz = this->n[0]*this->n[1]; #pragma omp parallel for for (unsigned int i = 0; i < sz; ++i) { this->at(i) /= e; } } /* -------------------------------------------------------------------------- */ template template class surf, typename T2> void Map2d::operator*=(const surf & e){ UInt sz = this->n[0]*this->n[1]; #pragma omp parallel for for (unsigned int i = 0; i < sz; ++i) { this->at(i) *= e.at(i); } } /* -------------------------------------------------------------------------- */ template template class surf, typename T2> void Map2d::operator/=(const surf & e){ UInt sz = this->n[0]*this->n[1]; #pragma omp parallel for for (unsigned int i = 0; i < sz; ++i) { this->at(i) /= e.at(i); } } /* -------------------------------------------------------------------------- */ __END_TAMAAS__ #endif /* __MAP_2D_HH__ */