diff --git a/src/bem_gigi.cpp b/src/bem_gigi.cpp index c0ae58f..4c683b5 100644 --- a/src/bem_gigi.cpp +++ b/src/bem_gigi.cpp @@ -1,478 +1,480 @@ /** * * @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 #include "surface.hh" #include "bem_gigi.hh" #include #include #include #include #include #include /* -------------------------------------------------------------------------- */ #define TIMER #include "surface_timer.hh" /* -------------------------------------------------------------------------- */ Real BemGigi::computeEquilibrium(Real epsilon, Real mean_displacement) { this->computeSpectralInfluenceOverDisplacement(); Real Rold = 1.; + Real Gold=1.; + Real f = 1e300; this->search_direction = 0.; this->true_displacements =0; this->true_displacements = mean_displacement; this->computeGaps(); this->optimizeToMeanDisplacement(mean_displacement); std::cout << "moyenne deplacement "<< SurfaceStatistics::computeAverage(this->true_displacements, 0)<< std::endl; convergence_iterations.clear(); nb_iterations = 0; UInt crit2=10; max_iterations =2000; while (f> epsilon && nb_iterations++ < max_iterations) { this->computeGaps(); this->functional->computeGradF(); Real R = this->functional->computeGradientNorm(); std::cout << "norme gradient "<< R << std::endl; this->updateSearchDirection(R / Rold); Rold = R; Real alpha = this->computeOptimalStep(); //alpha=0.001; std::cout << "alpha vaut "<< alpha<< std::endl; this->old_displacements=this->true_displacements; this->updateDisplacements(alpha); //std::cout << "moyenne deplacement "<< SurfaceStatistics::computeAverage(this->true_displacements, 0)<< std::endl; this->computeGaps(); this->optimizeToMeanDisplacement(mean_displacement); //espace admissible this->computeGaps(); this->computePressures(mean_displacement); //p=K-1*u Real G=this->computeG(); G=0.; // std::cout << "G vaut "<< G<< std::endl; UInt inner_loop_cpt=0; //Inner loop while(G > 0. && inner_loop_cpt < crit2 ) { ++inner_loop_cpt; this->computeGaps(); this->functional->computeGradF(); this->updateSearchDirection(R / Rold); Real tau = this->computeTau(); - Gold = G; + //Gold = G; this->updateDisplacementsB(tau); this->computeGaps(); this->optimizeToMeanDisplacement(mean_displacement); //espace admissible this->computePressures(mean_displacement); //p=K-1*u this->computeGaps(); G = this->computeG(); std::cout << "G vaut "<< G<< std::endl; } f = computeStoppingCriterion(); if (nb_iterations % dump_freq == 0) { std::cout << std::scientific << std::setprecision(10) << nb_iterations << " " << f << std::fixed << std::endl; } convergence_iterations.push_back(f); } this->computePressures(mean_displacement); return f; } /* -------------------------------------------------------------------------- */ Real BemGigi::computeStoppingCriterion() { Real crit=0.; Real disp_norm = 0.; UInt n = surface.size(); UInt size = n*n; #pragma omp parallel for reduction(+:crit, disp_norm) for (UInt i = 0; i < size; ++i) { crit += ( this->old_displacements(i) - true_displacements(i))*( this->old_displacements(i) - true_displacements(i)); disp_norm += (true_displacements(i)*true_displacements(i)); } return crit / disp_norm; } /* -------------------------------------------------------------------------- */ Real BemGigi::computeG(){ STARTTIMER("computeG"); unsigned int n = surface.size(); unsigned int size = n*n; Real res = 0.; #pragma omp parallel for reduction(+: res) for (unsigned int i = 0; i < size; ++i) { if (this->gap(i) > 0) { Real val = this->surface_tractions(i); res += val*val;} } STOPTIMER("computeG"); return res; } /* -------------------------------------------------------------------------- */ void BemGigi::optimizeToMeanDisplacement(Real imposed_mean) { Real target_value = imposed_mean - SurfaceStatistics::computeAverage(surface, 0); UInt n = surface.size(); UInt size = n * n; // Initial guesses for upper and lower bound Real step_min = -10; Real step_max = 10; // Gaps for upper and lower bound Real gap_min = positiveGapAverage(step_min); Real gap_max = positiveGapAverage(step_max); UInt max_expansion = 8; // Expand bounds if necessary for (UInt i = 0 ; gap_max < target_value && i < max_expansion ; i++, step_max *= 10) gap_max = positiveGapAverage(step_max); for (UInt i = 0 ; gap_min > target_value && i < max_expansion ; i++, step_min *= 10) gap_min = positiveGapAverage(step_min); Real g = 0.; Real epsilon = 1e-12; Real step = 0; while (fabs(g - target_value) > epsilon) { step = (step_min + step_max) / 2.; g = positiveGapAverage(step); if (g > target_value) step_max = step; else if (g < target_value) step_min = step; else { step_max = step; step_min = step; } } step = (step_min + step_max) / 2.; #pragma omp parallel for for (UInt i = 0 ; i < size ; i++) { gap(i) += step; if (gap(i) < 0) gap(i) = 0; true_displacements(i) = gap(i) + surface(i); } } /* -------------------------------------------------------------------------- */ Real BemGigi::positiveGapAverage(Real shift) { UInt n = surface.size(); Real res = 0; #pragma omp parallel for reduction(+: res) for (UInt i = 0 ; i < n * n ; i++) { Real shifted_gap = gap(i) + shift; res += shifted_gap * (shifted_gap > 0); } return res / (n * n); } /* -------------------------------------------------------------------------- */ void BemGigi::updateSearchDirection(Real factor) { STARTTIMER("updateSearchDirection"); UInt n = surface.size(); UInt size = n*n; Surface & gradF = this->functional->getGradF(); #pragma omp parallel for for (UInt i = 0; i < size; ++i) { this->search_direction(i)= gradF(i); } STOPTIMER("updateSearchDirection"); } /* -------------------------------------------------------------------------- */ Real BemGigi::computeOptimalStep() { STARTTIMER("computeOptimalStep"); search_direction.FFTTransform(spectral_search_direction, nthreads); UInt n = surface.size(); UInt size = n*n; spectral_search_direction(0) = 0; #pragma omp parallel for for (UInt i = 1; i < size; ++i) { spectral_search_direction(i) /= this->surface_spectral_influence_disp(i); } // /!\ does not contain the spectral search direction anymore spectral_search_direction.FFTITransform(nthreads); // Real average = SurfaceStatistics::computeAverage(spectral_search_direction.real(), 0); // spectral_search_direction -= average; Surface & gradF = this->functional->getGradF(); Real numerator = 0., denominator = 0.; #pragma omp parallel for reduction(+: numerator, denominator) for (UInt i = 0; i < size; ++i) { numerator += gradF(i) * search_direction(i); denominator += spectral_search_direction(i).real() * search_direction(i); } Real alpha = numerator / denominator; STOPTIMER("computeOptimalStep"); return alpha; } /* -------------------------------------------------------------------------- */ Real BemGigi::computeTau() { STARTTIMER("computeOptimalStep"); search_direction.FFTTransform(spectral_search_direction, nthreads); UInt n = surface.size(); UInt size = n*n; spectral_search_direction(0) = 0; #pragma omp parallel for for (UInt i = 1; i < size; ++i) { spectral_search_direction(i) /= this->surface_spectral_influence_disp(i); } // /!\ does not contain the spectral search direction anymore spectral_search_direction.FFTITransform(nthreads); // Real average = SurfaceStatistics::computeAverage(spectral_search_direction.real(), 0); // spectral_search_direction -= average; Surface & gradF = this->functional->getGradF(); Real numerator = 0., denominator = 0.; #pragma omp parallel for reduction(+: numerator, denominator) for (UInt i = 0; i < size; ++i) { if (this->gap(i) > 0) { numerator += gradF(i) * search_direction(i); denominator += spectral_search_direction(i).real() * search_direction(i);} } Real tau = numerator / denominator; STOPTIMER("computeOptimalStep"); return tau; } /* -------------------------------------------------------------------------- */ void BemGigi::updateDisplacements(Real alpha) { STARTTIMER("updateDisplacements"); UInt n = surface.size(); UInt size = n*n; #pragma omp parallel for for (UInt i = 0; i < size; ++i) { this->true_displacements(i) -= alpha*this->search_direction(i); } STOPTIMER("updateDisplacements"); } /* -------------------------------------------------------------------------- */ void BemGigi::updateDisplacementsB(Real alpha) { STARTTIMER("updateDisplacements"); UInt n = surface.size(); UInt size = n*n; #pragma omp parallel for for (UInt i = 0; i < size; ++i) { if (this->gap(i)>0){ this->true_displacements(i) -= alpha*this->search_direction(i); } } STOPTIMER("updateDisplacements"); } /* -------------------------------------------------------------------------- */ void BemGigi::emptyOverlap() { STARTTIMER("emptyoverlap"); UInt n = surface.size(); UInt size = n*n; #pragma omp parallel for for (UInt i = 0; i < size; ++i) { if (gap(i) < 0) this->true_displacements(i) = this->surface(i); } STOPTIMER("emptyoverlap"); } /* -------------------------------------------------------------------------- */ void BemGigi::enforceMeanDisplacement(Real mean_displacement) { STARTTIMER("enforceMeanDisplacement"); UInt n = surface.size(); UInt size = n*n; Real average = SurfaceStatistics::computeAverage(this->true_displacements, 0); Real factor = mean_displacement / average; #pragma omp parallel for for (UInt i = 0; i < size; ++i) { this->true_displacements(i) *= factor; } STOPTIMER("enforceMeanDisplacement"); } /* -------------------------------------------------------------------------- */ void BemGigi::computePressures(Real mean_displacement) { UInt n = surface.size(); UInt size = n*n; Real moy_surface=SurfaceStatistics::computeAverage(this->surface, 0); this->true_displacements.FFTTransform(this->surface_spectral_tractions, nthreads); this->surface_spectral_tractions(0) = 0; #pragma omp parallel for for (UInt i = 1 ; i < size ; ++i) { this->surface_spectral_tractions(i) /= this->surface_spectral_influence_disp(i); } this->surface_spectral_tractions.FFTITransform(this->surface_tractions, nthreads); Real true_pressure = 0.; for (UInt i = 0 ; i < n * n ; i++) { true_pressure+=this->surface_tractions(i)*(this->true_displacements(i)-mean_displacement-this->surface(i))-0.002/2.071e-3 * exp(- gap(i) / 2.071e-3)*gap(i); // true_pressure+=this->surface_tractions(i)*(this->true_displacements(i)-mean_displacement-this->surface(i)); } true_pressure/=(moy_surface*size-mean_displacement*size); // std::cout << "true_pressure "<< true_pressure << std::endl; // this->surface_tractions += true_pressure; } /* -------------------------------------------------------------------------- */ void BemGigi::computeTruePressures(Real mean_displacement) { this->computeGaps(); this->functional->computeGradF(); UInt n = gap.size(); //Orthogonalite for (UInt i = 0 ; i < n * n ; i++) { if (this->gap(i) > 0){ this->surface_tractions(i)=0; } } } diff --git a/src/bem_penalty.hh b/src/bem_penalty.hh index b82e396..e1bf7a9 100644 --- a/src/bem_penalty.hh +++ b/src/bem_penalty.hh @@ -1,95 +1,95 @@ /** * * @author Valentine Rey * * @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 BEM_PENALTY_H #define BEM_PENALTY_H /* -------------------------------------------------------------------------- */ #include "bem_fft_base.hh" /* -------------------------------------------------------------------------- */ class BemPenalty : public BemFFTBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: BemPenalty(Surface & p) : BemFFTBase(p), + search_direction(p.size(), p.getL()), + spectral_search_direction(p.size(), p.getL()), surface_t(p.size(),p.getL()), surface_r(p.size(),p.getL()), surface_spectral_r(p.size(),p.getL()), - search_direction(p.size(), p.getL()), - spectral_search_direction(p.size(), p.getL()), mean_disp_search_direction(p.size(), p.getL()) { e_star = 1.; max_iterations = 10000; }; virtual ~BemPenalty(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: //! compute the equilibrium situation Real computeEquilibrium(Real epsilon,Real pressure,Real penalization_parameter); void computeSearchDirection(Real mean_displacement,Real penalization_parameter); void updateUnknown(Real tau, Real mean_displacement); Real computeStoppingCriterion(); void computePressures(Real mean_displacement); Real computeOptimalStep(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: //! get the number of iterations UInt getNbIterations() const{return this->nb_iterations;}; //! get the convergence steps of iterations const std::vector & getConvergenceIterations() const{return this->convergence_iterations;}; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: //! exploration direction for the Gigi algo Surface search_direction; //! projected exploration direction for the Gigi algo (fourier version) SurfaceComplex spectral_search_direction; //! exploration direction for the polonski algo Surface surface_t; //! projected exploration direction for the polonski algo Surface surface_r; //! projected exploration direction for the polonski algo (fourier version) SurfaceComplex surface_spectral_r; //! exploration direction for optimization of mean displacement Surface mean_disp_search_direction; }; #endif /* BEM_PENALTY_H */ diff --git a/src/surface.cpp b/src/surface.cpp index d715713..2a99b2f 100644 --- a/src/surface.cpp +++ b/src/surface.cpp @@ -1,449 +1,448 @@ /** * * @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 #include #include #include #include #include /* -------------------------------------------------------------------------- */ #include "surface.hh" #include "surface_statistics.hh" /* -------------------------------------------------------------------------- */ #ifdef USING_IOHELPER #include "dumper_paraview.hh" #endif /* -------------------------------------------------------------------------- */ std::string fname = "surface_height.pdf"; /* -------------------------------------------------------------------------- */ template void Surface::expandByLinearInterpolation() { UInt n = this->size(); Surface * old_s = new Surface(n,1.); int new_n = n*2; *old_s = *this; this->setGridSize(new_n); for (UInt i=0; i void Surface::expandByShannonInterpolation(int factor) { this->FFTTransform(); UInt n = this->size(); UInt N = std::pow(2,factor)*this->size(); std::cout << N << " " << factor << std::endl; Surface s = Surface(N,1.); for (UInt i = 0; i < n/2; ++i) for (UInt j = 0; j < n/2; ++j) { s(i,j) = this->at(i,j); } for (UInt i = n/2; i < n; ++i) for (UInt j = 0; j < n/2; ++j) { s(N-n+i,j) = this->at(i,j); } for (UInt i = n/2; i < n; ++i) for (UInt j = n/2; j < n; ++j) { s(N-n+i,N-n+j) = this->at(i,j); } for (UInt i = 0; i < n/2; ++i) for (UInt j = n/2; j < n; ++j) { s(i,N-n+j) = this->at(i,j); } // s.dumpToTextFile("temp.csv"); s.FFTITransform(); this->setGridSize(N); Real f = std::pow(2,factor); f = f*f; for (UInt i = 0; i < N*N; ++i) this->at(i) = f*s(i); // int new_n = 2*n; // Surface s(*this); // this->setGridSize(new_n); // // put the original signal with zeros for to be interpolated points // for (int i=0; iat(2*i,j*2) = s(i,j); // // do shannon interpolation // int rcut = 64; // //interpolate lines // for (int i=0; i= new_n) i2 -= new_n; // if (i2%2) continue; // Real d = fabs(k); // s[i+j*new_n] += s(i2,j)*sinc(d/2); // } // } // } // //interpolate columns // for (int i=0; i= new_n) j2 -= new_n; // if (j2%2) continue; // Real d = fabs(k); // s[i+j*new_n] += complex(s[i+j2*new_n].real()*sinc(d/2), // s[i+j2*new_n].imag()*sinc(d/2)); // } // } // } // // for (int i=0; i void Surface::expandByMirroring() { UInt n = this->size(); UInt new_n = n*2; Surface s(*this); this->setGridSize(new_n); for (UInt i=0; i n) i1 = new_n - i1; UInt j1 = j; if (j1 > n) j1 = new_n - j1; if (i == n || j == n) { this->at(i,j) = 0.; continue; } this->at(i,j) = s(i1,j1); } } } /* -------------------------------------------------------------------------- */ template void Surface::expandByPuttingZeros() { UInt n = this->size(); UInt new_n = n*2; Surface s(*this); this->setGridSize(new_n); for (UInt i=0; i< n; i++) { for (UInt j=0; j< n; j++) { this->at(2*i,j*2) = s(i,j); } } } /* -------------------------------------------------------------------------- */ template void Surface::contractByTakingSubRegion() { UInt n = this->size(); Surface s(*this); this->setGridSize(n/2); for (UInt i=0; i < n/2; i++) { for (UInt j=0; j < n/2; j++) { this->at(i,j) = s(i,j); } } } /* -------------------------------------------------------------------------- */ template void Surface::contractByIgnoringMidPoints() { UInt n = this->size(); Surface s(*this); this->setGridSize(n/2); for (UInt i=0; iat(i/2,j/2) = s(i,j); } } } /* -------------------------------------------------------------------------- */ // void Surface::dumpToTextFile(string filename, bool pr) { // cout << "Writing surface file " << filename << endl; // ofstream file(filename.c_str()); // file.precision(15); // if (pr) // { // for (int i=0; i::loadFromTextFile(std::string filename) { // std::string line; // std::ifstream myfile (filename.c_str()); // if (!myfile.is_open()){ // SURFACE_FATAL("cannot open file " << filename); // } // Surface * my_surface = NULL; // UInt n = 0; // if (myfile.is_open()) // { // while (! myfile.eof() ) // { // getline (myfile,line); // if (line[0] == '#') // continue; // if (line.size() == 0) // continue; // std::stringstream s; // s << line; // int i,j; // s >> i; // s >> j; // if (n < i) n = i; // if (n < j) n = j; // } // ++n; // std::cout << "read " << n << " x " << n << " grid points" << std::endl; // myfile.clear(); // forget we hit the end of file // myfile.seekg(0, std::ios::beg); // move to the start of the file // my_surface = new Surface(n); // while (! myfile.eof() ) // { // getline (myfile,line); // if (line[0] == '#') // continue; // if (line.size() == 0) // continue; // std::stringstream s; // s << line; // int i,j; // Real h,hIm; // s >> i; // s >> j; // s >> h; // s >> hIm; // my_surface->heights[i+j*n] = complex(h,hIm); // } // myfile.close(); // } // return my_surface; // } /* -------------------------------------------------------------------------- */ template void Surface::dumpToParaview(std::string filename) const { #ifdef USING_IOHELPER UInt n = this->size(); const Surface & data = *this; /* build 3D coordinates array to be usable with iohelper */ // cerr << "allocate coords for paraview" << endl; Real * coords = new Real[n*n*3]; //Real * coords = new Real[(2*n-1)*(2*n-1)*3]; //cerr << "allocate zcoords for paraview" << endl; Real * zcoords = new Real[n*n*3]; //Real * zcoords = new Real[(2*n-1)*(2*n-1)*3]; //cerr << "allocate zcoords2 for paraview" << endl; Real * zcoords2 = new Real[n*n*3]; // Real * zcoords2 = new Real[(2*n-1)*(2*n-1)*3]; int index = 0; // for (int i=-n+1; i Surface::Surface(UInt a, Real L) : Map2dSquare(a,L){ this->setGridSize(a); } /* -------------------------------------------------------------------------- */ template Surface::~Surface(){ } /* -------------------------------------------------------------------------- */ // void Surface::copy(Surface & s){ // this->n = s.n; // this->L = s.L; // this->heights = s.heights; // } /* -------------------------------------------------------------------------- */ template void Surface::recenterHeights(){ UInt n = this->size(); Real zmean = SurfaceStatistics::computeAverage(*this); for (UInt i = 0 ; i < n*n ; ++i) this->at(i) = this->at(i) - zmean; } /* -------------------------------------------------------------------------- */ template void Surface::generateWhiteNoiseSurface(Surface & sources, long random_seed){ //set the random gaussian generator std::mt19937 gen(random_seed); std::normal_distribution<> gaussian_generator; Surface * origins; origins = new Surface(1024,1.); UInt n = sources.size(); for (UInt i = 0 ; i < 1024 ; ++i) for (UInt j = 0 ; j < 1024 ; ++j){ origins->at(i,j) = gaussian_generator(gen); } for (UInt i = 0 ; i < n ; ++i) for (UInt j = 0 ; j < n ; ++j){ sources(i,j) = origins->at(i*1024/n,j*1024/n); } delete origins; - std::cout << "\t>> coucou from white noise" << std::endl; } /* -------------------------------------------------------------------------- */ template class Surface; template class Surface; template class Surface; template class Surface; template class Surface;