diff --git a/src/model/westergaard.cpp b/src/model/westergaard.cpp index 431a4e5..a8e2b51 100644 --- a/src/model/westergaard.cpp +++ b/src/model/westergaard.cpp @@ -1,254 +1,252 @@ /** * @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 "fft_plan_manager.hh" #include "grid_view.hh" #include "influence.hh" #include "loop.hh" #include "model.hh" #include "static_types.hh" #include "westergaard.hh" /* -------------------------------------------------------------------------- */ __BEGIN_TAMAAS__ /* -------------------------------------------------------------------------- */ template Westergaard::Westergaard(Model* model) : IntegralOperator(model) { // Copy sizes std::array sizes; auto bdisc = model->getBoundaryDiscretization(); // Ignoring first dimension if model is volumetric std::copy(bdisc.begin(), bdisc.end(), sizes.begin()); auto boundary_hermitian_sizes = GridHermitian::hermitianDimensions( sizes); constexpr UInt nb_components = trait::components; buffer.setNbComponents(nb_components); buffer.resize(boundary_hermitian_sizes); influence.setNbComponents(nb_components * nb_components); influence.resize(boundary_hermitian_sizes); initInfluence(); } /* -------------------------------------------------------------------------- */ namespace detail { template struct boundary_fft_helper { template static void backwardTransform(Buffer&& buffer, Out&& out) { auto view = make_view(out, 0); FFTPlanManager::get().createPlan(view, buffer).backwardTransform(); } }; template struct boundary_fft_helper { template static void backwardTransform(Buffer&& buffer, Out&& out) { FFTPlanManager::get().createPlan(out, buffer).backwardTransform(); } }; } template template void Westergaard::fourierApply(Functor func, GridBase& in, GridBase& out) const try { Grid& i = dynamic_cast(in); Grid& full_out = dynamic_cast(out); FFTPlanManager::get().createPlan(i, buffer).forwardTransform(); /// Applying influence func(buffer, influence); /// Backward fourier transform on boundary only detail::boundary_fft_helper::backwardTransform(buffer, full_out); } catch (const std::bad_cast& e) { TAMAAS_EXCEPTION("Neumann and dirichlet types do not match model type"); } /* -------------------------------------------------------------------------- */ template template void Westergaard::initFromFunctor(Functor func) { // Compute wavevectors for influence auto wavevectors = FFTransform::template computeFrequencies( influence.sizes()); // Get boundary physical size auto system_size = this->model->getBoundarySystemSize(); VectorProxy domain(system_size[0]); - for (auto x : domain) - std::cout << x << std::endl; // Normalize wavevectors wavevectors *= 2 * M_PI; wavevectors /= domain; // Apply functor Loop::stridedLoop(func, wavevectors, influence); // Set fundamental mode to zero MatrixProxy mat(influence(0)); mat = 0; } /* -------------------------------------------------------------------------- */ #define NEUMANN_BASIC(type) \ template <> \ void Westergaard::initInfluence() { \ auto E_star = model->getHertzModulus(); \ auto basic = [E_star] CUDA_LAMBDA(VectorProxy && q, \ Complex & k) { \ k = 2. / (E_star * q.l2norm()); \ }; \ initFromFunctor(basic); \ } #define DIRICHLET_BASIC(type) \ template <> \ void Westergaard::initInfluence() { \ auto E_star = model->getHertzModulus(); \ auto basic = [E_star] CUDA_LAMBDA(VectorProxy && q, \ Complex & k) { \ k = E_star * q.l2norm() / 2; \ }; \ initFromFunctor(basic); \ } NEUMANN_BASIC(model_type::basic_1d); NEUMANN_BASIC(model_type::basic_2d); DIRICHLET_BASIC(model_type::basic_1d); DIRICHLET_BASIC(model_type::basic_2d); #undef NEUMANN_BASIC #undef DIRICHLET_BASIC /* -------------------------------------------------------------------------- */ template <> void Westergaard::initInfluence() { auto E = model->getYoungModulus(); auto nu = model->getPoissonRatio(); const Complex I(0, 1); auto surface = [E, nu, I] CUDA_LAMBDA(VectorProxy && q, MatrixProxy && F) { Real q_norm = q.l2norm(); q /= q_norm; F(0, 0) = 2 * (1 + nu) * (1 - nu * q(0) * q(0)); F(1, 1) = 2 * (1 + nu) * (1 - nu * q(1) * q(1)); F(2, 2) = 2 * (1 - nu * nu); F(0, 1) = F(1, 0) = -q(0) * q(1) * 2 * nu * (1 + nu); F(0, 2) = I * q(0) * (1 + nu) * (1. - 2. * nu); F(1, 2) = I * q(1) * (1 + nu) * (1 - 2 * nu); F(2, 0) = -F(0, 2); F(2, 1) = -F(1, 2); F *= 1. / (E * q_norm); }; initFromFunctor(surface); } /* -------------------------------------------------------------------------- */ template void Westergaard::initInfluence() {} /* ------------------------------------------------------------------------ */ template void Westergaard::apply(GridBase& input, GridBase& output) const { auto apply = [](decltype(buffer)& buffer, const decltype(influence)& influence) { Loop::stridedLoop([] CUDA_LAMBDA(VectorProxy && i, MatrixProxy && F) { i = F * i; }, buffer, influence); }; fourierApply(apply, input, output); } /* -------------------------------------------------------------------------- */ template Real Westergaard::getOperatorNorm() { constexpr UInt comp = model_type_traits::components; Real _norm = 0.0; _norm = Loop::stridedReduce( [] CUDA_LAMBDA(MatrixProxy&& m) { Real n = thrust::norm(m.l2squared()); return std::isnan(n) ? 0 : n; }, influence); auto size = model->getSystemSize(); auto disc = model->getDiscretization(); auto dim = model_type_traits::dimension; /// TODO: why? switch (dim) { case 1: _norm /= (size[0] / disc[0]) * (size[0] / disc[0]); break; default: for (UInt i = 0; i < dim; i++) { _norm /= size[i] / disc[i]; } } return std::sqrt(_norm); } /* -------------------------------------------------------------------------- */ /* Template instanciation */ /* -------------------------------------------------------------------------- */ template class Westergaard; template class Westergaard; template class Westergaard; template class Westergaard; template class Westergaard; template class Westergaard; template class Westergaard; template class Westergaard; template class Westergaard; template class Westergaard; template class Westergaard; template class Westergaard; /* -------------------------------------------------------------------------- */ __END_TAMAAS__ /* -------------------------------------------------------------------------- */