Page MenuHomec4science

surface_statistics.hh
No OneTemporary

File Metadata

Created
Mon, May 6, 20:40

surface_statistics.hh

/**
* @file
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @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 <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef __SURFACE_STATISTICS_HH__
#define __SURFACE_STATISTICS_HH__
/* -------------------------------------------------------------------------- */
#include "fft_plan_manager.hh"
#include "fftransform.hh"
#include "surface.hh"
#include <thrust/complex.h>
/* -------------------------------------------------------------------------- */
__BEGIN_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<Real>& s);
inline static Real computeMinimum(const Surface<Real>& s);
inline static UInt computeAverage(const Surface<UInt>& s, UInt epsilon = 0) {
SURFACE_FATAL("TO IMPLEMENT");
};
inline static unsigned long computeAverage(const Surface<unsigned long>& s,
unsigned long epsilon = 0) {
SURFACE_FATAL("TO IMPLEMENT");
};
inline static Real
computeAverage(const Surface<Real>& s,
Real epsilon = -1. * std::numeric_limits<Real>::max()) {
return computeAverage<Real>(s, epsilon);
}
template <typename T>
inline static T computeAverage(const Surface<T>& s,
T epsilon = -1. *
std::numeric_limits<T>::max());
inline static Real
computeStdev(const Grid<Real, 2>& s,
Real epsilon = -1. * std::numeric_limits<Real>::max());
inline static Real computeSkewness(const Surface<Real>& surface, Real avg,
Real std);
inline static Real computeKurtosis(const Surface<Real>& surface, Real avg,
Real std);
inline static Real computeRMSSlope(const Surface<Real>& surface);
inline static Real computeSpectralRMSSlope(Surface<Real>& surface);
inline static Real computeSpectralMeanCurvature(Surface<Real>& surface);
inline static Real computeSpectralStdev(Surface<Real>& surface);
// inline static void computeStatistics(Surface<Real> & surface);
inline static std::vector<Real> computeMoments(Surface<Real>& 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<Real>& surface,
Real eps = 1e-10);
//! get real contact area
inline static Real computeContactArea(const Surface<Real>& surface);
//! get real contact area
inline static Real computeContactAreaRatio(const Surface<Real>& surface);
template <bool consider_zeros = false>
inline static std::vector<int>
computeDistribution(const Surface<Real>& surface, unsigned int n_bins,
Real min_value = std::numeric_limits<Real>::max(),
Real max_value = -1 * std::numeric_limits<Real>::max());
inline static std::vector<Complex>
computeSpectralDistribution(const Surface<Real>& surface, unsigned int n_bins,
UInt cutoff = std::numeric_limits<UInt>::max());
//! compute average amplitude
inline static Real computeAverageAmplitude(const Surface<Real>& surface);
inline static Complex
computeAverageAmplitude(const SurfaceComplex<Real>& surface);
//! sum all heights
inline static Real computeSum(const Surface<Real>& surface);
//! compute auto correlation
inline static Surface<Real> computeAutocorrelation(Surface<Real>& surface);
//! compute powerspectrum
inline static SurfaceComplex<Real>
computePowerSpectrum(Surface<Real>& surface);
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
//#include "surface_statistics_inline_impl.cc"
/* -------------------------------------------------------------------------- */
template <bool consider_zeros>
std::vector<int>
SurfaceStatistics::computeDistribution(const Surface<Real>& surface,
unsigned int n_bins, Real min_value,
Real max_value) {
if (n_bins == 0)
SURFACE_FATAL("badly set number of bins");
Real min_heights;
Real max_heights;
std::vector<int> bins;
bins.resize(n_bins);
bins.assign(n_bins, 0);
min_heights = min_value;
max_heights = max_value;
if (max_value == -1. * std::numeric_limits<Real>::max())
max_heights = computeMaximum(surface);
if (min_value == std::numeric_limits<Real>::max())
min_heights = computeMinimum(surface);
int counter = 0;
const int n = surface.size();
for (int i = 0; i < n * n; ++i) {
Real value = surface(i);
if (!consider_zeros && value < zero_threshold)
continue;
if (value > max_heights || value < min_heights)
SURFACE_FATAL("out of bound value: "
<< min_heights << " <? " << value << " <? " << max_heights
<< " : bounds probably badly chosen");
Real ind = (value - min_heights) / (max_heights - min_heights);
unsigned int index = ind * n_bins;
if (index == n_bins)
--index;
++bins[index];
++counter;
}
if (consider_zeros && counter != n * n)
SURFACE_FATAL("problem in counting points");
// Real offset = (max_heights - min_heights)/n_bins;
// Real x = 0;
// Real f1 = 0, f2 = 0;
// for (unsigned int i = 0 ; i < n_bins ; ++i)
// {
// x = i*offset+min_heights;
// f1 = bins[i]/Real(n*n);
// f2 = bins[i]/Real(counter);
//}
Real min_non_zero = std::numeric_limits<Real>::max();
#pragma omp parallel for reduction(min : min_non_zero)
for (int i = 0; i < n * n; ++i) {
Real value = surface(i);
if (value < min_non_zero && value > 1e-14)
min_non_zero = value;
}
return bins;
}
/* -------------------------------------------------------------------------- */
std::vector<Complex> SurfaceStatistics::computeSpectralDistribution(
const Surface<Real>& surface, unsigned int n_bins, UInt cutoff) {
if (n_bins == 0)
SURFACE_FATAL("badly set number of bins");
const int n = surface.size();
Real min_value = SurfaceStatistics::computeMinimum(surface);
Real max_value = SurfaceStatistics::computeMaximum(surface);
std::vector<Complex> distrib_fft(n_bins);
const int N = n_bins;
Real L = max_value - min_value;
#pragma omp parallel for
for (int k = 0; k < N; ++k)
distrib_fft[k] = 0.;
#pragma omp parallel for
for (int k = 1; k < N / 2; ++k) {
for (int i = 0; i < n * n; ++i) {
Real value = surface(i);
Real angle = -2. * M_PI * k * (value - min_value) / L;
Complex phase = std::polar(1., angle);
distrib_fft[k] += phase;
distrib_fft[N - k] += phase;
}
}
for (int i = 0; i < n * n; ++i) {
Real value = surface(i);
Real angle = -2. * M_PI * N / 2 * (value - min_value) / L;
Complex phase = std::polar(1., angle);
distrib_fft[N / 2] += phase;
}
#pragma omp parallel for
for (int k = 1; k < N; ++k)
distrib_fft[k] /= n * n;
distrib_fft[0] = std::polar(1., 0.);
#pragma omp parallel for
for (int k = 1; k < N / 2; ++k) {
if (k >= (int)cutoff) {
distrib_fft[k] = 0.;
distrib_fft[N - k] = 0.;
}
}
// proceed to inverse fourier transform
#pragma omp parallel for
for (int k = 0; k < N; ++k) {
distrib_fft[k] = conj(distrib_fft[k]);
}
fftw_complex* in = (fftw_complex*)&distrib_fft[0];
fftw_plan p = fftw_plan_dft_1d(N, in, in, FFTW_FORWARD, FFTW_ESTIMATE);
fftw_execute(p);
fftw_destroy_plan(p);
std::vector<Complex> distrib;
distrib.resize(N);
#pragma omp parallel for
for (int k = 0; k < N; ++k) {
distrib[k] = conj(distrib_fft[k]);
}
return distrib;
}
/* -------------------------------------------------------------------------- */
Real SurfaceStatistics::computeAverageAmplitude(const Surface<Real>& surface) {
return surface.mean();
}
/* -------------------------------------------------------------------------- */
Complex SurfaceStatistics::computeAverageAmplitude(
const SurfaceComplex<Real>& surface) {
return surface.mean();
}
/* -------------------------------------------------------------------------- */
Real SurfaceStatistics::computeContactArea(const Surface<Real>& surface) {
Real L = surface.getL();
return SurfaceStatistics::computeContactAreaRatio(surface) * L * L;
}
/* -------------------------------------------------------------------------- */
Real SurfaceStatistics::computeContactAreaRatio(const Surface<Real>& surface) {
UInt area = 0;
UInt n = surface.size();
#pragma omp parallel for collapse(2), reduction(+ : area)
for (UInt i = 0; i < n; i++) {
for (UInt j = 0; j < n; j++) {
if (surface(i, j) > 1e-10)
area++;
}
}
return area / Real(n * n);
}
/* -------------------------------------------------------------------------- */
Surface<Real>
SurfaceStatistics::computeAutocorrelation(Surface<Real>& surface) {
SurfaceComplex<Real> correlation_heights = computePowerSpectrum(surface);
Surface<Real> acf(correlation_heights.size(), correlation_heights.getL());
FFTransform<Real, 2>& plan =
FFTPlanManager::get().createPlan(acf, correlation_heights);
plan.backwardTransform();
FFTPlanManager::get().destroyPlan(acf, correlation_heights);
return acf;
}
/* -------------------------------------------------------------------------- */
SurfaceComplex<Real>
SurfaceStatistics::computePowerSpectrum(Surface<Real>& surface) {
SurfaceComplex<Real> power_spectrum(surface.size(), surface.getL());
FFTransform<Real, 2>& plan =
FFTPlanManager::get().createPlan(surface, power_spectrum);
plan.forwardTransform();
UInt n = power_spectrum.dataSize();
UInt factor = power_spectrum.size() * power_spectrum.size();
#pragma omp parallel for
for (UInt i = 0; i < n; ++i)
power_spectrum(i) /= factor;
power_spectrum.makeItRealBySquare();
FFTPlanManager::get().destroyPlan(surface, power_spectrum);
return power_spectrum;
}
/* -------------------------------------------------------------------------- */
template <typename T>
T SurfaceStatistics::computeAverage(const Surface<T>& surface, T epsilon) {
Real avg = 0.0;
UInt cpt = 0;
UInt n = surface.size();
#pragma omp parallel for reduction(+ : avg, cpt)
for (UInt i = 0; i < n * n; i++) {
Real val = surface(i);
if (std::abs(val) > epsilon) {
avg += val;
++cpt;
}
}
avg /= cpt;
return avg;
}
/* -------------------------------------------------------------------------- */
Real SurfaceStatistics::computeSkewness(const Surface<Real>& surface, Real avg,
Real std) {
Real skw = 0.0;
UInt n = surface.size();
#pragma omp parallel for reduction(+ : skw)
for (UInt i = 0; i < n * n; i++) {
Real tmp = surface(i) - avg;
skw += (tmp * tmp * tmp);
}
skw /= (n * std * std * std);
return skw;
}
/* -------------------------------------------------------------------------- */
Real SurfaceStatistics::computeKurtosis(const Surface<Real>& surface, Real avg,
Real std) {
Real kur = 0.0;
UInt n = surface.size();
#pragma omp parallel for reduction(+ : kur)
for (UInt i = 0; i < n * n; i++) {
Real tmp = surface.size() - avg;
kur += (tmp * tmp * tmp * tmp);
}
kur /= (n * std * std * std * std);
return kur - 3;
}
/* -------------------------------------------------------------------------- */
Real SurfaceStatistics::computeMaximum(const Surface<Real>& surface) {
Real _max = -1. * std::numeric_limits<Real>::max();
UInt n = surface.size();
#pragma omp parallel for reduction(max : _max)
for (UInt i = 0; i < n * n; i++) {
_max = std::max(surface(i), _max);
}
return _max;
}
/* -------------------------------------------------------------------------- */
Real SurfaceStatistics::computeMinimum(const Surface<Real>& surface) {
Real _min = std::numeric_limits<Real>::max();
UInt n = surface.size();
#pragma omp parallel for reduction(min : _min)
for (UInt i = 0; i < n * n; i++) {
_min = std::min(surface(i), _min);
}
return _min;
}
/* -------------------------------------------------------------------------- */
Real SurfaceStatistics::computeRMSSlope(const Surface<Real>& surface) {
UInt n = surface.size();
Surface<Real> grad(n, 1.);
for (UInt i = 0, m = 0; i < n; i++) {
for (UInt j = 0; j < n; j++) {
UInt k = i + n * j;
// xl = ((i==0)?(k+n-1):(k-1));
UInt xh = ((i == (n - 1)) ? (k - n + 1) : (k + 1));
// yl = ((j==0)?(k+n*n-n):(k-n));
UInt yh = ((j == (n - 1)) ? (k - n * n + n) : (k + n));
Real gx = surface(xh) - surface(k);
Real gy = surface(yh) - surface(k);
grad(m++) = gx * gx + gy * gy;
}
}
Real avg = SurfaceStatistics::computeAverage(grad);
Real slp = sqrt(avg); /* According to paper Hyun PRE 70:026117 (2004) */
Real scale_factor = surface.getL() / n;
return slp / scale_factor;
}
/* -------------------------------------------------------------------------- */
Real SurfaceStatistics::computeSpectralRMSSlope(Surface<Real>& surface) {
SurfaceComplex<Real> power = computePowerSpectrum(surface);
UInt n = surface.size();
Real rms_slopes = 0;
// /!\ commented code was causing race conditions with dummy variable in
// GridHermitian
#pragma omp parallel for collapse(2), reduction(+ : rms_slopes)
for (UInt i = 1; i < n / 2; ++i)
for (UInt j = 1; j < n / 2; ++j) {
rms_slopes += 2. * ((i * i) + (j * j)) * power(i, j).real();
// rms_slopes += 1.*((i*i)+(j*j))*power(n-i,n-j).real();
rms_slopes += 2. * ((i * i) + (j * j)) * power(n - i, j).real();
// rms_slopes += 1.*((i*i)+(j*j))*power(i,n-j).real();
}
// external line (i or j == 0)
#pragma omp parallel for reduction(+ : rms_slopes)
for (UInt i = 1; i < n / 2; ++i) {
rms_slopes += 1. * (i * i) * power(i, 0).real();
rms_slopes += 1. * (i * i) * power(n - i, 0).real();
rms_slopes += 2. * (i * i) * power(0, i).real();
// rms_slopes += 1.*(i*i)*power(0,n-i).real();
}
// internal line (i or j == n/2)
#pragma omp parallel for reduction(+ : rms_slopes)
for (UInt i = 1; i < n / 2; ++i) {
rms_slopes += 0.5 * (i * i + n * n / 4) * power(i, n / 2).real();
rms_slopes += 0.5 * (i * i + n * n / 4) * power(n - i, n / 2).real();
rms_slopes += 1. * (i * i + n * n / 4) * power(n / 2, i).real();
// rms_slopes += 0.5*(i*i+n*n/4)*power(n/2,n-i).real();
}
{
// i == n/2 j == n/2
rms_slopes += 0.25 * (n * n / 2) * power(n / 2, n / 2).real();
// i == 0 j == n/2
rms_slopes += 1. * (n * n / 4) * power(0, n / 2).real();
// i == n/2 j == 0
rms_slopes += 1. * (n * n / 4) * power(n / 2, 0).real();
}
rms_slopes = 2. * M_PI / n * sqrt(rms_slopes);
Real scale_factor = surface.getL() / n;
return rms_slopes / scale_factor;
}
/* -------------------------------------------------------------------------- */
Real SurfaceStatistics::computeStdev(const Grid<Real, 2>& surface,
Real epsilon) {
UInt n = surface.dataSize();
UInt cpt = 0;
Real std = 0.0;
Real avg = 0.0;
#pragma omp parallel for reduction(+ : avg, std, cpt)
for (UInt i = 0; i < n; i++) {
Real val = surface(i);
if (val > epsilon) {
avg += val;
std += val * val;
++cpt;
}
}
avg /= cpt;
return sqrt(std / cpt - avg * avg);
}
/* -------------------------------------------------------------------------- */
Real SurfaceStatistics::computeSpectralStdev(Surface<Real>& surface) {
SurfaceComplex<Real> power = computePowerSpectrum(surface);
Real rms_heights = 0;
UInt n = surface.size();
#pragma omp parallel for collapse(2), reduction(+ : rms_heights)
for (UInt i = 0; i < n; ++i)
for (UInt j = 0; j < n; ++j) {
rms_heights += power(i, j).real();
}
rms_heights = sqrt(rms_heights);
return rms_heights;
}
/* -------------------------------------------------------------------------- */
Real SurfaceStatistics::computeSpectralMeanCurvature(Surface<Real>& surface) {
SurfaceComplex<Real> power = computePowerSpectrum(surface);
UInt n = surface.size();
Real rms_curvatures = 0;
#pragma omp parallel for collapse(2), reduction(+ : rms_curvatures)
for (UInt i = 1; i < n / 2; ++i)
for (UInt j = 1; j < n / 2; ++j) {
Real coeff = ((i * i) + (j * j));
coeff *= coeff;
rms_curvatures += 1. * coeff * power(i, j).real();
rms_curvatures += 1. * coeff * power(n - i, n - j).real();
rms_curvatures += 1. * coeff * power(n - i, j).real();
rms_curvatures += 1. * coeff * power(i, n - j).real();
}
// external line (i or j == 0)
#pragma omp parallel for reduction(+ : rms_curvatures)
for (UInt i = 1; i < n / 2; ++i) {
Real coeff = i * i;
coeff *= coeff;
rms_curvatures += 4. / 3. * coeff * power(i, 0).real();
rms_curvatures += 4. / 3. * coeff * power(n - i, 0).real();
rms_curvatures += 4. / 3. * coeff * power(0, i).real();
rms_curvatures += 4. / 3. * coeff * power(0, n - i).real();
}
// internal line (i or j == n/2)
#pragma omp parallel for reduction(+ : rms_curvatures)
for (UInt i = 1; i < n / 2; ++i) {
Real coeff = (i * i + n * n / 4);
coeff *= coeff;
rms_curvatures += 0.5 * coeff * power(i, n / 2).real();
rms_curvatures += 0.5 * coeff * power(n - i, n / 2).real();
rms_curvatures += 0.5 * coeff * power(n / 2, i).real();
rms_curvatures += 0.5 * coeff * power(n / 2, n - i).real();
}
{
// i == n/2 j == n/2
rms_curvatures +=
0.25 * (n * n / 2) * (n * n / 2) * power(n / 2, n / 2).real();
// i == 0 j == n/2
rms_curvatures +=
2. / 3. * (n * n / 4) * (n * n / 4) * power(0, n / 2).real();
// i == n/2 j == 0
rms_curvatures +=
2. / 3. * (n * n / 4) * (n * n / 4) * power(n / 2, 0).real();
}
rms_curvatures *= 9. / 4.;
rms_curvatures = M_PI / n / n * sqrt(rms_curvatures);
return rms_curvatures;
}
/* -------------------------------------------------------------------------- */
Real SurfaceStatistics::computePerimeter(const Surface<Real>& surface,
Real eps) {
int perimeter = 0;
UInt n = surface.size();
#pragma omp parallel for collapse(2), reduction(+ : perimeter)
for (UInt i = 0; i < n; ++i) {
for (UInt j = 0; j < n; ++j) {
if (j > 0 && ((surface(i, (j - 1)) < eps && surface(i, j) > eps) ||
(surface(i, (j - 1)) > eps && surface(i, j) < eps)))
perimeter++;
if (i > 0 && ((surface(j, (i - 1)) < eps && surface(j, i) > eps) ||
(surface(j, (i - 1)) > eps && surface(j, i) < eps)))
perimeter++;
}
}
return perimeter / Real(n);
}
/* -------------------------------------------------------------------------- */
Real SurfaceStatistics::computeSum(const Surface<Real>& surface) {
Real sum = 0.;
UInt n = surface.size();
#pragma omp parallel for reduction(+ : sum)
for (UInt i = 0; i < n * n; ++i)
sum += surface(i);
return sum;
}
/* -------------------------------------------------------------------------- */
std::vector<Real> SurfaceStatistics::computeMoments(Surface<Real>& surface) {
SurfaceComplex<Real> power = computePowerSpectrum(surface);
Real L = surface.getL();
UInt n = surface.size();
Real k_factor = 2. * M_PI / L;
std::vector<std::vector<Real>> moment;
moment.resize(6);
for (int i = 0; i < 5; i++)
moment[i].resize(5);
for (UInt i = 0; i < n / 2; i++) {
Real i0 = pow(Real(i) * k_factor, 0);
Real i2 = pow(Real(i) * k_factor, 2);
Real i4 = pow(Real(i) * k_factor, 4);
Real im0 = pow(-Real(i) * k_factor, 0);
Real im2 = pow(-Real(i) * k_factor, 2);
Real im4 = pow(-Real(i) * k_factor, 4);
for (UInt j = 0; j < n / 2; j++) {
Real Phi = power(i, j).real();
Real Phi_10;
Real Phi_01;
Real Phi_11;
if (i == 0 && j == 0) {
Phi_10 = 0;
Phi_11 = 0;
Phi_01 = 0;
} else if (i == 0) {
Phi_10 = 0;
Phi_11 = 0;
Phi_01 = power(i, (n - j)).real();
} else if (j == 0) {
Phi_10 = power(n - i, j).real();
Phi_11 = 0;
Phi_01 = 0;
} else {
Phi_10 = power(n - i, j).real();
Phi_11 = power(n - i, (n - j)).real();
Phi_01 = power(i, (n - j)).real();
}
Real j0 = pow(Real(j) * k_factor, 0);
Real j2 = pow(Real(j) * k_factor, 2);
Real j4 = pow(Real(j) * k_factor, 4);
Real jm0 = pow(-Real(j) * k_factor, 0);
Real jm2 = pow(-Real(j) * k_factor, 2);
Real jm4 = pow(-Real(j) * k_factor, 4);
moment[0][0] += i0 * j0 * Phi + im0 * j0 * Phi_10 + i0 * jm0 * Phi_01 +
im0 * jm0 * Phi_11;
moment[0][2] += i0 * j2 * Phi + im0 * j2 * Phi_10 + i0 * jm2 * Phi_01 +
im0 * jm2 * Phi_11;
moment[2][0] += i2 * j0 * Phi + im2 * j0 * Phi_10 + i2 * jm0 * Phi_01 +
im2 * jm0 * Phi_11;
moment[2][2] += i2 * j2 * Phi + im2 * j2 * Phi_10 + i2 * jm2 * Phi_01 +
im2 * jm2 * Phi_11;
moment[0][4] += i0 * j4 * Phi + im0 * j4 * Phi_10 + i0 * jm4 * Phi_01 +
im0 * jm4 * Phi_11;
moment[4][0] += i4 * j0 * Phi + im4 * j0 * Phi_10 + i4 * jm0 * Phi_01 +
im4 * jm0 * Phi_11;
}
}
std::vector<Real> mean_moments;
// m2
Real mean_m2 = 0.5 * (moment[0][2] + moment[2][0]);
mean_moments.push_back(mean_m2);
// m4
Real mean_m4 = (3 * moment[2][2] + moment[0][4] + moment[4][0]) / 3.;
mean_moments.push_back(mean_m4);
return mean_moments;
}
/* -------------------------------------------------------------------------- */
Real SurfaceStatistics::computeAnalyticFractalMoment(UInt order, UInt k1,
UInt k2, Real hurst,
Real A, Real L) {
Real xi = k2 / k1;
Real exp = -2. * hurst;
Real _k1 = 2. * M_PI / L * k1;
Real Cq;
switch (order) {
case 0:
Cq = 2. * M_PI;
break;
case 2:
Cq = M_PI;
break;
case 4:
Cq = 3. / 4. * M_PI;
break;
default:
SURFACE_FATAL("invalid order");
}
exp = order - 2. * hurst;
Real res = A * Cq * pow(_k1, exp) / exp * (pow(xi, exp) - 1);
return res;
}
/* -------------------------------------------------------------------------- */
__END_TAMAAS__
#endif /* __SURFACE_STATISTICS_HH__ */

Event Timeline