diff --git a/python/cast.hh b/python/cast.hh
index 1c39758..5001747 100644
--- a/python/cast.hh
+++ b/python/cast.hh
@@ -1,211 +1,211 @@
/**
* @file
* @section LICENSE
*
* Copyright (©) 2016-19 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
*/
/* -------------------------------------------------------------------------- */
#ifndef __CAST_HH__
#define __CAST_HH__
/* -------------------------------------------------------------------------- */
#include "grid_base.hh"
#include "numpy.hh"
#include "surface.hh"
/* -------------------------------------------------------------------------- */
#include
#include
/* -------------------------------------------------------------------------- */
namespace pybind11 {
// Format descriptor necessary for correct wrap of tamaas complex type
template
struct format_descriptor<
tamaas::complex, detail::enable_if_t::value>> {
static constexpr const char c = format_descriptor::c;
static constexpr const char value[3] = {'Z', c, '\0'};
static std::string format() { return std::string(value); }
};
#ifndef PYBIND11_CPP17
template
constexpr const char format_descriptor<
tamaas::complex,
detail::enable_if_t::value>>::value[3];
#endif
namespace detail {
// declare tamaas complex as a complex type for pybind11
template
struct is_complex> : std::true_type {};
template
struct is_fmt_numeric,
detail::enable_if_t::value>>
: std::true_type {
static constexpr int index = is_fmt_numeric::index + 3;
};
static inline handle policy_switch(return_value_policy policy, handle parent) {
switch (policy) {
case return_value_policy::copy:
case return_value_policy::move:
return handle();
case return_value_policy::automatic_reference: // happens in python-derived
// classes
case return_value_policy::reference:
return none();
case return_value_policy::reference_internal:
return parent;
default:
TAMAAS_EXCEPTION("Policy is not handled");
}
}
template
handle grid_to_python(const tamaas::Grid& grid,
return_value_policy policy, handle parent) {
parent = policy_switch(policy, parent); // reusing variable
std::vector sizes(dim);
std::copy(grid.sizes().begin(), grid.sizes().end(), sizes.begin());
if (grid.getNbComponents() != 1)
sizes.push_back(grid.getNbComponents());
return array(sizes, grid.getInternalData(), parent).release();
}
/**
* Type caster for grid classes
* inspired by https://tinyurl.com/y8m47qh3 from T. De Geus
* and pybind11/eigen.h
*/
template class G, typename T,
tamaas::UInt dim>
struct type_caster> {
using type = G;
using array_type =
array_t;
public:
PYBIND11_TYPE_CASTER(type, _("GridWrap"));
/**
* Conversion part 1 (Python->C++): convert a PyObject into a grid
* instance or return false upon failure. The second argument
* indicates whether implicit conversions should be applied.
*/
bool load(handle src, bool convert) {
if (!array_type::check_(src) or !convert)
return false;
auto buf = array_type::ensure(src);
if (!buf) return false;
value.move(tamaas::wrap::GridNumpy>(buf));
return true;
}
/**
* Conversion part 2 (C++ -> Python): convert a grid instance into
* a Python object. The second and third arguments are used to
* indicate the return value policy and parent object (for
* ``return_value_policy::reference_internal``) and are generally
* ignored by implicit casters.
*/
static handle cast(const type& src, return_value_policy policy,
handle parent) {
return grid_to_python(src, policy, parent);
}
};
/**
* Type caster for GridBase classes
*/
template
struct type_caster> {
using type = tamaas::GridBase;
using array_type =
array_t;
public:
PYBIND11_TYPE_CASTER(type, _("GridBaseWrap"));
bool load(handle src, bool convert) {
if (!array_type::check_(src) or !convert)
return false;
auto buf = array_type::ensure(src);
if (!buf) return false;
value.move(tamaas::wrap::GridBaseNumpy(buf));
return true;
}
static handle cast(const type& src, return_value_policy policy,
handle parent) {
#define GRID_BASE_CASE(unused1, unused2, dim) \
case dim: { \
- const tamaas::Grid& conv = dynamic_cast(src); \
+ const auto& conv = dynamic_cast&>(src); \
return grid_to_python(conv, policy, parent); \
}
switch (src.getDimension()) {
BOOST_PP_SEQ_FOR_EACH(GRID_BASE_CASE, ~, (1)(2)(3));
default:
return nullptr;
}
#undef GRID_BASE_CASE
}
};
/**
* Type caster for surface class
*/
template
struct type_caster> {
using type = tamaas::Surface;
using array_type =
array_t;
public:
PYBIND11_TYPE_CASTER(type, _("SurfaceWrap"));
bool load(handle src, bool convert) {
if (!array_type::check_(src) or !convert)
return false;
auto buf = array_type::ensure(src);
if (!buf) return false;
value.move(tamaas::wrap::SurfaceNumpy(buf));
return true;
}
static handle cast(const type& src, return_value_policy policy,
handle parent) {
return grid_to_python(src, policy, parent);
}
};
} // namespace detail
} // namespace pybind11
#endif // __CAST_HH__
diff --git a/src/bem/bem_grid_polonski.hh b/src/bem/bem_grid_polonski.hh
index 7bfa662..c01163e 100644
--- a/src/bem/bem_grid_polonski.hh
+++ b/src/bem/bem_grid_polonski.hh
@@ -1,77 +1,77 @@
/**
*
* @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 __BEM_GRID_POLONSKI_HH__
#define __BEM_GRID_POLONSKI_HH__
/* -------------------------------------------------------------------------- */
#include "bem_grid_kato.hh"
/* -------------------------------------------------------------------------- */
namespace tamaas {
// typedef for swig
-typedef Grid Grid1dReal;
+using Grid1dReal = Grid;
/**
* @brief multi component implementation of Polonski algorithm
* This method's main unknown is the pressure.
*/
class BemGridPolonski : public BemGridKato {
public:
/// Constructor
BemGridPolonski(Surface& surface);
/// Destructor
virtual ~BemGridPolonski();
public:
/* --------------------------------------------------------------------------
*/
/* Actual computations */
/* --------------------------------------------------------------------------
*/
/// Compute equilibrium
virtual void computeEquilibrium(Real tol, const Grid& p_target);
/// Compute gap functional
Real computeGradientNorm();
/// Compute optimal step size
Real computeOptimalStep();
/// Center field on contact area
void centerOnContactArea(Grid& field);
/// Update search direction
void updateSearchDirection(Real delta, Real G, Real G_old);
/// Update tractions
Real updateTractions(Real tau);
/// Set pressure on all points
void setPressure(const Grid& p_target);
protected:
Grid search_direction;
Grid projected_search_direction;
};
} // namespace tamaas
#endif // __BEM_GRID_POLONSKI_HH__
diff --git a/src/core/fftransform.cpp b/src/core/fftransform.cpp
index 43bc827..9717c20 100644
--- a/src/core/fftransform.cpp
+++ b/src/core/fftransform.cpp
@@ -1,55 +1,55 @@
/**
* @file
* @section LICENSE
*
* Copyright (©) 2016-19 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
*/
/* -------------------------------------------------------------------------- */
#include "fftransform.hh"
namespace tamaas {
template
FFTransform::FFTransform(Grid& real_,
GridHermitian& spectral_)
: real(), spectral() {
this->real.wrap(real_);
this->spectral.wrap(spectral_);
}
/* -------------------------------------------------------------------------- */
template
-FFTransform::~FFTransform() {}
+FFTransform::~FFTransform() = default;
/* -------------------------------------------------------------------------- */
template
void FFTransform::normalize() {
real *= 1. / real.getNbPoints();
}
/* -------------------------------------------------------------------------- */
template class FFTransform;
template class FFTransform;
template class FFTransform;
} // namespace tamaas
diff --git a/src/core/fftransform_fftw.cpp b/src/core/fftransform_fftw.cpp
index 2e8c58c..c69a16b 100644
--- a/src/core/fftransform_fftw.cpp
+++ b/src/core/fftransform_fftw.cpp
@@ -1,103 +1,103 @@
/**
* @file
* @section LICENSE
*
* Copyright (©) 2016-19 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
*/
/* -------------------------------------------------------------------------- */
#include "fftransform_fftw.hh"
#define TAMAAS_FFTW_FLAG FFTW_ESTIMATE
namespace tamaas {
template
FFTransformFFTW::FFTransformFFTW(Grid& real,
GridHermitian& spectral)
: FFTransform(real, spectral), forward_plan(nullptr),
backward_plan(nullptr) {
TAMAAS_ASSERT(real.getNbComponents() == spectral.getNbComponents(),
"components for FFTW do not match");
// Data pointers
Real* in = this->real.getInternalData();
- complex_t* out =
+ auto* out =
reinterpret_cast(this->spectral.getInternalData());
int components = real.getNbComponents();
// fftw parameters
int rank = dim; // dimension of fft
int n[dim] = {0};
std::copy(real.sizes().begin(), real.sizes().end(),
n); // size of individual fft
int howmany = components; // how many fft to compute
int idist = 1, odist = 1; // components are next to each other in memory
int istride = real.getStrides().back() * components,
ostride = spectral.getStrides().back() * components;
int *inembed = nullptr, *onembed = nullptr; // row major
#if TAMAAS_FFTW_FLAG != FFTW_ESTIMATE
// backup the input
Grid backup(real);
#endif
forward_plan =
fftw::plan_many_forward(rank, n, howmany, in, inembed, istride, idist,
out, onembed, ostride, odist, TAMAAS_FFTW_FLAG);
backward_plan =
fftw::plan_many_backward(rank, n, howmany, out, onembed, ostride, odist,
in, inembed, istride, idist, TAMAAS_FFTW_FLAG);
#if TAMAAS_FFTW_FLAG != FFTW_ESTIMATE
// restore the backup
real = backup;
#endif
}
/* -------------------------------------------------------------------------- */
template
FFTransformFFTW::~FFTransformFFTW() {
fftw::destroy(forward_plan);
fftw::destroy(backward_plan);
}
/* -------------------------------------------------------------------------- */
template
void FFTransformFFTW::forwardTransform() {
fftw::execute(forward_plan);
}
/* -------------------------------------------------------------------------- */
template
void FFTransformFFTW::backwardTransform() {
fftw::execute(backward_plan);
this->normalize();
}
/* -------------------------------------------------------------------------- */
template class FFTransformFFTW;
template class FFTransformFFTW;
template class FFTransformFFTW;
} // namespace tamaas
diff --git a/src/core/fftransform_fftw.hh b/src/core/fftransform_fftw.hh
index 6313469..9755b6f 100644
--- a/src/core/fftransform_fftw.hh
+++ b/src/core/fftransform_fftw.hh
@@ -1,62 +1,62 @@
/**
* @file
* @section LICENSE
*
* Copyright (©) 2016-19 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
*/
/* -------------------------------------------------------------------------- */
#ifndef FFTRANSFORM_FFTW_HH
#define FFTRANSFORM_FFTW_HH
#include "fftransform.hh"
#include "fftw_interface.hh"
namespace tamaas {
/**
* @brief Class wrapping fftw's interface
*/
template
class FFTransformFFTW : public FFTransform {
using plan_t = typename fftw::helper::plan;
using complex_t = typename fftw::helper::complex;
public:
/// Constructor
FFTransformFFTW(Grid& real, GridHermitian& spectral);
/// Destructor
- virtual ~FFTransformFFTW();
+ ~FFTransformFFTW() override;
public:
/// Perform FFT
void forwardTransform() override;
/// Perform IFFT
void backwardTransform() override;
private:
plan_t forward_plan;
plan_t backward_plan;
};
} // namespace tamaas
#endif // FFTRANSFORM_FFTW_HH
diff --git a/src/core/loop.hh b/src/core/loop.hh
index 33354c7..df91c9b 100644
--- a/src/core/loop.hh
+++ b/src/core/loop.hh
@@ -1,234 +1,235 @@
/**
* @file
* @section LICENSE
*
* Copyright (©) 2016-19 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
*/
/* -------------------------------------------------------------------------- */
#ifndef LOOP_HH
#define LOOP_HH
/* -------------------------------------------------------------------------- */
#include "loops/apply.hh"
#include "loops/loop_utils.hh"
#include "ranges.hh"
#include "tamaas.hh"
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace tamaas {
template
struct is_policy : std::false_type {};
template <>
struct is_policy : std::true_type {};
template <>
struct is_policy : std::true_type {};
template <>
struct is_policy : std::true_type {};
template <>
struct is_policy : std::true_type {};
template <>
struct is_policy : std::true_type {};
template <>
struct is_policy : std::true_type {};
/**
* @brief Singleton class for automated loops using lambdas
* This class is sweet candy :) It provides abstraction of the paralelism
* paradigm used in loops and allows simple and less error-prone loop syntax,
* with minimum boiler plate. I love it <3
*/
class Loop {
public:
/// Backends enumeration
enum backend {
omp, ///< [OpenMP](http://www.openmp.org/specifications/) backend
cuda, ///< [Cuda](http://docs.nvidia.com/cuda/index.html) backend
};
/// Helper class to count iterations within lambda-loop
template
class arange {
public:
using it_type = thrust::counting_iterator;
using reference = typename it_type::reference;
arange(T start, T size) : start(start), range_size(size) {}
it_type begin(UInt /*i*/ = 1) const { return it_type(T(start)); }
it_type end(UInt /*i*/ = 1) const { return it_type(range_size); }
UInt getNbComponents() const { return 1; }
private:
T start, range_size;
};
template
static arange range(T size) {
return arange(0, size);
}
template
static arange range(U start, T size) {
return arange(start, size);
}
private:
/// Replacement for thrust::transform_iterator which copies values
template
class transform_iterator
: public thrust::iterator_adaptor<
transform_iterator, Iterator, Value,
thrust::use_default, thrust::use_default, Value> {
Functor func;
public:
using super_t =
thrust::iterator_adaptor,
Iterator, Value, thrust::use_default,
thrust::use_default, Value>;
__host__ __device__ transform_iterator(const Iterator& x,
const Functor& func)
: super_t(x), func(func) {}
friend class thrust::iterator_core_access;
private:
__host__ __device__ auto dereference() const
-> decltype(func(*this->base())) {
return func(*this->base());
}
};
public:
/// Loop functor over ranges
template
static auto loop(Functor&& func, Ranges&&... ranges) ->
typename std::enable_if::value, void>::type {
loopImpl(thrust::device, std::forward(func),
std::forward(ranges)...);
}
/// Loop over ranges with non-default policy
template
static void loop(const thrust::execution_policy& policy,
Functor&& func, Ranges&&... ranges) {
loopImpl(policy, std::forward(func),
std::forward(ranges)...);
}
private:
template
using reference_type = typename std::decay::type::reference;
public:
/// Reduce functor over ranges
template
static auto reduce(Functor&& func, Ranges&&... ranges) ->
typename std::enable_if<
not is_policy::value,
decltype(func(std::declval>()...))>::type {
return reduceImpl(thrust::device, std::forward(func),
std::forward(ranges)...);
}
/// Reduce over ranges with non-default policy
template
static auto reduce(const thrust::execution_policy& policy,
Functor&& func, Ranges&&... ranges)
-> decltype(func(std::declval>()...)) {
return reduceImpl(policy, std::forward(func),
std::forward(ranges)...);
}
private:
/// Loop over ranges and apply functor
template
static void loopImpl(const thrust::execution_policy& policy,
Functor&& func, Ranges&&... ranges);
/// Loop over ranges, apply functor and reduce result
template
static auto reduceImpl(const thrust::execution_policy& policy,
Functor&& func, Ranges&&... ranges)
-> decltype(func(std::declval>()...));
+public:
/// Constructor
Loop() = delete;
};
/* -------------------------------------------------------------------------- */
/* Template implementation */
/* -------------------------------------------------------------------------- */
template
void Loop::loopImpl(const thrust::execution_policy& policy,
Functor&& func, Ranges&&... ranges) {
auto begin = thrust::make_zip_iterator(thrust::make_tuple(ranges.begin()...));
auto end = thrust::make_zip_iterator(thrust::make_tuple(ranges.end()...));
checkLoopSize(ranges...);
thrust::for_each(policy, begin, end,
detail::ApplyFunctor(std::forward(func)));
#if (defined(USE_CUDA) && THRUST_VERSION < 100904)
cudaDeviceSynchronize();
#endif
}
/* -------------------------------------------------------------------------- */
template
auto Loop::reduceImpl(const thrust::execution_policy& policy,
Functor&& func, Ranges&&... ranges)
-> decltype(func(std::declval>()...)) {
using return_type = decltype(func(std::declval>()...));
using apply_type = detail::ApplyFunctor;
checkLoopSize(ranges...);
auto applier = apply_type(func);
detail::reduction_helper red_helper;
auto begin_zip =
thrust::make_zip_iterator(thrust::make_tuple(ranges.begin()...));
auto end_zip = thrust::make_zip_iterator(thrust::make_tuple(ranges.end()...));
transform_iterator begin(
begin_zip, applier);
transform_iterator end(end_zip,
applier);
auto result =
thrust::reduce(policy, begin, end, red_helper.init(), red_helper);
#if (defined(USE_CUDA) && THRUST_VERSION < 100904)
cudaDeviceSynchronize();
#endif
return result;
}
} // namespace tamaas
#endif // LOOP_HH
diff --git a/src/core/ranges.hh b/src/core/ranges.hh
index c5817b4..1100e0e 100644
--- a/src/core/ranges.hh
+++ b/src/core/ranges.hh
@@ -1,114 +1,115 @@
/**
* @file
* @section LICENSE
*
* Copyright (©) 2016-19 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
*/
/* -------------------------------------------------------------------------- */
#ifndef RANGES_HH
#define RANGES_HH
/* -------------------------------------------------------------------------- */
#include "iterator.hh"
#include "static_types.hh"
/* -------------------------------------------------------------------------- */
namespace tamaas {
/* -------------------------------------------------------------------------- */
/// Range class for complex iterators
template
class Range {
class iterator : public iterator_::iterator {
using parent = iterator_::iterator;
public:
using value_type = LocalType;
using reference = value_type;
iterator(const parent& o) : parent(o) {}
inline reference operator*() { return LocalType(this->data); }
inline reference operator*() const { return LocalType(this->data); }
};
public:
// useful type trait
template
struct is_valid_container
: std::is_same<
std::remove_cv_t::value_type>,
std::remove_cv_t> {};
public:
using value_type = LocalType;
using reference = value_type&&;
/// Construct from a container
template
Range(Container&& cont) : _begin(cont.begin()), _end(cont.end()) {
if (cont.getNbComponents() != local_size)
TAMAAS_EXCEPTION(
"Number of components does not match local tensor type size ("
<< cont.getNbComponents() << ", expected " << local_size << ")");
_begin.setStep(local_size);
_end.setStep(local_size);
}
/// Construct from two iterators
- Range(iterator _begin, iterator _end) : _begin(_begin), _end(_end) {}
+ Range(iterator _begin, iterator _end)
+ : _begin(std::move(_begin)), _end(std::move(_end)) {}
iterator begin() { return _begin; }
iterator end() { return _end; }
Range headless() const {
iterator shift(_begin);
return Range{++shift, _end};
}
private:
iterator _begin, _end;
};
/// Make range with proxy type
template
std::enable_if_t<
is_proxy::value,
Range>
range(Container&& cont) {
using RangeClass =
Range;
static_assert(
RangeClass::template is_valid_container::value,
"Mismatch between range's value type and container's value type");
return RangeClass(std::forward(cont));
}
/// Make range with standard type
template
std::enable_if_t::value, Range>
range(Container&& cont) {
using RangeClass = Range;
static_assert(
RangeClass::template is_valid_container::value,
"Mismatch between range's value type and container's value type");
return RangeClass(std::forward(cont));
}
/* -------------------------------------------------------------------------- */
} // namespace tamaas
#endif
diff --git a/src/core/surface.cpp b/src/core/surface.cpp
index cb3158b..4d778d7 100644
--- a/src/core/surface.cpp
+++ b/src/core/surface.cpp
@@ -1,422 +1,421 @@
/**
* @file
* @section LICENSE
*
* Copyright (©) 2016-19 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include
#include
#ifdef USE_CUDA
#include
#else
#include
#endif
/* -------------------------------------------------------------------------- */
#include "surface.hh"
#include "surface_statistics.hh"
/* -------------------------------------------------------------------------- */
#ifdef USING_IOHELPER
#include "dumper_paraview.hh"
#endif
/* -------------------------------------------------------------------------- */
namespace tamaas {
std::string fname = "surface_height.pdf";
/* -------------------------------------------------------------------------- */
template
void Surface::expandByLinearInterpolation() {
UInt n = this->size();
- Surface* old_s = new Surface(n, 1.);
+ auto old_s = std::make_unique(n, 1.);
int new_n = n * 2;
*old_s = *this;
this->setGridSize(new_n);
for (UInt i = 0; i < n; i++) {
for (UInt j = 0; j < n; j++) {
(*this)(i, j) = (*old_s)(i, j);
}
}
- delete old_s;
}
Real sinc(Real x) { return sin(M_PI * x) / (M_PI * x); }
/* -------------------------------------------------------------------------- */
template
void Surface::expandByShannonInterpolation(int /*factor*/) {
/* /!\ this->FFTTransform(); /!\ */
TAMAAS_EXCEPTION("Shannon interpolation needs old FFTTransform interface");
#if 0
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)(i,j);
}
for (UInt i = n/2; i < n; ++i)
for (UInt j = 0; j < n/2; ++j) {
s(N-n+i,j) = (*this)(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)(i,j);
}
for (UInt i = 0; i < n/2; ++i)
for (UInt j = n/2; j < n; ++j) {
s(i,N-n+j) = (*this)(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)(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; 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 < new_n; i++) {
for (UInt j = 0; j < new_n; j++) {
UInt i1 = i;
if (i1 > n)
i1 = new_n - i1;
UInt j1 = j;
if (j1 > n)
j1 = new_n - j1;
if (i == n || j == n) {
(*this)(i, j) = 0.;
continue;
}
(*this)(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)(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)(i, j) = s(i, j);
}
}
}
/* -------------------------------------------------------------------------- */
template
void Surface::contractByIgnoringMidPoints() {
UInt n = this->size();
Surface s(*this);
this->setGridSize(n / 2);
for (UInt i = 0; i < n; i++) {
for (UInt j = 0; j < n; j++) {
if (i % 2)
continue;
if (j % 2)
continue;
(*this)(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 = nullptr;
// 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
void Surface::recenterHeights() {
UInt n = this->size();
Real zmean = SurfaceStatistics::computeAverage(*this);
for (UInt i = 0; i < n * n; ++i)
(*this)(i) = (*this)(i)-zmean;
}
/* -------------------------------------------------------------------------- */
template
void Surface::generateWhiteNoiseSurface(Surface& sources,
long random_seed) {
// set the random gaussian generator
random_engine gen(random_seed);
normal_distribution gaussian_generator;
UInt n = sources.size();
for (UInt i = 0; i < n; ++i)
for (UInt j = 0; j < n; ++j) {
sources(i, j) = gaussian_generator(gen);
}
}
/* -------------------------------------------------------------------------- */
template class Surface;
template class Surface;
template class Surface;
template class Surface;
} // namespace tamaas
diff --git a/src/core/surface.hh b/src/core/surface.hh
index c95c163..3affae4 100644
--- a/src/core/surface.hh
+++ b/src/core/surface.hh
@@ -1,117 +1,117 @@
/**
* @file
* @section LICENSE
*
* Copyright (©) 2016-19 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
*/
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#ifndef __SURFACE_HH__
#define __SURFACE_HH__
/* -------------------------------------------------------------------------- */
#include
#include
#include
#include
/* -------------------------------------------------------------------------- */
#include "grid.hh"
/* -------------------------------------------------------------------------- */
namespace tamaas {
/**
* @deprecated should use Grid class instead
* @brief Square 2D surface class
*/
template
class Surface : public Grid {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
Surface() : Grid() {}
Surface(UInt a, Real L) : Grid() {
setGridSize(a);
setL(L);
}
- virtual ~Surface() {}
+ ~Surface() override = default;
Surface(const Surface& o) : Grid(o) {}
Surface(Surface&& o) : Grid(std::forward(o)) {}
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
//! set the grid size
void setGridSize(UInt n) { this->resize({n, n}); }
//! get lateral number of discretization points
inline UInt size() const { return this->n[0]; };
//! get the lateral size of the sample
inline Real getL() const { return 1.; };
//! get the lateral size of the sample
inline void setL(Real) {}
Surface& operator=(T val) {
Grid::operator=(val);
return *this;
}
Surface& operator=(const Surface& o) {
Grid::operator=(o);
return *this;
}
Surface& operator=(Surface&& o) {
Grid::operator=(std::forward(o));
return *this;
}
//! Write VTU file that is a set of points
void dumpToParaview(std::string filename) const;
//! create a new surface with linear interpolated points
void expandByLinearInterpolation();
//! create a new surface with linear interpolated points
void expandByShannonInterpolation(int factor);
//! create a new surface with mirroring
void expandByMirroring();
//! create a new surface with mirroring
void expandByPuttingZeros();
//! contract the surface by ignoring extra data
void contractByIgnoringMidPoints();
//! contract the surface by taking left bottom part of it
void contractByTakingSubRegion();
// recenter the heights to zero value
void recenterHeights();
// set all the members of the map to a given value
static void generateWhiteNoiseSurface(Surface& surface,
long random_seed);
virtual const Surface& getWrappedNumpy() { return *this; };
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
} // namespace tamaas
#include "surface_complex.hh"
#endif /* __SURFACE_HH__ */
diff --git a/src/core/surface_statistics.hh b/src/core/surface_statistics.hh
index 73dc73f..26e1a97 100644
--- a/src/core/surface_statistics.hh
+++ b/src/core/surface_statistics.hh
@@ -1,709 +1,702 @@
/**
* @file
* @section LICENSE
*
* Copyright (©) 2016-19 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
*/
/* -------------------------------------------------------------------------- */
#ifndef __SURFACE_STATISTICS_HH__
#define __SURFACE_STATISTICS_HH__
/* -------------------------------------------------------------------------- */
#include "fft_plan_manager.hh"
#include "fftransform.hh"
#include "surface.hh"
#include
/* -------------------------------------------------------------------------- */
namespace tamaas {
/**
* @deprecated should move code to Statistics class instead
* @brief Statistics calculations on surfaces
*/
class SurfaceStatistics {
- /* ------------------------------------------------------------------------ */
- /* Constructors/Destructors */
- /* ------------------------------------------------------------------------ */
-public:
- SurfaceStatistics(){};
- virtual ~SurfaceStatistics(){};
-
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
inline static Real computeMaximum(const Surface& s);
inline static Real computeMinimum(const Surface& s);
inline static Real
computeAverage(const Surface& s,
Real epsilon = std::numeric_limits::lowest()) {
return computeAverage(s, epsilon);
}
template
inline static T computeAverage(const Surface& s,
T epsilon = std::numeric_limits::lowest());
inline static Real
computeStdev(const Grid& s,
Real epsilon = std::numeric_limits::lowest());
inline static Real computeSkewness(const Surface& surface, Real avg,
Real std);
inline static Real computeKurtosis(const Surface& surface, Real avg,
Real std);
inline static Real computeRMSSlope(const Surface& surface);
inline static Real computeSpectralRMSSlope(Surface& surface);
inline static Real computeSpectralMeanCurvature(Surface& surface);
inline static Real computeSpectralStdev(Surface& surface);
// inline static void computeStatistics(Surface & surface);
inline static std::vector computeMoments(Surface& surface);
inline static Real computeAnalyticFractalMoment(UInt order, UInt k1, UInt k2,
Real hurst, Real rms, Real L);
//! compute perimeter
inline static Real computePerimeter(const Surface& surface,
Real eps = 1e-10);
//! get real contact area
inline static Real computeContactArea(const Surface& surface);
//! get real contact area
inline static Real computeContactAreaRatio(const Surface& surface);
template
inline static std::vector
computeDistribution(const Surface& surface, unsigned int n_bins,
Real min_value = std::numeric_limits::max(),
Real max_value = std::numeric_limits::lowest());
inline static std::vector
computeSpectralDistribution(const Surface& surface, unsigned int n_bins,
UInt cutoff = std::numeric_limits::max());
//! compute average amplitude
inline static Real computeAverageAmplitude(const Surface& surface);
inline static Complex
computeAverageAmplitude(const SurfaceComplex& surface);
//! sum all heights
inline static Real computeSum(const Surface