Page MenuHomec4science

kelvin_helper.hh
No OneTemporary

File Metadata

Created
Sat, Jul 6, 23:59

kelvin_helper.hh

/**
* @file
*
* @author Lucas Frérot <lucas.frerot@epfl.ch>
*
* @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 <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef KELVIN_HELPER_HH
#define KELVIN_HELPER_HH
/* -------------------------------------------------------------------------- */
#include "grid.hh"
#include "grid_hermitian.hh"
#include "influence.hh"
#include "integration/accumulator.hh"
#include "model_type.hh"
/* -------------------------------------------------------------------------- */
__BEGIN_TAMAAS__
namespace detail {
/// Trait for kelvin local types
template <typename T>
struct KelvinTrait;
template <UInt dim>
struct KelvinTrait<influence::Kelvin<dim, 0>> {
using source_t = VectorProxy<Complex, dim>;
using out_t = VectorProxy<Complex, dim>;
};
template <UInt dim>
struct KelvinTrait<influence::Kelvin<dim, 1>> {
using source_t = MatrixProxy<Complex, dim, dim>;
using out_t = VectorProxy<Complex, dim>;
};
template <UInt dim>
struct KelvinTrait<influence::Kelvin<dim, 2>> {
using source_t = MatrixProxy<Complex, dim, dim>;
using out_t = MatrixProxy<Complex, dim, dim>;
};
template <UInt dim>
struct KelvinTrait<influence::Boussinesq<dim, 0>> {
using source_t = VectorProxy<Complex, dim>;
using out_t = VectorProxy<Complex, dim>;
};
template <UInt dim>
struct KelvinTrait<influence::Boussinesq<dim, 1>> {
using source_t = VectorProxy<Complex, dim>;
using out_t = MatrixProxy<Complex, dim, dim>;
};
/// Helper to apply integral representation on output
template <model_type type, typename kelvin_t,
typename = typename KelvinTrait<kelvin_t>::source_t>
struct KelvinHelper {
using trait = model_type_traits<type>;
static constexpr UInt dim = trait::dimension;
static constexpr UInt bdim = trait::boundary_dimension;
using BufferType = GridHermitian<Real, bdim>;
using source_t = typename KelvinTrait<kelvin_t>::source_t;
using out_t = typename KelvinTrait<kelvin_t>::out_t;
/// Apply the regular part of Kelvin to source and sum into output
void applyIntegral(std::vector<BufferType>& source,
std::vector<BufferType>& out,
const Grid<Real, bdim>& wavevectors, Real domain_size,
const kelvin_t& kelvin) {
accumulator.makeUniformMesh(source.size(), domain_size);
auto waverange = range<VectorProxy<const Real, bdim>>(wavevectors);
for (auto [l, xl_, acc_g0, acc_g1] :
accumulator.forward(source, wavevectors)) {
Loop::loop(
[xl = xl_, &kelvin](auto qv, auto u, auto acc_g0, auto acc_g1) {
Real q = qv.l2norm();
auto tmp = kelvin.template applyU1<false, true>(qv, acc_g0);
tmp *= -q * xl;
tmp += kelvin.template applyU0<false, true>(qv, acc_g0);
tmp += kelvin.template applyU1<false, true>(qv, acc_g1);
tmp *= std::exp(-q * xl);
u += tmp;
},
waverange, range<out_t>(out[l]), range<source_t>(acc_g0),
range<source_t>(acc_g1));
}
for (auto [l, xl_, acc_g0, acc_g1] :
accumulator.backward(source, wavevectors)) {
Loop::loop(
[xl = xl_, &kelvin](auto qv, auto u, auto acc_g0, auto acc_g1) {
Real q = qv.l2norm();
auto tmp = kelvin.template applyU1<true, true>(qv, acc_g0);
tmp *= -q * xl;
tmp += kelvin.template applyU0<true, true>(qv, acc_g0);
tmp += kelvin.template applyU1<true, true>(qv, acc_g1);
tmp *= std::exp(q * xl);
u += tmp;
},
waverange, range<out_t>(out[l]), range<source_t>(acc_g0),
range<source_t>(acc_g1));
}
}
/// Apply free term of distribution derivative
void applyFreeTerm(std::vector<BufferType>& /*source*/,
std::vector<BufferType>& /*out*/,
const kelvin_t& /*kelvin*/) {}
/// Making the output free of communist NaN
void makeFundamentalGreatAgain(std::vector<BufferType>& /*source*/,
std::vector<BufferType>& /*out*/,
const kelvin_t& /*kelvin*/) {}
protected:
Accumulator<type, source_t> accumulator;
};
/// Applying free term for double gradient of Kelvin
template <>
inline void
KelvinHelper<model_type::volume_2d, influence::Kelvin<3, 2>>::applyFreeTerm(
std::vector<BufferType>& source, std::vector<BufferType>& out,
const influence::Kelvin<3, 2>& kelvin) {
for (UInt l : Loop::range(source.size())) {
Loop::loop(
[&kelvin](auto u, auto w) { u += kelvin.applyDiscontinuityTerm(w); },
range<out_t>(out[l]), range<source_t>(source[l]));
}
}
/// Setting fundamental mode to zero: we've got no other choice here
template <>
inline void KelvinHelper<model_type::volume_2d, influence::Kelvin<3, 0>>::
makeFundamentalGreatAgain(std::vector<BufferType>& /*source*/,
std::vector<BufferType>& out,
const influence::Kelvin<3, 0>& /*kelvin*/) {
for (auto&& layer : out) {
out_t u(&layer(0));
u = 0;
}
}
} // namespace detail
__END_TAMAAS__
#endif // KELVIN_HELPER_HH

Event Timeline