diff --git a/python/wrap/solvers.cpp b/python/wrap/solvers.cpp index 8f362f5..edc1cab 100644 --- a/python/wrap/solvers.cpp +++ b/python/wrap/solvers.cpp @@ -1,119 +1,120 @@ /** * @file * * @author Lucas Frérot * * @section LICENSE * * Copyright (©) 2017 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 "wrap.hh" #include "contact_solver.hh" #include "polonsky_keer_rey.hh" #include "kato.hh" #include "beck_teboulle.hh" #include "condat.hh" #include "polonsky_keer_tan.hh" #include "epic.hh" #include "ep_solver.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ namespace wrap { /* -------------------------------------------------------------------------- */ using namespace py::literals; class PyEPSolver : public EPSolver { public: using EPSolver::EPSolver; void solve() override { PYBIND11_OVERLOAD_PURE(void, EPSolver, solve); } }; /* -------------------------------------------------------------------------- */ void wrapSolvers(py::module& mod) { py::class_(mod, "ContactSolver") // .def(py::init&, Real>(), "model"_a, // "surface"_a, "tolerance"_a) .def("setMaxIterations", &ContactSolver::setMaxIterations, "max_iter"_a) .def("setDumpFrequency", &ContactSolver::setDumpFrequency, "dump_freq"_a) .def("addFunctionalTerm", &ContactSolver::addFunctionalTerm); py::class_ pkr(mod, "PolonskyKeerRey"); pkr.def(py::init&, Real, PolonskyKeerRey::type, PolonskyKeerRey::type>(), "model"_a, "surface"_a, "tolerance"_a, "primal_type"_a, "constraint_type"_a, py::keep_alive<1, 2>(), py::keep_alive<1, 3>()) .def("solve", &PolonskyKeerRey::solve, "target"_a) .def("computeError", &PolonskyKeerRey::computeError); py::enum_(pkr, "type") .value("gap", PolonskyKeerRey::gap) .value("pressure", PolonskyKeerRey::pressure) .export_values(); py::class_ kato(mod, "Kato"); kato.def(py::init&, Real, Real>(), "model"_a, "surface"_a, "tolerance"_a, "mu"_a, py::keep_alive<1, 2>(), py::keep_alive<1, 3>()) .def("solve", &Kato::solve, "p0"_a, "proj_iter"_a=50) .def("solveRelaxed", &Kato::solveRelaxed, "g0"_a) .def("solveRegularized", &Kato::solveRegularized, "p0"_a, "r"_a=0.01) .def("computeCost", &Kato::computeCost, "use_tresca"_a=false); py::class_ bt(mod, "BeckTeboulle"); bt.def(py::init&, Real, Real>(), "model"_a, "surface"_a, "tolerance"_a, "mu"_a, py::keep_alive<1, 2>(), py::keep_alive<1, 3>()) .def("solve", &BeckTeboulle::solve, "p0"_a) .def("computeCost", &BeckTeboulle::computeCost); py::class_ cd(mod, "Condat"); cd.def(py::init&, Real, Real>(), "model"_a, "surface"_a, "tolerance"_a, "mu"_a, py::keep_alive<1, 2>(), py::keep_alive<1, 3>()) .def("solve", &Condat::solve, "p0"_a, "grad_step"_a=0.9) .def("computeCost", &Condat::computeCost); py::class_ pkt(mod, "PolonskyKeerTan"); pkt.def(py::init&, Real, Real>(), "model"_a, "surface"_a, "tolerance"_a, "mu"_a, py::keep_alive<1, 2>(), py::keep_alive<1, 3>()) .def("solve", &PolonskyKeerTan::solve, "p0"_a) .def("solveTresca", &PolonskyKeerTan::solveTresca, "p0"_a) .def("computeCost", &PolonskyKeerTan::computeCost, "use_tresca"_a=false); py::class_(mod, "EPSolver") .def(py::init()) .def("solve", &EPSolver::solve) .def("getStrainIncrement", &EPSolver::getStrainIncrement) - .def("getResidual", &EPSolver::getResidual); + .def("getResidual", &EPSolver::getResidual) + .def("updateState", &EPSolver::updateState); py::class_(mod, "EPICSolver") .def(py::init(), "contact_solver"_a, "elasto_plastic_solver"_a, "tolerance"_a = 1e-10) .def("solve", &EPICSolver::solve, "load"_a); } } // namespace wrap __END_TAMAAS__ diff --git a/src/SConscript b/src/SConscript index 3ff0802..b005dcf 100644 --- a/src/SConscript +++ b/src/SConscript @@ -1,129 +1,131 @@ import os Import('main_env') def prepend(path, list): return [os.path.join(path, x) for x in list] -env = main_env +env = main_env.Clone() # Core core_list = """ fft_plan_manager.cpp fftransform.cpp fftransform_fftw.cpp grid.cpp grid_hermitian.cpp statistics.cpp surface.cpp tamaas.cpp legacy_types.cpp loop.cpp """.split() core_list = prepend('core', core_list) core_list.append('tamaas_info.cpp') # Lib roughcontact generator_list = """ surface_generator.cpp surface_generator_filter.cpp surface_generator_filter_fft.cpp isopowerlaw.cpp """.split() generator_list = prepend('surface', generator_list) # Lib PERCOLATION percolation_list = """ flood_fill.cpp """.split() percolation_list = prepend('percolation', percolation_list) # BEM PERCOLATION bem_list = """ bem_kato.cpp bem_polonski.cpp bem_gigi.cpp bem_gigipol.cpp bem_penalty.cpp bem_uzawa.cpp bem_fft_base.cpp bem_functional.cpp bem_meta_functional.cpp elastic_energy_functional.cpp exponential_adhesion_functional.cpp squared_exponential_adhesion_functional.cpp maugis_adhesion_functional.cpp complimentary_term_functional.cpp bem_grid.cpp bem_grid_polonski.cpp bem_grid_kato.cpp bem_grid_teboulle.cpp bem_grid_condat.cpp """.split() bem_list = prepend('bem', bem_list) # Model model_list = """ model.cpp model_factory.cpp model_type.cpp model_template.cpp be_engine.cpp westergaard.cpp elastic_functional.cpp meta_functional.cpp adhesion_functional.cpp volume_potential.cpp kelvin.cpp mindlin.cpp boussinesq.cpp elasto_plastic/isotropic_hardening.cpp elasto_plastic/elasto_plastic_model.cpp elasto_plastic/residual.cpp """.split() model_list = prepend('model', model_list) # Solvers solvers_list = """ contact_solver.cpp polonsky_keer_rey.cpp kato.cpp beck_teboulle.cpp condat.cpp polonsky_keer_tan.cpp ep_solver.cpp epic.cpp """.split() solvers_list = prepend('solvers', solvers_list) # GPU API gpu_list = """ fftransform_cufft.cpp """.split() gpu_list = prepend('gpu', gpu_list) # Assembling total list rough_contact_list = \ core_list + generator_list + percolation_list + model_list + solvers_list # For some reason collapse OMP loops don't compile on intel if env['CXX'] != 'icpc': rough_contact_list += bem_list # Adding GPU if needed if env['backend'] == 'cuda': rough_contact_list += gpu_list # Generating dependency files # env.AppendUnique(CXXFLAGS=['-MMD']) # for file_name in rough_contact_list: # obj = file_name.replace('.cpp', '.os') # dep_file_name = file_name.replace('.cpp', '.d') # env.SideEffect(dep_file_name, obj) # env.ParseDepends(dep_file_name) +# Adding extra warnings for Tamaas base lib +env.AppendUnique(CXXFLAGS=['-Wextra']) libTamaas = env.SharedLibrary('Tamaas', rough_contact_list) Export('libTamaas') diff --git a/src/bem/bem_functional.cpp b/src/bem/bem_functional.cpp index 4477583..a71e9c3 100644 --- a/src/bem/bem_functional.cpp +++ b/src/bem/bem_functional.cpp @@ -1,44 +1,44 @@ /** * * @author Lucas Frérot * * @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 "bem_functional.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ Functional::Functional(BemFFTBase& bem) : parameters(), bem(bem), gradF(nullptr) {} Functional::~Functional() {} void Functional::setGradFPointer(Surface* p) { this->gradF = p; } -void Functional::copyParameters(const std::map& params) { +void Functional::copyParameters(const std::map& /*params*/) { // auto it = params.begin(); // auto end = params.end(); // for (; it != end ; ++it) this->parameters.insert(*it); } __END_TAMAAS__ diff --git a/src/bem/bem_gigi.cpp b/src/bem/bem_gigi.cpp index 49f8e89..c55cd03 100644 --- a/src/bem/bem_gigi.cpp +++ b/src/bem/bem_gigi.cpp @@ -1,280 +1,280 @@ /** * * @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 "bem_gigi.hh" #include "surface.hh" #include #include #include #include #include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ Real BemGigi::computeEquilibrium(Real epsilon, Real mean_displacement) { this->computeSpectralInfluenceOverDisplacement(); Real Rold = 1.; Real f = 1e300; this->search_direction = 0.; this->true_displacements = 0; this->true_displacements = mean_displacement; this->computeGaps(); this->optimizeToMeanDisplacement(mean_displacement); this->computeGaps(); convergence_iterations.clear(); nb_iterations = 0; max_iterations = 50; Real R = 0; while (f > epsilon && nb_iterations++ < max_iterations) { this->computeGaps(); this->functional->computeGradFU(); this->updateSearchDirection(R / Rold); Rold = R; Real alpha = this->computeOptimalStep(); std::cout << "alpha vaut " << alpha << std::endl; this->old_displacements = this->true_displacements; this->updateDisplacements(alpha); this->computeGaps(); this->optimizeToMeanDisplacement(mean_displacement); // espace admissible this->computeGaps(); this->computePressures(mean_displacement); f = computeStoppingCriterion(); } this->computePressures(mean_displacement); return f; } /* -------------------------------------------------------------------------- */ Real BemGigi::computeStoppingCriterion() { Real rho = this->functional->getParameter("rho"); Real surface_energy = this->functional->getParameter("surface_energy"); Real crit = 0.; // Real disp_norm = 0.; UInt n = surface.size(); UInt size = n * n; //#pragma omp parallel for reduction(+:crit, disp_norm) #pragma omp parallel for reduction(+ : crit) for (UInt i = 0; i < size; ++i) { crit += std::abs(this->gap(i) * (this->surface_tractions(i) + surface_energy / rho * exp(-(gap(i)) / rho))); } return crit; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ 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) { +void BemGigi::updateSearchDirection(Real /*factor*/) { UInt n = surface.size(); UInt size = n * n; const Surface& gradF = this->functional->getGradF(); #pragma omp parallel for for (UInt i = 0; i < size; ++i) { this->search_direction(i) = gradF(i); } } /* -------------------------------------------------------------------------- */ Real BemGigi::computeOptimalStep() { this->applyInverseInfluenceFunctions(search_direction, projected_direction); UInt n = surface.size(); UInt size = n * n; const 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 += projected_direction(i) * search_direction(i); } Real alpha = numerator / denominator; return alpha; } /* -------------------------------------------------------------------------- */ Real BemGigi::computeTau() { return computeOptimalStep(); } /* -------------------------------------------------------------------------- */ void BemGigi::updateDisplacements(Real alpha) { 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); } } /* -------------------------------------------------------------------------- */ void BemGigi::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); } } /* -------------------------------------------------------------------------- */ void BemGigi::enforceMeanDisplacement(Real mean_displacement) { UInt n = surface.size(); UInt size = n * n; Real moyenne_surface = SurfaceStatistics::computeAverage(this->surface, 0); Real average = SurfaceStatistics::computeAverage(this->true_displacements, 0); Real factor = (mean_displacement - moyenne_surface) / (average - moyenne_surface); #pragma omp parallel for for (UInt i = 0; i < size; ++i) { this->true_displacements(i) = factor * (this->true_displacements(i) - this->surface(i)) + this->surface(i); } } /* -------------------------------------------------------------------------- */ -void BemGigi::computePressures(Real mean_displacement) { +void BemGigi::computePressures(Real /*mean_displacement*/) { this->computeTractionsFromDisplacements(); UInt n = surface.size(); UInt size = n * n; Real rho = this->functional->getParameter("rho"); Real surface_energy = this->functional->getParameter("surface_energy"); Real mini = 3000; for (UInt i = 0; i < size; ++i) { if (gap(i) < rho) { if (this->surface_tractions(i) + surface_energy / rho < mini) mini = this->surface_tractions(i) + surface_energy / rho; } else { if (this->surface_tractions(i) < mini) mini = this->surface_tractions(i); } } this->surface_tractions -= mini; } __END_TAMAAS__ diff --git a/src/bem/bem_gigipol.cpp b/src/bem/bem_gigipol.cpp index 551a5b6..00356b3 100644 --- a/src/bem/bem_gigipol.cpp +++ b/src/bem/bem_gigipol.cpp @@ -1,755 +1,755 @@ /** * * @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 "bem_gigipol.hh" #include "surface.hh" #include #include #include #include #include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ void BemGigipol::computeTractionsFromDisplacements() { this->applyInverseInfluenceFunctions(this->true_displacements, this->surface_tractions); } Real BemGigipol::computeEquilibrium(Real epsilon, Real mean_displacement) { this->computeSpectralInfluenceOverDisplacement(); this->surface_t = 0.; this->surface_r = 0.; this->search_direction = 0.; this->pold = 0.; this->surface_displacements = 0.; Real delta = 0.; Real Gold = 1.; Real f = 1e300; Real fPrevious = 1e300; UInt n = surface.size(); UInt size = n * n; Real current_disp = SurfaceStatistics::computeAverage(true_displacements, 0); std::cout << "current disp " << current_disp << std::endl; if (current_disp <= 0.) { true_displacements = mean_displacement; std::cout << "je re initialise " << std::endl; } this->computeGaps(); this->optimizeToMeanDisplacement(mean_displacement); std::ofstream file("output.txt"); this->computeGaps(); convergence_iterations.clear(); nb_iterations = 0; max_iterations = 10000; while (f > epsilon && nb_iterations < max_iterations) { fPrevious = f; this->functional->computeGradFU(); this->search_direction = this->functional->getGradF(); Real gbar = this->computeMeanPressuresInNonContact(); this->search_direction -= gbar; Real G = this->computeG(); this->updateT(G, Gold, delta); Real tau = this->computeTau(); this->old_displacements = this->true_displacements; Gold = G; #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { this->true_displacements(i) -= tau * this->surface_t(i); } // Projection on admissible space this->computeGaps(); #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { if (this->gap(i) < 0) { this->true_displacements(i) = this->surface(i); } } this->computeGaps(); delta = this->updateDisplacements(tau, mean_displacement); // Projection on admissible space this->computeGaps(); this->enforceMeanDisplacement(mean_displacement); this->computeGaps(); this->computePressures(); f = this->computeStoppingCriterion(); if (nb_iterations % dump_freq == 0) { std::cout << "G vaut " << G << std::endl; std::cout << "f vaut " << f << std::endl; std::cout << std::scientific << std::setprecision(10) << nb_iterations << " " << f << " " << f - fPrevious << " " << 'G' << " " << G << " " << std::endl; UInt n = surface.size(); UInt size = n * n; Real crit = 0; Real disp_norm = 0; for (UInt i = 0; i < size; ++i) { crit += this->search_direction(i) * this->search_direction(i); disp_norm += (true_displacements(i) * true_displacements(i)); } file << std::scientific << std::setprecision(10) << nb_iterations << " " << crit / disp_norm << " " << f << std::endl; } convergence_iterations.push_back(f); ++nb_iterations; } this->computePressures(); return f; } /* -------------------------------------------------------------------------- */ Real BemGigipol::computeEquilibrium2(Real epsilon, Real mean_pressure) { this->computeSpectralInfluenceOverDisplacement(); this->surface_t = 0.; this->surface_r = 0.; this->search_direction = 0.; this->pold = 0.; this->surface_displacements = 0.; Real delta = 0.; Real Gold = 1.; Real f = 1e300; Real fPrevious = 1e300; UInt n = surface.size(); UInt size = n * n; Real current_disp = SurfaceStatistics::computeAverage(surface, 0.); true_displacements = current_disp; this->computeGaps(); #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { if (this->gap(i) < 0) { this->true_displacements(i) = this->surface(i); } } this->computeGaps(); // this->optimizeToMeanDisplacement(mean_displacement); std::ofstream file("output.txt"); convergence_iterations.clear(); nb_iterations = 0; max_iterations = 200000; while (f > epsilon && nb_iterations < max_iterations) { fPrevious = f; this->functional->computeGradFU(); this->search_direction = this->functional->getGradF(); Real gbar = this->computeMeanPressuresInNonContact(); this->search_direction += (2 * mean_pressure + gbar); Real G = this->computeG(); this->updateT(G, Gold, delta); Real tau = this->computeTau(mean_pressure); this->old_displacements = this->true_displacements; Gold = G; #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { this->true_displacements(i) -= tau * this->surface_t(i); } // Projection on admissible space this->computeGaps(); #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { if (this->gap(i) < 0) { this->true_displacements(i) = this->surface(i); } } this->computeGaps(); delta = this->updateDisplacements(tau, 0.); // Projection on admissible space this->computeGaps(); this->computePressures(); f = this->computeStoppingCriterion(); this->computeTractionsFromDisplacements(); this->functional->computeGradFU(); const Surface& gradF = this->functional->getGradF(); Real min = SurfaceStatistics::computeMinimum(gradF); if (f < epsilon && epsilon < std::abs(min + mean_pressure)) f = 3.; if (nb_iterations % dump_freq == 0) { std::cout << "G vaut " << G << std::endl; std::cout << "f vaut " << f << std::endl; std::cout << std::scientific << std::setprecision(10) << nb_iterations << " " << f << " " << f - fPrevious << " " << 'G' << " " << G << " " << std::endl; UInt n = surface.size(); UInt size = n * n; Real crit = 0; Real disp_norm = 0; for (UInt i = 0; i < size; ++i) { crit += this->search_direction(i) * this->search_direction(i); disp_norm += (true_displacements(i) * true_displacements(i)); } file << std::scientific << std::setprecision(10) << nb_iterations << " " << crit / disp_norm << " " << f << std::endl; } convergence_iterations.push_back(f); ++nb_iterations; } this->computePressures(); return f; } /* -------------------------------------------------------------------------- */ Real BemGigipol::computeEquilibrium2init(Real epsilon, Real mean_pressure, Surface& init) { this->computeSpectralInfluenceOverDisplacement(); this->surface_t = 0.; this->surface_r = 0.; this->search_direction = 0.; this->pold = 0.; this->surface_displacements = 0.; Real delta = 0.; Real Gold = 1.; Real f = 1e300; Real fPrevious = 1e300; UInt n = surface.size(); UInt size = n * n; this->true_displacements = init; this->computeGaps(); #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { if (this->gap(i) < 0) { this->true_displacements(i) = this->surface(i); } } this->computeGaps(); std::ofstream file("output.txt"); convergence_iterations.clear(); nb_iterations = 0; max_iterations = 200000; while (f > epsilon && nb_iterations < max_iterations) { fPrevious = f; this->functional->computeGradFU(); this->search_direction = this->functional->getGradF(); Real gbar = this->computeMeanPressuresInNonContact(); this->search_direction += (2 * mean_pressure + gbar); Real G = this->computeG(); this->updateT(G, Gold, delta); Real tau = this->computeTau(mean_pressure); tau = 0.01 * tau; this->old_displacements = this->true_displacements; Gold = G; #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { this->true_displacements(i) -= tau * this->surface_t(i); } // Projection on admissible space this->computeGaps(); #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { if (this->gap(i) < 0) { this->true_displacements(i) = this->surface(i); } } this->computeGaps(); delta = this->updateDisplacements(tau, 0.); // Projection on admissible space this->computeGaps(); this->computePressures(); f = this->computeStoppingCriterion(); this->computeTractionsFromDisplacements(); this->functional->computeGradFU(); const Surface& gradF = this->functional->getGradF(); Real min = SurfaceStatistics::computeMinimum(gradF); if (f < epsilon && epsilon < std::abs(min + mean_pressure)) f = 3.; if (nb_iterations % dump_freq == 0) { std::cout << "G vaut " << G << std::endl; std::cout << "f vaut " << f << std::endl; std::cout << std::scientific << std::setprecision(10) << nb_iterations << " " << f << " " << f - fPrevious << " " << 'G' << " " << G << " " << std::endl; UInt n = surface.size(); UInt size = n * n; Real crit = 0; Real disp_norm = 0; for (UInt i = 0; i < size; ++i) { crit += this->search_direction(i) * this->search_direction(i); disp_norm += (true_displacements(i) * true_displacements(i)); } file << std::scientific << std::setprecision(10) << nb_iterations << " " << crit / disp_norm << " " << f << std::endl; } convergence_iterations.push_back(f); ++nb_iterations; } this->computePressures(); return f; } /* -------------------------------------------------------------------------- */ Real BemGigipol::computeEquilibriuminit(Real epsilon, Real mean_displacement, Surface& init) { this->computeSpectralInfluenceOverDisplacement(); this->surface_t = 0.; this->surface_r = 0.; this->search_direction = 0.; this->pold = 0.; this->surface_displacements = 0.; Real delta = 0.; Real Gold = 1.; Real f = 1e300; Real fPrevious = 1e300; UInt n = surface.size(); UInt size = n * n; this->true_displacements = init; Real current_disp = SurfaceStatistics::computeAverage(this->true_displacements, 0); std::cout << "current disp " << current_disp << std::endl; if (current_disp == 0.) { true_displacements = mean_displacement; std::cout << "je reinitialise " << current_disp << std::endl; } this->computeGaps(); this->optimizeToMeanDisplacement(mean_displacement); std::ofstream file("output.txt"); this->computeGaps(); convergence_iterations.clear(); nb_iterations = 0; max_iterations = 100000; while (f > epsilon && nb_iterations < max_iterations) { fPrevious = f; this->functional->computeGradFU(); this->search_direction = this->functional->getGradF(); Real gbar = this->computeMeanPressuresInNonContact(); this->search_direction -= gbar; Real G = this->computeG(); this->updateT(G, Gold, delta); Real tau = this->computeTau(); this->old_displacements = this->true_displacements; Gold = G; #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { this->true_displacements(i) -= tau * this->surface_t(i); } // Projection on admissible space this->computeGaps(); #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { if (this->gap(i) < 0) { this->true_displacements(i) = this->surface(i); } } this->computeGaps(); delta = this->updateDisplacements(tau, mean_displacement); // Projection on admissible space this->computeGaps(); this->enforceMeanDisplacement(mean_displacement); this->computeGaps(); this->computePressures(); f = this->computeStoppingCriterion(); if (nb_iterations % dump_freq == 0) { std::cout << "G vaut " << G << std::endl; std::cout << "f vaut " << f << std::endl; std::cout << std::scientific << std::setprecision(10) << nb_iterations << " " << f << " " << f - fPrevious << " " << 'G' << " " << G << " " << std::endl; UInt n = surface.size(); UInt size = n * n; Real crit = 0; Real disp_norm = 0; for (UInt i = 0; i < size; ++i) { crit += this->search_direction(i) * this->search_direction(i); disp_norm += (true_displacements(i) * true_displacements(i)); } file << std::scientific << std::setprecision(10) << nb_iterations << " " << crit / disp_norm << " " << f << std::endl; } convergence_iterations.push_back(f); ++nb_iterations; } this->computePressures(); return f; } /* -------------------------------------------------------------------------- */ Real BemGigipol::computeStoppingCriterion() { UInt n = surface.size(); UInt size = n * n; Real res = 0; Real t_sum = std::abs(SurfaceStatistics::computeSum(this->true_displacements)); this->computeTractionsFromDisplacements(); this->functional->computeGradFU(); const Surface& gradF = this->functional->getGradF(); Real min = SurfaceStatistics::computeMinimum(gradF); #pragma omp parallel for reduction(+ : res) for (UInt i = 0; i < size; ++i) { res += std::abs((gradF(i) - min) * (this->true_displacements(i) - surface(i))); // res += // this->surface_tractions[i].real() // *(surface_displacements[i].real() - surface[i].real()); } return res / std::abs(t_sum); } /* -------------------------------------------------------------------------- */ Real BemGigipol::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->search_direction(i); res += val * val; } } return res; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ Real BemGigipol::computeMeanPressuresInNonContact() { unsigned int n = surface.size(); unsigned int size = n * n; Real res = 0.; UInt nb_contact = 0; #pragma omp parallel for reduction(+ : nb_contact, res) for (unsigned int i = 0; i < size; ++i) { if (this->gap(i) == 0.) continue; ++nb_contact; res += this->search_direction(i); } res /= nb_contact; return res; } /* -------------------------------------------------------------------------- */ void BemGigipol::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 BemGigipol::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 BemGigipol::updateT(Real G, Real Gold, Real delta) { unsigned int n = surface.size(); unsigned int size = n * n; Real factor = delta * G / Gold; #pragma omp parallel for for (unsigned int i = 0; i < size; ++i) { if (this->gap(i) == 0.) this->surface_t(i) = 0.; else { this->surface_t(i) *= factor; this->surface_t(i) += this->search_direction(i); } } } /* -------------------------------------------------------------------------- */ Real BemGigipol::computeTau() { const UInt n = surface.size(); const UInt size = n * n; this->applyInverseInfluenceFunctions(surface_t, surface_r); Real rbar = 0; UInt nb_contact = 0; #pragma omp parallel for reduction(+ : nb_contact, rbar) for (unsigned int i = 0; i < size; ++i) { if (this->gap(i) == 0) continue; ++nb_contact; rbar += surface_r(i); } rbar /= nb_contact; surface_r -= rbar; Real tau_sum1 = 0., tau_sum2 = 0.; #pragma omp parallel for reduction(+ : tau_sum1, tau_sum2) for (unsigned int i = 0; i < size; ++i) { if (this->gap(i) == 0) continue; tau_sum1 += this->search_direction(i) * surface_t(i); tau_sum2 += surface_r(i) * surface_t(i); } Real tau = tau_sum1 / tau_sum2; return tau; } /* -------------------------------------------------------------------------- */ Real BemGigipol::computeTau(Real mean_pressure) { const UInt n = surface.size(); const UInt size = n * n; this->applyInverseInfluenceFunctions(surface_t, surface_r); Real rbar = 0; UInt nb_contact = 0; #pragma omp parallel for reduction(+ : nb_contact, rbar) for (unsigned int i = 0; i < size; ++i) { if (this->gap(i) == 0) continue; ++nb_contact; rbar += surface_r(i); } rbar /= nb_contact; surface_r += 2 * mean_pressure + rbar; Real tau_sum1 = 0., tau_sum2 = 0.; #pragma omp parallel for reduction(+ : tau_sum1, tau_sum2) for (unsigned int i = 0; i < size; ++i) { if (this->gap(i) == 0) continue; tau_sum1 += this->search_direction(i) * surface_t(i); tau_sum2 += surface_r(i) * surface_t(i); } Real tau = tau_sum1 / tau_sum2; return tau; } /* -------------------------------------------------------------------------- */ -Real BemGigipol::updateDisplacements(Real tau, Real mean_displacement) { +Real BemGigipol::updateDisplacements(Real tau, Real /*mean_displacement*/) { unsigned int n = surface.size(); unsigned int size = n * n; // compute number of interpenetration without contact UInt nb_iol = 0; #pragma omp parallel for reduction(+ : nb_iol) for (unsigned int i = 0; i < size; ++i) { if (this->search_direction(i) < 0 && this->gap(i) == 0.) { this->true_displacements(i) -= tau * this->search_direction(i); ++nb_iol; } } Real delta = 0; if (nb_iol > 0) delta = 0.; else delta = 1.; return delta; } /* -------------------------------------------------------------------------- */ void BemGigipol::enforceMeanDisplacement(Real mean_displacement) { UInt n = surface.size(); UInt size = n * n; Real moyenne_surface = SurfaceStatistics::computeAverage(this->surface, 0); Real average = SurfaceStatistics::computeAverage(this->true_displacements, 0); Real factor = (mean_displacement - moyenne_surface) / (average - moyenne_surface); #pragma omp parallel for for (UInt i = 0; i < size; ++i) { this->true_displacements(i) = factor * (this->true_displacements(i) - this->surface(i)) + this->surface(i); } } /* -------------------------------------------------------------------------- */ void BemGigipol::computePressures() { this->computeTractionsFromDisplacements(); this->functional->computeGradFU(); const Surface& gradF = this->functional->getGradF(); Real min = SurfaceStatistics::computeMinimum(gradF); this->surface_tractions -= min; } /* -------------------------------------------------------------------------- */ __END_TAMAAS__ diff --git a/src/bem/bem_penalty.cpp b/src/bem/bem_penalty.cpp index a21f133..820b425 100644 --- a/src/bem/bem_penalty.cpp +++ b/src/bem/bem_penalty.cpp @@ -1,200 +1,200 @@ /** * * @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 "bem_penalty.hh" #include "surface.hh" #include #include #include #include #include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ void BemPenalty::computeTractionsFromDisplacements() { this->applyInverseInfluenceFunctions(this->true_displacements, this->surface_tractions); } Real BemPenalty::computeEquilibrium(Real epsilon, Real mean_displacement, Real penalization_parameter) { this->computeSpectralInfluenceOverDisplacement(); this->search_direction = 0.; this->true_displacements = 0; this->true_displacements = mean_displacement; this->computeGaps(); std::ofstream file("output.txt"); Real f = 1e300; std::cout << "moyenne deplacement " << SurfaceStatistics::computeAverage(this->true_displacements, 0) << std::endl; convergence_iterations.clear(); nb_iterations = 0; max_iterations = 5000; while (f > epsilon && nb_iterations++ < max_iterations) { this->functional->computeGradFU(); this->computeSearchDirection(mean_displacement, penalization_parameter); Real alpha = 0.001; this->old_displacements = this->true_displacements; this->updateUnknown(alpha, mean_displacement); this->computeGaps(); f = computeStoppingCriterion(); if (nb_iterations % dump_freq == 0) { std::cout << std::scientific << std::setprecision(10) << nb_iterations << " " << f << std::fixed << std::endl; this->computePressures(mean_displacement); Real orth = 0.; UInt n = surface.size(); UInt size = n * n; #pragma omp parallel for reduction(+ : orth) for (UInt i = 0; i < size; ++i) { orth += std::abs(surface_tractions(i) * (this->true_displacements(i) - surface(i))); } file << std::scientific << std::setprecision(10) << nb_iterations << " " << f << " " << orth << std::endl; } convergence_iterations.push_back(f); } this->computePressures(mean_displacement); file.close(); return f; } /* -------------------------------------------------------------------------- */ Real BemPenalty::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->search_direction(i) * this->search_direction(i); disp_norm += (true_displacements(i) * true_displacements(i)); } return crit / disp_norm; } /* -------------------------------------------------------------------------- */ -void BemPenalty::computeSearchDirection(Real mean_displacement, +void BemPenalty::computeSearchDirection(Real /*mean_displacement*/, Real penalization_parameter) { UInt n = surface.size(); UInt size = n * n; const Surface& gradF = this->functional->getGradF(); #pragma omp parallel for for (UInt i = 1; i < size; ++i) { this->search_direction(i) = gradF(i); if (gap(i) < 0) { this->search_direction(i) += penalization_parameter * gap(i); } } } /* -------------------------------------------------------------------------- */ Real BemPenalty::computeOptimalStep() { this->applyInverseInfluenceFunctions(search_direction, surface_r); UInt n = surface.size(); UInt size = n * n; Real numerator = 0., denominator = 0.; #pragma omp parallel for reduction(+ : numerator, denominator) for (UInt i = 0; i < size; ++i) { numerator += search_direction(i) * search_direction(i); denominator += surface_r(i) * search_direction(i); } Real alpha = numerator / denominator; return alpha; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void BemPenalty::updateUnknown(Real alpha, Real mean_displacement) { 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); } Real moyenne = SurfaceStatistics::computeAverage(this->true_displacements, 0); for (UInt i = 0; i < size; ++i) { this->true_displacements(i) = this->true_displacements(i) - moyenne + mean_displacement; } } /* -------------------------------------------------------------------------- */ -void BemPenalty::computePressures(Real mean_displacement) { +void BemPenalty::computePressures(Real /*mean_displacement*/) { this->computeTractionsFromDisplacements(); this->functional->computeGradFU(); // const Surface & gradF = this->functional->getGradF(); // Real min = SurfaceStatistics::computeMinimum(gradF); this->surface_tractions -= this->surface_tractions(0); } /* -------------------------------------------------------------------------- */ __END_TAMAAS__ diff --git a/src/bem/bem_uzawa.cpp b/src/bem/bem_uzawa.cpp index cd4e67d..38c7b27 100644 --- a/src/bem/bem_uzawa.cpp +++ b/src/bem/bem_uzawa.cpp @@ -1,255 +1,255 @@ /** * * @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 "bem_uzawa.hh" #include "surface.hh" #include #include #include #include #include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ void BemUzawa::computeTractionsFromDisplacements() { this->applyInverseInfluenceFunctions(this->true_displacements, this->surface_tractions); } Real BemUzawa::computeEquilibrium(Real epsilon, Real mean_displacement, Real penalization_parameter) { this->computeSpectralInfluenceOverDisplacement(); this->search_direction = 0.; this->true_displacements = 0; this->true_displacements = mean_displacement; this->computeGaps(); this->multipliers = 0; Real f_2 = 1e300; Real new_pen = 1e300; Real old_pen = 1e300; convergence_iterations.clear(); UInt nb_iterations_1 = 0; UInt nb_iterations_2 = 0; std::ofstream file("output.txt"); Real max_iterations_1 = 500; Real max_iterations_2 = 1000; while (new_pen > epsilon && nb_iterations_1++ < max_iterations_1) { std::cout << "iter ext " << nb_iterations_1 << std::endl; while (f_2 > 1e-12 && nb_iterations_2++ < max_iterations_2) { std::cout << "iter int " << nb_iterations_2 << std::endl; this->functional->computeGradFU(); this->computeSearchDirection(mean_displacement, penalization_parameter); Real alpha = 1 / (10 * penalization_parameter); this->old_displacements = this->true_displacements; this->updateUnknown(alpha, mean_displacement); this->computeGaps(); f_2 = computeStoppingCriterion(); if (nb_iterations_2 % dump_freq == 0) { std::cout << std::scientific << std::setprecision(10) << nb_iterations << " " << f_2 << std::fixed << std::endl; this->computePressures(); Real orth = 0.; UInt n = surface.size(); UInt size = n * n; #pragma omp parallel for reduction(+ : orth) for (UInt i = 0; i < size; ++i) { orth += std::abs(surface_tractions(i) * (this->true_displacements(i) - surface(i))); } file << std::scientific << std::setprecision(10) << nb_iterations_2 << " " << f_2 << " " << orth << std::endl; } } this->updateMultipliers(penalization_parameter); old_pen = computeInterpenetration(this->old_displacements); new_pen = computeInterpenetration(this->true_displacements); std::cout << "old penetration is " << old_pen << std::endl; std::cout << "new penetration is " << new_pen << std::endl; penalization_parameter = this->updatePenalization(penalization_parameter, old_pen, new_pen); // to avoid ill conditioned system if (penalization_parameter > 1.0e8) new_pen = 0.; nb_iterations_2 = 0; f_2 = 1e300; std::cout << "penalization is " << penalization_parameter << std::endl; } this->computeGaps(); this->computePressures(); return new_pen; } /* -------------------------------------------------------------------------- */ Real BemUzawa::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->search_direction(i)) * (this->search_direction(i)); disp_norm += (true_displacements(i) * true_displacements(i)); } return crit / disp_norm; } /* -------------------------------------------------------------------------- */ -void BemUzawa::computeSearchDirection(Real mean_displacement, +void BemUzawa::computeSearchDirection(Real /*mean_displacement*/, Real penalization_parameter) { UInt n = surface.size(); UInt size = n * n; const Surface& gradF = this->functional->getGradF(); #pragma omp parallel for for (UInt i = 1; i < size; ++i) { this->search_direction(i) = gradF(i); if (this->multipliers(i) + penalization_parameter * gap(i) <= 0) { this->search_direction(i) = this->search_direction(i) + this->multipliers(i) + penalization_parameter * gap(i); } } } /* -------------------------------------------------------------------------- */ Real BemUzawa::computeOptimalStep() { this->applyInverseInfluenceFunctions(search_direction, surface_r); UInt n = surface.size(); UInt size = n * n; Real numerator = 0., denominator = 0.; #pragma omp parallel for reduction(+ : numerator, denominator) for (UInt i = 0; i < size; ++i) { numerator += search_direction(i) * search_direction(i); denominator += surface_r(i) * search_direction(i); } Real alpha = numerator / denominator; return alpha; } /* -------------------------------------------------------------------------- */ void BemUzawa::updateMultipliers(Real penalization_parameter) { UInt n = surface.size(); UInt size = n * n; #pragma omp parallel for for (UInt i = 0; i < size; ++i) { if (this->multipliers(i) + penalization_parameter * gap(i) > 0.) { this->multipliers(i) = 0; } else { this->multipliers(i) += penalization_parameter * gap(i); } } } /* -------------------------------------------------------------------------- */ Real BemUzawa::updatePenalization(Real penalization_parameter, Real old_pen, Real new_pen) { if (new_pen > 0.25 * old_pen) { penalization_parameter *= 5; } return penalization_parameter; } /* -------------------------------------------------------------------------- */ -Real BemUzawa::computeInterpenetration(Surface& displacements) { +Real BemUzawa::computeInterpenetration(Surface& /*displacements*/) { UInt n = surface.size(); UInt size = n * n; Real res = 0.; #pragma omp parallel for for (UInt i = 0; i < size; ++i) { if (0 > this->true_displacements(i) - surface(i)) { res += (this->true_displacements(i) - surface(i)) * (this->true_displacements(i) - surface(i)); } } return sqrt(res); } /* -------------------------------------------------------------------------- */ void BemUzawa::updateUnknown(Real alpha, Real mean_displacement) { 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); } Real moyenne = SurfaceStatistics::computeAverage(this->true_displacements, 0); for (UInt i = 0; i < size; ++i) { this->true_displacements(i) = this->true_displacements(i) - moyenne + mean_displacement; } } /* -------------------------------------------------------------------------- */ void BemUzawa::computePressures() { this->computeTractionsFromDisplacements(); this->functional->computeGradFU(); // const Surface & gradF = this->functional->getGradF(); // Real min = SurfaceStatistics::computeMinimum(gradF); this->surface_tractions -= this->surface_tractions(0); } /* -------------------------------------------------------------------------- */ __END_TAMAAS__ diff --git a/src/core/grid.cpp b/src/core/grid.cpp index e18317e..898f8d4 100644 --- a/src/core/grid.cpp +++ b/src/core/grid.cpp @@ -1,125 +1,126 @@ /** * @file * * @author Lucas Frérot * * @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 "grid.hh" #include "tamaas.hh" #include #include #include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ template Grid::Grid() : GridBase() { this->n.fill(0); this->strides.fill(1); this->nb_components = 1; } /* -------------------------------------------------------------------------- */ template Grid::Grid(const std::array& n, UInt nb_components, value_type* data) : GridBase() { this->n = n; + this->nb_components = nb_components; UInt size = this->computeSize(); this->data.wrapMemory(data, size); this->computeStrides(); } template Grid::Grid(const Grid& o) : GridBase(o), n(o.n), strides(o.strides) {} template Grid::Grid(Grid&& o) : GridBase(o), n(std::move(o.n)), strides(std::move(o.strides)) {} /* -------------------------------------------------------------------------- */ template void Grid::resize(const std::array& n) { this->resize(n.begin(), n.end()); } /* -------------------------------------------------------------------------- */ template void Grid::resize(const std::vector& n) { TAMAAS_ASSERT(n.size() == dim, "Shape vector not matching grid dimensions"); this->resize(n.begin(), n.end()); } /* -------------------------------------------------------------------------- */ template void Grid::resize(std::initializer_list n) { TAMAAS_ASSERT(n.size() == dim, "Shape initializer list not matching grid dimensions"); this->resize(std::begin(n), std::end(n)); } /* -------------------------------------------------------------------------- */ template void Grid::computeStrides() { std::copy(n.begin() + 1, n.end(), strides.rbegin() + 2); strides[dim] = 1; strides[dim - 1] = this->nb_components; std::partial_sum(strides.rbegin(), strides.rend(), strides.rbegin(), std::multiplies()); } /* -------------------------------------------------------------------------- */ template void Grid::printself(std::ostream& str) const { str << "Grid(" << dim << ", " << this->nb_components << ") {"; for (auto& val : *this) { str << val << ", "; } str << "\b\b}"; } /* -------------------------------------------------------------------------- */ /// Class instanciation #define GRID_INSTANCIATE_TYPE(type) \ template class Grid; \ template class Grid; \ template class Grid GRID_INSTANCIATE_TYPE(Real); GRID_INSTANCIATE_TYPE(UInt); GRID_INSTANCIATE_TYPE(Complex); GRID_INSTANCIATE_TYPE(int); GRID_INSTANCIATE_TYPE(bool); GRID_INSTANCIATE_TYPE(unsigned long); #undef GRID_INSTANCIATE_TYPE __END_TAMAAS__ diff --git a/src/core/grid_view.hh b/src/core/grid_view.hh index bbbaaba..cd888fb 100644 --- a/src/core/grid_view.hh +++ b/src/core/grid_view.hh @@ -1,161 +1,161 @@ /** * @file * * @author Lucas Frérot * * @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 __GRID_VIEW_HH__ #define __GRID_VIEW_HH__ /* -------------------------------------------------------------------------- */ #include "grid.hh" #include "tamaas.hh" #include /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ /** * @brief View type on grid * This is a view on a *contiguous* chunk of data defined by a grid */ template