diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bd1cc9d --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*~ +.sconf_temp +.sconsign.dblite +*.log +build* \ No newline at end of file diff --git a/README b/README new file mode 100644 index 0000000..31855e5 --- /dev/null +++ b/README @@ -0,0 +1,27 @@ +* Welcome to the Rough surface toolkit of LSMS +* Build +The build system uses SCons. In order to construct the library you should hit: + +scons + +And to speedup the process you can do: + +scons -j 6 + +In order to clean the build + +scons -c + +In order to compile in debug + +scons build_type=debug + +Indeed the default was + +scons build_type=release + + +In order to make the compilation more verbose + +scons verbose=true + diff --git a/Sconstruct b/Sconstruct new file mode 100644 index 0000000..6b8bfc6 --- /dev/null +++ b/Sconstruct @@ -0,0 +1,71 @@ +import os,sys +path = '/usr/lib/scons/' +sys.path.append(path) + +#from SCons import * +#from SCons.Environment import * +#from SCons.Variables import * +#from SCons.Util import * + + +#script_dir = GetOption('file') +#if script_dir == []: +# script_dir = '.' +#else: +# script_dir = script_dir[0] + +colors = {} +colors['cyan'] = '' +colors['purple'] = '' +colors['blue'] = '' +colors['green'] = '' +colors['yellow'] = '' +colors['red'] = '' +colors['end'] = '' + +#colors['cyan'] = '\033[96m' +#colors['purple'] = '\033[95m' +#colors['blue'] = '\033[94m' +#colors['green'] = '\033[92m' +#colors['yellow'] = '\033[93m' +#colors['red'] = '\033[91m' +#colors['end'] = '\033[0m' + + +main_env = Environment() + +vars = Variables('build-setup.conf') +vars.Add('build_type', 'Could be RELEASE or DEBUG', 'release') +vars.Add('prefix', 'Prefix where to install', '/usr/local') +vars.Add('verbose', 'Activate verbosity', False) +vars.Update(main_env) + +build_type = main_env['build_type'].lower() +build_dir = 'build-' + main_env['build_type'].lower() +print "Building in ", build_dir +if type(main_env['verbose']) is not bool: + main_env['verbose'] = (main_env['verbose'].lower() == 'true' or main_env['verbose'] == 1) + +verbose = main_env['verbose'] +if not verbose: + main_env['SHCXXCOMSTR'] = unicode('{0}[Compiling] {1}$SOURCE{2}'.format(colors['green'],colors['blue'],colors['end'])) + main_env['SHLINKCOMSTR'] = unicode('{0}[Linking] {1}$TARGET{2}'.format(colors['purple'],colors['blue'],colors['end'])) + main_env['SWIGCOMSTR'] = unicode('{0}[Swig] {1}$SOURCE{2}'.format(colors['yellow'],colors['blue'],colors['end'])) + +main_env['build_dir'] = build_dir +main_env['include_dirs'] = ['src','python'] +main_env['CXXFLAGS'] = ['-std=c++11', '-Wall', '-fopenmp'] +if build_type == 'debug': main_env['CXXFLAGS'] += ['-g'] +else : main_env['CXXFLAGS'] += ['-O3'] +main_env['LIBPATH'] = [os.path.abspath(os.path.join(build_dir,'src'))] +main_env['RPATH'] = "$LIBPATH" + + +# save new values +vars.Save('build-setup.conf', main_env) +Export('main_env') + +SConscript('src/SConscript',variant_dir=os.path.join(build_dir,'src'),duplicate=False) +SConscript('python/SConscript',variant_dir=os.path.join(build_dir,'python'),duplicate=False) + + diff --git a/doc/spectral_statistical_moments.tex b/doc/spectral_statistical_moments.tex new file mode 100644 index 0000000..080353d --- /dev/null +++ b/doc/spectral_statistical_moments.tex @@ -0,0 +1,285 @@ +\documentclass[10pt]{article} + +\usepackage[T1]{fontenc} +\usepackage[latin1]{inputenc} +\usepackage{color,graphicx} +\usepackage{url} +\usepackage{xifthen} +\usepackage{wrapfig} +\usepackage{fullpage} + +\newcommand{\phx}{\frac{2\pi k_x}{N}} +\newcommand{\phy}{\frac{2\pi k_y}{N}} + +\newcommand{\cox}{\cos\left(\phx x\right)} +\newcommand{\coy}{\cos\left(\phy y\right)} + +\newcommand{\six}{\sin\left(\phx x\right)} +\newcommand{\siy}{\sin\left(\phy y\right)} + +\newcommand{\ncox}[1]{\cos^{#1}\left(\phx x\right)} +\newcommand{\ncoy}[1]{\cos^{#1}\left(\phy y\right)} + +\newcommand{\nsix}[1]{\sin^{#1}\left(\phx x\right)} +\newcommand{\nsiy}[1]{\sin^{#1}\left(\phy y\right)} + + +\newcommand{\scox}{\ncox{2}} +\newcommand{\scoy}{\ncoy{2}} + +\newcommand{\ssix}{\nsix{2}} +\newcommand{\ssiy}{\nsiy{2}} + + +\begin{document} +Our surface is described with: +\begin{eqnarray*} +h(x,y) = \cox \coy +\end{eqnarray*} + +\section{Root mean square of heights} +The RMS is defined as: +\begin{eqnarray*} + &=& \frac{1}{N^2} \int_0^N \int_0^N \scox \scoy dx dy = \frac{1}{N^2} \int_0^N \scox dx \int_0^N \scoy dy \\ +&=& \frac{1}{N^2} \frac{N^2}{4 \pi^2 k_x k_y} \int_0^{2\pi k_x} \cos^2(x) dx \int_0^{2\pi k_y} \cos^2(y) dy +\end{eqnarray*} +Let us focus on the integral: +\begin{eqnarray} +\label{I1} +\int_0^{2\pi k_x} \cos^2(x) dx = \frac{1}{2} \left[ x + \frac{\sin(2x)}{2} \right]_0^{2\pi k_x} + = \pi k_x +\end{eqnarray} +We finally obtain: +\begin{eqnarray*} + &=& \frac{1}{4 \pi^2 k_x k_y} \pi^2 k_x k_y = \frac{1}{4} +\end{eqnarray*} +\section{Root mean square of slopes} +The gradient is expressed as: +\begin{eqnarray*} +\nabla h(x,y) = \left( +\begin{array}{c} + - \phx \six \coy \\ + - \phy \cox \siy \\ +\end{array} +\right) +\end{eqnarray*} +The length of the gradient is: +\begin{eqnarray*} +\nabla h(x,y)^2 = \frac{4\pi^2}{N^2} \left\{ +k_x^2 \ssix \scoy + k_y^2 \scox \ssiy +\right\} +\end{eqnarray*} +\subsection{General direction $k_x \neq 0$, $k_y \neq 0$ } +Let us define the value: +\begin{eqnarray*} +A &=& \int_0^N \int_0^N \ssix \scoy dxdy \\ + &=& \int_0^N \ssix dx \int_0^N \scoy dy + = \frac{N^2}{4\pi^2 k_x k_y} \int_0^{2\pi k_x} \cos^2(x) dx \int_0^{2\pi k_y} \cos^2(y) dy \\ + %&=& \int_0^N \ssix dx \frac{N}{2\pi k_y} \left[ \frac{1}{2} \left( y + \frac{\sin(2y)}{2} \right) \right]_0^{2\pi k_y} + %= \frac{2\pi k_y N}{4\pi k_y} \int_0^N \ssix dx \\ + %&=& \frac{N}{2} \int_0^N \ssix dx = \frac{N}{2} \frac{N}{2\pi k_x} \left[ \frac{1}{2} \left( x + \frac{\sin(2x)}{2} \right) \right]_0^{2\pi k_x} = \frac{N^2}{8\pi k_x} \left[ x + \frac{\sin(2x)}{2} \right]_0^{2\pi k_x} \\ +%&=& \frac{N^2 2\pi k_x}{8\pi k_x} = \frac{N^2}{4} +\end{eqnarray*} + +With equation (\ref{I1}) we then we obtain: +\begin{eqnarray*} +A &=& \frac{N^2}{4\pi^2 k_x k_y} \int_0^{2\pi k_x} \cos^2(x) dx \int_0^{2\pi k_y} \cos^2(y) dy \\ + &=& \frac{N^2}{4\pi^2 k_x k_y} \pi^2 k_x k_y = \frac{N^2}{4} +\end{eqnarray*} + +So that the average length of the gradient is becoming: +\begin{eqnarray*} +< \nabla h(x,y)^2 > = \frac{1}{N^2} \int_0^N \int_0^N \nabla h(x,y)^2 dx dy = +\frac{4\pi^2}{N^4} A \left( k_x^2 + k_y^2 \right) = +\frac{\pi^2}{N^2} \left( k_x^2 + k_y^2 \right) +\end{eqnarray*} + +\subsection{Single direction case $k_y = 0$} + +\begin{eqnarray*} +\nabla h(x,y)^2 = \frac{4\pi^2}{N^2} k_x^2 \ssix +\end{eqnarray*} +et: +\begin{eqnarray*} +A &=& \int_0^N \int_0^N \ssix dxdy \\ + &=& N \int_0^N \ssix dx + = N \frac{N}{2\pi k_x} \int_0^N \sin^2(x) dx = \frac{N^2}{2\pi k_x} \pi k_x + = \frac{N^2}{2} +\end{eqnarray*} + +and finally: + +\begin{eqnarray*} +< \nabla h(x,y)^2 > = \frac{1}{N^2} \int_0^N \int_0^N \nabla h(x,y)^2 dx dy = +\frac{4\pi^2}{N^4} k_x^2 \frac{N^2}{2} = +\frac{2\pi^2}{N^2} k_x^2 +\end{eqnarray*} + +\section{Root mean square of Gauss Curvature} + +The gauss curvature is defined as the product of the principal curvatures. +It is thus extracted from the determinent of the square gradient matrix: +\begin{eqnarray*} +\nabla^2 h(x,y) &= \left( +\begin{array}{cc} + \frac{4\pi^2 k_x^2}{N^2} \cox \coy & \frac{4\pi^2 k_x k_y}{N^2} \six \siy \\ + \frac{4\pi^2 k_x k_y}{N^2} \six \siy & \frac{4\pi^2 k_y^2}{N^2} \cox \coy \\ +\end{array} +\right) +\\ +&= \frac{4\pi^2}{N^2} \left( +\begin{array}{cc} + k_x^2 \cox \coy & k_x k_y \six \siy \\ + k_x k_y \six \siy & k_y^2 \cox \coy \\ +\end{array} +\right) +\end{eqnarray*} +we obtain: +\begin{eqnarray*} +\kappa = det (\nabla^2 h(x,y)) +&=& \frac{16\pi^4 k_x^2 k_y^2}{N^4} \left( \scox \scoy +- \ssix \ssiy \right) \\ +\end{eqnarray*} +we want to compute $<\kappa^2>$ : +\begin{eqnarray*} +<\kappa^2> &=& + \frac{1}{N^2} \left( \frac{16\pi^4 k_x^2 k_y^2}{N^4} \right)^2 \int_0^N \int_0^N \left[ \ncox{2} \ncoy{2} +- \nsix{2} \nsiy{2} \right]^2 dxdy \\ +&=& \frac{2^8\pi^8 k_x^4 k_y^4}{N^{10}} \int_0^N \int_0^N +\left[ \quad \ncox{4} \ncoy{4} ++ \nsix{4} \nsiy{4} \right. \\ +& & \qquad \qquad \qquad \qquad \qquad \left. - 2 \ncox{2} \ncoy{2} \nsix{2} \nsiy{2} \qquad \right]dx dy\\ +\end{eqnarray*} + +\subsection{General direction $k_x \neq 0$, $k_y \neq 0$ } +Let us focus on the integral: +\begin{eqnarray*} +A &=& \int_0^N \int_0^N \ncox{4} \ncoy{4} dxdy = \int_0^N \ncox{4} dx \int_0^N \ncoy{4} dy \\ +&=& \frac{N^2}{4\pi^2 k_x k_y} \int_0^{2\pi k_x} \cos^4(x) dx \int_0^{2\pi k_y} \cos^4(y) dy +\end{eqnarray*} + +If we focus again only on the simple integral: +\begin{eqnarray*} +\int_0^{2\pi k_x} \cos^4(x) dx = \left[ \frac{\cos^{3}(x) \sin(x)}{4} + \frac{3}{4} \int_0^x \cos^2(x')dx' \right]_0^{2\pi k_x} += \frac{3}{4} \left[ \int_0^{2\pi k_x} \cos^2(x')dx' \right] = \frac{3 \pi k_x}{4} +\end{eqnarray*} +Then: +\begin{eqnarray*} +A = \frac{N^2}{4\pi^2 k_x k_y} \int_0^{2\pi k_x} \cos^4(x) dx \int_0^{2\pi k_y} \cos^4(y) dy = +\frac{N^2}{4\pi^2 k_x k_y} \frac{9 \pi^2 k_xk_y}{16} = N^2 \frac{9}{2^6} +\end{eqnarray*} +It can be demonstrated that: +\begin{eqnarray*} +\int_0^N \int_0^N \nsix{4} \nsix{4} dxdy = N^2 \frac{9}{2^6} +\end{eqnarray*} +The other integral we need to focus on is: +\begin{eqnarray*} +B &=& \int_0^N \int_0^N \ncox{2} \ncoy{2} \nsix{2} \nsiy{2} dxdy \\ +&=& \int_0^N \ncox{2} \nsix{2} dx \int_0^N \ncoy{2} \nsiy{2} dy \\ +&=& \frac{N^2}{4\pi^2 k_x k_y} \int_0^{2\pi k_x} \cos^2(x) \sin^2(x) dx \int_0^{2\pi k_y} \cos^2(y) \sin^2(y) dy +\end{eqnarray*} +Again we focus on a sub integral: +\begin{eqnarray*} +\int_0^{2\pi k_x} \cos^2(x) \sin^2(x) dx &=& \int_0^{2\pi k_x} \cos^2(x) - \int_0^{2\pi k_x} \cos^4(x) dx = \frac{2\pi k_x}{2} - \frac{3\pi k_x}{4} \\ +&=& \frac{\pi k_x}{4} \\ +\end{eqnarray*} +So that: +\begin{eqnarray*} +B &=& \frac{N^2}{4\pi^2 k_x k_y} \frac{\pi^2 k_x k_y}{16} = \frac{N^2}{2^6} +\end{eqnarray*} +Finally: +\begin{eqnarray*} +<\kappa^2> &=& + \frac{2^8\pi^8 k_x^4 k_y^4}{N^{10}} \left( 2 A - 2 B \right) += \frac{2^9\pi^8 k_x^4 k_y^4}{N^{10}} \left( N^2 \frac{9}{2^6} - N^2 \frac{1}{2^6} \right) += \frac{2^9\pi^8 k_x^4 k_y^4}{2^6 N^8} \left( 9 - 1 \right) \\ +&=& \frac{2^{12} \pi^8 k_x^4 k_y^4}{2^6 N^8} = \frac{2^6 \pi^8 k_x^4 k_y^4}{N^4} +\end{eqnarray*} + +\subsection{Single direction case $k_y = 0$} + + +In that case the double derivative of heights becomes: +\begin{eqnarray*} +\nabla^2 h(x,y) = \left( +\begin{array}{cc} + \frac{4\pi^2 k_x^2}{N^2} \cox & 0 \\ + 0 & 0 \\ +\end{array} +\right) +\end{eqnarray*} +Since the determinent is null, we should define the single direction curvature as: +$$\kappa = \frac{4\pi^2 k_x^2}{N^2} \cox$$ +and the root mean square of curvatures we want to compute becomes: + +\begin{eqnarray*} +<\kappa^2> &=& + \frac{1}{N^2} \left( \frac{4\pi^2 k_x^2 }{N^2} \right)^2 \int_0^N \int_0^N \ncox{2} dxdy \\ +&=& \frac{2^4\pi^4 k_x^4}{N^{6}} N \int_0^N \ncox{2} dx = \frac{2^4\pi^4 k_x^4}{N^{5}} \frac{N}{2\pi k_x} \int_0^{2\pi k_x} \cos^2(x) dx = \frac{2^4\pi^4 k_x^4}{N^{4}} \frac{1}{2\pi k_x} \pi k_x \\ +&=& \frac{2^3\pi^4 k_x^4}{N^{4}} +\end{eqnarray*} + +\section{Root mean square of Mean Curvature} + +\subsection{General direction $k_x \neq 0$, $k_y \neq 0$ } + +The mean curvature is half the sum of the principal curvatures. +It is thus extracted from the trace of the square gradient matrix. + +\begin{eqnarray*} +\kappa = \frac{1}{2} tr(\nabla^2 h(x,y)) &=& +\frac{2\pi^2 k_x^2 }{N^2} \scox \scoy + +\frac{2\pi^2 k_y^2}{N^2} \scox \scoy +\end{eqnarray*} +Then we obtain: +\begin{eqnarray*} +<\kappa^2> &=& + \frac{1}{N^2} \int_0^N \int_0^N \left[ \frac{2\pi^2 k_x^2 }{N^2} \scox \scoy + +\frac{2\pi^2 k_y^2}{N^2} \scox \scoy \right]^2 dxdy \\ +&=& \frac{1}{N^2} \int_0^N \int_0^N \left[ \frac{2\pi^2 (k_x^2 + k_y^2)}{N^2} \scox \scoy \right]^2 dxdy \\ +&=& \frac{4\pi^4(k_x^2 + k_y^2)^2}{N^6} \int_0^N \int_0^N \ncox{4} \ncoy{4} dxdy \\ +&=& \frac{4\pi^4(k_x^2 + k_y^2)^2}{N^6} \frac{N^2}{4\pi^2 k_x k_y} \int_0^{2\pi k_x} \cos^4(x) dx \int_0^{2\pi k_y} \cos^4(y) dy \\ +&=& \frac{\pi^2(k_x^2 + k_y^2)^2}{N^4} \frac{1}{k_x k_y} \int_0^{2\pi k_x} \cos^4(x) dx \int_0^{2\pi k_y} \cos^4(y) dy \\ +&=& \frac{\pi^2(k_x^2 + k_y^2)^2}{N^4} \frac{1}{k_x k_y} \frac{3\pi k_x}{4} \frac{3\pi k_y}{4} = +\frac{(k_x^2 + k_y^2)^2}{N^4} \frac{9\pi^4}{16} +\end{eqnarray*} + +\subsection{Single direction case $k_y = 0$} +In that case the curvature becomes: + +\begin{eqnarray*} +\kappa = tr(\nabla^2 h(x,y)) &=& +\frac{2\pi^2 k_x^2 }{N^2} \scox +\end{eqnarray*} + +Then we obtain: +\begin{eqnarray*} +<\kappa^2> &=& + \frac{1}{N^2} \int_0^N \int_0^N \left[ \frac{2\pi^2 k_x^2 }{N^2} \scox \right]^2 dxdy \\ +&=& \frac{4\pi^4 k_x^4 }{N^6} \int_0^N \int_0^N \ncox{4} dxdy = \frac{4\pi^4 k_x^4}{N^6} N \frac{N}{2\pi k_x} \int_0^{2\pi k_x} \cos^4(x) dx \\ +&=& \frac{2\pi^3 k_x^4}{N^4} \frac{1}{k_x} \int_0^{2\pi k_x} \cos^4(x) dx = \frac{2\pi^3 k_x^4}{N^4} \frac{1}{k_x} \frac{3\pi k_x}{4} = \frac{3\pi^4 k_x^4}{2N^4} +\end{eqnarray*} + +\section{computation of Alpha} + +By definition: +\begin{eqnarray*} + \alpha = \frac{m_0 m_4}{m_2^2} = \frac{M_0 3/8 M_4}{1/4 M_2^2} +\end{eqnarray*} +Dans le cas d'un unique mode $(k_x,k_y)$ we obtain: +\begin{eqnarray*} + \alpha = \frac{1/4 \cdot 3/8 (k_x^2 + k_y^2)^2}{1/4 (k_x^2 + k_y^2)^2} = \frac{3}{8} +\end{eqnarray*} +or with geometric definition (if $k_x \neq 0$ and $k_y \neq 0$): +\begin{eqnarray*} + \alpha = \frac{1/4 \cdot 3/8 \pi^4 9/16 (k_x^2 + k_y^2)^2}{1/4 \pi^4 (k_x^2 + k_y^2)^2} = \frac{3}{8} \frac{9}{16} = \frac{3^3}{2^7} +\end{eqnarray*} +or with geometric definition (if $k_y = 0$): +\begin{eqnarray*} + \alpha = \frac{1/2 \cdot 3/8 \pi^4 3/2 (k_x^2 + k_y^2)^2}{1/4 4 \pi^4 (k_x^2 + k_y^2)^2} = \frac{9}{4} \frac{1}{8} = \frac{3^2}{2^5} +\end{eqnarray*} + +It does not work !!! unless I made an(other) arithmetic error. + +\end{document} + diff --git a/python-examples/fractal_surface.py b/python-examples/fractal_surface.py new file mode 100644 index 0000000..6923649 --- /dev/null +++ b/python-examples/fractal_surface.py @@ -0,0 +1,78 @@ +from python_surface import * + +#generate surface +SG = SurfaceGeneratorFilterFFT() +SG.getGridSize().assign(512) +SG.getHurst().assign(0.8) +SG.getRMS().assign(1.); +SG.getQ0().assign(4); +SG.getQ1().assign(4); +SG.getQ2().assign(32); +SG.getRandomSeed().assign(156); +SG.Init() +a = SG.buildSurface() +a.setL(1.); +#save the surface +a.dumpToTextFile('generated-surface.plot') +a.dumpToTextFileWithImaginary('generated-surface-im.plot') + +#compute and print surface statistics +class Stats: + + def __getitem__(self,key): + return self.__dict__[key] + + +stats = Stats() + +stats.size = SG.getGridSize() +stats.hurst = SG.getHurst().value() +stats.rms = SG.getRMS() +stats.k0 = SG.getQ0() +stats.k1 = SG.getQ1().value() +stats.k2 = SG.getQ2().value() +stats.seed = SG.getRandomSeed() +stats.rms_spectral = SurfaceStatistics.computeSpectralStdev(a); +stats.rms_slopes_spectral = SurfaceStatistics.computeSpectralRMSSlope(a); +stats.rms_geometric = SurfaceStatistics.computeStdev(a); +stats.rms_slopes_geometric = SurfaceStatistics.computeRMSSlope(a); +stats.moments = SurfaceStatistics.computeMoments(a); +stats.m0 = stats['rms_spectral']**2 +stats.m2 = stats.moments[0] +stats.m4 = stats.moments[1] +stats.alpha = stats['m0']*stats['m4']/(stats['m2']**2) +stats.L = a.getL() +stats.m0prime = SurfaceStatistics.computeAnalyticFractalMoment(0,stats.k1,stats.k2,stats.hurst,1. , stats.L) +stats.moment_A = stats.m0/stats.m0prime +stats.analytic_m0 = SurfaceStatistics.computeAnalyticFractalMoment(0,stats.k1,stats.k2,stats.hurst,stats.moment_A,stats.L); +stats.analytic_m2 = SurfaceStatistics.computeAnalyticFractalMoment(2,stats.k1,stats.k2,stats.hurst,stats.moment_A,stats.L); +stats.analytic_m4 = SurfaceStatistics.computeAnalyticFractalMoment(4,stats.k1,stats.k2,stats.hurst,stats.moment_A,stats.L); +stats.analytic_alpha = stats.analytic_m0*stats.analytic_m4/(stats.analytic_m2*stats.analytic_m2); + +print """ +[N] {size} +[rms] {rms} +[rmsSpectral] {rms_spectral} +[rmsSlopeSpectral] {rms_slopes_spectral} +[rmsSlopeGeometric] {rms_slopes_geometric} +[Hurst] {hurst} +[k1] {k1} +[k2] {k2} +[moment A] {moment_A} +[m0] {m0} +[analytic m0] {analytic_m0} +[m2] {m2} +[analytic m2] {analytic_m2} +[m4] {m4} +[analytic m4] {analytic_m4} +[alpha] {alpha} +[analytic_alpha] {analytic_alpha} +[seed] {seed} +""".format(**stats.__dict__) + +#plot the surface +b = a.getWrappedNumpy().real +import matplotlib.pyplot as plt +plt.imshow(b) +plt.show() + diff --git a/python-examples/test_hertz.py b/python-examples/test_hertz.py new file mode 100644 index 0000000..f243920 --- /dev/null +++ b/python-examples/test_hertz.py @@ -0,0 +1,381 @@ +from python_surface import * +import matplotlib.pyplot as plt +import numpy as np +import scipy.optimize +import math +#generate surface +n = 32 +L = 1. +a = Surface(n,L) +r = 10. +applied_load = .001 +N2 = a.size()*a.size() + +ss = a.getWrappedNumpy() +for i in range(0,n): + for j in range(0,n): + x = 1.*i - n/2; + y = 1.*j - n/2; + d = (x*x + y*y)*1./n/n*L*L; + if d < r*r: ss[i,j] = - r + math.sqrt(r*r-d); + else : ss[i,j] = - r; + +#plot surface function + +fig_by_titles = {} +axe_by_titles = {} +img_by_titles = {} +cbar_by_titles = {} + + +def plotCurve(curve,title): + if not title in fig_by_titles: + fig = plt.figure() + axe = fig.add_subplot(1,1,1) + + fig_by_titles[title] = fig + axe_by_titles[title] = axe + + fig = fig_by_titles[title] + axe = axe_by_titles[title] + axe.clear() + axe.set_title(title) + axe.plot(curve[:,0],np.log(curve[:,1]),'-') +# print curve + fig.show() + plt.draw() + + +def plotSurface(surf,title): + + try: s = surf.getWrappedNumpy() + except: s = surf + + print "{0} range: {1} - {2}".format(title,s.min(),s.max()) + if len(s.shape) == 1: + n = np.sqrt(s.shape[0]) + s = np.reshape(s,(n,n)) + + if not title in fig_by_titles: + fig = plt.figure() + axe = fig.add_subplot(1,1,1) + img = axe.imshow(s.real) + cbar = plt.colorbar(img) + + fig_by_titles[title] = fig + axe_by_titles[title] = axe + img_by_titles[title] = img + cbar_by_titles[title] = cbar + + fig = fig_by_titles[title] + axe = axe_by_titles[title] + img = img_by_titles[title] + img.set_data(s.real) + img.autoscale() + + + axe.set_title(title) + fig.show() +# plt.show() + plt.draw() + +#plot the surface +plotSurface(a,'surface') + +#construct the bem +bem = BemFFTBase(a) + +#make a bem calculation +bem.setEffectiveModulus(1.) +bem.computeDisplacement() +disp = bem.getDisplacements() + +################################################################ + +class ConvergenceMonitor(): + + def __init__(self): + self.cpt = 1 + self.curves = {} + + def addValue(self,title,value): + if title not in self.curves: + self.curves[title] = np.zeros((0,2)) + a = np.array([[self.cpt,value]]) + self.curves[title] = np.concatenate((self.curves[title],a)) + + def incCpt(self): + self.cpt += 1 + + def plot(self): + for title in self.curves.keys(): + plotCurve(self.curves[title],title) + +convergence = ConvergenceMonitor() + +################################################################ + +#compute the objective function +def display(x): + F = computeF(x,bem,terms,display=True) + convergence.addValue('F',F) + + _kwargs = computeDisplacement(x,bem) + for f in ['disp','trac','gap']: + plotSurface(_kwargs[f],f) + + grad = computeGradientF(x,bem,terms) + convergence.addValue('gradientNorm',np.linalg.norm(grad)) + plotSurface(grad[:n*n],'gradient') + convergence.incCpt() + + convergence.plot() + pass + +################################################################ +class EnergyTerm: + def __init__(self,need_multiplier=False): + self.need_multiplier = need_multiplier + self.name = self.__class__.__name__ + + def setMultiplierRank(self,m_rank): + self.m_rank = m_rank + +################################################################ +class DeformationEnergy(EnergyTerm): + + def __init__(self): + EnergyTerm.__init__(self) + + def compute(self,trac=None,disp=None,**kwargs): + return 0.5*(trac*disp).sum() + + def computeGradient(self,disp=None,**kwargs): + return 0.5*disp + +################################################################ + +class OrthogonalityCondition(EnergyTerm): + + def __init__(self): + EnergyTerm.__init__(self) + + def compute(self,trac=None,gap=None,**kwargs): + return (trac*gap).sum() + + def computeGradient(self,gap=None,**kwargs): + return gap + + +################################################################ + +class LoadBalance(EnergyTerm): + + def __init__(self,applied_pressure,beta): + EnergyTerm.__init__(self) + self.applied_pressure = applied_pressure + self.beta = beta + + def compute(self,trac=None,**kwargs): + avg_pressure = np.average(trac) + return self.beta*(avg_pressure-self.applied_pressure)**2 + + def computeGradient(self,trac=None,multipliers=None,N=None,**kwargs): + avg_pressure = np.average(trac) + grad = self.beta*(avg_pressure-self.applied_pressure)*1./N*np.ones(trac.shape) + return grad + +################################################################ + +class LoadBalanceMultiplier(EnergyTerm): + + def __init__(self,applied_pressure): + EnergyTerm.__init__(self,need_multiplier=True) + self.applied_pressure = applied_pressure + + def compute(self,trac=None,multipliers=None,**kwargs): + mult = multipliers[self.m_rank] + avg_pressure = np.average(trac) + return mult*(avg_pressure-self.applied_pressure)**2 + + def computeGradient(self,trac=None,multipliers=None,N=None,**kwargs): + mult = multipliers[self.m_rank] + avg_pressure = np.average(trac) + grad1 = mult*(avg_pressure-self.applied_pressure)*1./N*np.ones(trac.shape) + grad2 = (avg_pressure-self.applied_pressure)**2 + return grad1,grad2 + + + + +################################################################ +class LoadBalanceQuadraticMultiplier(EnergyTerm): + + def __init__(self,applied_pressure): + EnergyTerm.__init__(self,need_multiplier=True) + self.applied_pressure = applied_pressure + + def compute(self,trac=None,multipliers=None,**kwargs): + mult = multipliers[self.m_rank] + avg_pressure = np.average(trac) + return mult**2*(avg_pressure-self.applied_pressure)**2 + + def computeGradient(self,trac=None,multipliers=None,N=None,**kwargs): + mult = multipliers[self.m_rank] + avg_pressure = np.average(trac) + grad1 = mult**2*(avg_pressure-self.applied_pressure)*1./N*np.ones(trac.shape) + grad2 = 2*mult*(avg_pressure-self.applied_pressure)**2 + return grad1,grad2 + + + + +################################################################ + + +class PositivePenalty(EnergyTerm): + + def __init__(self,beta): + EnergyTerm.__init__(self) + self.beta = beta + + def compute(self,gradient_flag=False,beta=None,trac=None,gap=None,**kwargs): + penalty1 = np.copy(trac) + penalty1[penalty1 > 0] = 0 + + penalty2 = np.copy(gap) + penalty2[penalty2 > 0] = 0 + + return self.beta*((penalty1**2).sum()+(penalty2**2).sum()) + + def computeGradient(self,gradient_flag=False,beta=None,trac=None,gap=None,**kwargs): + penalty1 = np.copy(trac) + penalty1[penalty1 > 0] = 0 + + penalty2 = np.copy(gap) + penalty2[penalty2 > 0] = 0 + + return 2.*(penalty1+penalty2)*self.beta + + +################################################################ + +def computeDisplacement(unknowns,bemModel): + surface = bemModel.getSurface().getWrappedNumpy().real + N = surface.shape[0]*surface.shape[1] + trac = unknowns[0:N] + trac = np.reshape(trac,surface.shape) + multipliers = unknowns[N:] + + np.copyto(bemModel.getTractions().getWrappedNumpy(),trac) + bemModel.computeDisplacement() + disp = bemModel.getDisplacements().getWrappedNumpy().real + bemModel.computeTrueDisplacement() + true_disp = bemModel.getTrueDisplacements().getWrappedNumpy().real + bemModel.computeGap() + gap = bemModel.getGap().getWrappedNumpy().real +# plotSurface(trac,'trac') +# print disp +# print true_disp +# print surface +# print gap +# plotSurface(disp,'disp') +# plotSurface(true_disp,'truedisp') +# plotSurface(surface,'surface') +# plotSurface(gap,'gap') + + # print trac + return {'trac':trac,'multipliers':multipliers,'disp':true_disp,'surface':surface,'gap':gap,'N':N} + +################################################################ + +def computeGradF(unknowns,bemModel,terms): + _kwargs = computeDisplacement(unknowns,bemModel) + avg_pressure = np.average(trac) + # grad1 = disp - surface + 2.*multipliers*np.ones(surface.shape)*(sum_pressure-applied_pressure) + N = surface.shape[0]*surface.shape[1] + grad1 = disp - surface + multipliers**2*np.ones(surface.shape)*(avg_pressure-applied_pressure)*1./N +# grad1 += positivePenaltyGradient(trac,1.) + grad1 = np.reshape(grad1,N) + grad = np.empty(N+1) + grad[:-1] = grad1 + grad[-1] = 2.*multipliers*(avg_pressure-applied_pressure)**2 +# grad[-1] = 0 +# print "current unknowns(grad)" +# print unknowns +# print "current gradient" +# print grad + return grad + +################################################################ + +def computeGradientF(unknowns,bemModel,terms): + _kwargs = computeDisplacement(unknowns,bemModel) + grad = np.zeros(unknowns.shape) + N = _kwargs['N'] + + for t in terms: + if t.need_multiplier: + g,m_var = t.computeGradient(**_kwargs) + else: g = t.computeGradient(**_kwargs) + +# plotSurface(g,'gradient-{0}'.format(t.name)) + + if not len(g.shape) == 1: + g = np.reshape(g,g.shape[0]*g.shape[1]) + grad[:N] += g[:N] + if t.need_multiplier: + grad[N+t.m_rank] = m_var + +# plotSurface(grad[:N],'gradient-total') + return grad + +################################################################ + +def computeF(unknowns,bemModel,terms,display=False): + _kwargs = computeDisplacement(unknowns,bemModel) + res = [t.compute(**_kwargs) for t in terms] + F = sum(res) + if display: + avg_pressure = np.average(_kwargs['trac']) + formated = ["{0:.5e}".format(t) for t in [avg_pressure]+res+[F]] + print "\t".join(formated) + return F + +################################################################ +def printHead(terms): + titles = ['avg_pressure'] + titles += [i.name for i in terms] + titles += 'F' + formated = ["{0}".format(t) for t in titles] + print "\t".join(formated) + +################################################################ + + +terms = [DeformationEnergy(),OrthogonalityCondition(),LoadBalance(applied_load,10000.),PositivePenalty(10000.)] +#terms = [LoadBalance(applied_load)] + +multipliers_number = 0 +for t in terms: + if t.need_multiplier: + t.setMultiplierRank(multipliers_number) + multipliers_number += 1 + +x0 = np.zeros((n*n+multipliers_number,)) +#x0[:n*n] = applied_load +x0[n*n:] = 1. + + +printHead(terms) +x = scipy.optimize.fmin_cg(computeF,x0,args=(bem,terms),callback=display,gtol=1e-3,fprime=computeGradientF) +x = scipy.optimize.fmin_cg(computeF,x,args=(bem,terms),callback=display,gtol=1e-8)#,fprime=computeGradientF) +plt.show() +xx = np.reshape(x[:n*n],a.getWrappedNumpy().shape) +print xx +plotSurface(xx,'pressure solution') +plt.show() +F = computeF(x,bem,terms) +bem.computeDisplacement() +plotSurface(bem.getTrueDisplacements(),'displacements') +plt.show() diff --git a/python-examples/test_hertz_spectral.py b/python-examples/test_hertz_spectral.py new file mode 100644 index 0000000..77b5edc --- /dev/null +++ b/python-examples/test_hertz_spectral.py @@ -0,0 +1,351 @@ +from python_surface import * +import matplotlib.pyplot as plt +import numpy as np +import scipy.optimize +import scipy +import math +import sys +#generate surface +n = 32 +L = 1. +a = Surface(n,L) +r = 2. +applied_load = .001 +N2 = a.size()*a.size() + +ss = a.getWrappedNumpy() +for i in range(0,n): + for j in range(0,n): + x = 1.*i - n/2; + y = 1.*j - n/2; + d = (x*x + y*y)*1./n/n*L*L; + if d < r*r: ss[i,j] = - r + math.sqrt(r*r-d); + else : ss[i,j] = - r; + +#plot surface function + +fig_by_titles = {} +axe_by_titles = {} +img_by_titles = {} +cbar_by_titles = {} + + +def plotCurve(curve,title): + if not title in fig_by_titles: + fig = plt.figure() + axe = fig.add_subplot(1,1,1) + + fig_by_titles[title] = fig + axe_by_titles[title] = axe + + fig = fig_by_titles[title] + axe = axe_by_titles[title] + axe.clear() + axe.set_title(title) + fig.canvas.set_window_title(title) + axe.plot(curve[:,0],curve[:,1],'-') +# print curve + fig.show() + plt.draw() + + +def plotSurface(surf,title,complex_part='real'): + + try: s = surf.getWrappedNumpy() + except: s = surf + + if complex_part == 'real': s = s.real + else: s = s.imag + + print "{0} range: {1} - {2}".format(title,s.min(),s.max()) + if len(s.shape) == 1: + n = np.sqrt(s.shape[0]) + s = np.reshape(s,(n,n)) + + if not title in fig_by_titles: + fig = plt.figure() + axe = fig.add_subplot(1,1,1) + img = axe.imshow(s) + cbar = plt.colorbar(img) + + fig_by_titles[title] = fig + axe_by_titles[title] = axe + img_by_titles[title] = img + cbar_by_titles[title] = cbar + + fig = fig_by_titles[title] + axe = axe_by_titles[title] + img = img_by_titles[title] + img.set_data(s) + + img.autoscale() + + + axe.set_title(title) + fig.canvas.set_window_title(title) + fig.show() +# plt.show() + plt.draw() + +#plot the surface +plotSurface(a,'surface') + + + + +################################################################ + +class ConvergenceMonitor(): + + def __init__(self): + self.cpt = 1 + self.curves = {} + + def addValue(self,title,value,log_flag=False): + if title not in self.curves: + self.curves[title] = np.zeros((0,2)) + if log_flag: a = np.array([[self.cpt,np.log10(np.abs(value))]]) + else: a = np.array([[self.cpt,value]]) + self.curves[title] = np.concatenate((self.curves[title],a)) + + def incCpt(self): + self.cpt += 1 + + def plot(self): + for title in self.curves.keys(): + plotCurve(self.curves[title],title) + +convergence = ConvergenceMonitor() + +################################################################ + +#compute the objective function +def display(x): + F = computeF(x,bem,terms,display=True) + convergence.addValue('F',F) + + _kwargs = computeInternals(x,bem) + for f in ['disp','trac']: + plotSurface(_kwargs[f],f) + + grad = computeGradientF(x,bem,terms) + convergence.addValue('gradientNorm',np.linalg.norm(grad),log_flag=True) + plotSurface(grad[:n*n],'gradient') + convergence.incCpt() + convergence.plot() + pass + +################################################################ +class EnergyTerm: + def __init__(self,need_multiplier=False): + self.need_multiplier = need_multiplier + self.name = self.__class__.__name__ + + def setMultiplierRank(self,m_rank): + self.m_rank = m_rank + +################################################################ +class DeformationEnergy(EnergyTerm): + + def __init__(self): + EnergyTerm.__init__(self) + + def compute(self,trac=None,disp=None,**kwargs): + return 0.5*(trac*disp).sum() + + def computeGradient(self,disp_spectral=None,N=None,**kwargs): + grad = 1./N*disp_spectral.conj() + grad[0,0] = 0. + return grad + +################################################################ + +class OrthogonalityCondition(EnergyTerm): + + def __init__(self): + EnergyTerm.__init__(self) + + def compute(self,trac=None,disp=None,surface=None,**kwargs): + return (trac*(disp-surface)).sum() + + def computeGradient(self,disp_spectral=None,surface_spectral=None,N=None,**kwargs): + grad = 1./N*(2.*disp_spectral - surface_spectral).conj() + grad[0,0] = 0 + # plotSurface(grad,'orthogonality gradient') + return grad + +################################################################ + +class OrthogonalityCondition2(EnergyTerm): + + def __init__(self): + EnergyTerm.__init__(self) + + def compute(self,trac=None,disp=None,surface=None,**kwargs): + return (trac*(disp-surface)).sum() + + def computeGradient(self,disp_spectral=None,surface_spectral=None,N=None,**kwargs): + grad = 1./N*(disp_spectral - surface_spectral).conj() + grad[0,0] = 0 + # plotSurface(grad,'orthogonality gradient') + return grad + +################################################################ + +class NegativePenalty(EnergyTerm): + + def __init__(self,beta): + EnergyTerm.__init__(self) + self.beta = beta + + def compute(self,trac=None,disp=None,surface=None,**kwargs): + trac = np.copy(trac) + trac[trac>0] = 0 + plotSurface(trac,'negative traction') + return self.beta*(trac**2).sum() + + def computeGradient(self,trac=None,N=None,**kwargs): + trac = np.copy(trac) + trac[trac>0] = 0 + trac = 2.*trac + trac = np.fft.fft2(trac) + grad = self.beta/N*trac.conj() + grad[0,0] = 0. + plotSurface(grad,'penalty gradient') + return grad + +################################################################ + + +def computeInternals(unknowns,bemModel): + surface = bemModel.getSurface().getWrappedNumpy().real + N = surface.shape[0]*surface.shape[1] + spectral_trac = unknowns[:N] + spectral_trac = np.reshape(spectral_trac,surface.shape) + + np.copyto(bemModel.getSpectralTractions().getWrappedNumpy(),spectral_trac) + bemModel.computeSpectralDisplacements() + bemModel.computeRealDisplacementsFromSpectral() + bemModel.computeRealTractionsFromSpectral() + disp = bemModel.getDisplacements().getWrappedNumpy().real + sdisp = bemModel.getSpectralDisplacements().getWrappedNumpy() + trac = bemModel.getTractions().getWrappedNumpy().real + ssurf = bemModel.getSpectralSurface().getWrappedNumpy() + return {'trac':trac,'disp':disp,'surface':surface,'N':N,'disp_spectral':sdisp,'surface_spectral':ssurf} + +################################################################ + +def computeGradF(unknowns,bemModel,terms): + _kwargs = computeDisplacement(unknowns,bemModel) + avg_pressure = np.average(trac) + # grad1 = disp - surface + 2.*multipliers*np.ones(surface.shape)*(sum_pressure-applied_pressure) + N = surface.shape[0]*surface.shape[1] + grad1 = disp - surface + multipliers**2*np.ones(surface.shape)*(avg_pressure-applied_pressure)*1./N +# grad1 += positivePenaltyGradient(trac,1.) + grad1 = np.reshape(grad1,N) + grad = np.empty(N+1) + grad[:-1] = grad1 + grad[-1] = 2.*multipliers*(avg_pressure-applied_pressure)**2 +# grad[-1] = 0 +# print "current unknowns(grad)" +# print unknowns +# print "current gradient" +# print grad + return grad + +################################################################ + +def computeGradientF(unknowns,bemModel,terms): + _kwargs = computeInternals(unknowns,bemModel) + grad = np.zeros(unknowns.shape,dtype=complex) + N = _kwargs['N'] + + for t in terms: + g = t.computeGradient(**_kwargs) +# plotSurface(g,'gradient-{0}'.format(t.name)) + + if not len(g.shape) == 1: + g = np.reshape(g,g.shape[0]*g.shape[1]) + grad[:N] += g[:N] + +# plotSurface(grad[:N],'gradient-total') + return grad + +################################################################ + +def computeF(unknowns,bemModel,terms,display=False): + _kwargs = computeInternals(unknowns,bemModel) + res = [t.compute(**_kwargs) for t in terms] + F = sum(res) + if display: + avg_pressure = np.average(_kwargs['trac']) + formated = ["{0:.5e}".format(t) for t in [avg_pressure]+res+[F]] + print "\t".join(formated) + return F + +################################################################ +def printHead(terms): + titles = ['avg_pressure'] + titles += [i.name for i in terms] + titles += 'F' + formated = ["{0}".format(t) for t in titles] + print "\t".join(formated) + +################################################################ + +def stepFunction(trac, Delta): + trac = np.copy(trac.getWrappedNumpy()) + trac[trac>0] = 0 + res = 0.5*(trac**2)/(Delta**2) + return res + +def stepFunctionVariation(trac, Delta): + trac = trac.getWrappedNumpy() + trac[trac>0] = 0 + res = 2.*trac/(Delta**2) + return res + +################################################################ + +##make a bem calculation (old method first) +#old_bem = BemFFT(a) +#F = old_bem.computeEquilibrium(1e-9,applied_load,0); +# +#trac = old_bem.getTractions() +#plotSurface(trac,'initial solution trac') +#plotSurface(old_bem.getDisplacements(),'initial solution displacement') +#sdisp = old_bem.getSpectralDisplacements().getWrappedNumpy() +#plotSurface(sdisp,'initial solution spectral displacement',complex_part='imag') +#strac = old_bem.getSpectralTractions().getWrappedNumpy() +#plotSurface(strac,'initial solution spectral tractions',complex_part='imag') +#plotSurface(stepFunction(trac,1./n),'initial solution step function') +#plotSurface(stepFunctionVariation(trac,1./n),'initial solution step function variation') +# +##old_bem.computeSpectralDisplacement +#plt.show() +#sys.exit(0) + +#make a bem calculation +bem = BemFFTBase(a) +bem.setEffectiveModulus(1.) + +x = np.zeros((n*n,),dtype=complex) +x[:n*n] = 0 +x[0] = applied_load*n*n + +for beta in [1e4, 2e4, 3e4]: + terms = [DeformationEnergy(),OrthogonalityCondition(),NegativePenalty(beta)] + #terms = [LoadBalance(applied_load)] + + printHead(terms) + x = scipy.optimize.fmin_cg(computeF,x,args=(bem,terms),callback=display,gtol=1e-4,fprime=computeGradientF) + + +xx = np.reshape(x[:n*n],a.getWrappedNumpy().shape) +print xx +plotSurface(xx,'spectral pressure solution') +F = computeF(x,bem,terms) +trac = bem.getTractions() +plotSurface(trac,'pressure solution') +plotSurface(bem.getDisplacements(),'displacements') +plt.show() diff --git a/python/SConscript b/python/SConscript new file mode 100644 index 0000000..c73739c --- /dev/null +++ b/python/SConscript @@ -0,0 +1,18 @@ +Import('main_env') +import distutils.sysconfig + +env_swig = main_env.Clone( + tools=['swig'], + CPPPATH=[distutils.sysconfig.get_python_inc()], + SWIG = 'swig3.0', + SHLIBPREFIX = '', +) +include_flags = ["-I{0}".format(i) for i in main_env['include_dirs']] +env_swig['SWIGFLAGS'] = ['-python','-c++'] + include_flags +env_swig['CXXFLAGS'] += include_flags + +env_swig.SharedLibrary( + target = '_rough_contact.so', + source = ['rough_contact.i' ], + LIBS= ['RoughContact'] +) diff --git a/python/bem.i b/python/bem.i new file mode 100644 index 0000000..0524b76 --- /dev/null +++ b/python/bem.i @@ -0,0 +1,11 @@ + + +/* -------------------------------------------------------------------------- */ +/* Wrapping bem capabilities +/* -------------------------------------------------------------------------- */ + +%include "bem_interface.hh" +%include "bem_fft_base.hh" +%include "bem_kato.hh" +%include "bem_polonski.hh" + diff --git a/python/clusters.i b/python/clusters.i new file mode 100644 index 0000000..0cb3769 --- /dev/null +++ b/python/clusters.i @@ -0,0 +1,11 @@ +/* -------------------------------------------------------------------------- */ +/* Wrapping contact clusters classes */ +/* -------------------------------------------------------------------------- */ + +%include "contact_area.hh" +%include "contact_cluster_collection.hh" + +%include "std_vector.i" +%template(VectorClusters) std::vector; + +%include "contact_cluster.hh" diff --git a/python/numpy.i b/python/numpy.i new file mode 100644 index 0000000..f2714cc --- /dev/null +++ b/python/numpy.i @@ -0,0 +1,3085 @@ +/* -*- C -*- (not really, but good for syntax highlighting) */ +#ifdef SWIGPYTHON + +%{ +#ifndef SWIG_FILE_WITH_INIT +#define NO_IMPORT_ARRAY +#endif +#include "stdio.h" +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#include +%} + +/**********************************************************************/ + +%fragment("NumPy_Backward_Compatibility", "header") +{ +%#if NPY_API_VERSION < 0x00000007 +%#define NPY_ARRAY_DEFAULT NPY_DEFAULT +%#define NPY_ARRAY_FARRAY NPY_FARRAY +%#define NPY_FORTRANORDER NPY_FORTRAN +%#endif +} + +/**********************************************************************/ + +/* The following code originally appeared in + * enthought/kiva/agg/src/numeric.i written by Eric Jones. It was + * translated from C++ to C by John Hunter. Bill Spotz has modified + * it to fix some minor bugs, upgrade from Numeric to numpy (all + * versions), add some comments and functionality, and convert from + * direct code insertion to SWIG fragments. + */ + +%fragment("NumPy_Macros", "header") +{ +/* Macros to extract array attributes. + */ +%#if NPY_API_VERSION < 0x00000007 +%#define is_array(a) ((a) && PyArray_Check((PyArrayObject*)a)) +%#define array_type(a) (int)(PyArray_TYPE((PyArrayObject*)a)) +%#define array_numdims(a) (((PyArrayObject*)a)->nd) +%#define array_dimensions(a) (((PyArrayObject*)a)->dimensions) +%#define array_size(a,i) (((PyArrayObject*)a)->dimensions[i]) +%#define array_strides(a) (((PyArrayObject*)a)->strides) +%#define array_stride(a,i) (((PyArrayObject*)a)->strides[i]) +%#define array_data(a) (((PyArrayObject*)a)->data) +%#define array_descr(a) (((PyArrayObject*)a)->descr) +%#define array_flags(a) (((PyArrayObject*)a)->flags) +%#define array_enableflags(a,f) (((PyArrayObject*)a)->flags) = f +%#else +%#define is_array(a) ((a) && PyArray_Check(a)) +%#define array_type(a) PyArray_TYPE((PyArrayObject*)a) +%#define array_numdims(a) PyArray_NDIM((PyArrayObject*)a) +%#define array_dimensions(a) PyArray_DIMS((PyArrayObject*)a) +%#define array_strides(a) PyArray_STRIDES((PyArrayObject*)a) +%#define array_stride(a,i) PyArray_STRIDE((PyArrayObject*)a,i) +%#define array_size(a,i) PyArray_DIM((PyArrayObject*)a,i) +%#define array_data(a) PyArray_DATA((PyArrayObject*)a) +%#define array_descr(a) PyArray_DESCR((PyArrayObject*)a) +%#define array_flags(a) PyArray_FLAGS((PyArrayObject*)a) +%#define array_enableflags(a,f) PyArray_ENABLEFLAGS((PyArrayObject*)a,f) +%#endif +%#define array_is_contiguous(a) (PyArray_ISCONTIGUOUS((PyArrayObject*)a)) +%#define array_is_native(a) (PyArray_ISNOTSWAPPED((PyArrayObject*)a)) +%#define array_is_fortran(a) (PyArray_ISFORTRAN((PyArrayObject*)a)) +} + +/**********************************************************************/ + +%fragment("NumPy_Utilities", + "header") +{ + /* Given a PyObject, return a string describing its type. + */ + const char* pytype_string(PyObject* py_obj) + { + if (py_obj == NULL ) return "C NULL value"; + if (py_obj == Py_None ) return "Python None" ; + if (PyCallable_Check(py_obj)) return "callable" ; + if (PyString_Check( py_obj)) return "string" ; + if (PyInt_Check( py_obj)) return "int" ; + if (PyFloat_Check( py_obj)) return "float" ; + if (PyDict_Check( py_obj)) return "dict" ; + if (PyList_Check( py_obj)) return "list" ; + if (PyTuple_Check( py_obj)) return "tuple" ; +%#if PY_MAJOR_VERSION < 3 + if (PyFile_Check( py_obj)) return "file" ; + if (PyModule_Check( py_obj)) return "module" ; + if (PyInstance_Check(py_obj)) return "instance" ; +%#endif + + return "unkown type"; + } + + /* Given a NumPy typecode, return a string describing the type. + */ + const char* typecode_string(int typecode) + { + static const char* type_names[25] = {"bool", + "byte", + "unsigned byte", + "short", + "unsigned short", + "int", + "unsigned int", + "long", + "unsigned long", + "long long", + "unsigned long long", + "float", + "double", + "long double", + "complex float", + "complex double", + "complex long double", + "object", + "string", + "unicode", + "void", + "ntypes", + "notype", + "char", + "unknown"}; + return typecode < 24 ? type_names[typecode] : type_names[24]; + } + + /* Make sure input has correct numpy type. This now just calls + PyArray_EquivTypenums(). + */ + int type_match(int actual_type, + int desired_type) + { + return PyArray_EquivTypenums(actual_type, desired_type); + } + +%#ifdef SWIGPY_USE_CAPSULE + void free_cap(PyObject * cap) + { + void* array = (void*) PyCapsule_GetPointer(cap,SWIGPY_CAPSULE_NAME); + if (array != NULL) free(array); + } +%#endif + + +} + +/**********************************************************************/ + +%fragment("NumPy_Object_to_Array", + "header", + fragment="NumPy_Backward_Compatibility", + fragment="NumPy_Macros", + fragment="NumPy_Utilities") +{ + /* Given a PyObject pointer, cast it to a PyArrayObject pointer if + * legal. If not, set the python error string appropriately and + * return NULL. + */ + PyArrayObject* obj_to_array_no_conversion(PyObject* input, + int typecode) + { + PyArrayObject* ary = NULL; + if (is_array(input) && (typecode == NPY_NOTYPE || + PyArray_EquivTypenums(array_type(input), typecode))) + { + ary = (PyArrayObject*) input; + } + else if is_array(input) + { + const char* desired_type = typecode_string(typecode); + const char* actual_type = typecode_string(array_type(input)); + PyErr_Format(PyExc_TypeError, + "Array of type '%s' required. Array of type '%s' given", + desired_type, actual_type); + ary = NULL; + } + else + { + const char* desired_type = typecode_string(typecode); + const char* actual_type = pytype_string(input); + PyErr_Format(PyExc_TypeError, + "Array of type '%s' required. A '%s' was given", + desired_type, + actual_type); + ary = NULL; + } + return ary; + } + + /* Convert the given PyObject to a NumPy array with the given + * typecode. On success, return a valid PyArrayObject* with the + * correct type. On failure, the python error string will be set and + * the routine returns NULL. + */ + PyArrayObject* obj_to_array_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + PyArrayObject* ary = NULL; + PyObject* py_obj; + if (is_array(input) && (typecode == NPY_NOTYPE || + PyArray_EquivTypenums(array_type(input),typecode))) + { + ary = (PyArrayObject*) input; + *is_new_object = 0; + } + else + { + py_obj = PyArray_FROMANY(input, typecode, 0, 0, NPY_ARRAY_DEFAULT); + /* If NULL, PyArray_FromObject will have set python error value.*/ + ary = (PyArrayObject*) py_obj; + *is_new_object = 1; + } + return ary; + } + + /* Given a PyArrayObject, check to see if it is contiguous. If so, + * return the input pointer and flag it as not a new object. If it is + * not contiguous, create a new PyArrayObject using the original data, + * flag it as a new object and return the pointer. + */ + PyArrayObject* make_contiguous(PyArrayObject* ary, + int* is_new_object, + int min_dims, + int max_dims) + { + PyArrayObject* result; + if (array_is_contiguous(ary)) + { + result = ary; + *is_new_object = 0; + } + else + { + result = (PyArrayObject*) PyArray_ContiguousFromObject((PyObject*)ary, + array_type(ary), + min_dims, + max_dims); + *is_new_object = 1; + } + return result; + } + + /* Given a PyArrayObject, check to see if it is Fortran-contiguous. + * If so, return the input pointer, but do not flag it as not a new + * object. If it is not Fortran-contiguous, create a new + * PyArrayObject using the original data, flag it as a new object + * and return the pointer. + */ + PyArrayObject* make_fortran(PyArrayObject* ary, + int* is_new_object) + { + PyArrayObject* result; + if (array_is_fortran(ary)) + { + result = ary; + *is_new_object = 0; + } + else + { + Py_INCREF(array_descr(ary)); + result = (PyArrayObject*) PyArray_FromArray(ary, + array_descr(ary), + NPY_FORTRANORDER); + *is_new_object = 1; + } + return result; + } + + /* Convert a given PyObject to a contiguous PyArrayObject of the + * specified type. If the input object is not a contiguous + * PyArrayObject, a new one will be created and the new object flag + * will be set. + */ + PyArrayObject* obj_to_array_contiguous_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + int is_new1 = 0; + int is_new2 = 0; + PyArrayObject* ary2; + PyArrayObject* ary1 = obj_to_array_allow_conversion(input, + typecode, + &is_new1); + if (ary1) + { + ary2 = make_contiguous(ary1, &is_new2, 0, 0); + if ( is_new1 && is_new2) + { + Py_DECREF(ary1); + } + ary1 = ary2; + } + *is_new_object = is_new1 || is_new2; + return ary1; + } + + /* Convert a given PyObject to a Fortran-ordered PyArrayObject of the + * specified type. If the input object is not a Fortran-ordered + * PyArrayObject, a new one will be created and the new object flag + * will be set. + */ + PyArrayObject* obj_to_array_fortran_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + int is_new1 = 0; + int is_new2 = 0; + PyArrayObject* ary2; + PyArrayObject* ary1 = obj_to_array_allow_conversion(input, + typecode, + &is_new1); + if (ary1) + { + ary2 = make_fortran(ary1, &is_new2); + if (is_new1 && is_new2) + { + Py_DECREF(ary1); + } + ary1 = ary2; + } + *is_new_object = is_new1 || is_new2; + return ary1; + } +} /* end fragment */ + +/**********************************************************************/ + +%fragment("NumPy_Array_Requirements", + "header", + fragment="NumPy_Backward_Compatibility", + fragment="NumPy_Macros") +{ + /* Test whether a python object is contiguous. If array is + * contiguous, return 1. Otherwise, set the python error string and + * return 0. + */ + int require_contiguous(PyArrayObject* ary) + { + int contiguous = 1; + if (!array_is_contiguous(ary)) + { + PyErr_SetString(PyExc_TypeError, + "Array must be contiguous. A non-contiguous array was given"); + contiguous = 0; + } + return contiguous; + } + + /* Require that a numpy array is not byte-swapped. If the array is + * not byte-swapped, return 1. Otherwise, set the python error string + * and return 0. + */ + int require_native(PyArrayObject* ary) + { + int native = 1; + if (!array_is_native(ary)) + { + PyErr_SetString(PyExc_TypeError, + "Array must have native byteorder. " + "A byte-swapped array was given"); + native = 0; + } + return native; + } + + /* Require the given PyArrayObject to have a specified number of + * dimensions. If the array has the specified number of dimensions, + * return 1. Otherwise, set the python error string and return 0. + */ + int require_dimensions(PyArrayObject* ary, + int exact_dimensions) + { + int success = 1; + if (array_numdims(ary) != exact_dimensions) + { + PyErr_Format(PyExc_TypeError, + "Array must have %d dimensions. Given array has %d dimensions", + exact_dimensions, + array_numdims(ary)); + success = 0; + } + return success; + } + + /* Require the given PyArrayObject to have one of a list of specified + * number of dimensions. If the array has one of the specified number + * of dimensions, return 1. Otherwise, set the python error string + * and return 0. + */ + int require_dimensions_n(PyArrayObject* ary, + int* exact_dimensions, + int n) + { + int success = 0; + int i; + char dims_str[255] = ""; + char s[255]; + for (i = 0; i < n && !success; i++) + { + if (array_numdims(ary) == exact_dimensions[i]) + { + success = 1; + } + } + if (!success) + { + for (i = 0; i < n-1; i++) + { + sprintf(s, "%d, ", exact_dimensions[i]); + strcat(dims_str,s); + } + sprintf(s, " or %d", exact_dimensions[n-1]); + strcat(dims_str,s); + PyErr_Format(PyExc_TypeError, + "Array must have %s dimensions. Given array has %d dimensions", + dims_str, + array_numdims(ary)); + } + return success; + } + + /* Require the given PyArrayObject to have a specified shape. If the + * array has the specified shape, return 1. Otherwise, set the python + * error string and return 0. + */ + int require_size(PyArrayObject* ary, + npy_intp* size, + int n) + { + int i; + int success = 1; + int len; + char desired_dims[255] = "["; + char s[255]; + char actual_dims[255] = "["; + for(i=0; i < n;i++) + { + if (size[i] != -1 && size[i] != array_size(ary,i)) + { + success = 0; + } + } + if (!success) + { + for (i = 0; i < n; i++) + { + if (size[i] == -1) + { + sprintf(s, "*,"); + } + else + { + sprintf(s, "%ld,", (long int)size[i]); + } + strcat(desired_dims,s); + } + len = strlen(desired_dims); + desired_dims[len-1] = ']'; + for (i = 0; i < n; i++) + { + sprintf(s, "%ld,", (long int)array_size(ary,i)); + strcat(actual_dims,s); + } + len = strlen(actual_dims); + actual_dims[len-1] = ']'; + PyErr_Format(PyExc_TypeError, + "Array must have shape of %s. Given array has shape of %s", + desired_dims, + actual_dims); + } + return success; + } + + /* Require the given PyArrayObject to to be Fortran ordered. If the + * the PyArrayObject is already Fortran ordered, do nothing. Else, + * set the Fortran ordering flag and recompute the strides. + */ + int require_fortran(PyArrayObject* ary) + { + int success = 1; + int nd = array_numdims(ary); + int i; + npy_intp * strides = array_strides(ary); + if (array_is_fortran(ary)) return success; + /* Set the Fortran ordered flag */ + array_enableflags(ary,NPY_ARRAY_FARRAY); + /* Recompute the strides */ + strides[0] = strides[nd-1]; + for (i=1; i < nd; ++i) + strides[i] = strides[i-1] * array_size(ary,i-1); + return success; + } +} + +/* Combine all NumPy fragments into one for convenience */ +%fragment("NumPy_Fragments", + "header", + fragment="NumPy_Backward_Compatibility", + fragment="NumPy_Macros", + fragment="NumPy_Utilities", + fragment="NumPy_Object_to_Array", + fragment="NumPy_Array_Requirements") +{ +} + +/* End John Hunter translation (with modifications by Bill Spotz) + */ + +/* %numpy_typemaps() macro + * + * This macro defines a family of 74 typemaps that allow C arguments + * of the form + * + * 1. (DATA_TYPE IN_ARRAY1[ANY]) + * 2. (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + * 3. (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + * + * 4. (DATA_TYPE IN_ARRAY2[ANY][ANY]) + * 5. (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 6. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + * 7. (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 8. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + * + * 9. (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + * 10. (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 11. (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 12. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) + * 13. (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 14. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) + * + * 15. (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) + * 16. (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 17. (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 18. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, , DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) + * 19. (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 20. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) + * + * 21. (DATA_TYPE INPLACE_ARRAY1[ANY]) + * 22. (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + * 23. (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + * + * 24. (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + * 25. (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 26. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + * 27. (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 28. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + * + * 29. (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + * 30. (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 31. (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 32. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) + * 33. (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 34. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) + * + * 35. (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) + * 36. (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 37. (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 38. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) + * 39. (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 40. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) + * + * 41. (DATA_TYPE ARGOUT_ARRAY1[ANY]) + * 42. (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + * 43. (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + * + * 44. (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + * + * 45. (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + * + * 46. (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) + * + * 47. (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) + * 48. (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) + * + * 49. (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 50. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) + * 51. (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 52. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) + * + * 53. (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 54. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) + * 55. (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 56. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) + * + * 57. (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 58. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) + * 59. (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 60. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) + * + * 61. (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) + * 62. (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) + * + * 63. (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 64. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) + * 65. (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 66. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) + * + * 67. (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 68. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) + * 69. (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 70. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) + * + * 71. (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 72. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) + * 73. (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 74. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) + * + * where "DATA_TYPE" is any type supported by the NumPy module, and + * "DIM_TYPE" is any int-like type suitable for specifying dimensions. + * The difference between "ARRAY" typemaps and "FARRAY" typemaps is + * that the "FARRAY" typemaps expect Fortran ordering of + * multidimensional arrays. In python, the dimensions will not need + * to be specified (except for the "DATA_TYPE* ARGOUT_ARRAY1" + * typemaps). The IN_ARRAYs can be a numpy array or any sequence that + * can be converted to a numpy array of the specified type. The + * INPLACE_ARRAYs must be numpy arrays of the appropriate type. The + * ARGOUT_ARRAYs will be returned as new numpy arrays of the + * appropriate type. + * + * These typemaps can be applied to existing functions using the + * %apply directive. For example: + * + * %apply (double* IN_ARRAY1, int DIM1) {(double* series, int length)}; + * double prod(double* series, int length); + * + * %apply (int DIM1, int DIM2, double* INPLACE_ARRAY2) + * {(int rows, int cols, double* matrix )}; + * void floor(int rows, int cols, double* matrix, double f); + * + * %apply (double IN_ARRAY3[ANY][ANY][ANY]) + * {(double tensor[2][2][2] )}; + * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) + * {(double low[2][2][2] )}; + * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) + * {(double upp[2][2][2] )}; + * void luSplit(double tensor[2][2][2], + * double low[2][2][2], + * double upp[2][2][2] ); + * + * or directly with + * + * double prod(double* IN_ARRAY1, int DIM1); + * + * void floor(int DIM1, int DIM2, double* INPLACE_ARRAY2, double f); + * + * void luSplit(double IN_ARRAY3[ANY][ANY][ANY], + * double ARGOUT_ARRAY3[ANY][ANY][ANY], + * double ARGOUT_ARRAY3[ANY][ANY][ANY]); + */ + +%define %numpy_typemaps(DATA_TYPE, DATA_TYPECODE, DIM_TYPE) + +/************************/ +/* Input Array Typemaps */ +/************************/ + +/* Typemap suite for (DATA_TYPE IN_ARRAY1[ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY1[ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY1[ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = { $1_dim0 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY1[ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = { -1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = {-1}; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY2[ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY2[ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY2[ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { $1_dim0, $1_dim1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY2[ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + /* for now, only concerned with lists */ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL, int* is_new_object_array=NULL) +{ + npy_intp size[2] = { -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + int is_new_object; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + is_new_object_array = (int *)calloc($2,sizeof(int)); + + if (array == NULL || object_array == NULL || is_new_object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_contiguous_allow_conversion(PySequence_GetItem($input,i), DATA_TYPECODE, &is_new_object); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + is_new_object_array[i] = is_new_object; + + if (!temp_array || !require_dimensions(temp_array, 2)) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + } + + if (!require_size(temp_array, size, 2)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; +} +%typemap(freearg) + (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + Py_ssize_t i; + + if (array$argnum!=NULL) free(array$argnum); + + /*freeing the individual arrays if needed */ + if (object_array$argnum!=NULL) + { + if (is_new_object_array$argnum!=NULL) + { + for (i=0; i<$2; i++) + { + if (object_array$argnum[i] != NULL && is_new_object_array$argnum[i]) + { Py_DECREF(object_array$argnum[i]); } + } + free(is_new_object_array$argnum); + } + free(object_array$argnum); + } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* IN_ARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3) | !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* IN_FARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { $1_dim0, $1_dim1, $1_dim2 , $1_dim3}; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + /* for now, only concerned with lists */ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL, int* is_new_object_array=NULL) +{ + npy_intp size[3] = { -1, -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + int is_new_object; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + is_new_object_array = (int *)calloc($2,sizeof(int)); + + if (array == NULL || object_array == NULL || is_new_object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_contiguous_allow_conversion(PySequence_GetItem($input,i), DATA_TYPECODE, &is_new_object); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + is_new_object_array[i] = is_new_object; + + if (!temp_array || !require_dimensions(temp_array, 3)) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + size[2] = array_size(temp_array,2); + } + + if (!require_size(temp_array, size, 3)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; + $5 = (DIM_TYPE) size[2]; +} +%typemap(freearg) + (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + Py_ssize_t i; + + if (array$argnum!=NULL) free(array$argnum); + + /*freeing the individual arrays if needed */ + if (object_array$argnum!=NULL) + { + if (is_new_object_array$argnum!=NULL) + { + for (i=0; i<$2; i++) + { + if (object_array$argnum[i] != NULL && is_new_object_array$argnum[i]) + { Py_DECREF(object_array$argnum[i]); } + } + free(is_new_object_array$argnum); + } + free(object_array$argnum); + } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, + * DATA_TYPE* IN_ARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1 , -1}; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4) | !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, + * DATA_TYPE* IN_FARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1 , -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/***************************/ +/* In-Place Array Typemaps */ +/***************************/ + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY1[ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY1[ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY1[ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[1] = { $1_dim0 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_size(array, size, 1) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + (PyArrayObject* array=NULL, int i=1) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = 1; + for (i=0; i < array_numdims(array); ++i) $2 *= array_size(array,i); +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + (PyArrayObject* array=NULL, int i=0) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = 1; + for (i=0; i < array_numdims(array); ++i) $1 *= array_size(array,i); + $2 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[2] = { $1_dim0, $1_dim1 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_size(array, size, 2) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_size(array, size, 3) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} + +/* Typemap suite for (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL) +{ + npy_intp size[2] = { -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + + if (array == NULL || object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_no_conversion(PySequence_GetItem($input,i), DATA_TYPECODE); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + + if ( !temp_array || !require_dimensions(temp_array, 2) || + !require_contiguous(temp_array) || + !require_native(temp_array) || + !PyArray_EquivTypenums(array_type(temp_array), DATA_TYPECODE) + ) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + } + + if (!require_size(temp_array, size, 2)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; +} +%typemap(freearg) + (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (array$argnum!=NULL) free(array$argnum); + if (object_array$argnum!=NULL) free(object_array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_ARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_FARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[4] = { $1_dim0, $1_dim1, $1_dim2 , $1_dim3 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_size(array, size, 4) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} + +/* Typemap suite for (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL) +{ + npy_intp size[3] = { -1, -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + + if (array == NULL || object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_no_conversion(PySequence_GetItem($input,i), DATA_TYPECODE); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + + if ( !temp_array || !require_dimensions(temp_array, 3) || + !require_contiguous(temp_array) || + !require_native(temp_array) || + !PyArray_EquivTypenums(array_type(temp_array), DATA_TYPECODE) + ) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + size[2] = array_size(temp_array,2); + } + + if (!require_size(temp_array, size, 3)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; + $5 = (DIM_TYPE) size[2]; +} +%typemap(freearg) + (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + if (array$argnum!=NULL) free(array$argnum); + if (object_array$argnum!=NULL) free(object_array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, + * DATA_TYPE* INPLACE_ARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_FARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} + +/*************************/ +/* Argout Array Typemaps */ +/*************************/ + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY1[ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY1[ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[1] = { $1_dim0 }; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY1[ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + */ +%typemap(in,numinputs=1, + fragment="NumPy_Fragments") + (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + (PyObject* array = NULL) +{ + npy_intp dims[1]; + if (!PyInt_Check($input)) + { + const char* typestring = pytype_string($input); + PyErr_Format(PyExc_TypeError, + "Int dimension expected. '%s' given.", + typestring); + SWIG_fail; + } + $2 = (DIM_TYPE) PyInt_AsLong($input); + dims[0] = (npy_intp) $2; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); +} +%typemap(argout) + (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + */ +%typemap(in,numinputs=1, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + (PyObject* array = NULL) +{ + npy_intp dims[1]; + if (!PyInt_Check($input)) + { + const char* typestring = pytype_string($input); + PyErr_Format(PyExc_TypeError, + "Int dimension expected. '%s' given.", + typestring); + SWIG_fail; + } + $1 = (DIM_TYPE) PyInt_AsLong($input); + dims[0] = (npy_intp) $1; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $2 = (DATA_TYPE*) array_data(array); +} +%typemap(argout) + (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[2] = { $1_dim0, $1_dim1 }; + array = PyArray_SimpleNew(2, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = PyArray_SimpleNew(3, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[4] = { $1_dim0, $1_dim1, $1_dim2, $1_dim3 }; + array = PyArray_SimpleNew(4, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/*****************************/ +/* Argoutview Array Typemaps */ +/*****************************/ + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim_temp) +{ + $1 = &data_temp; + $2 = &dim_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) +{ + npy_intp dims[1] = { *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEW_ARRAY1) + (DIM_TYPE dim_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim_temp; + $2 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) +{ + npy_intp dims[1] = { *$1 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_ARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_FARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEW_ARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEW_FARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEW_FARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEW_ARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEW_ARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEW_FARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEW_FARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/*************************************/ +/* Managed Argoutview Array Typemaps */ +/*************************************/ + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim_temp) +{ + $1 = &data_temp; + $2 = &dim_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) +{ + npy_intp dims[1] = { *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEWM_ARRAY1) + (DIM_TYPE dim_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim_temp; + $2 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) +{ + npy_intp dims[1] = { *$1 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEWM_ARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEWM_FARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEWM_ARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEWM_ARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj= PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEWM_FARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEWM_FARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_ARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_ARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_FARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_FARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_ARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_ARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_FARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_FARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +%enddef /* %numpy_typemaps() macro */ +/* *************************************************************** */ + +/* Concrete instances of the %numpy_typemaps() macro: Each invocation + * below applies all of the typemaps above to the specified data type. + */ +%numpy_typemaps(signed char , NPY_BYTE , int) +%numpy_typemaps(unsigned char , NPY_UBYTE , int) +%numpy_typemaps(short , NPY_SHORT , int) +%numpy_typemaps(unsigned short , NPY_USHORT , int) +%numpy_typemaps(int , NPY_INT , int) +%numpy_typemaps(unsigned int , NPY_UINT , int) +%numpy_typemaps(long , NPY_LONG , int) +%numpy_typemaps(unsigned long , NPY_ULONG , int) +%numpy_typemaps(long long , NPY_LONGLONG , int) +%numpy_typemaps(unsigned long long, NPY_ULONGLONG, int) +%numpy_typemaps(float , NPY_FLOAT , int) +%numpy_typemaps(double , NPY_DOUBLE , int) + +/* *************************************************************** + * The follow macro expansion does not work, because C++ bool is 4 + * bytes and NPY_BOOL is 1 byte + * + * %numpy_typemaps(bool, NPY_BOOL, int) + */ + +/* *************************************************************** + * On my Mac, I get the following warning for this macro expansion: + * 'swig/python detected a memory leak of type 'long double *', no destructor found.' + * + * %numpy_typemaps(long double, NPY_LONGDOUBLE, int) + */ + +/* *************************************************************** + * Swig complains about a syntax error for the following macro + * expansions: + * + * %numpy_typemaps(complex float, NPY_CFLOAT , int) + * + * %numpy_typemaps(complex double, NPY_CDOUBLE, int) + * + * %numpy_typemaps(complex long double, NPY_CLONGDOUBLE, int) + */ + +#endif /* SWIGPYTHON */ diff --git a/python/rough_contact.i b/python/rough_contact.i new file mode 100644 index 0000000..c0d5659 --- /dev/null +++ b/python/rough_contact.i @@ -0,0 +1,18 @@ +%module rough_contact + +/* %exception { */ +/* try { */ +/* $action */ +/* } */ +/* catch (SurfaceException e) { */ +/* PyErr_SetString(PyExc_IndexError,e.what()); */ +/* return NULL; */ +/* } */ +/* } */ + + +%include "surface.i" +%include "surface_generator.i" +%include "surface_statistics.i" +%include "bem.i" +%include "clusters.i" diff --git a/python/smart_pointer.hh b/python/smart_pointer.hh new file mode 100644 index 0000000..8608b6f --- /dev/null +++ b/python/smart_pointer.hh @@ -0,0 +1,51 @@ +#ifndef __SURFACE_SMART_POINTER_HH__ +#define __SURFACE_SMART_POINTER_HH__ +/* -------------------------------------------------------------------------- */ +#include +/* -------------------------------------------------------------------------- */ + +template +class SmartPointer{ + +public: + + SmartPointer(T * t){ptr = t;} + //SmartPointer(T & t){ptr = &t;} + + std::string __str__(){ + std::stringstream sstr; + sstr << *ptr; + return sstr.str(); + } + + T value(){return *ptr;} + void assign(const T & t){*ptr = t;} + + T * ptr; + +}; + +template +class SmartPointer >{ + +public: + + SmartPointer(std::vector * t){ptr = t;} + SmartPointer(std::vector & t){ptr = &t;} + + std::string __str__(){ + std::stringstream sstr; + sstr << "std::vector(" << ptr->size() << ")"; + return sstr.str(); + } + + std::vector value(){return *ptr;} + void assign(const std::vector & t){*ptr = t;} + + std::vector * ptr; + +}; + + + +#endif /* __SURFACE_SMART_POINTER_HH__ */ diff --git a/python/surface.i b/python/surface.i new file mode 100644 index 0000000..1b792e0 --- /dev/null +++ b/python/surface.i @@ -0,0 +1,185 @@ +%{ +#include +#include "map_2d.hh" +#include "surface.hh" +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#include +#include "surface_generator_filter_fft.hh" +#include "smart_pointer.hh" +#include "surface_statistics.hh" +#include "bem_kato.hh" +#include "bem_polonski.hh" +#include "bem_fft_base.hh" +#include "contact_area.hh" +#include "contact_cluster_collection.hh" +%} +%include "cpointer.i" +%include "typemaps.i" +%include "numpy.i" +%init %{ + import_array(); +%} + + /* -------------------------------------------------------------------------- */ +/* Wrapping returned pointers +/* -------------------------------------------------------------------------- */ + +//%include "typemaps.i" +%include "std_string.i" +%include "std_vector.i" +%include "smart_pointer.hh" +%template(VectorReal) std::vector; +%pointer_functions(int, intp); +%pointer_functions(long, longp); +%pointer_functions(unsigned int, uintp); +%pointer_functions(double, doublep); +%pointer_functions(float, floatp); +%pointer_functions(std::complex, comlpexp); + +//%define %my_pointer_class(NAME,TYPE) +// +//%template(SmartPointer##NAME) SmartPointer< TYPE >; +// +//%typemap(out) TYPE & { +//#define TOREPLACE SWIGTYPE_p_SmartPointerT_##NAME##_t +// SmartPointer * ptr = new SmartPointer($1); +// $result = SWIG_NewPointerObj(SWIG_as_voidptr(ptr), TOREPLACE, 0 | 0 ); +//#undef TOREPLACE +// } +//%enddef +// +//%my_pointer_class(int,int) +//%my_pointer_class(Real,Real) +//%my_pointer_class(long,long) +//%my_pointer_class(vectorReal,std::vector) + + /* -------------------------------------------------------------------------- */ +/* Wrapping Surface class */ +/* -------------------------------------------------------------------------- */ + +%include "types.hh" +%include "map_2d.hh" +%template(Map2dComplex) Map2d; +%template(Map2dInt) Map2d; +%template(Map2dReal) Map2d; + +%include "map_2d_square.hh" +%template(Map2dSquareComplex) Map2dSquare; +%template(Map2dSquareInt) Map2dSquare; +%template(Map2dSquareReal) Map2dSquare; + +%include "surface.hh" +%include "surface_complex.hh" + +%template(SurfaceReal) Surface; +%template(SurfaceRealComplex) SurfaceComplex; + +%inline %{ +template + class SurfaceForPython : public Surface{ + + public: + + SurfaceForPython(T * wrapped_memory, + UInt n, + Real L) + : Surface(0,L){ + this->__init__(wrapped_memory,n,L); + }; + + + void __init__(T * wrapped_memory, + UInt n, + Real L){ + this->n[0] = n; + this->n[1] = n; + this->data.wrapMemory(wrapped_memory,n*n); + } + + SurfaceForPython(PyObject * input,Real L = 1.) + : Surface(0,L){ + + if (!PyArray_Check(input)){ + PyObject* obj_type = PyObject_Type(input); + std::string type = PyString_AsString(obj_type); + throw SurfaceException("incompatible input which is not a numpy: " + type); + } + UInt _n = PyArray_NDIM((PyArrayObject*)input); + if (_n != 2) SURFACE_FATAL("incompatible numpy dimension " << _n); + npy_intp * ndims = PyArray_DIMS((PyArrayObject*)input); + UInt sz = ndims[0]; + UInt sz2 = ndims[1]; + if (sz != sz2) SURFACE_FATAL("incompatible numpy dimensions " << sz << " " << sz2); + PyArrayIterObject *iter = (PyArrayIterObject *)PyArray_IterNew(input); + if (iter == NULL) throw; + this->__init__(( T *)(iter->dataptr),sz,L); + Py_DECREF(iter); + }; + + ~SurfaceForPython(){ + }; + + void resize(UInt new_size){ + if (this->size() != new_size) + throw SurfaceException("cannot resize a temporary vector"); + } + + }; +%} + + + +%define %surface_typemaps(SURFACE_CLASS, DATA_TYPE, DATA_TYPECODE) + +%typemap(out, fragment="NumPy_Fragments") (SURFACE_CLASS &) +{ + UInt nz = $1->size(); + npy_intp dims[2] = {nz,nz}; + DATA_TYPE * data = const_cast($1->getInternalData()); + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, &data[0]); + PyArrayObject* array = (PyArrayObject*) obj; + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result, obj); +} + +%typemap(in) Surface< DATA_TYPE > & { + if (!PyArray_Check($input)){ + PyObject* objectsRepresentation = PyObject_Repr(PyObject_Type($input)); + const char* s = PyString_AsString(objectsRepresentation); + std::string __type = s; + + if (__type == "") + SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor,0); + else throw SurfaceException("incompatible input which is not a numpy: " + __type); + } + else{ + UInt _n = PyArray_NDIM((PyArrayObject*)$input); + if (_n != 2) SURFACE_FATAL("incompatible numpy dimension " << _n); + npy_intp * ndims = PyArray_DIMS((PyArrayObject*)$input); + UInt sz = ndims[0]; + UInt sz2 = ndims[1]; + if (sz != sz2) SURFACE_FATAL("incompatible numpy dimensions " << sz << " " << sz2); + PyArrayIterObject *iter = (PyArrayIterObject *)PyArray_IterNew($input); + if (iter == NULL) throw; + $1 = new SurfaceForPython< DATA_TYPE >(( DATA_TYPE *)(iter->dataptr),sz,1.); + PyArray_ITER_NEXT(iter); + } + } + + +%enddef + +%surface_typemaps(Surface, Real, NPY_DOUBLE) +%surface_typemaps(SurfaceComplex, std::complex, NPY_COMPLEX128 ) +%surface_typemaps(Surface, unsigned long, NPY_UINT ) +%surface_typemaps(Surface, UInt, NPY_UINT ) +%surface_typemaps(Surface, int, NPY_INT ) + +%template(SurfaceForPythonReal) SurfaceForPython< Real >; + + + + + + + diff --git a/python/surface_generator.i b/python/surface_generator.i new file mode 100644 index 0000000..dae716c --- /dev/null +++ b/python/surface_generator.i @@ -0,0 +1,8 @@ +/* -------------------------------------------------------------------------- */ +/* Wrapping surface generator classes */ +/* -------------------------------------------------------------------------- */ + +%include "surface_generator.hh" +%include "surface_generator_filter.hh" +%include "surface_generator_filter_fft.hh" + diff --git a/python/surface_statistics.i b/python/surface_statistics.i new file mode 100644 index 0000000..62bd854 --- /dev/null +++ b/python/surface_statistics.i @@ -0,0 +1,21 @@ +/* -------------------------------------------------------------------------- */ +/* Wrapping surface statistics +/* -------------------------------------------------------------------------- */ + +//%include "surface.i" +%include "surface_statistics.hh" +%template(computeDistribution) SurfaceStatistics::computeDistribution; +%template(computeDistributionWithZeros) SurfaceStatistics::computeDistribution; +%template(vecInt) std::vector; +%include "contact_area.hh" +%include "contact_cluster_collection.hh" + +%extend ContactArea +{ + Surface & getSurface() { + return *$self; + } +} + + + diff --git a/site_scons/site_init.py b/site_scons/site_init.py new file mode 100644 index 0000000..485eb0c --- /dev/null +++ b/site_scons/site_init.py @@ -0,0 +1,45 @@ +def fftw(env): + """A Tool to search for fftw headers and libraries""" + + if env.GetOption('clean'): return + if 'FFTW_VERSION' not in env: env['FFTW_VERSION'] = "3" + env['FFTW_VERSION'] = str(env['FFTW_VERSION']) + + if 'FFTW_INCLUDE_DIR' in env: + env['CXXFLAGS'].append('-I{0}'.format(env['FFTW_INCLUDE_DIR'])) + env['CFLAGS'].append('-I{0}'.format(env['FFTW_INCLUDE_DIR'])) + + if 'FFTW_LIBRARY_WISH' not in env: env['FFTW_LIBRARY_WISH'] = ['main'] + if 'main' not in env['FFTW_LIBRARY_WISH']: + env['FFTW_LIBRARY_WISH'] = env['FFTW_LIBRARY_WISH'] + ['main'] + + if 'FFTW_LIBRARY_DIR' in env: + if 'LIBPATH' not in env: env['LIBPATH'] = [] + env['LIBPATH'] += [env['FFTW_LIBRARY_DIR']] + + version = env['FFTW_VERSION'] + if version == "2": + lib_names = {'main':'fftw'} + inc_names = ['fftw.h'] + else: + lib_names = {'main':'fftw3','thread':'fftw3_threads','omp':'fftw3_omp'} + inc_names = ['fftw3.h'] + + try: + libs = [lib_names[i] for i in env['FFTW_LIBRARY_WISH']] + except: + print 'Incompatible wishlist {0} from version {1}'.format(env['FFTW_WISH_LIST'], + env['FFTW_VERSION']) + Exit(1) + + + for l in libs: + conf = Configure(env) + if not conf.CheckLibWithHeader(l,inc_names,'c'): + print 'Did not find {0}, exiting!'.format(l) + Exit(1) + env = conf.Finish() + env['FFTW_LIBRARIES'] = lib_names + + + diff --git a/src/SConscript b/src/SConscript new file mode 100644 index 0000000..802cf7a --- /dev/null +++ b/src/SConscript @@ -0,0 +1,60 @@ +Import('main_env') +import distutils.sysconfig + +env = main_env.Clone( + tools=[fftw], + FFTW_INCLUDE_DIR = '/home/anciaux/src/fftw-3.3.4/api', + FFTW_LIBRARY_DIR = '/home/anciaux/src/fftw-3.3.4/.libs', + FFTW_LIBRARY_WISH = ['main','thread', 'omp'] +) + +# Lib roughcontact +generator_list = """ +surface_generator.cpp +surface_generator_voss.cpp +surface_generator_crenel.cpp +surface_generator_ellipsoid.cpp +surface_generator_filter.cpp +surface_generator_filter_bessel.cpp +surface_generator_filter_fft.cpp +""".split() +#env.SharedLibrary('Generator',generator_list) + +# Lib SURFACE +surface_list = """ +map_2d.cpp +map_2d_square.cpp +surface.cpp +surface_timer.cpp +""".split() +#env.SharedLibrary('Surface',surface_list) + +# Lib PERCOLATION +percolation_list = """ +cluster_grow.cpp +contact_area.cpp +contact_cluster.cpp +contact_cluster_collection.cpp +""".split() +#env.SharedLibrary('Percolation',percolation_list) + +# BEM PERCOLATION +bem_list = """ +bem_kato.cpp +bem_polonski.cpp +bem_fft_base.cpp +""".split() +#env.SharedLibrary('BEM',bem_list) + +rough_contact_list = generator_list + surface_list + percolation_list + bem_list +import os +current_files = set(os.listdir(Dir('.').srcnode().abspath)) +unexpected_files = list(current_files - set(rough_contact_list)) + +unexpected_headers = [ f for f in unexpected_files if os.path.splitext(f)[1] == '.hh' ] + +unexpected_files = [ f for f in unexpected_files if not os.path.splitext(f)[1] == '.hh' ] + +print unexpected_files +#print unexpected_headers +env.SharedLibrary('RoughContact',rough_contact_list) diff --git a/src/bem_fft_base.cpp b/src/bem_fft_base.cpp new file mode 100644 index 0000000..1643a7d --- /dev/null +++ b/src/bem_fft_base.cpp @@ -0,0 +1,329 @@ +#include "bem_fft_base.hh" +/* -------------------------------------------------------------------------- */ +#define TIMER +#include "surface_timer.hh" +#include "surface_statistics.hh" +/* -------------------------------------------------------------------------- */ +#include +/* -------------------------------------------------------------------------- */ + +const Surface & BemFFTBase::getTractions() const{ + return surface_tractions; +} +/* -------------------------------------------------------------------------- */ +const Surface & BemFFTBase::getDisplacements()const{ + return surface_displacements; +} +/* -------------------------------------------------------------------------- */ +const Surface & BemFFTBase::getSpectralInfluenceOverDisplacement(){ + return surface_spectral_influence_disp; +} +/* -------------------------------------------------------------------------- */ +const SurfaceComplex & BemFFTBase::getSpectralDisplacements()const{ + return surface_spectral_displacements; +} +/* -------------------------------------------------------------------------- */ +const SurfaceComplex & BemFFTBase::getSpectralTractions()const{ + return surface_spectral_tractions; +} +/* -------------------------------------------------------------------------- */ + +Real BemFFTBase::getF(){ + return computed_F; +} +/* -------------------------------------------------------------------------- */ +Real BemFFTBase::getOldF(){ + return computed_oldF; +} +/* -------------------------------------------------------------------------- */ +const Surface & BemFFTBase::getGradF() const{ + return gradient_F; +} +/* -------------------------------------------------------------------------- */ +void BemFFTBase::setNumberOfThreads(UInt nthreads){ + this->nthreads = nthreads; + omp_set_num_threads(nthreads); +} +/* -------------------------------------------------------------------------- */ +void BemFFTBase::setEffectiveModulus(Real e_star){ + this->e_star = e_star; + this->computeSpectralInfluenceOverDisplacement(); +} +/* -------------------------------------------------------------------------- */ + +void BemFFTBase::computeSpectralInfluenceOverDisplacement(){ + + STARTTIMER("computeSpectralInfluenceOverDisplacement"); + + if (std::isnan(tmp_coeff)) SURFACE_FATAL("constant tmp_coeff is nan"); + if (std::isnan(e_star)) SURFACE_FATAL("constant e_star is nan"); + + UInt n = surface.size(); + + surface_spectral_influence_disp(0) = 0.; + + // everything but the external lines and central lines +#pragma omp parallel for + for (unsigned int i = 1; i < n/2; ++i) { + for (unsigned int j = 1; j < n/2; ++j) { + + Real d = sqrt(i*i+j*j); + surface_spectral_influence_disp(i,j) = 1./d; + surface_spectral_influence_disp(n-i,j) = 1./d; + surface_spectral_influence_disp(i,n-j) = 1./d; + surface_spectral_influence_disp(n-i,n-j) = 1./d; + + } + } + // external line (i or j == 0) +#pragma omp parallel for + for (unsigned int i = 1; i < n/2; ++i) { + Real d = i; + surface_spectral_influence_disp(i,0) = 1./d; + surface_spectral_influence_disp(n-i,0) = 1./d; + surface_spectral_influence_disp(0,i) = 1./d; + surface_spectral_influence_disp(0,n-i) = 1./d; + + } + + //internal line (i or j == n/2) +#pragma omp parallel for + for (unsigned int i = 1; i < n/2; ++i) { + Real d = sqrt(i*i+n/2*n/2); + surface_spectral_influence_disp(i,n/2) = 1./d; + surface_spectral_influence_disp(n-i,n/2) = 1./d; + surface_spectral_influence_disp(n/2,i) = 1./d; + surface_spectral_influence_disp(n/2,n-i) = 1./d; + } + + { + //i == n/2 j == n/2 + Real d = sqrt(2*n/2*n/2); + surface_spectral_influence_disp(n/2,n/2) = 1./d; + //i == 0 j == n/2 + d = n/2; + surface_spectral_influence_disp(0,n/2) = 1./d; + //i == n/2 j == 0 + surface_spectral_influence_disp(n/2,0) = 1./d; + } + + unsigned int size = n*n; + Real L = surface.getL(); + + #pragma omp parallel for + for (unsigned int i = 0; i < size; ++i) { + surface_spectral_influence_disp(i) *= tmp_coeff/this->e_star*L; + } + + STOPTIMER("computeSpectralInfluenceOverDisplacement"); + +} + + +/* -------------------------------------------------------------------------- */ + +void BemFFTBase::computeSpectralDisplacements(){ + + STARTTIMER("computeSpectralDisplacement"); + + UInt n = surface.size(); + UInt size = n*n; + + // std::cerr << "000000000000 " << surface_spectral_tractions(n*n-1) << std::endl; + // std::cerr << "000000000000 " << surface_spectral_displacements(n*n-1) << std::endl; + + surface_spectral_displacements = surface_spectral_tractions; + // std::cerr << "AAAAAAAAAAAA " << surface_spectral_tractions(n*n-1) << std::endl; + // std::cerr << "AAAAAAAAAAAA " << surface_spectral_displacements(n*n-1) << std::endl; + // std::cerr << "AAAAAAAAAAAA " << &surface_spectral_displacements(n*n-1) << std::endl; + // std::cerr << "AAAAAAAAAAAA " << &surface_spectral_displacements(0) << std::endl; + +#pragma omp parallel for + for (UInt i = 0; i < size; ++i) { + surface_spectral_displacements(i) *= surface_spectral_influence_disp(i); + } + + // std::cerr << "BBBBBBBBBBBB " << surface_spectral_displacements(n*n-1) << std::endl; + // std::cerr << "BBBBBBBBBBBB " << surface_spectral_influence_disp(n*n-1) << std::endl; + + + STOPTIMER("computeSpectralDisplacement"); + +} + +/* -------------------------------------------------------------------------- */ + +void BemFFTBase::computeSpectralTractions(){ + + STARTTIMER("computeSpectralTraction"); + + surface_tractions.FFTTransform(surface_spectral_tractions,nthreads); + + STOPTIMER("computeSpectralTraction"); + +} + +/* -------------------------------------------------------------------------- */ + + +void BemFFTBase::computeDisplacements(){ + + STARTTIMER("computeDisplacement"); + + this->computeSpectralTractions(); + this->computeSpectralDisplacements(); + this->computeRealDisplacementsFromSpectral(); + + STOPTIMER("computeDisplacement"); + +} + +/* -------------------------------------------------------------------------- */ + +void BemFFTBase::computeRealTractionsFromSpectral(){ + + STARTTIMER("computeRealTractionsFromSpectral"); + + surface_spectral_tractions.FFTITransform(surface_tractions,nthreads); + + STOPTIMER("computeRealDisplacementFromSpectral"); + +} + +/* -------------------------------------------------------------------------- */ + + +void BemFFTBase::computeRealDisplacementsFromSpectral(){ + + STARTTIMER("computeRealDisplacementFromSpectral"); + + surface_spectral_displacements.FFTITransform(surface_displacements,nthreads); + + STOPTIMER("computeRealDisplacementFromSpectral"); + +} + +/* -------------------------------------------------------------------------- */ + + +void BemFFTBase::computeGradF(){ + + STARTTIMER("computeGradient"); + + unsigned int n = surface.size(); + unsigned int size = n*n; +#pragma omp parallel for + for (unsigned int i = 0; i < size; ++i) { + gradient_F(i) = + (surface_displacements(i) - surface(i)); + } + + STOPTIMER("computeGradient"); + +} + +/* -------------------------------------------------------------------------- */ + + +void BemFFTBase::computeF(){ + + STARTTIMER("computeF"); + + unsigned int n = surface.size(); + unsigned int size = n*n; + Real res = 0; + Real d_max = SurfaceStatistics::computeMaximum(surface_displacements); + Real t_sum = std::abs(SurfaceStatistics::computeSum(surface_tractions)); + Real s_max = SurfaceStatistics::computeMaximum(surface); + +#pragma omp parallel for reduction(+:res) + for (unsigned int i = 0; i < size; ++i) { + + res += std::abs(surface_tractions(i) + *(surface_displacements(i)-d_max-surface(i)+s_max) + ); + + // res += + // this->surface_tractions[i].real() + // *(surface_displacements[i].real() - surface[i].real()); + } + + STOPTIMER("computeF"); + + // this->computed_F = -1.0*res; + this->computed_F = res/std::abs(t_sum); + +} + +/* -------------------------------------------------------------------------- */ + + +void BemFFTBase::computeOldF(){ + + STARTTIMER("computeF"); + + unsigned int n = surface.size(); + unsigned int size = n*n; + Real res = 0; + // Real d_max = SurfaceStatistics::computeMaximum(surface_displacements); + //Real t_sum = std::abs(SurfaceStatistics::computeSum(surface_tractions)); + //Real s_max = SurfaceStatistics::computeMaximum(surface); + +#pragma omp parallel for reduction(+:res) + for (unsigned int i = 0; i < size; ++i) { + + res += + this->surface_tractions(i) + *(surface_displacements(i) - surface(i)); + } + + STOPTIMER("computeF"); + + this->computed_oldF = -1.0*res; +} + + +/* -------------------------------------------------------------------------- */ + +void BemFFTBase::computeGaps() { + int size = surface.size(); + + for (int i=0; i < size*size; i++) { + gap(i) = true_displacements(i) - surface(i); + // if (std::norm(surface_tractions(i)) > zero_threshold*zero_threshold) + // gap(i) = 0.; + } +} + + +/* -------------------------------------------------------------------------- */ + +void BemFFTBase::computeTrueDisplacements(){ + this->true_displacements = this->surface_displacements; + + // choose a point in contact + //UInt index = 0; + //Real max_pressure = 0; + unsigned int n = surface.size(); + unsigned int size = n*n; + // for (unsigned int i = 0; i < size; ++i) { + // if (surface_tractions(i).real() > max_pressure) { + // index = i; + // max_pressure = surface_tractions(i).real(); + // } + // } + // Real shift = surface_displacements[index].real() - surface[index].real(); + + Real shift = 0; + for (unsigned int i = 0; i < size; ++i) { + if (surface_displacements(i) - shift - surface(i) < 0.){ + shift = surface_displacements(i) - surface(i); + } + } + + for (unsigned int i = 0; i < size; ++i) { + true_displacements(i) = surface_displacements(i) - shift; + } +} + +/* -------------------------------------------------------------------------- */ diff --git a/src/bem_fft_base.hh b/src/bem_fft_base.hh new file mode 100644 index 0000000..eb5034e --- /dev/null +++ b/src/bem_fft_base.hh @@ -0,0 +1,164 @@ +#ifndef BEM_FFT_BASE_H +#define BEM_FFT_BASE_H +/* -------------------------------------------------------------------------- */ +#include "bem_interface.hh" +#include +#include "surface_statistics.hh" +/* -------------------------------------------------------------------------- */ + +class BemFFTBase : public BemInterface { + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ +public: + + BemFFTBase(Surface & p): + BemInterface(p), + computed_F(std::nan("")), + gradient_F(p.size(),p.getL()), + surface_tractions(p.size(),p.getL()), + surface_displacements(p.size(),p.getL()), + surface_spectral_tractions(p.size(),p.getL()), + surface_spectral_displacements(p.size(),p.getL()), + surface_spectral_influence_disp(p.size(),p.getL()), + true_displacements(p.size(),p.getL()), + gap(p.size(),p.getL()), + e_star(std::nan("")), + nthreads(1), + tmp_coeff(1./M_PI){ + this->setNumberOfThreads(this->nthreads); + max_iterations = 100000; + dump_freq = 100; + + std::cerr << this << " is setting up the surfaces"; + std::cerr << &p << " has size " << p.size() << std::endl; + + }; + + + virtual ~BemFFTBase(){}; + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ +public: + + //! compute the influcence coefficients of pressure over displacement + virtual void computeSpectralInfluenceOverDisplacement(); + //! compute real tractions from fourier represnetation (IFFT) + virtual void computeRealTractionsFromSpectral(); + //! compute real displacements from fourier represnetation (IFFT) + virtual void computeRealDisplacementsFromSpectral(); + //! compute the displacement in real space + virtual void computeDisplacements(); + //! compute the displacement fourier space + virtual void computeSpectralDisplacements(); + //! compute the tractions in fourier space + virtual void computeSpectralTractions(); + //! compute the gradient the objective function (with respect to traction) + virtual void computeGradF(); + //! compute the objective function + virtual void computeF(); + //! compute the objective function (old version) + virtual void computeOldF(); + //! compute the real displacement field + virtual void computeTrueDisplacements(); + //! compute the gap + virtual void computeGaps(); + + //! get the number of iterations + virtual UInt getNbIterations() const = 0; + //! get the convergence steps of iterations + virtual const std::vector & getConvergenceIterations() const = 0; + + + /* ------------------------------------------------------------------------ */ + /* Accessors */ + /* ------------------------------------------------------------------------ */ +public: + + //! return the influcence coefficients + virtual const Surface & getSpectralInfluenceOverDisplacement(); + //! return the actual tractions + virtual const Surface & getTractions() const; + //! return the actual displacements + virtual const Surface & getDisplacements()const; + //! return the actual displacements + virtual const SurfaceComplex & getSpectralDisplacements()const; + //! return the actual displacements + virtual const SurfaceComplex & getSpectralTractions()const; + //! get the computed true displacement + const Surface & getTrueDisplacements(){return true_displacements;}; + //! get the computed gap + const Surface & getGap(){return gap;}; + //! return the actual value of the objective function + virtual Real getF(); + //! return the actual value of the objective function (old version) + virtual Real getOldF(); + //! return the actual value of gradient of the objective function + virtual const Surface & getGradF() const; + //! set the number of threads to be used to perform the calculations + void setNumberOfThreads(UInt nthreads); + //! set the elastic effective modulus + void setEffectiveModulus(Real e_star); + //! set the maximal number of iterations + void setMaxIterations(UInt max_iter){this->max_iterations = max_iter;}; + //! set dump freq + void setDumpFreq(Real dump_freq){this->dump_freq = dump_freq;}; + + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ +protected: + + //! the value of the objective function + Real computed_F; + //! the value of the objective function (old version) + Real computed_oldF; + //! the gradient of the objective function + Surface gradient_F; + //! surface tractions + Surface surface_tractions; + //! surface displacement + Surface surface_displacements; + //! surface tractions + SurfaceComplex surface_spectral_tractions; + //! surface displacement + SurfaceComplex surface_spectral_displacements; + //! surface influcence coefficient over displacement + Surface surface_spectral_influence_disp; + //! shifted displacement in order to get the true displacement + Surface true_displacements; + //! computing of the gap + Surface gap; + //! Effective young modulus + Real e_star; + //! Number of threads to use during calculations + UInt nthreads; + //! maximum of iterations + UInt max_iterations; + //! number of iterations + UInt nb_iterations; + //! number of iterations + std::vector convergence_iterations; + //! frequency at which to dump iteration info + UInt dump_freq; + + /* ------------------------------------------------------------------------ */ + /* temporary trick about some obscure scaling factor */ + /* ------------------------------------------------------------------------ */ + /* + 0 2 = 2*1 + 1 4 = 2*2 + 2 10 = 2*5 + 3 20 = 2*10 + 4 34 = 2*12 + */ + + //#define tmp_coeff (2.*n/M_PI) + //#define tmp_coeff (n/M_PI) + const Real tmp_coeff; + +}; + +#endif /* BEM_FFT_BASE_H */ diff --git a/src/bem_interface.hh b/src/bem_interface.hh new file mode 100644 index 0000000..9e745b5 --- /dev/null +++ b/src/bem_interface.hh @@ -0,0 +1,78 @@ +#ifndef BEM_INTERFACE_H +#define BEM_INTERFACE_H + +#include "surface.hh" +/* -------------------------------------------------------------------------- */ + + + +class BemInterface { + + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ +public: + + BemInterface(Surface & surface): + surface(surface), + spectral_surface(surface.size(),surface.getL()) { + this->computeSpectralSurface(); + }; + virtual ~BemInterface(){}; + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ + +protected: + + //! compute the displacement from the pressure field + virtual void computeDisplacements() = 0; + //! compute the gradient the objective function (with respect to traction) + virtual void computeGradF() = 0; + //! compute the objective function + virtual void computeF() = 0; + +public: + + //! compute the spectral surface + virtual void computeSpectralSurface(){ + surface.FFTTransform(spectral_surface); + }; + + + /* ------------------------------------------------------------------------ */ + /* Accessors */ + /* ------------------------------------------------------------------------ */ + +public: + + //! return the actual tractions + virtual const Surface & getTractions() const = 0; + //! return the actual displacements + virtual const Surface & getDisplacements() const = 0; + //! return the actual value of the objective function + virtual Real getF() = 0; + //! return the actual value of gradient of the objective function + virtual const Surface & getGradF() const = 0; + //! return the manipulated surface + const Surface & getSurface() const{return this->surface;}; + //! return the manipulated surface in fourier space + const SurfaceComplex & getSpectralSurface() const{return this->spectral_surface;}; + //! return the manipulated surface + void setSurface(Surface & surface){this->surface = surface;}; + + + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ +protected: + + //! the surface profile we work with + Surface & surface; + //! the surface profile in fourier space + SurfaceComplex spectral_surface; + +}; + +#endif /* BEM_INTERFACE_H */ diff --git a/src/bem_kato.cpp b/src/bem_kato.cpp new file mode 100644 index 0000000..12d35c6 --- /dev/null +++ b/src/bem_kato.cpp @@ -0,0 +1,230 @@ +#include +#include "surface.hh" +#include "bem_kato.hh" +#include +#include +#include +#include +#include +#include +/* -------------------------------------------------------------------------- */ +#define TIMER +#include "surface_timer.hh" +/* -------------------------------------------------------------------------- */ + + +Real BemKato::linescan(Real scale,Real pressure){ + updatePressure(scale); + shiftPressure(pressure); + truncatePressure(); + this->computeF(); + Real res = this->getF(); + + return res; +} +/* -------------------------------------------------------------------------- */ + + +Real BemKato::linesearch(Real & hmax, Real fold, + Real pressure, int search_flag){ + if (search_flag){ + Real h = hmax; + // Real fold = bem.computeF(); + //if (fold == 0) fold = 1e300; + Real f = linescan(h,pressure); + if (f < fold) return f; + + while (f > fold){ + h *= 0.5; + if (h < 1e-3) throw 1; + f = linescan(h,pressure); + } + f = linescan(h,pressure); + // if (hmax / h > 10) hmax /=2; + return f; + } + return linescan(hmax,pressure); +} + +/* -------------------------------------------------------------------------- */ + + +Real BemKato::computeEquilibrium(Real epsilon, + Real pressure, + int nthreads){ + + this->setNumberOfThreads(nthreads); + + // UInt n = surface.size(); + // UInt size = n*n; + + this->computeDisplacements(); + this->computeGradF(); + this->backupTractions(); + Real f = 1.; + Real fPrevious = 1e300; + Real fOldVer = 1.; + Real fOldVerPrevious = 1e300; + + this->nb_iterations = 0; + this->convergence_iterations.clear(); + + while(f > epsilon && this->nb_iterations < this->max_iterations) { + + fPrevious = f; + fOldVerPrevious = fOldVer; + this->computeDisplacements(); + this->computeGradF(); + this->backupTractions(); + try { + f = linescan(1.,pressure); + this->computeOldF(); + fOldVer = this->getOldF(); + } + catch (int e){ + std::cout << " line search failed " << std::endl; + f = linescan(1,pressure); + nb_iterations = 0; + break; + } + if (nb_iterations % dump_freq == 0) + // std::cout << std::scientific << std::setprecision(10) << nb_iterations << " " << f << " " << f-fold << " " << ((f-fold)/forigin) << std::endl; + std::cout << std::scientific << std::setprecision(10) + << nb_iterations << " " + << f << " " << f-fPrevious << " " + << fOldVer << " " << ((fOldVer-fOldVerPrevious)/fOldVer) + << std::endl; + convergence_iterations.push_back(f); + ++nb_iterations; + } + + + this->computeTrueDisplacements(); + this->computeGaps(); + + return f; +} + +/* -------------------------------------------------------------------------- */ + + +void BemKato::updatePressure(Real scale){ + STARTTIMER("updatePressure"); + unsigned int n = surface.size(); + unsigned int size = n*n; +#pragma omp parallel for + for (unsigned int i = 0; i < size; ++i) { + this->surface_tractions(i) = + this->surface_tractions_backup(i) - this->gradient_F(i) * scale; + } + STOPTIMER("updatePressure"); +} + +/* -------------------------------------------------------------------------- */ + +void BemKato::backupTractions(){ + STARTTIMER("switchPressure"); + + unsigned int n = surface.size(); + unsigned int size = n*n; +#pragma omp parallel for + for (unsigned int i = 0; i < size; ++i) { + this->surface_tractions_backup(i) = this->surface_tractions(i); + } + + STOPTIMER("switchPressure"); +} + + +/* -------------------------------------------------------------------------- */ +Real BemKato::positivePressure(Real step){ + STARTTIMER("positivePressure"); + + unsigned int n = surface.size(); + unsigned int size = n*n; + Real p_tot = 0.0; + +#pragma omp parallel for reduction(+:p_tot) + for (unsigned int i = 0; i < size; ++i) { + Real sh_press = this->surface_tractions(i) + step; + if (sh_press > max_pressure) p_tot += max_pressure; + else p_tot += sh_press*(sh_press > 0); + } + + STOPTIMER("positivePressure"); + return p_tot/n/n; +} + +/* -------------------------------------------------------------------------- */ + + +void BemKato::shiftPressure(Real required_pressure){ + + Real step_min = -10; + Real step_max = 10; + + STARTTIMER("shiftPressureInitialGuess"); + + Real p_max = positivePressure(step_max); + Real p_min = positivePressure(step_min); + + + for(UInt i = 0; p_max < required_pressure && i < 8; ++i, step_max*=10) { + p_max = positivePressure(step_max); + } + for(UInt i = 0; p_min > required_pressure && i < 8; ++i, step_min*=10) { + p_min = positivePressure(step_min); + } + + Real p = positivePressure(0.0); + Real epsilon = 1e-12; + + STOPTIMER("shiftPressureInitialGuess"); + + STARTTIMER("shiftPressureDichotomy"); + while (fabs(step_min - step_max) > epsilon){ + Real step = (step_min + step_max)/2; + p = positivePressure(step); + if (p > required_pressure) step_max = step; + else if (p < required_pressure) step_min = step; + else { + step_max = step; + step_min = step; + } + } + STOPTIMER("shiftPressureDichotomy"); + + STARTTIMER("shiftPressureTrueShift"); + unsigned int n = surface.size(); + unsigned int size = n*n; + //shift the pressure so that satisfies the constraint +#pragma omp parallel for + for (unsigned int i = 0; i < size; ++i) { + this->surface_tractions(i) += (step_max+step_min)/2; + } + STOPTIMER("shiftPressureTrueShift"); +} + +/* -------------------------------------------------------------------------- */ + +void BemKato::truncatePressure(){ + STARTTIMER("truncatePressure"); + + unsigned int n = surface.size(); + unsigned int size = n*n; + //shift the pressure so that satisfies the constraint +#pragma omp parallel for + for (unsigned int i = 0; i < size; ++i) { + if (this->surface_tractions(i) > max_pressure) + this->surface_tractions(i) = max_pressure; + + else this->surface_tractions(i) *= (this->surface_tractions(i) > 0); + } + + STOPTIMER("truncatePressure"); +} + +/* -------------------------------------------------------------------------- */ + + + diff --git a/src/bem_kato.hh b/src/bem_kato.hh new file mode 100644 index 0000000..e1c5515 --- /dev/null +++ b/src/bem_kato.hh @@ -0,0 +1,79 @@ +#ifndef BEM_KATO_H +#define BEM_KATO_H +/* -------------------------------------------------------------------------- */ +#include "bem_fft_base.hh" +/* -------------------------------------------------------------------------- */ + +class BemKato : public BemFFTBase { + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ +public: + + BemKato(Surface & p) : + BemFFTBase(p), + surface_tractions_backup(p.size(),p.getL()){ + e_star = 1.; + max_pressure = 1e300; + }; + virtual ~BemKato(){}; + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ +public: + + + //! compute the equilibrium situation + Real computeEquilibrium(Real epsilon,Real pressure, + int nthreads = 1); + +public: + + //! perform a line scan in a given direction + Real linescan(Real scale,Real pressure); + //! perform a line search + Real linesearch(Real & hmax, Real fold, + Real pressure, int search_flag); + + //! make a step in the gradient direction(copy in pressure2) + void updatePressure(Real scale); + //! backup tractions before doing the linescan + void backupTractions(); + //! find the constant pressure shift making balance with load + void shiftPressure(Real required_pressure); + //! truncate the pressure to positive values + Real positivePressure(Real step); + //! compute the reaction (sum positive pressures) + void truncatePressure(); + + /* ------------------------------------------------------------------------ */ + /* Accessors */ + /* ------------------------------------------------------------------------ */ +public: + + //! get the number of iterations + UInt getNbIterations() const{return this->nb_iterations;}; + //! get the convergence steps of iterations + const std::vector & getConvergenceIterations() const{return this->convergence_iterations;}; + //! set the maximal pressure admissible + void setMaxPressure(Real max_pressure){this->max_pressure = max_pressure;}; + + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ +protected: + + //! surface of tractions used during steepest descent + Surface surface_tractions_backup; + //! maximal pressure admissible (for perfectly plastic purpose) + Real max_pressure; + +}; + + + + + +#endif /* BEM_KATO_H */ + diff --git a/src/bem_polonski.cpp b/src/bem_polonski.cpp new file mode 100644 index 0000000..6559021 --- /dev/null +++ b/src/bem_polonski.cpp @@ -0,0 +1,257 @@ +#include +#include "surface.hh" +#include "bem_polonski.hh" +#include +#include +#include +#include +#include +#include +/* -------------------------------------------------------------------------- */ +#define TIMER +#include "surface_timer.hh" +/* -------------------------------------------------------------------------- */ + +Real BemPolonski::computeEquilibrium(Real epsilon, + Real pressure, + int nthreads){ + + this->setNumberOfThreads(nthreads); + this->computeSpectralInfluenceOverDisplacement(); + this->surface_t = 0.; + this->surface_r = 0.; + this->surface_spectral_r = 0.; + this->pold = 0.; + this->surface_displacements = 0.; + Real delta = 0.; + Real Gold = 1.; + Real f = 1e300; + Real fPrevious = 1e300; + + Real current_pressure = SurfaceStatistics::computeAverage(surface_tractions); + if (current_pressure <= 0.) surface_tractions = pressure; + this->enforcePressureBalance(pressure); + + convergence_iterations.clear(); + nb_iterations = 0; + + while(f > epsilon && nb_iterations < max_iterations) { + fPrevious = f; + this->computeDisplacements(); + this->computeGaps(); + + Real gbar = this->computeMeanGapsInContact(); + // std::cerr << std::scientific << std::setprecision(10) + // << "gbar " << gbar << std::endl; + this->gap -= gbar; + Real G = this->computeG(); + // std::cerr << std::scientific << std::setprecision(10) + // << "G " << G << std::endl; + this->updateT(G,Gold,delta); + Real tau = this->computeTau(); + // std::cerr << std::scientific << std::setprecision(10) + // << "tau " << tau << std::endl; + pold = this->surface_tractions; + Gold = G; + delta = this->updateTractions(tau); + //if (nb_iterations % 1000 == 0) delta = 0; + + this->enforcePressureBalance(pressure); + this->computeF(); + f = this->getF(); + + if (nb_iterations % dump_freq == 0){ + Real A = SurfaceStatistics::computeContactAreaRatio(surface_tractions); + std::cout << std::scientific << std::setprecision(10) + << nb_iterations << " " + << f << " " << f-fPrevious << " " << A + << std::endl; + } + + convergence_iterations.push_back(f); + ++nb_iterations; + + } + return f; +} + +/* -------------------------------------------------------------------------- */ + +void BemPolonski::computeGaps() { + UInt size = surface.size(); + +#pragma omp parallel for + for (UInt i=0; i < size*size; i++) { + gap(i) = surface_displacements(i) - surface(i); + } +} + + +/* -------------------------------------------------------------------------- */ +Real BemPolonski::computeMeanGapsInContact(){ + STARTTIMER("computeMeanGapsInContact"); + + 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->surface_tractions(i) <= 0) continue; + ++nb_contact; + res += this->gap(i); + } + + res /= nb_contact; + STOPTIMER("computeMeanGapsInContact"); + return res; +} + +/* -------------------------------------------------------------------------- */ + +Real BemPolonski::computeG(){ + STARTTIMER("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->surface_tractions(i) <= 0) continue; + Real val = this->gap(i); + res += val*val; + } + + STOPTIMER("computeG"); + return res; +} + +/* -------------------------------------------------------------------------- */ + +void BemPolonski::updateT(Real G, Real Gold, Real delta){ + STARTTIMER("updateT"); + + 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->surface_tractions(i) <= 0) this->surface_t(i) = 0.; + else{ + this->surface_t(i) *= factor; + this->surface_t(i) += this->gap(i); + } + } + + STOPTIMER("updateT"); +} + + +/* -------------------------------------------------------------------------- */ + +Real BemPolonski::computeTau(){ + STARTTIMER("computeTau"); + + surface_spectral_r = surface_t; + surface_spectral_r.FFTTransform(nthreads); + + unsigned int n = surface.size(); + unsigned int size = n*n; +#pragma omp parallel for + for (unsigned int i = 0; i < size; ++i) { + surface_spectral_r(i) *= this->surface_spectral_influence_disp(i); + } + + + surface_spectral_r.FFTITransform(surface_r,nthreads); + + 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->surface_tractions(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->surface_tractions(i) <= 0) continue; + tau_sum1 += this->gap(i)*surface_t(i); + tau_sum2 += surface_r(i)*surface_t(i); + } + Real tau = tau_sum1/tau_sum2; + + STOPTIMER("computeTau"); + return tau; +} + + + +/* -------------------------------------------------------------------------- */ + +Real BemPolonski::updateTractions(Real tau){ + STARTTIMER("updateTractions"); + + unsigned int n = surface.size(); + unsigned int size = n*n; +#pragma omp parallel for + for (unsigned int i = 0; i < size; ++i) { + if (this->surface_tractions(i) <= 0) continue; + this->surface_tractions(i) -= tau*this->surface_t(i); + if (this->surface_tractions(i) < 0.) this->surface_tractions(i) = 0; + } + + //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->surface_tractions(i) <= 0. && + this->gap(i) < 0.){ + + this->surface_tractions(i) -= tau*this->gap(i); + ++nb_iol; + } + } + + Real delta = 0; + if (nb_iol > 0) delta = 0.; + else delta = 1.; + + STOPTIMER("updateTractions"); + return delta; +} + +/* -------------------------------------------------------------------------- */ + +void BemPolonski::enforcePressureBalance(Real applied_pressure){ + STARTTIMER("enforcePressureBalance"); + + unsigned int n = surface.size(); + unsigned int size = n*n; + Real pressure = 0.; +#pragma omp parallel for reduction(+: pressure) + for (unsigned int i = 0; i < size; ++i) { + pressure += this->surface_tractions(i); + } + + pressure *= 1./size; + +#pragma omp parallel for + for (unsigned int i = 0; i < size; ++i) { + this->surface_tractions(i) *= applied_pressure/pressure; + } + + STOPTIMER("enforcePressureBalance"); + } + +/* -------------------------------------------------------------------------- */ + + + + + diff --git a/src/bem_polonski.hh b/src/bem_polonski.hh new file mode 100644 index 0000000..b1f7c58 --- /dev/null +++ b/src/bem_polonski.hh @@ -0,0 +1,80 @@ +#ifndef BEM_POLONSKI_H +#define BEM_POLONSKI_H +/* -------------------------------------------------------------------------- */ +#include "bem_fft_base.hh" +/* -------------------------------------------------------------------------- */ + +class BemPolonski : public BemFFTBase { + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ +public: + + BemPolonski(Surface & p) : + BemFFTBase(p), + surface_t(p.size(),p.getL()), + surface_r(p.size(),p.getL()), + surface_spectral_r(p.size(),p.getL()), + pold(p.size(),p.getL()){ + e_star = 1.; + max_iterations = 10000; + }; + virtual ~BemPolonski(){}; + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ +public: + + + //! compute the equilibrium situation + Real computeEquilibrium(Real epsilon,Real pressure, + int nthreads = 1); + // compute the mean of the gaps in the contact region + Real computeMeanGapsInContact(); + // compute the non zero gap penalty functional + Real computeG(); + // update the search direction + void updateT(Real G, Real Gold, Real delta); + // compute the conjugate step size + Real computeTau(); + // update the tractions + Real updateTractions(Real tau); + // enforce the applied and contact pressures balance + void enforcePressureBalance(Real applied_pressure); + + void computeGaps(); + + /* ------------------------------------------------------------------------ */ + /* Accessors */ + /* ------------------------------------------------------------------------ */ +public: + + //! get the number of iterations + UInt getNbIterations() const{return this->nb_iterations;}; + //! get the convergence steps of iterations + const std::vector & getConvergenceIterations() const{return this->convergence_iterations;}; + + Surface & getSurfaceT(){return surface_t;}; + + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ +protected: + + //! exploration direction for the polonski algo + Surface surface_t; + //! projected exploration direction for the polonski algo + Surface surface_r; + //! projected exploration direction for the polonski algo (fourier version) + SurfaceComplex surface_spectral_r; + //! previous pressure + Surface pold; +}; + + + + + +#endif /* BEM_POLONSKI_H */ + diff --git a/src/cluster_grow.cpp b/src/cluster_grow.cpp new file mode 100644 index 0000000..3c2140a --- /dev/null +++ b/src/cluster_grow.cpp @@ -0,0 +1,77 @@ +#include "cluster_grow.hh" +/* -------------------------------------------------------------------------- */ + +ClusterGrow::ClusterGrow(Map2d & area, + int initial_state, + int to_check_state, + int contact_state, + int no_contact_state): + current_state (initial_state), + to_check_state (to_check_state), + contact_state (contact_state), + no_contact_state(no_contact_state), + area(area){ + +} + +/* -------------------------------------------------------------------------- */ + +ClusterGrow::~ClusterGrow(){ + +} + +/* -------------------------------------------------------------------------- */ + + +void ClusterGrow::addIndicesToExplore(std::vector > & + indices_to_add){ + + auto it = indices_to_add.begin(); + auto end = indices_to_add.end(); + + for( ; it != end ; ++it){ + int & val = area(*it); + + if (val == contact_state) { + + index_to_explore.push(*it); + + val = to_check_state; + } + } +} +/* -------------------------------------------------------------------------- */ + +template +void ClusterGrow::grow(UInt i, UInt j){ + + if (area(i,j) != contact_state) return; + + ++current_state; + + area(i,j) = current_state; + + std::vector > v = area.getNeighborIndexes(i,j); + this->addIndicesToExplore(v); + + while (!index_to_explore.empty()){ + + std::pair ind = index_to_explore.front(); + + int & val = area(ind); + + if (val == contact_state || val == to_check_state){ + val = current_state; + std::vector > v = area.getNeighborIndexes(ind); + this->addIndicesToExplore(v); + } + + index_to_explore.pop(); + + } +} + +/* -------------------------------------------------------------------------- */ + +template void ClusterGrow::grow(UInt i, UInt j); +template void ClusterGrow::grow(UInt i, UInt j); diff --git a/src/cluster_grow.hh b/src/cluster_grow.hh new file mode 100644 index 0000000..13f0726 --- /dev/null +++ b/src/cluster_grow.hh @@ -0,0 +1,76 @@ +#ifndef __CLUSTER_GROW_HH__ +#define __CLUSTER_GROW_HH__ +/* -------------------------------------------------------------------------- */ +#include "contact_area.hh" +/* -------------------------------------------------------------------------- */ +#include +/* -------------------------------------------------------------------------- */ + + +class ClusterGrow { + + /* ------------------------------------------------------------------------ */ + /* Typedefs */ + /* ------------------------------------------------------------------------ */ + +public: + + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ +public: + + ClusterGrow(Map2d & area, + int initial_state, + int to_check_state = -1, + int contact_state = 1, + int no_contact_state = 0); + virtual ~ClusterGrow(); + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ +public: + + //! start grow of a cluster from a given point + template + void grow(UInt i, UInt j); + +private: + + void addIndicesToExplore(std::vector > & indices_to_add); + + /* ------------------------------------------------------------------------ */ + /* Accessors */ + /* ------------------------------------------------------------------------ */ + +public: + + UInt getNbClusters(){ + UInt tmp = current_state - 2; + return tmp; + }; + + + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ + +private: + + int current_state; + + const int to_check_state ; + const int contact_state ; + const int no_contact_state; + + Map2d & area; + + std::queue > index_to_explore; +}; + +/* -------------------------------------------------------------------------- */ + + + +#endif /* __CLUSTER_GROW_HH__ */ diff --git a/src/contact_area.cpp b/src/contact_area.cpp new file mode 100644 index 0000000..ff8823e --- /dev/null +++ b/src/contact_area.cpp @@ -0,0 +1,116 @@ +#include"contact_area.hh" +#include +#include "cluster_grow.hh" +/* -------------------------------------------------------------------------- */ + +ContactArea::ContactArea(UInt n, Real L): Surface(n,L) { + //num_cluster = 0; +} + +/* -------------------------------------------------------------------------- */ + +template <> +ContactArea::ContactArea(const Map2dSquare & m) : + Surface(m.size(),m.getL()){ + + UInt n = this->size(); + + for (UInt i = 0 ; i < n*n ; ++i) + this->at(i) = (m(i) > 0.); + +} + +/* -------------------------------------------------------------------------- */ + + +ContactArea::~ContactArea() {} + +/* -------------------------------------------------------------------------- */ + +void ContactArea::detectContactClusters() { + + // starting state was push as 2 by vlad + ClusterGrow clg(*this,2); + UInt N = this->size(); + + for (UInt i = 0; i < N; ++i) { + for (UInt j = 0; j < N; ++j) { + clg.grow(i,j); + } + } + + for (UInt i = 0; i < N; ++i) { + for (UInt j = 0; j < N; ++j) { + if (this->at(i,j) == -1) + SURFACE_FATAL("problem " << i << " " << j << " is -1"); + } + } + + for (UInt i = 0; i < clg.getNbClusters(); ++i) + colors.push_back(i+3); +} +/* -------------------------------------------------------------------------- */ + + +void ContactArea::replaceColors(int from, int to) { + // Repalce color "from" by the color "to" + UInt n = this->size(); + for (UInt i = 0; i < n; i++) + for (UInt j = 0; j < n; j++) + if (this->at(i,j) == from) + this->at(i,j) = to; +} +/* -------------------------------------------------------------------------- */ + +void ContactArea::randomizeClusterID(UInt seed) { + std::cout << "/ Randomize colors of contact clusters." << std::endl; + UInt shift=1000, tryid; + bool found; + std::vector cid; + UInt num_cluster = colors.size(); + cid.resize(num_cluster); + while (shift < num_cluster) + shift*=10; + srand(seed); + for (int i = 0; i < int(colors.size()); i++) { + tryid=-1; + do { + tryid = shift+int((num_cluster+10)*random()/Real(RAND_MAX)); + found = true; + for (int j = 0; j < i; j++) + if (cid[j] == tryid) + found = false; + } + while (!found); + cid[i]=tryid; + replaceColors(colors[i],tryid); + colors[i]=tryid; + } + // Shift all colors back to 1 + for (int i = 0; i < int(colors.size()); i++) { + replaceColors(colors[i],colors[i]-shift+1); + colors[i]-=shift-1; + } +} + +/* -------------------------------------------------------------------------- */ + +std::vector ContactArea::getContactClusters() { + + std::vector clusters; + UInt nb_colors = this->colors.size(); + + for (UInt i = 0; i < nb_colors; i++) { + // std::cout << "Extracting contact cluster " << i << std::endl; + ContactCluster c(colors[i], *this); + //std::cout << "Compute statistics of contact cluster " << i << std::endl; + c.computeStatistics(); + clusters.push_back(c); + } + + return clusters; +} + +/* -------------------------------------------------------------------------- */ + + diff --git a/src/contact_area.hh b/src/contact_area.hh new file mode 100644 index 0000000..8a3470d --- /dev/null +++ b/src/contact_area.hh @@ -0,0 +1,66 @@ +//==================================================================// +// Percolation detection and characterization of contact clusters // +// To be integrated in FFT-BEM code // +// // +// V.A. Yastrebov, 2014 // +// Centre des Materiaux, CNRS, MINES ParisTech // +// // +// G. Anciaux, 2014 // +// EPFL, ENAC, IIC, LSMS // +//==================================================================// + +#ifndef __CONTACT_AREA__ +#define __CONTACT_AREA__ +/* -------------------------------------------------------------------------- */ +#include "map_2d.hh" +#include +#include "contact_cluster.hh" +/* -------------------------------------------------------------------------- */ + + +class ContactArea : public Surface { + + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ + +public: + + ContactArea(UInt n, Real L); + + template + ContactArea(const Map2dSquare & n); + ~ContactArea(); + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ + +public: + + //! TODO + void detectContactClusters(); + //! TODO + void replaceColors(int from, int to); + //! TODO + void randomizeClusterID(UInt seed); + //! generate contact clusters + std::vector getContactClusters(); + + /* ------------------------------------------------------------------------ */ + /* Accessors */ + /* ------------------------------------------------------------------------ */ + + UInt getNumClusters(){return colors.size();}; + + + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ + +private: + std::vector colors; + +}; + +#endif diff --git a/src/contact_cluster.cpp b/src/contact_cluster.cpp new file mode 100644 index 0000000..555e5ed --- /dev/null +++ b/src/contact_cluster.cpp @@ -0,0 +1,401 @@ +//==================================================================// +// Percolation detection and characterization of contact clusters // +// To be integrated in FFT-BEM code // +// // +// V.A. Yastrebov, 2014 // +// Centre des Materiaux, CNRS, MINES ParisTech // +// // +// G. Anciaux, 2014 // +// EPFL, ENAC, IIC, LSMS // +//==================================================================// + + +#include "contact_cluster.hh" +#include +#include +#include "contact_area.hh" +#include "cluster_grow.hh" +/* -------------------------------------------------------------------------- */ + +void ContactCluster::computeBoundingBox(ContactArea & contact_area) { + + int N = contact_area.size(); + + int i0 = -1; + int j0 = -1; + int i1 = -1; + int j1 = -1; + + for (int i=0; iid && i0 < 0) i0 = i; + if (contact_area(j,i) == this->id && j0 < 0) j0 = i; + if (contact_area(N-i-1,N-j-1) == this->id && i1 < 0) i1 = N-i-1; + if (contact_area(N-j-1,N-i-1) == this->id && j1 < 0) j1 = N-i-1; + + // if all extremum are found then break + if (i0 >= 0 && j0 >= 0 && i1 >= 0 && j1 >= 0) break; + } + // if all extremum are found then break + if (i0 >= 0 && j0 >= 0 && i1 >= 0 && j1 >= 0) break; + } + + if (i0 < 0 || j0 < 0) SURFACE_FATAL("bounds not found " << id << " " << contact_area(0,0)); + if (i1 < 0 || j1 < 0) SURFACE_FATAL("bounds not found"); + + lb_corner[0] = i0; + lb_corner[1] = j0; + + rt_corner[0] = i1; + rt_corner[1] = j1; + + bbox_size[0] = i1-i0+1; + bbox_size[1] = j1-j0+1; + +} + + +/* -------------------------------------------------------------------------- */ + +void ContactCluster::checkLines(UInt dir,ContactArea & contact_area){ + + UInt N = contact_area.size(); + UInt i0 = lb_corner[dir]; + + start[dir] = -1; + stop[dir] = -1; + + for (UInt i = 0; i < N; i++) { + + bool fail = false; + for (UInt j = 0; j < N; j++){ + int val = -1; + if (dir == 0) val = contact_area(i,j); + if (dir == 1) val = contact_area(j,i); + + if (val == id) { + fail = true; + break; + } + } + + if (i0 == 0 && !fail && start[dir] < 0) { + start[dir] = i; + if (stop[dir] >= 0) SURFACE_FATAL("Error occured at "<<__LINE__); + } + if (i0 == 0 && fail && start[dir] >= 0 && stop[dir] < 0) + stop[dir] = i; + } + +} + +/* -------------------------------------------------------------------------- */ + + +void ContactCluster::minimizeBoundingBox(ContactArea & contact_area) { + + this->split_cluster = false; + UInt N = contact_area.size(); + if (bbox_size[0] != N && bbox_size[1] != N) return; + + // Minimize bounding box + this->split_cluster = true; + + // Check if there are vertical lines that do not contact "id" + this->checkLines(0,contact_area); + // Check if there are horizontal lines that do not contact "id" + this->checkLines(1,contact_area); + + if (start[0] >= 0) bbox_size[0] -= (stop[0]-start[0])-1; + if (start[1] >= 0) bbox_size[1] -= (stop[1]-start[1])-1; + +} + +/* -------------------------------------------------------------------------- */ + +void ContactCluster::extractCluster(ContactArea & contact_area) { + + UInt Nx = this->size(0); + UInt Ny = this->size(1); + UInt i0 = lb_corner[0]; + UInt j0 = lb_corner[1]; + UInt N = contact_area.size(); + + mass_center[0] = 0; + mass_center[1] = 0; + + for (UInt i = 0; i < Nx; i++) { + for (UInt j = 0; j < Ny; j++) { + if (i+i0 >= N || j+j0 >= N) + SURFACE_FATAL(" i0=" << i0 + << ",j0=" << j0 + << ", i=" << i + << ", j=" << j); + + int val = contact_area(i+i0,j+j0); + if (val == id) { + this->at(i,j) = 1; + mass_center[0] += i+i0; + mass_center[1] += j+j0; + } + } + } +} + +/* -------------------------------------------------------------------------- */ + +void ContactCluster::extractClusterPeriodic(ContactArea & contact_area) { + + // if the cluster is split by periodicity + mass_center[0] = 0; + mass_center[1] = 0; + UInt Nx = this->size(0); + UInt Ny = this->size(1); + UInt N = contact_area.size(); + UInt i0 = lb_corner[0]; + UInt j0 = lb_corner[1]; + + UInt Nxmax = start[0]<0?Nx:N; + UInt Nymax = start[1]<0?Ny:N; + + for (UInt i = 0; i < Nxmax; i++) { + for (UInt j = 0; j < Nymax; j++) { + if (i+i0>=0 && i+i0=0 && j+j0= 0 && start[1] < 0) { + mass_center[1] += j+j0; + if ((int)i < start[0]) { + this->at(i,j) = 1; + mass_center[0]+=i; + } + else { + this->at(i-(stop[0]-start[0])+1,j) = 1; + mass_center[0] -= (N-i); + } + } + else if (start[1] >= 0 && start[0] < 0) { + mass_center[0]+=i+i0; + if ((int)j < start[1]) { + this->at(i,j) = 1; + mass_center[1]+=j; + } + else { + this->at(i,j-(stop[1]-start[1])+1) = 1; + mass_center[1] -= (N-j); + } + } + else if (start[1] >= 0 && start[0] >= 0) { + if ((int)j < start[1] && (int)i < start[0]) { + this->at(i,j) = 1; + mass_center[0] += i; + mass_center[1] += j; + } + else if ((int)j < start[1] && (int)i >= start[0]) { + this->at(i-(stop[0]-start[0])+1,j) = 1; + mass_center[1]+=j; + mass_center[0]-=(N-i); + } + else if ((int)j >= start[1] && (int)i >= start[0]) { + this->at(i-(stop[0]-start[0])+1,j-(stop[1]-start[1])+1) = 1; + mass_center[0] -= (N-i); + mass_center[1] -= (N-j); + } + else if ((int)j >= start[1] && (int)i < start[0]) { + this->at(i,j-(stop[1]-start[1])+1) = 1; + mass_center[0] += i; + mass_center[1] -= (N-j); + } + } + else if (start[0] < 0 && start[1] < 0) { + this->at(i,j) = 1; + mass_center[0] += i+i0; + mass_center[1]+=j+j0; + } + } + } + else { + std::cout<<"Error i0="<id = color; + + this->computeBoundingBox(contact_area); + + if (bbox_size[0] < 0 || bbox_size[1] < 0) { + SURFACE_FATAL("Something wrong with the detection of the bounding box of a contact cluster"); + } + + this->minimizeBoundingBox(contact_area); + this->setGridSize(bbox_size); + + if (!split_cluster) this->extractCluster(contact_area); + else this->extractClusterPeriodic(contact_area); +} + +/* -------------------------------------------------------------------------- */ + +void ContactCluster::computeStatistics() { + + bool start = false; + // UInt start_i, start_j; + A=0; + P=0; + IP=0; + + // UInt Nmax = bbox_size[0] > bbox_size[1] ? bbox_size[0]:bbox_size[1]; + UInt intersection[2] = {0,0}; + + for (UInt i = 0; i < bbox_size[0]; i++) { + intersection[0] = 0; + intersection[1] = 0; + for (UInt j = 0; j < bbox_size[1]; j++) { + // Area + A += this->at(i,j); + + // Perimeter at edges + if ( (i==0 || i== bbox_size[0] - 1) && this->at(i,j) == 1) { + if (!start) { + start=true; + // start_i=i; + //start_j=j; + } + P++; + } + if ( (j==0 || j== bbox_size[0] - 1) && + this->at(i,j) == 1) { + if (!start) { + start=true; + //start_i=i; + //start_j=j; + } + P++; + } + // Perimeter along lines + if (i>0 && this->at(i,j) != this->at(i-1,j)) { + if (!start) { + start=true; + //start_i=i; + //start_j=j; + } + P++; + } + // Perimeter along columns + if (j>0 && this->at(i,j) != this->at(i,j-1)) { + P++; + } + // Interpixel perimeter along lines + if (i>0 && this->at(i,j) == this->at(i-1,j) && this->at(i,j) > 0) + IP++; + // Interpixel perimeter along columns + if (j>0 && this->at(i,j) == this->at(i,j-1) && this->at(i,j) > 0) + IP++; + } + } + + for (UInt k = 0; k < 2; ++k) { + mass_center[k] /= Real(A); + //if (mass_center[k] < 0) { + // mass_center[k] += N; + //} + } + + this->comp = P/sqrt(Real(A)); + Cd = (A-P/4.)/(A-sqrt(1.*A)); + if (intersection[0] > 2 || intersection[1] > 2) + concave=true; + + this->findHoles(); +} + +/* -------------------------------------------------------------------------- */ + +void ContactCluster::findHoles() { + + UInt Nx = this->size(0); + UInt Ny = this->size(1); + + ClusterGrow clg(*this,id,-1,0,id); + + for (UInt i0 = 0; i0 < Nx; ++i0) { + for (UInt j0 = 0; j0 < Ny; ++j0) { + + // check if the point touch the border and is not in contact + if ( (i0 == 0 || j0 == 0 || + i0 == Nx-1 || j0 == Ny-1) && + this->at(i0,j0) == 0) { + + clg.grow(i0,j0); + } + } + } + // find the holes + std::map holes_areas; + for (UInt i=0; iat(i,j) > id){ + if (holes_areas.count(this->at(i,j)) == 0) + holes_areas[this->at(i,j)] = 0; + holes_areas[this->at(i,j)] += 1; + } + + // this->RI = (Nx*Ny-Ai-A)/Real(A); +} + + +/* -------------------------------------------------------------------------- */ + + +void ContactCluster::printself(std::ostream & stream, int indent) const { + + stream << mass_center[0] << " " << mass_center[1] << " " + << bbox_size[0] << " " << bbox_size[1] << " " + << sqrt(A) << " " + << P << " " + << comp << " " + << IP << " " + << Cd << " " + << this->getNbHoles() << " " + // << RI << " " + << id; +} + +/* -------------------------------------------------------------------------- */ + + diff --git a/src/contact_cluster.hh b/src/contact_cluster.hh new file mode 100644 index 0000000..60be66a --- /dev/null +++ b/src/contact_cluster.hh @@ -0,0 +1,167 @@ +//==================================================================// +// Percolation detection and characterization of contact clusters // +// To be integrated in FFT-BEM code // +// // +// V.A. Yastrebov, 2014 // +// Centre des Materiaux, CNRS, MINES ParisTech // +// // +// G. Anciaux, 2014 // +// EPFL, ENAC, IIC, LSMS // +//==================================================================// + +#ifndef __CONTACT_CLUSTER__ +#define __CONTACT_CLUSTER__ +/* -------------------------------------------------------------------------- */ +#include +#include "surface.hh" +/* -------------------------------------------------------------------------- */ +class ContactArea; +class ContactClusterCollection; +/* -------------------------------------------------------------------------- */ + + +/* Class Contact Cluster class + + based on the publication: + + [1] Ernesto Bribiesca, + "An easy measure of compactness for 2D and 3D shapes", + Pattern Recognition 41 (2008) 543--554. + doi:10.1016/j.patcog.2007.06.029 + +*/ + +class ContactCluster : public Map2d { + + + /* ------------------------------------------------------------------------ */ + /* Typedefs */ + /* ------------------------------------------------------------------------ */ + + friend class ContactClusterCollection; + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ + +public: + + ContactCluster() : Map2d(0,1.) {} + ~ContactCluster() {} + ContactCluster(int color, ContactArea & contact_area); + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ + +public: + + void computeBoundingBox(ContactArea & contact_area); + void minimizeBoundingBox(ContactArea & contact_area); + void extractCluster(ContactArea & contact_area); + void extractClusterPeriodic(ContactArea & contact_area); + void computeStatistics(); + void findHoles(); + + void checkLines(UInt dir,ContactArea & contact_area); + + + + //! function to print the contain of the class + virtual void printself(std::ostream & stream, int indent = 0) const; + + /* ------------------------------------------------------------------------ */ + /* Accessors */ + /* ------------------------------------------------------------------------ */ + +public: + + std::vector getHolesAreas() const{ + std::vector areas; + for (auto & x: holes_areas){ + areas.push_back(x.second); + } + return areas; + } + UInt getA(){return A;}; + UInt getP(){return P;}; + UInt getNbHoles() const {return holes_areas.size();}; + + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ + +private: + + /* If the shape is for sure concave then concave=true, + however it may be concave even if concave=false. + */ + //! concavity flag + bool concave; + + //! color id of the cluster + int id; + + //! coordinates of the left bottom corner of the bounding box (i0,j0) + UInt lb_corner[2]; + //! coordinates of the right top corner of the bounding box (i1,j1) + UInt rt_corner[2]; + + //! from clusters connected through periodicity start stop is identifying inner part + int start[2]; + int stop[2]; + + + //! size of the bounding box (Nx,Ny) + UInt bbox_size[2]; + + //! contact area (A) + UInt A; + + //! contact perimeter computed discretely (P) + UInt P; + + //! interpixel perimeter (IP), the same as contact perimeter in notions of [1] + int IP; + + //! the holes areas + std::map holes_areas; + + //! center of mass (ic,jc) + Real mass_center[2]; + + //! corrected contact perimeter (Ps) + Real Ps; + + //! discrete compactness (Cd=(n-P/4)/(n-sqrt(n)) ) from [1] + Real Cd; + + /* Ratio of the internal (closed gap) area to the contact area + $$RI = (A0-Ai-A)/Real(A)$$, + where Ai is the area within the bounding box that surrounds contact cluster + */ + // Real RI; + + //! compactness (comp = Ps/sqrt(A)) + Real comp; + + + //! TODO + bool split_cluster; + +}; + +/* -------------------------------------------------------------------------- */ + +inline std::ostream & operator <<(std::ostream & stream, const ContactCluster & _this) +{ + _this.printself(stream); + return stream; +} + + + +#endif + + + + diff --git a/src/contact_cluster_collection.cpp b/src/contact_cluster_collection.cpp new file mode 100644 index 0000000..06ff4c1 --- /dev/null +++ b/src/contact_cluster_collection.cpp @@ -0,0 +1,204 @@ +/* -------------------------------------------------------------------------- */ +#include "contact_cluster_collection.hh" +/* -------------------------------------------------------------------------- */ + + +ContactClusterCollection::ContactClusterCollection(ContactArea & area): + area(area){ + + clusters = area.getContactClusters(); + + TotalArea = 0; + TotalPerimeter = 0; + NumberOfClustersWithHoles = 0; + + for (UInt i = 0; i < clusters.size(); ++i) { + TotalArea += clusters[i].getA(); + TotalPerimeter += clusters[i].getP(); + NumberOfClustersWithHoles += clusters[i].getNbHoles(); + } + +} + +/* -------------------------------------------------------------------------- */ + +ContactClusterCollection::~ContactClusterCollection(){ + +} + + +/* -------------------------------------------------------------------------- */ + +void ContactClusterCollection::dumpAllClusters(const std::string & prefix){ + + for (UInt i = 0; i < clusters.size(); i++) { + std::stringstream sstr; + sstr << prefix << "-" << i << ".csv"; + clusters[i].dumpToTextFile(sstr.str()); + } + +} + +/* -------------------------------------------------------------------------- */ + + + +void ContactClusterCollection::dumpClusterInfoToFile(const std::string & filename){ + + std::ofstream clusterData(filename.c_str()); + // Output info on every cluster separately + clusterData << "# N=" << area.size() << std::endl; + clusterData << "# Number of clusters=" << clusters.size() << std::endl; + clusterData << "# [1]Num [2]ic [3]jc [4]Nx [5]Ny [6]sqrt(A) [7]P [8]comp [9]IP [10]Cd [11]holes [12]RI [13]color [14]TotalNumberOfClusters [15]TotalArea [16]TotalPerimeter [17]NumberOfClustersWithHoles" << std::endl; + for (UInt i = 0; i < clusters.size(); i++) { + clusterData << i+1 << " " << clusters[i] << " " + << clusters.size() << " " + << TotalArea << " " + << TotalPerimeter << " " + << NumberOfClustersWithHoles << std::endl; + } + +} + +/* -------------------------------------------------------------------------- */ + +Real ContactClusterCollection::getTotalArea(){ + return TotalArea; +} + +/* -------------------------------------------------------------------------- */ + + +Real ContactClusterCollection::getTotalPerimeter(){ + return TotalPerimeter; +} + +/* -------------------------------------------------------------------------- */ + +Real ContactClusterCollection::getNbClustersWithHole(){ + return NumberOfClustersWithHoles; +} + +/* -------------------------------------------------------------------------- */ + +Real ContactClusterCollection::getNbClusters(){ + return clusters.size(); +} + +/* -------------------------------------------------------------------------- */ + +std::vector ContactClusterCollection::getAreas(){ + + std::vector res; + for (UInt i = 0; i < clusters.size(); i++) { + // std::cerr << "AAAAAAAA " < ContactClusterCollection::getMassCenters(UInt i){ + + std::vector res; + for (UInt i = 0; i < clusters.size(); i++) { + std::cerr << "AAAAAAAA " < ContactClusterCollection::getPerimeters(){ + + std::vector res; + for (UInt i = 0; i < clusters.size(); i++) { + std::cerr << "AAAAAAAA " < ContactClusterCollection::getCompactnesses(){ + + std::vector res; + for (UInt i = 0; i < clusters.size(); i++) { + std::cerr << "AAAAAAAA " < ContactClusterCollection::getInterPixelPerimeters(){ + + std::vector res; + for (UInt i = 0; i < clusters.size(); i++) { + std::cerr << "AAAAAAAA " < ContactClusterCollection::getDiscretePerimeters(){ + + std::vector res; + for (UInt i = 0; i < clusters.size(); i++) { + std::cerr << "AAAAAAAA " < ContactClusterCollection::getNbHoles(){ + + std::vector res; + for (UInt i = 0; i < clusters.size(); i++) { + std::cerr << "AAAAAAAA " < ContactClusterCollection::getRIs(){ +// std::vector res; +// for (UInt i = 0; i < clusters.size(); i++) { +// std::cerr << "AAAAAAAA " < ContactClusterCollection::getColors(){ + std::vector res; + for (UInt i = 0; i < clusters.size(); i++) { + std::cerr << "AAAAAAAA " < getAreas(); + std::vector getMassCenters(UInt i); + std::vector getPerimeters(); + std::vector getCompactnesses(); + std::vector getInterPixelPerimeters(); + std::vector getDiscretePerimeters(); + std::vector getNbHoles(); + //std::vector getRIs(); + std::vector getColors(); + + /// write one file per cluster + void dumpAllClusters(const std::string & prefix); + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ +private: + + + //! the vector of clusters + std::vector clusters; + + //! the input area where to extract all the clusters + ContactArea & area; + + //! the total area + UInt TotalArea; + //! the total perimeter + UInt TotalPerimeter; + //! the number of clusters with holes + UInt NumberOfClustersWithHoles; + +}; + +/* -------------------------------------------------------------------------- */ + +#endif /* __CONTACT_CLUSTER_COLLECTION_HH__ */ diff --git a/src/function.cpp b/src/function.cpp new file mode 100755 index 0000000..4b7ce48 --- /dev/null +++ b/src/function.cpp @@ -0,0 +1,187 @@ +/* -------------------------------------------------------------------------- */ +#include "function.hh" +/* -------------------------------------------------------------------------- */ + +INTER_FUNC::INTER_FUNC() {} + +/* ------------------------------------------------------------------------ */ + + +INTER_FUNC::~INTER_FUNC() {} + +/* ------------------------------------------------------------------------ */ + +INTER_FUNC::INTER_FUNC(INTER_FUNCTION_TYPE type_, std::vector points_, Real a_) +{ + type = type_; + sm_error = false; + points.resize(points_.size()); + for (int i = 0; i < int(points.size()); i++) + points[i] = points_[i]; + + if (type == SQ_ROOT) + { + if (points.size() != 2) + { + std::cout << std::endl << "ERROR 1a: something wrong with interpolation; coef[0] = " << coef[0] << std::endl; + exit(1); + } + + coef.resize(3); + coef[2] = a_; + Real y1_sq = points[0]*points[0], + y2_sq = points[1]*points[1], + c0 = y2_sq/(y1_sq-y2_sq), + c1 = (2+c0), + c2 = (1 - coef[2]*coef[2] +0.75*c0), + x01 = 0.5*(c1+sqrt(c1*c1-4*c2)), + x02 = 0.5*(c1-sqrt(c1*c1-4*c2)); + if (y1_sq <= y2_sq) + { + if (x01 > 0.75 && x02 <= 0.75) + { + coef[0] = sqrt((y1_sq-y2_sq)/(0.75-x01)); + coef[1] = x01; + } + else if (x02 > 0.75 && x01 <= 0.75) + { + coef[0] = sqrt((y1_sq-y2_sq)/(0.75-x02)); + coef[1] = x02; + } + else if (x01 > 0.75 && x02 <= 0.75 && a_ <= 0.5) + { + coef[0] = sqrt((y1_sq-y2_sq)/(0.75-x02)); + coef[1] = x02; + } + else if (x02 > 0.75 && x01 <= 0.75 && a_ <= 0.5) + { + coef[0] = sqrt((y1_sq-y2_sq)/(0.75-x01)); + coef[1] = x01; + } + else + { + std::cout << std::endl << "ERROR 1b: something wrong with interpolation; coef[0] = " << coef[0] << std::endl; + exit(1); + } + } + else + { + coef[0] = 0; + coef[1] = 0; + coef[2] = 0; + sm_error = true; + } + return; + } + else + { + std::cout << std::endl << "ERROR 3: wrong constructor" << std::endl; + exit(1); + } +} + +/* ------------------------------------------------------------------------ */ + +INTER_FUNC::INTER_FUNC(INTER_FUNCTION_TYPE type_, std::vector points_) +{ + type = type_; + sm_error = false; + points.resize(points_.size()); + for (int i = 0; i < int(points.size()); i++) + points[i] = points_[i]; + + if (type == LINEAR) + { + if (points.size() != 2) + { + std::cout << "ERROR 21: Wrong initialization" << std::endl; + exit(1); + } + coef.resize(2); + coef[0] = points[0]; + coef[1] = points[1]-points[0]; + + return; + } + else if (type == PARABOLA) + { + if (points.size() != 3) + { + std::cout << "ERROR 22: Wrong initialization" << std::endl; + exit(1); + } + + coef.resize(3); + coef[2] = points[0]; + coef[1] = 4*points[1]-3*points[0]-points[2]; + coef[0] = 4*points[1]-4*points[0]-2*coef[1]; + return; + } + else if (type != ZERO) + { + std::cout << std::endl << "ERROR 4: wrong constructor" << std::endl; + exit(1); + } +} + +/* ------------------------------------------------------------------------ */ + +Real INTER_FUNC::get_value(Real x) +{ + if (type == ZERO) + { + return 0.; + } + else if (type == LINEAR) + { + return coef[0] + coef[1]*x; + } + else if (type == SQ_ROOT) + { + Real a_sq = coef[2]*coef[2], + x_x0_sq = (x-coef[1])*(x-coef[1]); + if (a_sq > x_x0_sq) + return coef[0]*sqrt(a_sq - x_x0_sq); + else + return 0.; + } + else if (type == PARABOLA) + { + return coef[0]*x*x + coef[1]*x + coef[2]; + } + + std::cout << std::endl << "ERROR 4.5: unknown interpolation type" << std::endl; + exit(1); + + return 0.; +} + +/* ------------------------------------------------------------------------ */ + +Real INTER_FUNC::get_derivative(Real x) +{ + if (type == ZERO) + { + return 0.; + } + else if (type == LINEAR) + { + return coef[1]*x; + } + else if (type == SQ_ROOT) + { + Real a_sq = coef[2]*coef[2], + x_x0_sq = (x-coef[1])*(x-coef[1]); + if (a_sq > x_x0_sq) + return coef[0]*(coef[1]-x)/sqrt(a_sq - x_x0_sq); + else + return 0.; + } + else if (type == PARABOLA) + { + return 2*coef[0]*x + coef[1]; + } + + std::cout << std::endl << "ERROR 3: something wrong with interpolation" << std::endl; + exit(1); +} diff --git a/src/function.hh b/src/function.hh new file mode 100755 index 0000000..97de836 --- /dev/null +++ b/src/function.hh @@ -0,0 +1,35 @@ +#ifndef __INTER_FUNC__ +#define __INTER_FUNC__ +/* -------------------------------------------------------------------------- */ +#include +/* -------------------------------------------------------------------------- */ +#include +#include +#include +#include +#include +/* -------------------------------------------------------------------------- */ +#include +#include +/* -------------------------------------------------------------------------- */ + +enum INTER_FUNCTION_TYPE { ZERO, LINEAR, SQ_ROOT, PARABOLA, CUBIC_HERMITE, CUBIC_BEZIER, QUADRATIC_BEZIER, TEST_INTER }; + +class INTER_FUNC { +public: + + INTER_FUNC(); + INTER_FUNC(INTER_FUNCTION_TYPE type_, std::vector points_); + INTER_FUNC(INTER_FUNCTION_TYPE type_, std::vector points_, Real a); + ~INTER_FUNC(); + + INTER_FUNCTION_TYPE type; + bool sm_error; + std::vector points, coef; + // return function value for 0<=x<1 + Real get_value(Real x); + Real get_derivative(Real x); + +}; + +#endif diff --git a/src/gzfstream.hh b/src/gzfstream.hh new file mode 100644 index 0000000..5355d28 --- /dev/null +++ b/src/gzfstream.hh @@ -0,0 +1,201 @@ +#ifndef __GZFSTREAM_HH__ +#define __GZFSTREAM_HH__ +/* -------------------------------------------------------------------------- */ +#include +#include +#include +/* -------------------------------------------------------------------------- */ + +class GZfstream { + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ +public: + + inline GZfstream(); + inline virtual ~GZfstream(); + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ +public: + + inline void open(const std::string & filename,std::ios_base::openmode mode); + inline void flush(); + inline void precision(int i); + inline void getline(std::string & str); + + + template + inline GZfstream & operator << (const T& value); + + template + inline GZfstream & operator >> (T& value); + + + inline GZfstream & operator << (std::ostream& (*op)(std::ostream&)); + + bool & getFlagBinary(){return flag_binary;}; + + /* ------------------------------------------------------------------------ */ + /* Accessors */ + /* ------------------------------------------------------------------------ */ +public: + + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ + + +private: + + bool flag_binary; + gzFile gzfile; + std::stringstream buffer; + bool opened; +}; + +/* -------------------------------------------------------------------------- */ +inline GZfstream::GZfstream(){ + opened = false; + flag_binary = false; +} + +/* -------------------------------------------------------------------------- */ + +inline void GZfstream::flush(){ + gzwrite(gzfile,buffer.str().c_str(),buffer.str().length()); + // cout << "flushing " << buffer.str() << endl; + buffer.str(""); +} + +/* -------------------------------------------------------------------------- */ +inline GZfstream::~GZfstream(){ + if (opened){ + flush(); + gzclose(gzfile); + } +} + +/* -------------------------------------------------------------------------- */ + +inline void GZfstream::precision(int p){ + buffer.precision(p); +} + + +/* -------------------------------------------------------------------------- */ + +inline void GZfstream::open(const std::string & filename,std::ios_base::openmode mode){ + std::string _mode = ""; + if (mode & std::ios::app) _mode += "a+"; + if (mode & std::ios::ate) _mode += "a+"; + if (mode & std::ios::in) _mode += "r"; + if (mode & std::ios::out) _mode += "w+"; + if (mode & std::ios::trunc) _mode += "w"; + + // string fn = filename + ".gz"; + std::string fn = filename; + + std::cout << "opening " << fn << std::endl; + + gzfile = NULL; + gzfile = gzopen(fn.c_str(),_mode.c_str()); + if (gzfile) opened = true; +} + +/* -------------------------------------------------------------------------- */ + +template +inline GZfstream & GZfstream::operator << (const T& value){ + buffer << value; + if (buffer.str().length() > 1024) flush(); + return (*this); +} + +/* -------------------------------------------------------------------------- */ + + +template <> +inline GZfstream & GZfstream::operator << (const Real& value){ + if(flag_binary){ + gzwrite(gzfile,&value,sizeof(Real)); + } + else{ + buffer << value; + if (buffer.str().length() > 1024) flush(); + } + return (*this); +} + +/* -------------------------------------------------------------------------- */ + +template +inline GZfstream & GZfstream::operator >> (T& value){ + std::cout << "not working" << std::endl; + exit (EXIT_FAILURE); + return (*this); +} + + +/* -------------------------------------------------------------------------- */ + +template <> +inline GZfstream & GZfstream::operator >> (Real& value){ + if(flag_binary){ + int ret = gzread(gzfile,&value,sizeof(Real)); + if (ret == 0){ + std::cout << "end of file" << std::endl; + exit(EXIT_FAILURE); + } + if (ret == -1){ + std::cout << "error" << std::endl; + exit(EXIT_FAILURE); + } + + + } + return (*this); +} + + + +/* -------------------------------------------------------------------------- */ + +inline GZfstream & GZfstream::operator << (std::ostream & (*op)(std::ostream&)){ + (*op)(buffer); + flush(); + return (*this); +} + +/* -------------------------------------------------------------------------- */ + +inline void GZfstream::getline(std::string & str){ + if (!opened) { + std::cout << "file not opened" << std::endl; + exit(EXIT_FAILURE); + } + int len = 512; + char buf[len]; + char * read = gzgets(gzfile,buf,len); + if (read){ + str = buf; + } + else { + std::cout << "could not read the content" << std::endl; + exit(EXIT_FAILURE); + } +} + +/* -------------------------------------------------------------------------- */ + +void getline(GZfstream & file,std::string & str){ + file.getline(str); +} + +/* -------------------------------------------------------------------------- */ + + + + +#endif /* __GZFSTREAM_HH__ */ diff --git a/src/interpolator.cpp b/src/interpolator.cpp new file mode 100644 index 0000000..77bb8f2 --- /dev/null +++ b/src/interpolator.cpp @@ -0,0 +1,3613 @@ +#include "interpolator.hh" + +using namespace::std; + +const Real DEF_SLOPE = 1.23456789e10; +const int shift = -1; + +Real Interpolator::getRelativeElement(const vector& line, int act_pos, int shift) +{ + int length = line.size(); + int new_pos = act_pos + shift; + + if (new_pos >= 0 && new_pos < length) + return line[new_pos]; + else if (new_pos < 0) + return line[length + new_pos]; + else + return line[new_pos - length]; +} + +/* ---------------------------------------------------------------------- */ +Real Interpolator::getRelativeElement(Surface& surface, int act_pos_x, int act_pos_y, int shift_x, int shift_y) +{ + int size = surface.n; + int new_pos_x = act_pos_x + shift_x, + new_pos_y = act_pos_y + shift_y; + + if (new_pos_x >= 0 && new_pos_x < size) + { + if (new_pos_y >= 0 && new_pos_y < size) + return surface(new_pos_x,new_pos_y).re; + else if (new_pos_y < 0) + return surface(new_pos_x,size+new_pos_y).re; + else + return surface(new_pos_x,new_pos_y-size).re; + } + else if (new_pos_x < 0) + { + if (new_pos_y >= 0 && new_pos_y < size) + return surface(size+new_pos_x,new_pos_y).re; + else if (new_pos_y < 0) + return surface(size+new_pos_x,size+new_pos_y).re; + else + return surface(size+new_pos_x,new_pos_y-size).re; + } + else + { + if (new_pos_y >= 0 && new_pos_y < size) + return surface(-size+new_pos_x,new_pos_y).re; + else if (new_pos_y < 0) + return surface(-size+new_pos_x,size+new_pos_y).re; + else + return surface(-size+new_pos_x,new_pos_y-size).re; + } +} + +/* ---------------------------------------------------------------- */ + +int Interpolator::interpolate(bool forward, bool horizontal, vector >& interpolated_surface, int ix, int iy, + vector& original_points, INTER_FUNCTION_TYPE type, + vector& deja_interpolated, vector& slope, Real radius, Real val, int steps) +{ + if (type == ZERO) + { + for (int i = 0; i < num_inter_points; i++) + assign_value(interpolated_surface, ix + (1-horizontal)*i, iy + horizontal*i, 0.); + + assign_value(deja_interpolated, (1-horizontal)*ix/num_inter_points + horizontal*iy/num_inter_points - 1, 1); + assign_value(slope, (1-horizontal)*ix/num_inter_points + horizontal*iy/num_inter_points, 0.); + + return 1; + } + else if (type == SQ_ROOT) + { + INTER_FUNC func(SQ_ROOT, original_points, radius); + + if (forward) // :: from noncontact to contact + { + for (int i = 0; i < 2*num_inter_points; i++) + assign_value(interpolated_surface, ix + (1-horizontal)*i, iy + horizontal*i, func.get_value( i/(2.*num_inter_points) )); + + assign_value(deja_interpolated, (1-horizontal)*ix/num_inter_points + horizontal*iy/num_inter_points - 1, 1); + assign_value(deja_interpolated, (1-horizontal)*ix/num_inter_points + horizontal*iy/num_inter_points, 1); + assign_value(deja_interpolated, (1-horizontal)*ix/num_inter_points + horizontal*iy/num_inter_points + 1, 1); + + assign_value(slope, (1-horizontal)*ix/num_inter_points + horizontal*iy/num_inter_points + 2, 0.5*func.get_derivative(1.)); + + return 2; + } + else // backward :: from contact to noncontact + { + for (int i = 0; i < 2*num_inter_points; i++) + assign_value(interpolated_surface, ix - (1-horizontal)*i, iy - horizontal*i, func.get_value( i/(2.*num_inter_points) )); + + assign_value(deja_interpolated, (1-horizontal)*ix/num_inter_points + horizontal*iy/num_inter_points - 1, 1); + assign_value(deja_interpolated, (1-horizontal)*ix/num_inter_points + horizontal*iy/num_inter_points - 2, 1); + + assign_value(slope, (1-horizontal)*ix/num_inter_points + horizontal*iy/num_inter_points - 2, -0.5*func.get_derivative(1.) ); + + return 1; + } + } + else if (type == QUADRATIC_BEZIER) // See "http://en.wikipedia.org/wiki/B%C3%A9zier_curve" + { + Real t, + p0 = original_points[1], + p2 = original_points[2], + m0 = ( original_points[1] - original_points[0] ), + m1 = ( original_points[3] - original_points[2] ), + p1 = 0.5 * ( (p0 + m0*0.5) + (p2 - m1*0.5) ); + // Interpolation + for (int i = 0; i < num_inter_points; i++) + { + t = i/Real(num_inter_points); + assign_value(interpolated_surface, ix + (1-horizontal)*i, iy + horizontal*i, pow(1-t,2.)*p0 + 2*(1-t)*t*p1 + t*t*p2); + } + return 1; + } + else if (type == CUBIC_BEZIER) // See "http://en.wikipedia.org/wiki/B%C3%A9zier_curve" + { + Real t, alpha = 0.3, + p0 = original_points[1], + p3 = original_points[2], + m0 = 0.5 * ( original_points[2] - original_points[0] ), + m1 = 0.5 * ( original_points[3] - original_points[1] ), + p1 = p0 + m0 * alpha, + p2 = p3 - m1 * alpha; + // Interpolation + for (int i = 0; i < num_inter_points; i++) + { + t = i/Real(num_inter_points); + assign_value(interpolated_surface, ix + (1-horizontal)*i, iy + horizontal*i, pow(1-t,3)*p0 + 3*pow(1-t,2)*t*p1 + 3*(1-t)*t*t*p2 + t*t*t*p3); + } + return 1; + } + else if (type == CUBIC_HERMITE) // See "http://en.wikipedia.org/wiki/Cubic_interpolation", Cardinal Spline, alpha in [0;1] + { +// int ci = horizontal*ix/num_inter_points + (1-horizontal)*iy/num_inter_points; +// if ( !deja_interpolated[ci] ) +// { + Real t, alpha = 0., + p0 = original_points[1], + p1 = original_points[2], + m0 = (1-alpha) * 0.5 * ( original_points[2] - original_points[0] ), + m1 = (1-alpha) * 0.5 * ( original_points[3] - original_points[1] ); + // Left slope +/* + if (fabs(slope[ci] - DEF_SLOPE) < 0.1) + m0 = 0.5 * ( original_points[3] - original_points[1] ); + else + m0 = slope[ci]; + // Right slope + int ci_1; + if (ci + 1 < int(slope.size())) + ci_1 = ci + 1; + else + ci_1 = 0; + if (fabs(slope[ci_1] - DEF_SLOPE) < 0.1) + m1 = 0.5 * ( original_points[2] - original_points[0] ); + else + m1 = slope[ci_1]; +*/ + // Interpolation + for (int i = 0; i < num_inter_points; i++) + { + t = i/Real(num_inter_points); + Real t3 = t*t*t, t2 = t*t; + assign_value(interpolated_surface, ix + (1-horizontal)*i, iy + horizontal*i, (2*t3 - 3*t2 + 1)*p0 + (t3 - 2*t2 + t)*m0 + (-2*t3 + 3*t2)*p1 + (t3 - t2)*m1); + } + return 1; + } + else if (type == LINEAR) + { + INTER_FUNC func(LINEAR, original_points); + + for (int i = 0; i < num_inter_points; i++) + assign_value(interpolated_surface, ix + (1-horizontal)*i, iy + horizontal*i, func.get_value( i/Real(num_inter_points) ) ); + return 1; + } + else if (type == PARABOLA) + { + cout << endl << "Error: unknown interpolation type." << endl; + exit(1); + } + else if (type == TEST_INTER) + { + if (val == 0.) + val = 3.; + if (forward) + { + for (int i = 0; i < steps*num_inter_points; i++) + assign_value(interpolated_surface, ix + (1-horizontal)*i, iy + horizontal*i, val); + return steps; + } + else + { + for (int i = 0; i < steps*num_inter_points; i++) + assign_value(interpolated_surface, ix - (1-horizontal)*i, iy - horizontal*i, val); + return steps; + } + + } + else + { + cout << endl << "Error: unknown interpolation type." << endl; + exit(1); + } + +} + +/* ---------------------------------------------------------------- */ + +void Interpolator::assign_value(vector& vec, int i, Real value) +{ + if ( i >= 0 && i < int(vec.size()) ) + vec[i] = value; +} + +void Interpolator::assign_value(vector& vec, int i, Real value) +{ + if ( i >= 0 && i < int(vec.size()) ) + vec[i] = value; +} + +void Interpolator::assign_value(vector >& surf, int i, int j, Real value) +{ + if ( i >= 0 && i < int(surf.size()) && j >= 0 && j < int(surf[i].size()) ) + surf[i][j] = value; +} + +/* ---------------------------------------------------------------- */ +void Interpolator::make_by_patch2(Surface& original, int ix, int iy, int patch_size, int margin, bool parabola, Real max_value, vector >& pdfs, + Real& area, Real& perimeter, Real& pressure, vector >& interpolated_surface, string fname) +{ +//o test + bool to_be_interpolated = false; + for (int iline = 0; iline < patch_size; iline++) + for (int jline = 0; jline < patch_size; jline++) + if (getRelativeElement(original,ix,iy,iline,jline) > 1e-14) + { + to_be_interpolated = true; + break; + } + if (!to_be_interpolated) + return; +//x test + + int size = patch_size+2*margin; + bool concave_1, + concave_2; + vector data_points(4), + interp, + slope(size, DEF_SLOPE), + original_line(patch_size+2*margin, 0.); + vector deja_interpolated(size, 0); + +///////////////////////////////////////////////////////////////////////////////// +// INTERPOLATION ALONG PROFILES +///////////////////////////////////////////////////////////////////////////////// + for (int iline = 0; iline < patch_size+margin*2; iline++) + { + for (unsigned int i = 0; i < deja_interpolated.size(); i++) + deja_interpolated[i] = 0; + for (unsigned int i = 0; i < slope.size(); i++) + slope[i] = DEF_SLOPE; + for (unsigned int i = 0; i < interpolated_surface[iline].size(); i++) + assign_value(interpolated_surface, iline*num_inter_points, i, 0.); + for (int i = 0; i < patch_size+margin*2; i++) + original_line[i] = getRelativeElement(original, ix, iy, iline-margin, i-margin); + + int i = 1; + do + { + if (original_line[i-1] == 0 && original_line[i] == 0) + { + i+=interpolate(true, true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, ZERO, deja_interpolated, slope); + continue; + } + else if (original_line[i-1] == 0) + { + for (int k = 0; k < 4; k++) + data_points[k] = getRelativeElement(original_line,i,k); + + interp.resize(2); + interp[0] = data_points[0]; + interp[1] = data_points[1]; + Real radius = find_dist_to_max(true, original_line, i); + i += interpolate(true, true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, SQ_ROOT, deja_interpolated, slope, radius); + continue; + } + else if (original_line[i] == 0) + { + for (int k = 1; k < 3; k++) + data_points[k-1] = getRelativeElement(original_line,i,-k); + + interp.resize(2); + interp[0] = data_points[0]; + interp[1] = data_points[1]; + Real radius = find_dist_to_max(false, original_line, i); + i += interpolate(false, true, interpolated_surface, iline*num_inter_points, i*num_inter_points, interp, SQ_ROOT, deja_interpolated, slope, radius); + continue; + } + else + { +/* + interp.resize(2); + for (int k = 0; k < 2; k++) + interp[k] = getRelativeElement(original_line, i-1, k); + i += interpolate(true, true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, LINEAR, deja_interpolated, slope); +*/ + for (int k = 0; k < 4; k++) + data_points[k] = getRelativeElement(original_line, i-1, k-1); + i += interpolate(true, true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, data_points, QUADRATIC_BEZIER, deja_interpolated, slope); + //i += interpolate(true, true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, data_points, CUBIC_BEZIER, deja_interpolated, slope); + //i += interpolate(true, true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, data_points, CUBIC_HERMITE, deja_interpolated, slope); + continue; + } + } + while (i < size); + +/////////////////////////////////////////////////////////////////////////////// +// CUBIC INTERPOLATION +////////////////////////////////////////////////////////////////////////////// +/* + i = 1; + do + { + interp.resize(4); + interp[0] = getRelativeElement(original_line,i-1,-1); + interp[1] = getRelativeElement(original_line,i-1,0); + interp[2] = getRelativeElement(original_line,i-1,1); + interp[3] = getRelativeElement(original_line,i-1,2); + if (interp[1] > 1e-14 && interp[2] > 1e-14) + i += interpolate(false, true, interpolated_surface, iline*num_inter_points, i*num_inter_points, interp, CUBIC_HERMITE, deja_interpolated, slope); + else + i++; + } + while (i < size); +*/ + + // Plot files + if (fname != "" && iline >= margin && iline < patch_size+margin) + { + std::ofstream file; + std::stringstream max_value_str; + max_value_str << int(100*max_value); + file.open((fname+"_profiles_"+max_value_str.str()).c_str(),ios_base::app); + file.precision(15); + + for (int j = num_inter_points*margin; j < num_inter_points*(size-margin); j++) + // if (interpolated_surface[iline*num_inter_points][j] > 1e-14) + file << (ix+iline)*num_inter_points << " " << iy*num_inter_points+j << " " + << interpolated_surface[iline*num_inter_points][j] << " " << deja_interpolated[int(j/num_inter_points)] << " " << slope[int(j/num_inter_points)] << endl; + + file.close(); + } + } + +/////////////////////////////////////////////////////////////////////////////////////// +// ORTHOGONAL INTERPOLATION +///////////////////////////////////////////////////////////////////////////////// + for (int iline = 0; iline < (patch_size+margin*2)*num_inter_points; iline++) + { + for (unsigned int i = 0; i < slope.size(); i++) + { + slope[i] = DEF_SLOPE; + deja_interpolated[i] = 0; + } + for (int jline = 0; jline < patch_size+margin*2; jline++) + original_line[jline] = interpolated_surface[jline*num_inter_points][iline]; + for (int jline = 0; jline < (patch_size+margin*2)*num_inter_points; jline++) + if (jline % num_inter_points != 0) + assign_value(interpolated_surface,jline,iline,0.); + + int i = 1; + do + { + if (original_line[i-1] == 0 && original_line[i] == 0) + { + i+=interpolate(true, false, interpolated_surface, (i-1)*num_inter_points, iline, interp, ZERO, deja_interpolated, slope); + continue; + } + else if (original_line[i-1] == 0) + { + for (int k = 0; k < 4; k++) + data_points[k] = getRelativeElement(original_line,i,k); + + interp.resize(2); + interp[0] = data_points[0]; + interp[1] = data_points[1]; + Real radius = find_dist_to_max(true, original_line, i); + i += interpolate(true, false, interpolated_surface, (i-1)*num_inter_points, iline, interp, SQ_ROOT, deja_interpolated, slope, radius); + continue; + } + else if (original_line[i] == 0) + { + for (int k = 1; k < 3; k++) + data_points[k-1] = getRelativeElement(original_line,i,-k); + + interp.resize(2); + interp[0] = data_points[0]; + interp[1] = data_points[1]; + Real radius = find_dist_to_max(false, original_line, i); + i += interpolate(false, false, interpolated_surface, i*num_inter_points, iline, interp, SQ_ROOT, deja_interpolated, slope, radius); + continue; + } + else + { +/* + interp.resize(2); + for (int k = 0; k < 2; k++) + interp[k] = getRelativeElement(original_line, i-1, -k); + i += interpolate(true, false, interpolated_surface, (i-1)*num_inter_points, iline, interp, LINEAR, deja_interpolated, slope); +*/ + for (int k = 0; k < 4; k++) + data_points[k] = getRelativeElement(original_line, i-1, k-1); + i += interpolate(true, false, interpolated_surface, (i-1)*num_inter_points, iline, data_points, QUADRATIC_BEZIER, deja_interpolated, slope); + //i += interpolate(true, false, interpolated_surface, (i-1)*num_inter_points, iline, data_points, CUBIC_BEZIER, deja_interpolated, slope); + //i += interpolate(true, false, interpolated_surface, (i-1)*num_inter_points, iline, data_points, CUBIC_HERMITE, deja_interpolated, slope); + continue; +/* + for (int k = 0; k < 2; k++) + data_points[k] = getRelativeElement(original_line,i-1,k); + + interp.resize(2); + interp[0] = data_points[0]; + interp[1] = data_points[1]; + i += interpolate(true, false, interpolated_surface, (i-1)*num_inter_points, iline, interp, LINEAR, deja_interpolated, slope); + continue; +*/ + } + } + while (i < size); + } + +// Compute statistics + Real value; + for (unsigned int i = num_inter_points*margin; i < interpolated_surface.size()-num_inter_points*margin; i++) + { + for (unsigned int j = num_inter_points*margin; j < interpolated_surface[i].size()-num_inter_points*margin; j++) + { + value = interpolated_surface[i][j]; + pressure+=value; + if (value > 1e-14) + area+=1.; + for (unsigned int k = 0; k < pdfs.size() && value > 1e-14; k++) + { + int num = int((1-(max_value - value)/max_value)*pdfs[k].size()); + if (num >= int(pdfs[k].size())) + num = pdfs[k].size()-1; + pdfs[k][num] += 1.; + } + } + } +// Plot files + if (fname != "") + { + std::ofstream file; + std::stringstream max_value_str; + max_value_str << int(100*max_value); + // interpolated surface + file.open((fname+"_"+max_value_str.str()).c_str(),ios_base::app); + file.precision(15); + for (unsigned int i = num_inter_points*margin; i < interpolated_surface.size()-num_inter_points*margin; i++) + for (unsigned int j = num_inter_points*margin; j < interpolated_surface[i].size()-num_inter_points*margin; j++) + file << (ix-margin)*num_inter_points+i << " " << (iy-margin)*num_inter_points+j << " " << interpolated_surface[i][j] << " " << endl; + file.close(); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + +/* + ///////////////////////////////////////////////////////////////////////////////// + // GO ALONG THE LINE :: original_line + ///////////////////////////////////////////////////////////////////////////////// + int i = 1; + do + { + ////////////////////////////////////////////// + // non-contact 0------0-----? + // [i-1] [i] [i+1] + ////////////////////////////////////////////// + if (original_line[i-1] == 0 && original_line[i] == 0) + { + //i+=interpolate(true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, ZERO, deja_interpolated, slope); + i+=interpolate(true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, TEST_INTER, deja_interpolated, slope,0,0); + continue; + } + ////////////////////////////////////////////// + // contact 1------1------? + // [i-1] [i] [i+1] + ////////////////////////////////////////////// + else + { + ///////////////////////////////////////////////////////////////////////////// + // From non-contact to contact 0-----1-----? + // [i-1] [i] [i+1] + ///////////////////////////////////////////////////////////////////////////// + if (original_line[i-1] == 0) + { + for (int k = 0; k < 4; k++) + data_points[k] = getRelativeElement(original_line,i,k); + concave_1 = if_concave(original_line,i); + concave_2 = if_concave(original_line,i+1); + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Only few points are nonzero 0-----1-----0 OR 0-----1-----1------0 + // [i-1] [i] [i+1] [i-1] [i] [i+1] [i+2] + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + if (data_points[1]*data_points[2] < 1e-14) + { + //////////////////////////////////////////////////////////////////////////////////////////// + // Singular point in contact 0-----1-----0 + // [i-1] [i] [i+1] + //////////////////////////////////////////////////////////////////////////////////////////// + if (data_points[1] < 1e-14) + { + Real a = num_inter_points/2., + p0 = data_points[0]/a, + x, x2, a2 = a*a; + + for (int j = 0; j <= 2*num_inter_points; j++) + { + x = j-num_inter_points; + x2 = x*x; + if (a2 > x2) + assign_value(interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points+j, p0*sqrt(a2 - x2)); + else + assign_value(interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points+j, 0.); + } + assign_value(deja_interpolated, i-1, 1); + assign_value(deja_interpolated, i, 1); + i+=2; + continue; + } + //////////////////////////////////////////////////////////////////////////////////////////// + // Only two points are in contact 0-----1-----1------0 + // [i-1] [i] [i+1] [i+2] + //////////////////////////////////////////////////////////////////////////////////////////// + else + { + interp.resize(2); + interp[0] = data_points[0]; + interp[1] = data_points[1]; + INTER_FUNC func(SQ_ROOT,interp,0.5); + deja_interpolated[i-1] = 1; + for (int k = 0; k < 3; k++) + { + for (int t = 0; t < num_inter_points; t++) + assign_value(interpolated_surface,iline*num_inter_points,(i-1+k)*num_inter_points+t, func.get_value( (k*num_inter_points+t)/(3.*num_inter_points) ) ); + assign_value(deja_interpolated, i-1+k, 1); + } + + i+=3; + continue; + } + } + ///////////////////////////////////////////////////////////////////////////////////////// + // Sufficient number of points for interpolation 0------1------1------1------? + // [i-1] [i] [i+1] [i+2] ... + ///////////////////////////////////////////////////////////////////////////////////////// + else + { + if (data_points[2] < data_points[1] && data_points[1] > data_points[0]) + { + interp.resize(2); + interp[0] = data_points[0]; + interp[1] = data_points[1]; + //i += interpolate(true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, SQ_ROOT, deja_interpolated, slope, 0.5); + i += interpolate(true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, TEST_INTER, deja_interpolated, slope, 0.5, 2); + continue; + } + else if (concave_2) // It's concave for sure, so we use square root interpolation. + { + interp.resize(2); + interp[0] = data_points[1]; + interp[1] = data_points[2]; + + Real radius = find_dist_to_max(true, original_line, i); + INTER_FUNC func(SQ_ROOT, interp, radius); + + if ( !(func.get_value(0.) > 0 || interp[1] < interp[0]) ) + { + //i += interpolate(true, interpolated_surface, iline*num_inter_points, i*num_inter_points, interp, SQ_ROOT, deja_interpolated, slope, radius); + i += interpolate(true, interpolated_surface, iline*num_inter_points, i*num_inter_points, interp, TEST_INTER, deja_interpolated, slope, radius, 3); + continue; + } + else + { + interp[0] = data_points[0]; + interp[1] = data_points[1]; + + //i += interpolate(true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, SQ_ROOT, deja_interpolated, slope, radius); + i += interpolate(true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, TEST_INTER, deja_interpolated, slope, radius, 4); + continue; + } + } + else + { + if (concave_1 || !parabola) + { + interp.resize(2); + interp[0] = data_points[1]; + interp[1] = data_points[2]; + Real radius = find_dist_to_max(true, original_line, i); + + INTER_FUNC func(SQ_ROOT, interp, radius); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + //i += interpolate(true, interpolated_surface, iline*num_inter_points, i*num_inter_points, interp, SQ_ROOT, deja_interpolated, slope, radius); + i += interpolate(true, interpolated_surface, iline*num_inter_points, i*num_inter_points, interp, TEST_INTER, deja_interpolated, slope, radius, 5); + continue; + } + else + { + interp[0] = data_points[0]; + interp[1] = data_points[1]; + + //i += interpolate(true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, SQ_ROOT, deja_interpolated, slope, radius); + i += interpolate(true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, TEST_INTER, deja_interpolated, slope, radius, 6); + continue; + } + } + else + { + interp.resize(3); + interp[0] = data_points[0]; + interp[1] = data_points[1]; + interp[2] = data_points[2]; + INTER_FUNC func(PARABOLA,interp); + + //i += interpolate(true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, PARABOLA, deja_interpolated, slope); + i += interpolate(true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, TEST_INTER, deja_interpolated, slope, 7); + } + } + } + } + ///////////////////////////////////////////////////////////////////////////// + // From contact to non-contact 1-----0 + // [i-1] [i] + ///////////////////////////////////////////////////////////////////////////// + else if (original_line[i] == 0) + { + if (data_points[2] < data_points[1] && data_points[1] > data_points[0]) + { + interp.resize(2); + interp[0] = data_points[0]; + interp[1] = data_points[1]; + //i += interpolate(false, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, SQ_ROOT, deja_interpolated, slope, 0.5); + i += interpolate(false, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, TEST_INTER, deja_interpolated, slope, 0.5); + continue; + } + else if (concave_2) // It's concave for sure, so we use square root interpolation. + { + interp.resize(2); + interp[0] = data_points[1]; + interp[1] = data_points[2]; + + Real radius = find_dist_to_max(true, original_line, i); + cout << "* * * * * * 1, p[0] = " << interp[0] << "; p[1] = " << interp[1] << "; a = " << radius << endl; + INTER_FUNC func(SQ_ROOT, interp, radius); + + if ( !(func.get_value(0.) > 0 || interp[1] < interp[0]) ) + { + //i += interpolate(false, interpolated_surface, iline*num_inter_points, i*num_inter_points, interp, SQ_ROOT, deja_interpolated, slope, radius); + i += interpolate(false, interpolated_surface, iline*num_inter_points, i*num_inter_points, interp, TEST_INTER, deja_interpolated, slope, radius); + continue; + } + else + { + interp[0] = data_points[0]; + interp[1] = data_points[1]; + + //i += interpolate(false, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, SQ_ROOT, deja_interpolated, slope, radius); + i += interpolate(false, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, TEST_INTER, deja_interpolated, slope, radius); + continue; + } + } + else + { + if (concave_1 || !parabola) + { + interp.resize(2); + interp[0] = data_points[1]; + interp[1] = data_points[2]; + Real radius = find_dist_to_max(true, original_line, i); + + cout << "* * * * * * 2" << endl; + INTER_FUNC func(SQ_ROOT, interp, radius); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + //i += interpolate(false, interpolated_surface, iline*num_inter_points, i*num_inter_points, interp, SQ_ROOT, deja_interpolated, slope, radius); + i += interpolate(false, interpolated_surface, iline*num_inter_points, i*num_inter_points, interp, TEST_INTER, deja_interpolated, slope, radius); + continue; + } + else + { + interp[0] = data_points[0]; + interp[1] = data_points[1]; + + //i += interpolate(false, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, SQ_ROOT, deja_interpolated, slope, radius); + i += interpolate(false, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, TEST_INTER, deja_interpolated, slope, radius); + continue; + } + } + else + { + interp.resize(3); + interp[0] = data_points[0]; + interp[1] = data_points[1]; + interp[2] = data_points[2]; + cout << "* * * * * * 3" << endl; + INTER_FUNC func(PARABOLA,interp); + + //i += interpolate(false, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, PARABOLA, deja_interpolated, slope); + i += interpolate(false, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, TEST_INTER, deja_interpolated, slope); + } + } + } + else // Cubic + { + i+=interpolate(true, interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, TEST_INTER, deja_interpolated, slope,0,5.); + continue; + } + } + } + while (i < size); + +*/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} +/* ---------------------------------------------------------------- */ +void Interpolator::make_by_patch(Surface& original, int ix, int iy, int patch_size, int margin, bool parabola, Real max_value, vector >& pdfs, + Real& area, Real& perimeter, Real& pressure, vector >& interpolated_surface, string fname) +{ +// test + bool to_be_interpolated = false; + for (int iline = 0; iline < patch_size; iline++) + for (int jline = 0; jline < patch_size; jline++) + if (getRelativeElement(original,ix,iy,iline,jline) != 0) + { + to_be_interpolated = true; + break; + } + if (!to_be_interpolated) + return; +//oe test + + int size = (patch_size+2*margin); + Real value; + + vector convexity1(3), convexity(3), interp; + vector deja_interpolated(size,0); + vector slope(size,DEF_SLOPE); + + vector original_line(patch_size+2*margin); + vector > deja_interpolated_m; + deja_interpolated_m.resize(0); + +///////////////////////////////////////////////////////////////////////////////// +// INTERPOLATION ALONG PROFILES +///////////////////////////////////////////////////////////////////////////////// + for (int iline = 0; iline < patch_size+margin*2; iline++) + { + for (unsigned int i = 0; i < deja_interpolated.size(); i++) + deja_interpolated[i] = 0; + + for (unsigned int i = 0; i < interpolated_surface[iline].size(); i++) + assign_value(interpolated_surface,iline*num_inter_points,i, 0.); // 0 + + for (int jline = 0; jline < patch_size+margin*2; jline++) + original_line[jline] = getRelativeElement(original,ix,iy,iline-margin,jline-margin); + int i = 1; + do + { + // non-contact + if (original_line[i-1] == 0 && original_line[i] == 0) +// i+=interpolate(interpolated_surface, iline*num_inter_points, (i-1)*num_inter_points, interp, ZERO, deja_interpolated, slope); + { + for (int j = 0; j < num_inter_points; j++) + assign_value(interpolated_surface,iline*num_inter_points,(i-1)*num_inter_points+j, 0.); + deja_interpolated[i-1] = 1; + slope[i] = 0.; + i++; + } + // contact + else + { + // ================================================================================================ + // ================================================================================================ + // From non-contact to contact + // ================================================================================================ + // ================================================================================================ + if (original_line[i-1] == 0) + { + convexity1[0] = getRelativeElement(original_line,i,0); + convexity1[1] = getRelativeElement(original_line,i,1); + convexity1[2] = getRelativeElement(original_line,i,2); + + convexity[0] = getRelativeElement(original_line,i,1); + convexity[1] = getRelativeElement(original_line,i,2); + convexity[2] = getRelativeElement(original_line,i,3); + + bool concave_1 = if_concave(convexity1), + concave_2 = if_concave(convexity); + + // Only few points are nonzero + if (convexity1[0]*convexity1[1]*convexity1[2]*convexity[2] == 0.) + { + if (convexity1[1] == 0.) + { + Real a = num_inter_points/2., + p0 = convexity1[0]/a; + + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + Real x = (i-1+j)*num_inter_points+k; + if (a*a > (x-i*num_inter_points)*(x-i*num_inter_points)) + { + value = p0*sqrt(a*a - (x-i*num_inter_points)*(x-i*num_inter_points)); + if (i+j < size) + assign_value(interpolated_surface,iline*num_inter_points,(i-1+j)*num_inter_points+k, value); + } + else + { + if (i+j < size) + assign_value(interpolated_surface,iline*num_inter_points,(i-1+j)*num_inter_points+k, 0.); + } + } + if (i-1+j convexity1[0]) + { + interp.resize(2); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + INTER_FUNC func(SQ_ROOT,interp,0.5); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j < size) + assign_value(interpolated_surface,iline*num_inter_points,(i-1+j)*num_inter_points+k, value); + } + if (i-1+j < size) + deja_interpolated[i-1+j] = 1; + } + if (i+1 getRelativeElement(original_line,i,k+1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + for (int k = 0; k < num_inter_points; k++) + assign_value(interpolated_surface,iline*num_inter_points,(i-1)*num_inter_points+k, 0.); + deja_interpolated[i-1] = 1; + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j+1 < size) + assign_value(interpolated_surface,iline*num_inter_points,(i+j)*num_inter_points+k, value); + } + if (i-1+j < size) + deja_interpolated[i-1+j] = 1; + } + if (i+1 < size) + slope[i+1] = func.get_derivative(1.)/2.; + + i+=2; + } + else + { + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j < size) + assign_value(interpolated_surface,iline*num_inter_points,(i-1+j)*num_inter_points+k, value); + } + if (i-1+j < size) + deja_interpolated[i-1+j] = 1; + } + if (i+1 < size) + slope[i+1] = func.get_derivative(1.)/2.; + + interp[0] = convexity[0]; + interp[1] = convexity[1]; + func = INTER_FUNC(LINEAR,interp); + for (int k = 0; k < num_inter_points; k++) + if (i+2 < size) + assign_value(interpolated_surface,iline*num_inter_points,(i+1)*num_inter_points+k, func.get_value(k/(1.*num_inter_points))); + if (i+1 < size) + deja_interpolated[i+1] = 1; + if (i+2 < size) + slope[i+2] = func.get_derivative(1.); + + i+=2; + } + } + else + { + if (concave_1 || !parabola) //func.get_value(-0.5) > 0.) + { + interp.resize(2); + interp[0] = convexity[0]; + interp[1] = convexity[1]; + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line,i,k) > getRelativeElement(original_line,i,k+1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + for (int k = 0; k < num_inter_points; k++) + assign_value(interpolated_surface,iline*num_inter_points,(i-1)*num_inter_points+k, 0.); + deja_interpolated[i-1] = 1; + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j+1 < size) + assign_value(interpolated_surface,iline*num_inter_points,(i+j)*num_inter_points+k, value); + } + if (i+j 0. && func.get_derivative(-0.5+(j*num_inter_points+k)/(2.*num_inter_points)) > 0.) + { + if (i+j < size) + assign_value(interpolated_surface,iline*num_inter_points,(i-1+j)*num_inter_points+k, value); + if (!start && value > tolerance) + { + stop=true; + break; + } + start=true; + } + else + { + if (i+j < size) + assign_value(interpolated_surface,iline*num_inter_points,(i-1+j)*num_inter_points+k, 0.); + x_edge = -0.5+(j*num_inter_points+k)/(2.*num_inter_points); + } + } + if (i-1+j < size) + deja_interpolated[i-1+j] = 1; + if (stop) + break; + } + if (!stop) + { + if (i+3 getRelativeElement(original_line,i,k+1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j < size) + assign_value(interpolated_surface,iline*num_inter_points,(i-1+j)*num_inter_points+k, value); + } + if (i-1+j < size) + deja_interpolated[i-1+j] = 1; + } + if (i+1 (x-i*num_inter_points)*(x-i*num_inter_points)) + { + value = p0*sqrt(a*a - (x-i*num_inter_points)*(x-i*num_inter_points)); + if (i-j-2 >= 0) + assign_value(interpolated_surface,iline*num_inter_points,(i-1-j)*num_inter_points-k, value); + } + else + { + if (i-j-2 >= 0) + assign_value(interpolated_surface,iline*num_inter_points,(i-1-j)*num_inter_points-k, 0.); + } + } + if (i-j-2+shift>=0 && i-j-2+shift convexity1[0]) + { + interp.resize(2); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + INTER_FUNC func(SQ_ROOT,interp,0.5); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-1 >= 0) + assign_value(interpolated_surface,iline*num_inter_points,(i-j)*num_inter_points-k, value); + } + if (i-j-1+shift>=0 && i-j-1+shift=0) + slope[i-2] = -func.get_derivative(1.)/2.; + i++; + } + else if (concave_2) // It's concave for sure, so we use square root interpolation. + { + interp.resize(2); + interp[0] = convexity[0]; + interp[1] = convexity[1]; + + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line, i, -k) > getRelativeElement(original_line, i, -k-1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + for (int k = 0; k < num_inter_points; k++) + if (i-1 >= 0) + assign_value(interpolated_surface,iline*num_inter_points,(i)*num_inter_points-k, 0.); + if (i-1+shift < size) + deja_interpolated[i-1+shift] = 1; + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-2 >= 0) + assign_value(interpolated_surface,iline*num_inter_points,(i-1-j)*num_inter_points-k, value); + } + if (i-j-2+shift>=0 && i-j-2+shift=0) + slope[i-2] = -func.get_derivative(1.)/2.; + + i++; + } + else + { + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-1 >= 0) + assign_value(interpolated_surface,iline*num_inter_points,(i-j)*num_inter_points-k, value); + } + if (i-j-1+shift>=0 && i-j-1+shift=0) + slope[i-2] = -func.get_derivative(1.)/2.; + i++; + } + } + else + { + if (concave_1 || !parabola) //func.get_value(-0.5) > 0.) + { + interp.resize(2); + interp[0] = convexity[0]; + interp[1] = convexity[1]; + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line, i, -k) > getRelativeElement(original_line, i, -k-1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + for (int k = 0; k < num_inter_points; k++) + if (i >= 0) + assign_value(interpolated_surface,iline*num_inter_points,(i+1)*num_inter_points-k, 0.); + if (i+shift < size) + deja_interpolated[i+shift] = 1; + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-2 >= 0) + assign_value(interpolated_surface,iline*num_inter_points,(i-1-j)*num_inter_points-k, value); + } + if (i-j-1+shift>=0 && i-j-1+shift=0) + slope[i-2] = -func.get_derivative(1.)/2.; + + i++; + } + else + { + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-1 >= 0) + assign_value(interpolated_surface,iline*num_inter_points,(i-j)*num_inter_points-k, value); + } + if (i-j-1+shift>=0 && i-j-1+shift=0) + slope[i-1] = -func.get_derivative(1.)/2.; + i++; + } + } + else + { + interp.resize(3); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + interp[2] = convexity1[2]; + INTER_FUNC func(PARABOLA,interp); + + Real x_edge = -0.5; + for (int j = 0; j < 4; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value(-0.5+(j*num_inter_points+k)/(2.*num_inter_points)); + if (value > 0.) + { + if (i-j-1 >= 0) + assign_value(interpolated_surface,iline*num_inter_points,(i-j)*num_inter_points-k, value); + } + else + { + if (i-j-1 >= 0) + assign_value(interpolated_surface,iline*num_inter_points,(i-j)*num_inter_points-k, 0.); + x_edge = -0.5+(j*num_inter_points+k)/(2.*num_inter_points); + } + } + if (i-j-1+shift>=0) + deja_interpolated[i-j-1+shift] = 1; + } + if (i-3>=0) + slope[i-3] = -func.get_derivative(1.)/2.; + } + } + } + } + else + { + interp.resize(2); + interp[0] = original_line[i-1]; + interp[1] = original_line[i]; + INTER_FUNC f(LINEAR,interp); + if (i-2+shift < size && i-2+shift >=0) + deja_interpolated[i-2+shift] = 0; + for (int k = 0; k < num_inter_points; k++) + assign_value(interpolated_surface,iline*num_inter_points,(i-1)*num_inter_points+k, f.get_value(k/Real(num_inter_points))); + } + i++; + // ================================================================================================ + // ================================================================================================ + // ================================================================================================ + // ================================================================================================ + } + } + while (i < size); + +// Cubic interpolation, see "http://en.wikipedia.org/wiki/Cubic_interpolation", Catmull–Rom spline + + for (int ip = 1; ip < int(original_line.size()); ip++) + { + if (!deja_interpolated[ip-1]) + { + Real m0, m1, t, + p0 = original_line[ip], + p1 = getRelativeElement(original_line,ip,1); + if (p0 > 1e-14 || p1 > 1e-14) + { + // Left slope + if (fabs(slope[ip] - DEF_SLOPE) < 0.1) + m0 = 0.5 * ( getRelativeElement(original_line,ip,1) - getRelativeElement(original_line,ip,-1) ); + else + m0 = slope[ip]; + // Right slope + int ip_1; + if (ip + 1 < int(original_line.size())) + ip_1 = ip + 1; + else + ip_1 = 0; + if (fabs(slope[ip_1] - DEF_SLOPE) < 0.1) + m1 = 0.5 * ( getRelativeElement(original_line,ip,2) - original_line[ip] ); + else + m1 = slope[ip_1]; + // Interpolation + for (int j = 0; j < num_inter_points; j++) + { + t = j/Real(num_inter_points); + Real t3 = t*t*t, t2 = t*t; + assign_value(interpolated_surface,iline*num_inter_points,ip*num_inter_points+j, (2*t3 - 3*t2 + 1)*p0 + (t3 - 2*t2 + t)*m0 + (-2*t3 + 3*t2)*p1 + (t3 - t2)*m1); + } + } + else + { + for (int j = 0; j < num_inter_points; j++) + assign_value(interpolated_surface,iline*num_inter_points,ip*num_inter_points+j, 0.); + } + } + } + +// Plot files + if (fname != "") + { + std::ofstream file; + std::stringstream max_value_str; + max_value_str << int(100*max_value); + // interpolated surface + file.open((fname+"_profiles_"+max_value_str.str()).c_str(),ios_base::app); + file.precision(15); +// for (int ii = margin; ii < size-margin; ii++) +// file << ix+iline << " " << iy+ii << " 0. " << deja_interpolated[ii] << endl; + + for (int j = num_inter_points*margin; j < num_inter_points*(size-margin); j++) + file << (ix+iline)*num_inter_points << " " << iy*num_inter_points+j << " " + << interpolated_surface[iline*num_inter_points][j] << " " << deja_interpolated[int(j/num_inter_points)] << endl; + + file.close(); + } + } +///////////////////////////////////////////////////////////////////////////////// +// END OF :: INTERPOLATION ALONG PROFILES +///////////////////////////////////////////////////////////////////////////////// + + + + + + + + + + + + + + + + + + + + + + + + +// Plot files +// if (fname != "") +// { +// std::ofstream file; +// std::stringstream max_value_str; +// max_value_str << int(100*max_value); +// // interpolated surface +// file.open((fname+"_profiles_"+max_value_str.str()).c_str(),ios_base::app); +// file.precision(15); +// for (unsigned int i = margin; i < (interpolated_surface.size()/num_inter_points)-margin; i++) +// for (unsigned int j = num_inter_points*margin; j < interpolated_surface[i].size()-num_inter_points*margin; j++) +// file << ix*num_inter_points+(i-margin)*num_inter_points << " " << iy*num_inter_points+j-margin*num_inter_points << " " +// << interpolated_surface[i*num_inter_points][j] << " " << deja_interpolated_m[i][j/num_inter_points] << endl; +// file.close(); +// } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +///////////////////////////////////////////////////////////////////////////////// +// ORTHOGONAL INTERPOLATION +///////////////////////////////////////////////////////////////////////////////// + + for (int iline = 0; iline < (patch_size+margin*2)*num_inter_points; iline++) + { + for (unsigned int i = 0; i < slope.size(); i++) + { + slope[i] = DEF_SLOPE; + deja_interpolated[i] = 0; + } + for (int jline = 0; jline < patch_size+margin*2; jline++) + original_line[jline] = interpolated_surface[jline*num_inter_points][iline]; + for (int jline = 0; jline < (patch_size+margin*2)*num_inter_points; jline++) + if (jline % num_inter_points != 0) + assign_value(interpolated_surface,jline,iline,0.); + + int i = 1; + do + { + // non-contact + if (original_line[i-1] < 1e-14 && original_line[i] < 1e-14) + { + for (int j = 0; j < num_inter_points; j++) + assign_value(interpolated_surface,(i-1)*num_inter_points+j,iline,0.); + deja_interpolated[i-1] = 1; + slope[i] = 0.; + i++; + } + // contact + else + { + // ================================================================================================ + // ================================================================================================ + // From non-contact to contact + // ================================================================================================ + // ================================================================================================ + if (original_line[i-1] == 0) + { + convexity1[0] = getRelativeElement(original_line,i,0); + convexity1[1] = getRelativeElement(original_line,i,1); + convexity1[2] = getRelativeElement(original_line,i,2); + + convexity[0] = getRelativeElement(original_line,i,1); + convexity[1] = getRelativeElement(original_line,i,2); + convexity[2] = getRelativeElement(original_line,i,3); + + bool concave_1 = if_concave(convexity1), + concave_2 = if_concave(convexity); + + // Only few points are nonzero + if (convexity1[0]*convexity1[1]*convexity1[2]*convexity[2] == 0.) + { + if (convexity1[1] == 0.) + { + Real a = num_inter_points/2., + p0 = convexity1[0]/a; + + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + Real x = (i-1+j)*num_inter_points+k; + if (a*a > (x-i*num_inter_points)*(x-i*num_inter_points)) + { + value = p0*sqrt(a*a - (x-i*num_inter_points)*(x-i*num_inter_points)); + if (i+j < size) + assign_value(interpolated_surface,(i-1+j)*num_inter_points+k,iline,value); + } + else + { + if (i+j < size) + assign_value(interpolated_surface,(i-1+j)*num_inter_points+k,iline,0.); + } + } + if (i+j-1 < size) + deja_interpolated[i-1+j] = 1; + } + i+=2; + continue; + } + else if (convexity1[1] != 0. && (convexity[1] == 0. || convexity[2] == 0.) ) + { + interp.resize(2); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + INTER_FUNC func(SQ_ROOT,interp,0.5); + for (int k = 0; k < num_inter_points; k++) + assign_value(interpolated_surface,(i-1)*num_inter_points+k,iline,0.); + if (convexity[1] == 0.) + { + for (int j = 0; j < 3; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); // STRANGE THAT IT'S NOT 3 in the denominator + if (i+j < size) + assign_value(interpolated_surface,(i-1+j)*num_inter_points+k,iline,value); + } + if (i+j-1 < size) + deja_interpolated[i-1+j] = 1; + } + if (i+3 convexity1[0]) + { + interp.resize(2); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + INTER_FUNC func(SQ_ROOT,interp,0.5); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j < size) + assign_value(interpolated_surface,(i-1+j)*num_inter_points+k,iline, value); //1 + } + if (i-1+j < size) + deja_interpolated[i-1+j] = 1; + } + if (i+1 getRelativeElement(original_line,i,k+1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + for (int k = 0; k < num_inter_points; k++) + assign_value(interpolated_surface,(i-1)*num_inter_points+k,iline,0.); + deja_interpolated[i-1] = 1; + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j+1 < size) + assign_value(interpolated_surface,(i+j)*num_inter_points+k,iline, value); //2 + } + if (i-1+j < size) + deja_interpolated[i-1+j] = 1; + } + if (i+1= 0) + assign_value(interpolated_surface,(i-1+j)*num_inter_points+k,iline, value); //3 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + } + if (i+j-1 < size && i+j-1 >= 0) + deja_interpolated[i+j-1] = 1; + } + if (i+1 0.) + { + interp.resize(2); + interp[0] = convexity[0]; + interp[1] = convexity[1]; + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line,i,k) > getRelativeElement(original_line,i,k+1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + for (int k = 0; k < num_inter_points; k++) + assign_value(interpolated_surface,(i-1)*num_inter_points+k,iline,0.); + deja_interpolated[i-1] = 1; + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j+1 < size) + assign_value(interpolated_surface,(i+j)*num_inter_points+k,iline, value); //4 + } + if (i+j < size) + deja_interpolated[i+j] = 1; + } + if (i+3 < size) + slope[i+3] = func.get_derivative(1.)/2.; // !! + + i+=2; + } + else + { + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j < size) + assign_value(interpolated_surface,(i-1+j)*num_inter_points+k,iline, value); //5 + } + if (i-1+j < size) + deja_interpolated[i-1+j] = 1; + } + if (i+2 < size) + slope[i+2] = func.get_derivative(1.)/2.; // !! + i+=2; + } + } + else + { + interp.resize(3); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + interp[2] = convexity1[2]; + INTER_FUNC func(PARABOLA,interp); + + Real x_edge = -0.5; + bool start = false, stop = false; + for (int j = 0; j < 4; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value(-0.5+(j*num_inter_points+k)/(2.*num_inter_points)); + if (value > 0. && func.get_derivative(-0.5+(j*num_inter_points+k)/(2.*num_inter_points)) > 0.) + { + if (i+j < size) + assign_value(interpolated_surface,(i-1+j)*num_inter_points+k,iline,value); + if (!start && value > tolerance) + { + stop=true; + break; + } + start=true; + } + else + { + if (i+j < size) + assign_value(interpolated_surface,(i-1+j)*num_inter_points+k,iline,0.); + x_edge = -0.5+(j*num_inter_points+k)/(2.*num_inter_points); + } + } + if (i-1+j < size) + deja_interpolated[i-1+j] = 1; + if (stop) + break; + } + if (!stop) + { + if (i+3 < size) + slope[i+3] = func.get_derivative(1.)/2.; + i+=3; // IGO + } + else // Use square root interpolation + { + interp.resize(2); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line,i,k) > getRelativeElement(original_line,i,k+1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j < size) + assign_value(interpolated_surface,(i-1+j)*num_inter_points+k,iline, value); //6 + } + if (i-1+j < size) + deja_interpolated[i-1+j] = 1; + } + if (i+1 < size) + slope[i+1] = func.get_derivative(1.)/2.; + i+=2; + } + } + } + } + } + // ================================================================================================ + // ================================================================================================ + // From contact to non-contact + // ================================================================================================ + // ================================================================================================ + else if (original_line[i] == 0.) + { + convexity1[0] = getRelativeElement(original_line,i-1,0); + convexity1[1] = getRelativeElement(original_line,i-1,-1); + convexity1[2] = getRelativeElement(original_line,i-1,-2); + + convexity[0] = getRelativeElement(original_line,i-1,-1); + convexity[1] = getRelativeElement(original_line,i-1,-2); + convexity[2] = getRelativeElement(original_line,i-1,-3); + + bool concave_1 = if_concave(convexity1), + concave_2 = if_concave(convexity); + + if (convexity1[0]*convexity1[1]*convexity1[2]*convexity[2] == 0.) + { + if (convexity1[1] == 0.) + { + Real a = num_inter_points/2., + p0 = convexity1[0]/a; + + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + Real x = (i-1+j)*num_inter_points+k; + if (a*a > (x-i*num_inter_points)*(x-i*num_inter_points)) + { + value = p0*sqrt(a*a - (x-i*num_inter_points)*(x-i*num_inter_points)); + if (i-j-2 >= 0) + assign_value(interpolated_surface,(i-1-j)*num_inter_points-k,iline,value); + } + else + { + if (i-j-2 >= 0) + assign_value(interpolated_surface,(i-1-j)*num_inter_points-k,iline,0.); + } + } + if (i-j-2+shift >= 0) + deja_interpolated[i-j-2+shift] = 1; + } + i++; + continue; + } + } + else + { + if (convexity1[2] < convexity1[1] && convexity1[1] > convexity1[0]) + { + interp.resize(2); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + INTER_FUNC func(SQ_ROOT,interp,0.5); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-1 >= 0) + assign_value(interpolated_surface,(i-j)*num_inter_points-k,iline, value); //-1 + } + if (i-j-1+shift >= 0) + deja_interpolated[i-j-1+shift] = 1; + } + if (i-2>=0) + slope[i-2] = -func.get_derivative(1.)/2.; + i++; + } + else if (concave_2) // It's concave for sure, so we use square root interpolation. + { + interp.resize(2); + interp[0] = convexity[0]; + interp[1] = convexity[1]; + + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line, i, -k) > getRelativeElement(original_line, i, -k-1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + for (int k = 0; k < num_inter_points; k++) + if (i-1 >= 0) + assign_value(interpolated_surface,(i)*num_inter_points-k,iline,0.); + if (i-1+shift < size) + deja_interpolated[i-1+shift] = 1; + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-2 >= 0) + assign_value(interpolated_surface,(i-1-j)*num_inter_points-k,iline, value); //-2 + } + if (i-j-2+shift>=0) + deja_interpolated[i-j-2+shift] = 1; + } + if (i-2>=0) + slope[i-2] = -func.get_derivative(1.)/2.; + + i++; + } + else + { + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-1 >= 0) + assign_value(interpolated_surface,(i-j)*num_inter_points-k,iline, value); //-3 + } + if (i-j-1+shift>=0) + deja_interpolated[i-j-1+shift] = 1; + } + if (i-2>=0) + slope[i-2] = -func.get_derivative(1.)/2.; + i++; + } + } + else + { + if (concave_1 || !parabola) //func.get_value(-0.5) > 0.) + { + interp.resize(2); + interp[0] = convexity[0]; + interp[1] = convexity[1]; + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line, i, -k) > getRelativeElement(original_line, i, -k-1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + for (int k = 0; k < num_inter_points; k++) + if (i >= 0) + assign_value(interpolated_surface,(i+1)*num_inter_points-k,iline,0.); + if (i+shift < size) + deja_interpolated[i+shift] = 1; + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-2 >= 0) + assign_value(interpolated_surface,(i-1-j)*num_inter_points-k,iline, value); //-4 + } + if (i-j-1+shift >= 0) + deja_interpolated[i-j-1+shift] = 1; + } + if (i-2 >= 0) + slope[i-2] = -func.get_derivative(1.)/2.; + + i++; + } + else + { + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-1 >= 0) + assign_value(interpolated_surface,(i-j)*num_inter_points-k,iline, value); //-5 + } + if (i-j-1+shift >= 0) + deja_interpolated[i-j-1+shift] = 1; + } + if (i-2 >= 0) + slope[i-2] = -func.get_derivative(1.)/2.; + i++; + } + } + else + { + interp.resize(3); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + interp[2] = convexity1[2]; + INTER_FUNC func(PARABOLA,interp); + + Real x_edge = -0.5; + for (int j = 0; j < 4; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value(-0.5+(j*num_inter_points+k)/(2.*num_inter_points)); + if (value > 0.) + { + if (i-j-1 >= 0) + assign_value(interpolated_surface,(i-j)*num_inter_points-k,iline,value); + } + else + { + if (i-j-1 >= 0) + assign_value(interpolated_surface,(i-j)*num_inter_points-k,iline,0.); + x_edge = -0.5+(j*num_inter_points+k)/(2.*num_inter_points); //IGO + } + } + if (i-j-1+shift >= 0) + deja_interpolated[i-j-1+shift] = 1; + } + if (i-3 >= 0) + slope[i-3] = -func.get_derivative(1.)/2.; + } + } + } + } + else + { + if (i-2+shift >=0) + deja_interpolated[i-2+shift] = 0; +/* + interp.resize(2); + interp[0] = original_line[i-1]; + interp[1] = original_line[i]; + INTER_FUNC f(LINEAR,interp); + if (i-2+shift >=0) + deja_interpolated[i-2+shift] = 0; + for (int k = 0; k < num_inter_points; k++) + assign_value(interpolated_surface,(i-1)*num_inter_points+k,iline,f.get_value(k/Real(num_inter_points))); +*/ + } + i++; + // ================================================================================================ + // ================================================================================================ + // ================================================================================================ + // ================================================================================================ + } + } + while (i < size); + +// Cubic interpolation, see "http://en.wikipedia.org/wiki/Cubic_interpolation", Catmull–Rom spline + + for (unsigned int ip = 1; ip < original_line.size(); ip++) + { + if (!deja_interpolated[ip-1]) + { + Real m0, m1, t, + p0 = original_line[ip], + p1 = getRelativeElement(original_line,ip,1); + if (p0 > 1e-14 && p1 > 1e-14) + { + // Left slope + if (fabs(slope[ip] - DEF_SLOPE) < 0.1) + m0 = 0.5 * ( getRelativeElement(original_line,ip,1) - getRelativeElement(original_line,ip,-1) ); + else + m0 = slope[ip]; + // Right slope + int ip_1; + if (ip + 1 < original_line.size()) + ip_1 = ip + 1; + else + ip_1 = 0; + if (fabs(slope[ip_1] - DEF_SLOPE) < 0.1) + m1 = 0.5 * ( getRelativeElement(original_line,ip,2) - original_line[ip] ); + else + m1 = slope[ip_1]; + // Interpolation + for (int j = 0; j < num_inter_points; j++) + { + t = j/Real(num_inter_points); + Real t3 = t*t*t, t2 = t*t; + assign_value(interpolated_surface,ip*num_inter_points+j,iline,(2*t3 - 3*t2 + 1)*p0 + (t3 - 2*t2 + t)*m0 + (-2*t3 + 3*t2)*p1 + (t3 - t2)*m1); + } + } +/* + else + { + for (int j = 0; j < num_inter_points; j++) + assign_value(interpolated_surface,ip*num_inter_points+j,iline,0); + } +*/ + } + else + { + // for (int j = 0; j < num_inter_points; j++) + // assign_value(interpolated_surface,ip*num_inter_points+j,iline,5); + } + } + } +///////////////////////////////////////////////////////////////////////////////// +// END OF :: ORTHOGONAL INTERPOLATION +///////////////////////////////////////////////////////////////////////////////// + +// Compute statistics + for (unsigned int i = num_inter_points*margin; i < interpolated_surface.size()-num_inter_points*margin; i++) + { + for (unsigned int j = num_inter_points*margin; j < interpolated_surface[i].size()-num_inter_points*margin; j++) + { + value = interpolated_surface[i][j]; + pressure+=value; + if (value > 1e-14) + area+=1.; + for (unsigned int k = 0; k < pdfs.size() && value > 1e-14; k++) + { + int num = int((1-(max_value - value)/max_value)*pdfs[k].size()); + if (num >= int(pdfs[k].size())) + num = pdfs[k].size()-1; + pdfs[k][num] += 1.; + } + } + } +// Plot files + if (fname != "") + { + std::ofstream file; + std::stringstream max_value_str; + max_value_str << int(100*max_value); + // interpolated surface + file.open((fname+"_"+max_value_str.str()).c_str(),ios_base::app); + file.precision(15); + for (unsigned int i = num_inter_points*margin; i < interpolated_surface.size()-num_inter_points*margin; i++) + for (unsigned int j = num_inter_points*margin; j < interpolated_surface[i].size()-num_inter_points*margin; j++) + file << ix*num_inter_points+i-num_inter_points*margin << " " << iy*num_inter_points+j-num_inter_points*margin << " " << interpolated_surface[i][j] << " " << endl; + file.close(); + } + +} + +/* ---------------------------------------------------------------- */ + +void Interpolator::make_by_profile(Surface original, int iline, bool parabola, bool vertical, Real max_value, vector >& pdfs, + Real& area, Real& perimeter, Real& pressure, string fname) +{ + Real value; + int size = original.n,g=0,g_=0; + + vector original_line(size), interpolated_line(num_inter_points*size,0.); + vector convexity1(3), convexity(3), interp; + vector deja_interpolated(size); + vector slope(size,DEF_SLOPE); + + if (!vertical) // Interpolate in rows + { + for (int j = 0; j < size; j++) + original_line[j] = original(iline,j).re; + } + else // Interpolate in columns + { + for (int j = 0; j < size; j++) + original_line[j] = original(j,iline).re; + } + + int i = 1; + do + { + // non-contact + if (original_line[i-1] == 0 && original_line[i] == 0) + { + for (int j = 0; j < num_inter_points; j++) + interpolated_line[(i-1)*num_inter_points+j] = 0.; + deja_interpolated[i-1] = 1; + slope[i] = 0.; + i++; + } + // contact + else + { + // ================================================================================================ + // ================================================================================================ + // From non-contact to contact + // ================================================================================================ + // ================================================================================================ + if (original_line[i-1] == 0) + { + convexity1[0] = getRelativeElement(original_line,i,0); + convexity1[1] = getRelativeElement(original_line,i,1); + convexity1[2] = getRelativeElement(original_line,i,2); + + convexity[0] = getRelativeElement(original_line,i,1); + convexity[1] = getRelativeElement(original_line,i,2); + convexity[2] = getRelativeElement(original_line,i,3); + + bool concave_1 = if_concave(convexity1), + concave_2 = if_concave(convexity); + + if (convexity1[0]*convexity1[1]*convexity1[2]*convexity[2] == 0.) + { + if (convexity1[1] == 0.) + { + Real a = num_inter_points/2., + p0 = convexity1[0]/a; + + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + Real x = (i-1+j)*num_inter_points+k; + if (a*a > (x-i*num_inter_points)*(x-i*num_inter_points)) + { + value = p0*sqrt(a*a - (x-i*num_inter_points)*(x-i*num_inter_points)); + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = value; + } + else + { + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = 0.; + } + } + deja_interpolated[i-1+j] = 1; + } + i+=2; + continue; + } + else if (convexity1[1] != 0. && (convexity[1] == 0. || convexity[2] == 0.) ) + { + interp.resize(2); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + INTER_FUNC func(SQ_ROOT,interp,0.5); + for (int k = 0; k < num_inter_points; k++) + interpolated_line[(i-1)*num_inter_points+k] = 0.; + if (convexity[1] == 0.) + { + for (int j = 0; j < 3; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); // STRANGE THAT IT'S NOT 3 in the denominator + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = value; + } + deja_interpolated[i-1+j] = 1; + } + slope[i+3] = func.get_derivative(1.)/3.; // !! + + i+=3; + } + else if (convexity[2] == 0.) + { + for (int j = 0; j < 4; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); // SHOULD BE 4, NO? + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = value; + } + deja_interpolated[i-1+j] = 1; + } + slope[i+3] = func.get_derivative(1.)/4.; // !! + + i+=3; + } + } + } + else + { + if (convexity1[2] < convexity1[1] && convexity1[1] > convexity1[0]) + { + interp.resize(2); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + INTER_FUNC func(SQ_ROOT,interp,0.5); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = value; + } + deja_interpolated[i-1+j] = 1; + } + slope[i+1] = func.get_derivative(1.)/2.; // !! + + i+=1; + } + else if (concave_2) // It's concave for sure, so we use square root interpolation. + { + interp.resize(2); + interp[0] = convexity[0]; + interp[1] = convexity[1]; + + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line,i,k) > getRelativeElement(original_line,i,k+1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + for (int k = 0; k < num_inter_points; k++) + interpolated_line[(i-1)*num_inter_points+k] = 0.; + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j+1 < size) + interpolated_line[(i+j)*num_inter_points+k] = value; + } + deja_interpolated[i-1+j] = 1; + } + slope[i+1] = func.get_derivative(1.)/2.; // !! + + i+=2; + } + else + { + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = value; + } + deja_interpolated[i-1+j] = 1; + } + slope[i+1] = func.get_derivative(1.)/2.; // !! + + interp[0] = convexity[0]; + interp[1] = convexity[1]; + func = INTER_FUNC(LINEAR,interp); + for (int k = 0; k < num_inter_points; k++) + if (i+2 < size) + interpolated_line[(i+1)*num_inter_points+k] = func.get_value(k/(1.*num_inter_points)); + deja_interpolated[i+1] = 1; + slope[i+2] = func.get_derivative(1.); // !! + + i+=2; + } + } + else + { + if (concave_1 || !parabola) //func.get_value(-0.5) > 0.) + { + interp.resize(2); + interp[0] = convexity[0]; + interp[1] = convexity[1]; + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line,i,k) > getRelativeElement(original_line,i,k+1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + for (int k = 0; k < num_inter_points; k++) + interpolated_line[(i-1)*num_inter_points+k] = 0.; + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j+1 < size) + interpolated_line[(i+j)*num_inter_points+k] = value; + } + deja_interpolated[i+j] = 1; + } + slope[i+3] = func.get_derivative(1.)/2.; // !! + + i+=2; + } + else + { + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = value; + } + deja_interpolated[i-1+j] = 1; + } + slope[i+2] = func.get_derivative(1.)/2.; // !! +/* + interp[0] = convexity[0]; + interp[1] = convexity[1]; + func = INTER_FUNC(LINEAR,interp); + for (int k = 0; k < num_inter_points; k++) + if (i+2 < size) + interpolated_line[(i+1)*num_inter_points+k] = func.get_value(k/(1.*num_inter_points)); + + deja_interpolated[i+1] = 1; + slope[i+2] = func.get_derivative(1.)/2.; // !! +*/ + i+=2; + } + } + else + { + interp.resize(3); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + interp[2] = convexity1[2]; + INTER_FUNC func(PARABOLA,interp); + + Real x_edge = -0.5; + bool start = false, stop = false; + for (int j = 0; j < 4; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value(-0.5+(j*num_inter_points+k)/(2.*num_inter_points)); + if (value > 0. && func.get_derivative(-0.5+(j*num_inter_points+k)/(2.*num_inter_points)) > 0.) + { + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = value; + if (!start && value > tolerance) + { + stop=true; + break; + } + start=true; + } + else + { + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = 0.; + x_edge = -0.5+(j*num_inter_points+k)/(2.*num_inter_points); + } + } + deja_interpolated[i-1+j] = 1; + if (stop) + break; + } + if (!stop) + { + slope[i+3] = func.get_derivative(1.)/2.; + i+=3; // IGO + } + else // Use square root interpolation + { + interp.resize(2); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line,i,k) > getRelativeElement(original_line,i,k+1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = value; + } + } +/* !!!!!!!! + interp[0] = convexity[0]; + interp[1] = convexity[1]; + func = INTER_FUNC(LINEAR,interp); + for (int k = 0; k < num_inter_points; k++) + if (i+2 < size) + interpolated_line[(i+1)*num_inter_points+k] = func.get_value(k/(1.*num_inter_points)); +*/ + slope[i+1] = func.get_derivative(1.)/2.; + i+=2; + } + } + } + } + } + // ================================================================================================ + // ================================================================================================ + // From contact to non-contact + // ================================================================================================ + // ================================================================================================ + else if (original_line[i] == 0.) + { + convexity1[0] = getRelativeElement(original_line,i-1,0); + convexity1[1] = getRelativeElement(original_line,i-1,-1); + convexity1[2] = getRelativeElement(original_line,i-1,-2); + + convexity[0] = getRelativeElement(original_line,i-1,-1); + convexity[1] = getRelativeElement(original_line,i-1,-2); + convexity[2] = getRelativeElement(original_line,i-1,-3); + + bool concave_1 = if_concave(convexity1), + concave_2 = if_concave(convexity); + + if (convexity1[0]*convexity1[1]*convexity1[2]*convexity[2] == 0.) + { + if (convexity1[1] == 0.) + { + Real a = num_inter_points/2., + p0 = convexity1[0]/a; + + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + Real x = (i-1+j)*num_inter_points+k; + if (a*a > (x-i*num_inter_points)*(x-i*num_inter_points)) + { + value = p0*sqrt(a*a - (x-i*num_inter_points)*(x-i*num_inter_points)); + if (i-j-2 >= 0) + interpolated_line[(i-1-j)*num_inter_points-k] = value; + } + else + { + if (i-j-2 >= 0) + interpolated_line[(i-1-j)*num_inter_points-k] = 0.; + } + } + deja_interpolated[i-j-2] = 1; + } + i++; + continue; + } + } + else + { + if (convexity1[2] < convexity1[1] && convexity1[1] > convexity1[0]) + { + interp.resize(2); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + INTER_FUNC func(SQ_ROOT,interp,0.5); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-1 >= 0) + interpolated_line[(i-j)*num_inter_points-k] = value; + } + deja_interpolated[i-j-2] = 1; + } + slope[i-2] = -func.get_derivative(1.)/2.; + //i+=2; + i++; + } + else if (concave_2) // It's concave for sure, so we use square root interpolation. + { + interp.resize(2); + interp[0] = convexity[0]; + interp[1] = convexity[1]; + + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line, i, -k) > getRelativeElement(original_line, i, -k-1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + for (int k = 0; k < num_inter_points; k++) + if (i-1 >= 0) + interpolated_line[(i)*num_inter_points-k] = 0.; + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-2 >= 0) + interpolated_line[(i-1-j)*num_inter_points-k] = value; + } + deja_interpolated[i-j-2] = 1; + } + slope[i-2] = -func.get_derivative(1.)/2.; + +// i+=2; + i++; + } + else + { + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-1 >= 0) + interpolated_line[(i-j)*num_inter_points-k] = value; + } + deja_interpolated[i-j-2] = 1; + } + slope[i-2] = -func.get_derivative(1.)/2.; +/* + interp[0] = convexity[0]; + interp[1] = convexity[1]; + func = INTER_FUNC(LINEAR,interp); + for (int k = 0; k < num_inter_points; k++) + if (i-3 >= 0) + interpolated_line[(i-2)*num_inter_points-k] = func.get_value(k/(1.*num_inter_points)); +*/ +// i+=2; + i++; + } + } + else + { + if (concave_1 || !parabola) //func.get_value(-0.5) > 0.) + { + interp.resize(2); + interp[0] = convexity[0]; + interp[1] = convexity[1]; + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line, i, -k) > getRelativeElement(original_line, i, -k-1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + for (int k = 0; k < num_inter_points; k++) + if (i >= 0) + interpolated_line[(i+1)*num_inter_points-k] = 0.; + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-2 >= 0) + interpolated_line[(i-1-j)*num_inter_points-k] = value; + } + deja_interpolated[i-j-2] = 1; + } + slope[i-2] = -func.get_derivative(1.)/2.; + +// i+=2; + i++; + } + else + { + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-1 >= 0) + interpolated_line[(i-j)*num_inter_points-k] = value; + } + deja_interpolated[i-j-2] = 1; + } + slope[i-2] = -func.get_derivative(1.)/2.; +/* + interp[0] = convexity[0]; + interp[1] = convexity[1]; + func = INTER_FUNC(LINEAR,interp); + for (int k = 0; k < num_inter_points; k++) + if (i-3 >= 0) + interpolated_line[(i-2)*num_inter_points-k] = func.get_value(k/(1.*num_inter_points)); +*/ +// i+=2; + i++; + } + } + else + { + interp.resize(3); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + interp[2] = convexity1[2]; + INTER_FUNC func(PARABOLA,interp); + + Real x_edge = -0.5; + for (int j = 0; j < 4; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value(-0.5+(j*num_inter_points+k)/(2.*num_inter_points)); + if (value > 0.) + { + if (i-j-1 >= 0) + interpolated_line[(i-j)*num_inter_points-k] = value; + } + else + { + if (i-j-1 >= 0) + interpolated_line[(i-j)*num_inter_points-k] = 0.; + x_edge = -0.5+(j*num_inter_points+k)/(2.*num_inter_points); //IGO + } + } + deja_interpolated[i-j-2] = 1; + } + slope[i-3] = -func.get_derivative(1.)/2.; + } + } + } + } + else + { + interp.resize(2); + interp[0] = original_line[i-1]; + interp[1] = original_line[i]; + INTER_FUNC f(LINEAR,interp); + for (int k = 0; k < num_inter_points; k++) + { + interpolated_line[(i-1)*num_inter_points+k] = f.get_value(k/Real(num_inter_points)); + } + } + i++; + // ================================================================================================ + // ================================================================================================ + // ================================================================================================ + // ================================================================================================ + } + if (g > i) + exit(1); + g_=g; + g=i; + } + while (i < size); + +// Cubic interpolation, see "http://en.wikipedia.org/wiki/Cubic_interpolation", Catmull–Rom spline + + for (unsigned int ip = 1; ip < original_line.size(); ip++) + { + if (!deja_interpolated[ip-1]) + { + Real m0, m1, t, + p0 = original_line[ip], + p1 = getRelativeElement(original_line,ip,1); + // Left slope + if (fabs(slope[ip] - DEF_SLOPE) < 0.1) + m0 = 0.5 * ( getRelativeElement(original_line,ip,1) - getRelativeElement(original_line,ip,-1) ); + else + m0 = slope[ip]; + // Right slope + int ip_1; + if (ip + 1 < original_line.size()) + ip_1 = ip + 1; + else + ip_1 = 0; + if (fabs(slope[ip_1] - DEF_SLOPE) < 0.1) + m1 = 0.5 * ( getRelativeElement(original_line,ip,2) - original_line[ip] ); + else + m1 = slope[ip_1]; + // Interpolation + for (int j = 0; j < num_inter_points; j++) + { + t = j/Real(num_inter_points); + Real t3 = t*t*t, t2 = t*t; +// cout << "p0 = " << p0 << "; p1 = " << p1 << "; m0 = " << m0 << "; m1 = " << m1 << "; --> t = " << t << "; y(t) = " << (2*t3 - 3*t2 + 1)*p0 + (t3 - 2*t2 + t)*m0 + (-2*t3 + 3*t2)*p1 + (t3 - t2)*m1 << endl; + interpolated_line[ip*num_inter_points+j] = (2*t3 - 3*t2 + 1)*p0 + (t3 - 2*t2 + t)*m0 + (-2*t3 + 3*t2)*p1 + (t3 - t2)*m1; + } + } + } + +// Compute statistics + for (unsigned int i = 0; i < interpolated_line.size(); i++) + { + value = interpolated_line[i]; + pressure+=value; + if (value > 1e-14) + area+=1.; + if ( (getRelativeElement(interpolated_line, i, 1) < 1e-14 && value > 1e-14) || + (getRelativeElement(interpolated_line, i, 1) > 1e-14 && value < 1e-14) ) + perimeter+=1.; + for (unsigned int j = 0; j < pdfs.size() && value > 1e-14; j++) + { + int num = int((1-(max_value - value)/max_value)*pdfs[j].size()); + if (num >= int(pdfs[j].size())) + num = pdfs[j].size()-1; + pdfs[j][num] += 1.; + } + } +// Plot files + if (fname != "") + { + std::ofstream file; + std::stringstream max_value_str; + max_value_str << max_value; + // original line + file.open((fname+"_"+max_value_str.str()).c_str(),ios_base::app); + file.precision(15); + for (unsigned int j = 0; j < original_line.size(); j++) + file << iline << " " << j << " " << original_line[j] << " " << deja_interpolated[j] << " " << slope[j] << endl; + file << std::endl; + if (iline == original.n-1) + file << std::endl; + file.close(); + // interpolated line + file.open((fname+"_inter_"+max_value_str.str()).c_str(),ios_base::app); + file.precision(15); + for (unsigned int j = 0; j < original_line.size(); j++) + { + if (fabs(slope[j]) < 1e3) + for (int k = 0; k < num_inter_points; k++) + file << iline << " " << j*num_inter_points+k << " " << interpolated_line[j*num_inter_points+k] << " " << original_line[j]+k*slope[j]/Real(num_inter_points) << endl; + else + for (int k = 0; k < num_inter_points; k++) + file << iline << " " << j*num_inter_points+k << " " << interpolated_line[j*num_inter_points+k] << " " << original_line[j] << endl; + } + file << std::endl; + if (iline == original.n-1) + file << std::endl; + file.close(); + } + +} + +/* ---------------------------------------------------------------- */ + +vector< vector > Interpolator::make_by_profile(Surface original, bool parabola, bool vertical) +{ + Real value; + int size = original.n; + + vector< vector > result(size); + vector original_line(size), interpolated_line(num_inter_points*size,0.); + vector convexity1(3), convexity(3), interp; + + for (int iline = 0; iline < size; iline++) + { + cout << "\xd Interpolator :: " << int((iline+1)*100./size) << "\% completed"; + if (!vertical) // Interpolate in rows + { + for (int j = 0; j < size; j++) + original_line[j] = original(iline,j).re; + } + else // Interpolate in columns + { + for (int j = 0; j < size; j++) + original_line[j] = original(j,iline).re; + } + + int i = 1; + do + { + // non-contact + if (original_line[i-1] == 0 && original_line[i] == 0) + { + for (int j = 0; j < num_inter_points; j++) + interpolated_line[(i-1)*num_inter_points+j] = 0.; + i++; + } + // contact + else + { + // ================================================================================================ + // ================================================================================================ + // From non-contact to contact + // ================================================================================================ + // ================================================================================================ + if (original_line[i-1] == 0) + { + convexity1[0] = getRelativeElement(original_line,i,0); + convexity1[1] = getRelativeElement(original_line,i,1); + convexity1[2] = getRelativeElement(original_line,i,2); + + convexity[0] = getRelativeElement(original_line,i,1); + convexity[1] = getRelativeElement(original_line,i,2); + convexity[2] = getRelativeElement(original_line,i,3); + + bool concave_1 = if_concave(convexity1), + concave_2 = if_concave(convexity); + + if (convexity1[0]*convexity1[1]*convexity1[2]*convexity[2] == 0.) + { + if (convexity1[1] == 0.) + { + Real a = num_inter_points/2., + p0 = convexity1[0]/a; + + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + Real x = (i-1+j)*num_inter_points+k; + if (a*a > (x-i*num_inter_points)*(x-i*num_inter_points)) + { + value = p0*sqrt(a*a - (x-i*num_inter_points)*(x-i*num_inter_points)); + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = value; + } + else + { + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = 0.; + } + } + } + i+=2; + continue; + } + else if (convexity1[1] != 0. && (convexity[1] == 0. || convexity[2] == 0.) ) + { + interp.resize(2); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + INTER_FUNC func(SQ_ROOT,interp,0.5); + for (int k = 0; k < num_inter_points; k++) + interpolated_line[(i-1)*num_inter_points+k] = 0.; + if (convexity[1] == 0.) + { + for (int j = 0; j < 3; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = value; + } + } + + i+=3; + } + else if (convexity[2] == 0.) + { + for (int j = 0; j < 4; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = value; + } + } + + i+=3; + } + } + } + else + { + if (convexity1[2] < convexity1[1] && convexity1[1] > convexity1[0]) + { + interp.resize(2); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + INTER_FUNC func(SQ_ROOT,interp,0.5); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = value; + } + } + + i+=1; + } + else if (concave_2) // It's concave for sure, so we use square root interpolation. + { + interp.resize(2); + interp[0] = convexity[0]; + interp[1] = convexity[1]; + + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line,i,k) > getRelativeElement(original_line,i,k+1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + for (int k = 0; k < num_inter_points; k++) + interpolated_line[(i-1)*num_inter_points+k] = 0.; + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j+1 < size) + interpolated_line[(i+j)*num_inter_points+k] = value; + } + } + + i+=2; + } + else + { + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = value; + } + } + interp[0] = convexity[0]; + interp[1] = convexity[1]; + func = INTER_FUNC(LINEAR,interp); + for (int k = 0; k < num_inter_points; k++) + if (i+2 < size) + interpolated_line[(i+1)*num_inter_points+k] = func.get_value(k/(1.*num_inter_points)); + + i+=2; + } + } + else + { + if (concave_1 || !parabola) //func.get_value(-0.5) > 0.) + { + interp.resize(2); + interp[0] = convexity[0]; + interp[1] = convexity[1]; + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line,i,k) > getRelativeElement(original_line,i,k+1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + for (int k = 0; k < num_inter_points; k++) + interpolated_line[(i-1)*num_inter_points+k] = 0.; + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j+1 < size) + interpolated_line[(i+j)*num_inter_points+k] = value; + } + } + + i+=2; + } + else + { + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = value; + } + } + interp[0] = convexity[0]; + interp[1] = convexity[1]; + func = INTER_FUNC(LINEAR,interp); + for (int k = 0; k < num_inter_points; k++) + if (i+2 < size) + interpolated_line[(i+1)*num_inter_points+k] = func.get_value(k/(1.*num_inter_points)); + + i+=2; + } + } + else + { + interp.resize(3); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + interp[2] = convexity1[2]; + INTER_FUNC func(PARABOLA,interp); + + Real x_edge = -0.5; + bool start = false, stop = false; + for (int j = 0; j < 4; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value(-0.5+(j*num_inter_points+k)/(2.*num_inter_points)); + if (value > 0. && func.get_derivative(-0.5+(j*num_inter_points+k)/(2.*num_inter_points)) > 0.) + { + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = value; + if (!start && value > tolerance) + { + stop=true; + break; + } + start=true; + } + else + { + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = 0.; + x_edge = -0.5+(j*num_inter_points+k)/(2.*num_inter_points); + } + } + if (stop) + break; + } + if (!stop) + { + i+=3; // IGO + } + else // Use square root interpolation + { + interp.resize(2); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line,i,k) > getRelativeElement(original_line,i,k+1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i+j < size) + interpolated_line[(i-1+j)*num_inter_points+k] = value; + } + } + interp[0] = convexity[0]; + interp[1] = convexity[1]; + func = INTER_FUNC(LINEAR,interp); + for (int k = 0; k < num_inter_points; k++) + if (i+2 < size) + interpolated_line[(i+1)*num_inter_points+k] = func.get_value(k/(1.*num_inter_points)); + i+=2; + + } + } + } + } + } + // ================================================================================================ + // ================================================================================================ + // From contact to non-contact + // ================================================================================================ + // ================================================================================================ + else if (original_line[i] == 0.) + { + convexity1[0] = getRelativeElement(original_line,i-1,0); + convexity1[1] = getRelativeElement(original_line,i-1,-1); + convexity1[2] = getRelativeElement(original_line,i-1,-2); + + convexity[0] = getRelativeElement(original_line,i-1,-1); + convexity[1] = getRelativeElement(original_line,i-1,-2); + convexity[2] = getRelativeElement(original_line,i-1,-3); + + bool concave_1 = if_concave(convexity1), + concave_2 = if_concave(convexity); + + if (convexity1[0]*convexity1[1]*convexity1[2]*convexity[2] == 0.) + { + if (convexity1[1] == 0.) + { + Real a = num_inter_points/2., + p0 = convexity1[0]/a; + + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + Real x = (i-1+j)*num_inter_points+k; + if (a*a > (x-i*num_inter_points)*(x-i*num_inter_points)) + { + value = p0*sqrt(a*a - (x-i*num_inter_points)*(x-i*num_inter_points)); + if (i-j-2 >= 0) + interpolated_line[(i-1-j)*num_inter_points-k] = value; + } + else + { + if (i-j-2 >= 0) + interpolated_line[(i-1-j)*num_inter_points-k] = 0.; + } + } + } +// i+=2; + i++; + continue; + } + } + else + { + if (convexity1[2] < convexity1[1] && convexity1[1] > convexity1[0]) + { + interp.resize(2); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + INTER_FUNC func(SQ_ROOT,interp,0.5); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-1 >= 0) + interpolated_line[(i-j)*num_inter_points-k] = value; + } + } + + //i+=2; + i++; + } + else if (concave_2) // It's concave for sure, so we use square root interpolation. + { + interp.resize(2); + interp[0] = convexity[0]; + interp[1] = convexity[1]; + + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line, i, -k) > getRelativeElement(original_line, i, -k-1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + for (int k = 0; k < num_inter_points; k++) + if (i-1 >= 0) + interpolated_line[(i)*num_inter_points-k] = 0.; + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-2 >= 0) + interpolated_line[(i-1-j)*num_inter_points-k] = value; + } + } + +// i+=2; + i++; + } + else + { + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-1 >= 0) + interpolated_line[(i-j)*num_inter_points-k] = value; + } + } + interp[0] = convexity[0]; + interp[1] = convexity[1]; + func = INTER_FUNC(LINEAR,interp); + for (int k = 0; k < num_inter_points; k++) + if (i-3 >= 0) + interpolated_line[(i-2)*num_inter_points-k] = func.get_value(k/(1.*num_inter_points)); + +// i+=2; + i++; + } + } + else + { + if (concave_1 || !parabola) //func.get_value(-0.5) > 0.) + { + interp.resize(2); + interp[0] = convexity[0]; + interp[1] = convexity[1]; + Real a = 0; // contact radius + for (int k = 0; k < size; k++) + if ( getRelativeElement(original_line, i, -k) > getRelativeElement(original_line, i, -k-1) ) + { + a = Real(k+1); + break; + } + + INTER_FUNC func(SQ_ROOT,interp,a); + if (!(func.get_value(0.) > 0 || interp[1] < interp[0])) + { + for (int k = 0; k < num_inter_points; k++) + if (i >= 0) + interpolated_line[(i+1)*num_inter_points-k] = 0.; + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-2 >= 0) + interpolated_line[(i-1-j)*num_inter_points-k] = value; + } + } + +// i+=2; + i++; + } + else + { + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + + INTER_FUNC func(SQ_ROOT,interp,a); + for (int j = 0; j < 2; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value((j*num_inter_points+k)/(2.*num_inter_points)); + if (i-j-1 >= 0) + interpolated_line[(i-j)*num_inter_points-k] = value; + } + } + interp[0] = convexity[0]; + interp[1] = convexity[1]; + func = INTER_FUNC(LINEAR,interp); + for (int k = 0; k < num_inter_points; k++) + if (i-3 >= 0) + interpolated_line[(i-2)*num_inter_points-k] = func.get_value(k/(1.*num_inter_points)); + +// i+=2; + i++; + } + } + else + { + interp.resize(3); + interp[0] = convexity1[0]; + interp[1] = convexity1[1]; + interp[2] = convexity1[2]; + INTER_FUNC func(PARABOLA,interp); + + Real x_edge = -0.5; + for (int j = 0; j < 4; j++) + { + for (int k = 0; k < num_inter_points; k++) + { + value = func.get_value(-0.5+(j*num_inter_points+k)/(2.*num_inter_points)); + if (value > 0.) + { + if (i-j-1 >= 0) + interpolated_line[(i-j)*num_inter_points-k] = value; + } + else + { + if (i-j-1 >= 0) + interpolated_line[(i-j)*num_inter_points-k] = 0.; + x_edge = -0.5+(j*num_inter_points+k)/(2.*num_inter_points); //IGO + } + } + } + } + } + } + } + else + { + interp.resize(2); + interp[0] = original_line[i-1]; + interp[1] = original_line[i]; + INTER_FUNC f(LINEAR,interp); + for (int k = 0; k < num_inter_points; k++) + { + interpolated_line[(i-1)*num_inter_points+k] = f.get_value(k/Real(num_inter_points)); + } + } + i++; + // ================================================================================================ + // ================================================================================================ + // ================================================================================================ + // ================================================================================================ + } + } + while (i < size); + + + result[iline] = interpolated_line; + } + + cout << endl; + return result; + +} + +/* -------------------------------------------------------------------------- */ + +bool Interpolator::if_concave(vector& points) +{ + if (points.size() != 3) + { + std::cout << std::endl << "ERROR : needs exactly 3 points to function " << std::endl; + exit(1); + } + + Real y0 = points[0], y1 = points[1], y2 = points[2]; + if ((y2-y1) < (y1-y0)) + return true; + else + return false; +} + +/* -------------------------------------------------------------------------- */ + +bool Interpolator::if_concave(vector& points, int start) +{ + vector p(3); + for (int i = 0; i < 3; i++) + p[i] = getRelativeElement(points,start,i); + + if ( (p[2]-p[1]) < (p[1]-p[0]) ) + return true; + else + return false; +} + +/* -------------------------------------------------------------------------- */ + +Real Interpolator::find_dist_to_max(bool forward, vector& points, int start) +{ + if (forward) + { + for (unsigned int i = 0; i < points.size(); i++) + if ( getRelativeElement(points, start, i) > getRelativeElement(points, start, i+1) ) + return Real(i+1); + } + else + { + for (unsigned int i = 0; i < points.size(); i++) + if ( getRelativeElement(points, start, -i) > getRelativeElement(points, start, -i-1) ) + return Real(i+1); + } + + return 0; +} diff --git a/src/interpolator.hh b/src/interpolator.hh new file mode 100644 index 0000000..67261b4 --- /dev/null +++ b/src/interpolator.hh @@ -0,0 +1,62 @@ +#ifndef INTERPOLATOR_H +#define INTERPOLATOR_H +/* -------------------------------------------------------------------------- */ +#include "surface.hh" +#include +#include +#include +#include +#include +#include "function.hh" +/* -------------------------------------------------------------------------- */ +using namespace std; +/* -------------------------------------------------------------------------- */ + +enum INTERPOLATION_TYPE { BY_PROFILE, BY_PROFILE_II, VOLUMETRIC }; + +class Interpolator { + +public: + Interpolator() { std::cout << "ERROR: Should not be here" << std::endl; exit(0); } + Interpolator(INTERPOLATION_TYPE it, int n, Real tol) {itype = it; num_inter_points = n; tolerance = tol;} + ~Interpolator() {} + + //! Interpolate by patch + void make_by_patch(Surface& original, int ix, int iy, int patch_size, int margin, bool parabola, Real max_value, vector >& pdfs, + Real& area, Real& perimeter, Real& pressure, vector >& interpolated_surface, string fname=""); + //! Interpolate by patch, version 2 + void make_by_patch2(Surface& original, int ix, int iy, int patch_size, int margin, bool parabola, Real max_value, vector >& pdfs, + Real& area, Real& perimeter, Real& pressure, vector >& interpolated_surface, string fname=""); + //! Interpolate profile by profile + void make_by_profile(Surface original, int iline, bool parabola, bool vertical, Real max_value, vector >& pdfs, + Real& area, Real& perimeter, Real& pressure, string fname=""); + //! Interpolate all profiles + vector > make_by_profile( Surface original, bool parabola, bool vertical=false ); + //! Get shifted element for line + Real getRelativeElement(const vector& line, int act_pos, int shift ); + //! Get shifted element for surface + Real getRelativeElement(Surface& surface, int act_pos_x, int act_pos_y, int shift_x, int shift_y); + //! Check convexity/concavity + bool if_concave( vector& points ); + bool if_concave( vector& points, int start ); + //! Find the distance to the closest local maximum + Real find_dist_to_max(bool forward, vector& points, int start); + //! assigning of elements + void assign_value(vector >& surf, int i, int j, Real value); + void assign_value(vector& vec, int i, Real value); + void assign_value(vector& vec, int i, Real value); + //! Interpolates locally along a profile, return increment to go to the next interpolation point + int interpolate(bool forward, bool horizontal, vector >& interpolated_surface, int ix, int iy, + vector& original_points, INTER_FUNCTION_TYPE type, vector& deja_interpolated, vector& slope, Real radius=0., +//o tmp +Real val=0., int steps=1); +//x tmp + +protected: + INTERPOLATION_TYPE itype; + int num_inter_points; + Real tolerance; + +}; + +#endif diff --git a/src/map_2d.cpp b/src/map_2d.cpp new file mode 100644 index 0000000..fcfe75c --- /dev/null +++ b/src/map_2d.cpp @@ -0,0 +1,195 @@ +#include "map_2d.hh" +#include +#include +#include +/* -------------------------------------------------------------------------- */ +#define TIMER +#include "surface_timer.hh" +/* -------------------------------------------------------------------------- */ + + +template +void Map2d::rescaleHeights(Real C){ + /* compute actual RMS */ + for (UInt i = 0 ; i < n[0] ; ++i) + for (UInt j = 0 ; j < n[1] ; ++j){ + this->at(i,j) *= C; + } +} + + +/* -------------------------------------------------------------------------- */ + +template +void Map2d::setGridSize(UInt n0, UInt n1){ + n[0] = n0; + n[1] = n1; + data.resize(n[0]*n[1]); + data.assign(n[0]*n[1],T(0.)); +} + +/* -------------------------------------------------------------------------- */ + +template +void Map2d::setGridSize(const UInt n[2]){ + setGridSize(n[0],n[1]); +} + +/* -------------------------------------------------------------------------- */ + +template +void Map2d::operator=(const T & e){ + + for (UInt i = 0 ; i < n[0]*n[1] ; ++i){ + this->at(i) = e; + } +} +/* -------------------------------------------------------------------------- */ + +template +Map2d::Map2d(UInt n0, UInt n1, Real L0, Real L1) { + setGridSize(n0,n1); + this->L[0] = L0; + this->L[1] = L1; +} +/* -------------------------------------------------------------------------- */ +template +Map2d::Map2d(const UInt * n, const Real *L) { + setGridSize(n[0],n[1]); + this->L[0] = L[0]; + this->L[1] = L[1]; +} + +/* -------------------------------------------------------------------------- */ + +template +Map2d::~Map2d() { +} + +/* -------------------------------------------------------------------------- */ + +template +void Map2d::FFTTransform(int nthreads){ + SURFACE_FATAL("impossible situation"); + throw; +} + +/* -------------------------------------------------------------------------- */ + + +template +void Map2d::FFTTransform(Map2d > & output, int nthreads){ + output = *this; + output.FFTTransform(nthreads); +} + +/* -------------------------------------------------------------------------- */ + +template +void Map2d::FFTITransform(Map2d > & output, int nthreads){ + output = *this; + output.FFTITransform(nthreads); +} +/* -------------------------------------------------------------------------- */ +template +void Map2d::FFTITransform(Map2d & output, int nthreads){ + const UInt * n = this->sizes(); + const Real * Ls = this->getLs(); + Map2d > _output(n,Ls); + _output = *this; + _output.FFTITransform(nthreads); + for (UInt i = 0; i < n[0]*n[1]; i++) { + output(i) = _output(i).real(); + } +} +/* -------------------------------------------------------------------------- */ + + +template <> +void Map2d::FFTTransform(int nthreads){ + + STARTTIMER("initFFTW"); + fftw_init_threads(); + fftw_plan_with_nthreads(nthreads); + + fftw_complex * in = (fftw_complex*)&data[0]; + fftw_plan p = fftw_plan_dft_2d(n[0],n[1], in,in,FFTW_FORWARD, FFTW_ESTIMATE); + STOPTIMER("initFFTW"); + STARTTIMER("FFTW"); + fftw_execute(p); + STOPTIMER("FFTW"); + STARTTIMER("closeFFTW"); + fftw_destroy_plan(p); + fftw_cleanup_threads(); + STOPTIMER("closeFFTW"); +} + + +/* -------------------------------------------------------------------------- */ + +template +void Map2d::FFTITransform(int nthreads){ + SURFACE_FATAL("impossible situation"); + throw; +} + +/* -------------------------------------------------------------------------- */ + + +template <> +void Map2d::FFTITransform(int nthreads){ + + for (UInt i = 0; i < n[0]*n[1]; ++i) { + data[i] = std::conj(data[i]); + } + FFTTransform(nthreads); + for (UInt i = 0; i < n[0]*n[1]; ++i) { + data[i] = std::conj(data[i]); + data[i] *= 1./(n[0]*n[1]); + } +} +/* -------------------------------------------------------------------------- */ + +template +void Map2d::dumpToTextFile(std::string filename) { + + UInt n1 = this->size(0); + UInt n2 = this->size(1); + std::cout << "Writing surface file " << filename << std::endl; + std::ofstream file(filename.c_str()); + if (!file.is_open()) SURFACE_FATAL("cannot open file " << filename); + + file.precision(15); + for (UInt i = 0; i < n1; i++) { + for (UInt j=0; j< n2; j++) { + file << i << " " << j << " "; + this->writeValue(file,this->at(i,j)); + file << std::endl; + } + file << std::endl; + } + file.close(); +} + +/* -------------------------------------------------------------------------- */ +template +void Map2d::writeValue(std::ostream & os, const T & val) { + os << val; +} + +/* -------------------------------------------------------------------------- */ +template <> +void Map2d::writeValue(std::ostream & os, const complex & val) { + + os << std::scientific << val.real(); + os << " " << val.imag(); +} + +/* -------------------------------------------------------------------------- */ + +template class Map2d; +template class Map2d; +template class Map2d; +template class Map2d; +template class Map2d; +template class Map2d; diff --git a/src/map_2d.hh b/src/map_2d.hh new file mode 100644 index 0000000..4560d25 --- /dev/null +++ b/src/map_2d.hh @@ -0,0 +1,427 @@ +#ifndef __MAP_2D_HH__ +#define __MAP_2D_HH__ +/* -------------------------------------------------------------------------- */ +#include +#include +#include "types.hh" +#include +#include "my_vector.hh" +/* -------------------------------------------------------------------------- */ + +template +class Map2d { + + + /* ------------------------------------------------------------------------ */ + /* Typedefs */ + /* ------------------------------------------------------------------------ */ + + // class iterator; + + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ +public: + + Map2d(UInt n1, UInt n2, Real L0 = 1., Real L1 = 1.); + Map2d(const UInt * n, const Real * L); + virtual ~Map2d(); + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ +public: + + template + std::vector > getNeighborIndexes(UInt i, UInt j); + template + std::vector > getNeighborIndexes(std::pair i); + + // //! return an iterator over the neighbors + // iterator beginNeighborhood(); + // //! return the end iterator over the neighbors + // iterator endNeighborhood(); + + //! perform fft transform + void FFTTransform(Map2d > & output,int nthreads = 1); + //! perform inverse fft transform + void FFTITransform(Map2d > & output, int nthreads = 1); + //! perform inverse fft transform + void FFTITransform(Map2d & output, int nthreads = 1); + //! perform fft transform + void FFTTransform(int nthreads = 1); + // //! inverse fft transform + void FFTITransform(int nthreads = 1); + //compute compute component by component product and put result in object + template + void fullProduct(Map2d & s1,Map2d &s2); + //! set the grid size + void setGridSize(const UInt n[2]); + //! set the grid size + void setGridSize(UInt n0,UInt n1); + //! rescale height profile + void rescaleHeights(Real factor); + //! Write heights array to text file usable with plot programs + void dumpToTextFile(std::string filename); + // set all the members of the map to a given value + void operator=(const T & e); + + template class surf, typename T2> + void operator=(const surf & s); + +/* -------------------------------------------------------------------------- */ + +private: + + //! write an entry to a stringstream + void writeValue(std::ostream & os, const T & val); + + /* ------------------------------------------------------------------------ */ + /* Accessors */ + /* ------------------------------------------------------------------------ */ + +public: + + // access to the i,j-th value in the surface + inline void operator+=(const Map2d & s); + // access to the i,j-th value in the surface + inline void operator+=(const T & val); + // access to the i,j-th value in the surface + inline void operator-=(const T & val); + // access to the i,j-th value in the surface + inline T & operator()(UInt i,UInt j); + // access to the i,j-th value in the surface + inline T & operator()(std::pair i); + // access to the i,j-th value in the surface + inline const T & operator()(UInt i,UInt j)const; + // access to the i,j-th value in the surface + inline const T & operator()(std::pair i)const; + // access to the i,j-th value in the surface + inline T & at(UInt i,UInt j); + // access to the i-th value in the array + inline T & at(UInt i); + // access to the i,j-th value in the surface + inline T & at(std::pair i); + // access to the i,j-th value in the surface + inline const T & at(UInt i,UInt j) const; + // access to the i,j-th value in the surface + inline const T & at(std::pair i) const; + // access to the i,j-th value in the surface + inline const T & at(UInt i) const; + // access to the i-th value in the array + inline T & operator()(int i); + // access to the i-th value in the array + // inline T & operator[](std::pair i); + // access to the i-th value in the array + inline const T & operator()(int i) const; + //! get lateral number of discretization points + inline UInt size(UInt dir)const {return n[dir];}; + //! get both lateral number of discretization points + inline const UInt* sizes()const {return n;}; + //! get the lateral size of the sample + inline const Real * getLs() const {return L;}; + //! get the lateral size of the sample + inline Real getL(UInt dir) const {return L[dir];}; + //! get the lateral size of the sample + inline void setL(Real L[2]){this->L[0] = L[0];this->L[1] = L[1];}; + //! get the lateral size of the sample + inline void setL(Real L0,Real L1){this->L[0] = L0;this->L[1] = L1;}; + + const T * getInternalData() const{return data.getPtr();}; + + //! Write heights array to text file usable with plot programs + template + void dumpToTextFile(std::string filename) const; + + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ + +protected: + + //! number of points in each direction + UInt n[2]; + //! size in each direction + Real L[2]; + //! internal storage of data + MyVector data; +}; + +/* -------------------------------------------------------------------------- */ +//#define _at(I,J,N) I+J*N[1] +#define _at(I,J,N) I*N[1]+J +/* -------------------------------------------------------------------------- */ +template +inline T & Map2d::at(UInt i,UInt j){ + + if (_at(i,j,n) >= n[0]*n[1]) SURFACE_FATAL("out of bound access " + << i << " " << j << " " + << n[0] << " " << n[1] << " " + << _at(i,j,n)); + return data[_at(i,j,n)]; +} + +/* -------------------------------------------------------------------------- */ + +template +inline const T & Map2d::at(UInt i,UInt j)const { + + if (_at(i,j,n) >= n[0]*n[1]) SURFACE_FATAL("out of bound access " + << i << " " << j << " " + << n[0] << " " << n[1] << " " + << _at(i,j,n)); + return data[_at(i,j,n)]; +} +/* -------------------------------------------------------------------------- */ +#undef _at +/* -------------------------------------------------------------------------- */ + +template +inline T & Map2d::at(UInt i){ + return data[i]; +} + +/* -------------------------------------------------------------------------- */ +template +inline const T & Map2d::at(UInt i) const{ + return data[i]; +} + +/* -------------------------------------------------------------------------- */ + + +template +inline T & Map2d::operator()(UInt i,UInt j){ + return this->at(i,j); +} + +/* -------------------------------------------------------------------------- */ + +template +inline T & Map2d::at(std::pair i){ + return this->at(i.first,i.second); +} + +/* -------------------------------------------------------------------------- */ + +template +inline const T & Map2d::at(std::pair i)const { + return this->at(i.first,i.second); +} + +/* -------------------------------------------------------------------------- */ + +template +inline T & Map2d::operator()(std::pair i){ + return this->at(i.first,i.second); +} + +/* -------------------------------------------------------------------------- */ + +template +inline const T & Map2d::operator()(UInt i,UInt j)const{ + return this->at(i,j); +} + +/* -------------------------------------------------------------------------- */ + +template +inline const T & Map2d::operator()(std::pair i)const { + return this->at(i.first,i.second); +} + +/* -------------------------------------------------------------------------- */ + +template +inline T & Map2d::operator()(int i){ + return data[i]; +} + +/* -------------------------------------------------------------------------- */ + +template +inline const T & Map2d::operator()(int i) const{ + return data[i]; +} + +/* -------------------------------------------------------------------------- */ +// template +// inline T & Map2d::operator[](std::pair c){ +// return this->at(c.first,c.second); +// } + +// /* -------------------------------------------------------------------------- */ + +template +void Map2d::operator-=(const T & e){ + + for (UInt i = 0 ; i < n[0]*n[1] ; ++i){ + this->at(i) -= e; + } +} +/* -------------------------------------------------------------------------- */ +template +void Map2d::operator+=(const T & e){ + + for (UInt i = 0 ; i < n[0]*n[1] ; ++i){ + this->at(i) += e; + } +} + +/* -------------------------------------------------------------------------- */ +template +void Map2d::operator+=(const Map2d & s){ + + for (UInt i = 0 ; i < n[0]*n[1] ; ++i){ + this->at(i) += s.at(i); + } +} + +/* -------------------------------------------------------------------------- */ + + +template +template +std::vector > Map2d::getNeighborIndexes(UInt i, UInt j){ + + std::vector > vres; + + + std::pair res; + + for (int ii = -1; ii < 2; ++ii) { + res.first = ii+static_cast(i); + if (res.first < 0 && !periodic) continue; + if (res.first >= (int)n[0] && !periodic) continue; + if (res.first < 0 && periodic) res.first += n[0]; + if (res.first >= (int)n[0] && periodic) res.first -= n[0]; + + for (int jj = -1; jj < 2; ++jj) { + + res.second = jj+static_cast(j); + if (res.second < 0 && !periodic) continue; + if (res.second >= (int)n[1] && !periodic) continue; + if (res.second < 0 && periodic) res.second += n[1]; + if (res.second >= (int)n[1] && periodic) res.second -= n[1]; + + if (ii == 0 && jj == 0) continue; + + { + UInt i = res.first; + UInt j = res.second; + + if (i+j*n[0] >= n[0]*n[1]) SURFACE_FATAL("out of bound access " + << i << " " << j << " " + << n[0] << " " << n[1] << " " + << i+j*n[0]); + } + vres.push_back(res); + } + } + return vres; +} + +/* -------------------------------------------------------------------------- */ + +template +template +std::vector > Map2d +::getNeighborIndexes(std::pair i){ + return this->getNeighborIndexes(i.first,i.second); +} + +/* -------------------------------------------------------------------------- */ +template +template +void Map2d::fullProduct(Map2d & s1,Map2d & s2){ + + auto n1 = s1.sizes(); + auto n2 = s2.sizes(); + + if (n1[0] != n2[0] || + n1[1] != n2[1]) SURFACE_FATAL("fullproduct of non compatible matrices"); + + if (n[0] != n1[0] || + n[1] != n1[1]) SURFACE_FATAL("fullproduct of non compatible matrices") + + for (UInt i = 0 ; i < n[0] ; ++i) + for (UInt j = 0 ; j < n[1] ; ++j){ + this->at(i,j) = s1(i,j)* s2(i,j); + } +} +/* -------------------------------------------------------------------------- */ +template +template +void Map2d::dumpToTextFile(std::string filename) const { + + UInt m = this->n[0]; + UInt n = this->n[1]; + std::cout << "Writing surface file " << filename << std::endl; + std::ofstream file(filename.c_str()); + if (!file.is_open()) SURFACE_FATAL("cannot open file " << filename); + + file.precision(15); + for (UInt i = 0; i < m; i++) { + for (UInt j=0; j< n; j++) { + if (!consider_zeros && + std::norm(this->at(i,j)) < zero_threshold*zero_threshold) + continue; + + file << i << " " << j << " "; + file << std::scientific << this->at(i,j); + file << std::endl; + } + file << std::endl; + } + file.close(); +} + + +// template +// class Map2d::iterator { + +// public: + +// iterator(std::vector & data, +// std::queue > & indices): +// data(data),indices(indices){ +// } + +// inline void operator++(){ +// indices.pop(); +// } + +// inline T & operator *(){ +// return data[indices.front]; +// } + +// bool operator != (Map2d::iterator & it){ +// return (indices.front == it.indices.front); +// } + +// private: + +// std::vector & data; +// std::queue > indices; + +// bool finished; +// }; + + +/* -------------------------------------------------------------------------- */ + +template +template class surf, typename T2> +void Map2d::operator=(const surf & s){ + this->setGridSize(s.sizes()); + UInt m = this->sizes()[0]; + UInt n = this->sizes()[1]; + for (UInt i = 0; i < m*n; i++) { + this->at(i) = s(i); + } +} + +/* -------------------------------------------------------------------------- */ + + +#endif /* __MAP_2D_HH__ */ diff --git a/src/map_2d_square.cpp b/src/map_2d_square.cpp new file mode 100644 index 0000000..a95d1f7 --- /dev/null +++ b/src/map_2d_square.cpp @@ -0,0 +1,76 @@ +#include "map_2d_square.hh" +#include +/* -------------------------------------------------------------------------- */ + + +template +void Map2dSquare::loadFromTextFile(std::string filename, int each) { + + std::string line; + std::ifstream myfile (filename.c_str()); + 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; + UInt 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 + + n = int(n/Real(each)); + setGridSize(n); + + while (! myfile.eof() ) { + getline (myfile,line); + if (line == "") continue; + std::stringstream s; + s << line; + int i,j; + s >> i; + s >> j; + T val = this->readValue(s); + if (i % each == 0 && j % each == 0) { + this->at(i/each,j/each) = val; + } + } + myfile.close(); + } +} + +/* -------------------------------------------------------------------------- */ +template +T Map2dSquare::readValue(std::stringstream & sstr) { + SURFACE_FATAL("To implement"); +} + +/* -------------------------------------------------------------------------- */ +template <> +complex Map2dSquare::readValue(std::stringstream & sstr) { + + Real h = 0.,hIm = 0.; + sstr >> h; + sstr >> hIm; + return complex(h,hIm); +} + +/* -------------------------------------------------------------------------- */ + + +template class Map2dSquare; +template class Map2dSquare; +template class Map2dSquare; +template class Map2dSquare; diff --git a/src/map_2d_square.hh b/src/map_2d_square.hh new file mode 100644 index 0000000..707ea4c --- /dev/null +++ b/src/map_2d_square.hh @@ -0,0 +1,53 @@ +#ifndef __MAP_2D_SQUARE_HH__ +#define __MAP_2D_SQUARE_HH__ +/* -------------------------------------------------------------------------- */ +#include "map_2d.hh" +/* -------------------------------------------------------------------------- */ + +template +class Map2dSquare : public Map2d { + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ +public: + + Map2dSquare(UInt n, Real L = 1.): Map2d(n,n,L,L){}; + virtual ~Map2dSquare(){}; + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ +public: + + //! get lateral number of discretization points + inline UInt size() const{return Map2d::size(0);}; + //! load all n-th point of heights array from text file usable with plot programs + void loadFromTextFile(std::string filename, int each=1); + + //! set the grid size + void setGridSize(UInt n){Map2d::setGridSize(n,n);}; + + +private: + //! read an entry from a stringstream + T readValue(std::stringstream & sstr); + + /* ------------------------------------------------------------------------ */ + /* Accessors */ + /* ------------------------------------------------------------------------ */ +public: + + //! get the lateral size of the sample + inline Real getL()const {return Map2d::getL(0);}; + //! get the lateral size of the sample + inline void setL(Real L){Map2d::setL(L,L);}; + + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ +private: + +}; + + +#endif /* __MAP_2D_SQUARE_HH__ */ diff --git a/src/my_vector.hh b/src/my_vector.hh new file mode 100644 index 0000000..b9919fa --- /dev/null +++ b/src/my_vector.hh @@ -0,0 +1,107 @@ +#ifndef MY_VECTOR_H +#define MY_VECTOR_H +/* -------------------------------------------------------------------------- */ +#include + +/* -------------------------------------------------------------------------- */ + +template +class MyVector { + + +public: + + + + MyVector(const MyVector & v){ + this->_data = NULL; + this->_size = 0; + this->wrapped = false; + this->resize(v._size); + memcpy(this->_data,v.getPtr(),this->_size*sizeof(T)); + } + + MyVector & operator=(const MyVector & v){ + this->wrapped = false; + if (v.size() != this->size()) this->resize(v.size()); + memcpy(this->_data,v.getPtr(),this->_size*sizeof(T)); + return *this; + } + + MyVector(){ + this->_data = NULL; + this->_size = 0; + this->wrapped = false; + } + + MyVector(UInt size){ + this->_size = 0; + this->resize(size); + this->wrapped = false; + } + + MyVector(T * data, UInt size){ + this->wrapped = false; + this->size = 0; + this->wrapMemory(data,size); + } + + void wrapMemory(T * data, UInt size){ + this->_data = data; + this->_size = size; + this->wrapped = true; + } + + ~MyVector(){ + if (wrapped == false && _data != NULL){ + delete [] _data; + } + } + + void assign(UInt size, const T & value){ + this->resize(size); + for (UInt i = 0; i < size; i++) { + _data[i] = value; + } + } + + const T * getPtr() const{ return _data; } + T * getPtr() { return _data; } + + void resize(UInt size){ + if (size == 0 && wrapped == false) { + if (_data != NULL) { + delete [] this->_data; + this->_data = NULL; + } + this->_size = 0; + return; + } + if (size == this->_size) return; + if (wrapped == true) SURFACE_FATAL("cannot resize wrapped surface"); + if (_data != NULL) delete [] _data; + this->_data = new T[size]; + this->_size = size; + } + + T & operator[](UInt i){ + if (i >= _size) SURFACE_FATAL("overflow"); + return _data[i]; + } + + const T & operator[](UInt i)const{ + return _data[i]; + } + + UInt size() const{return _size;} + + private: + + T * _data; + UInt _size; + + bool wrapped; +}; + +/* -------------------------------------------------------------------------- */ +#endif /* MY_VECTOR_H */ diff --git a/src/parser.hh b/src/parser.hh new file mode 100644 index 0000000..90f04b8 --- /dev/null +++ b/src/parser.hh @@ -0,0 +1,402 @@ +#include +#include +/* -------------------------------------------------------------------------- */ + +template +class default_val{ + +public: + + default_val(){ + is_set = false; + }; + + default_val(const T & v){ + is_set = true; + val = v; + }; + + bool is_set; + T val; +}; + +template <> +class default_val{ + +public: + + default_val(){ + is_set = true; + val = false; + }; + + default_val(const bool & v){ + is_set = true; + val = v; + }; + + bool is_set; + bool val; +}; + +/* -------------------------------------------------------------------------- */ +template class TypedParameter; +/* -------------------------------------------------------------------------- */ + +class Parameter { + +public: + + Parameter(const std::string & name){ + this->name = name; + } + + virtual ~Parameter(){}; + + void setHelp(const std::string & help){ + this->help = help; + } + + std::string getHelp(){ + return this->help; + } + + virtual std::string getStringDefault() = 0; + + + virtual void parse(std::stringstream & sstr)=0; + + template + operator T(){ + try { + return dynamic_cast &>(*this); + } + catch (...) { + SURFACE_FATAL("bad cast on parameter " << this->name); + } + }; + + virtual operator std::string() = 0; + + std::string name; + std::string help; + +}; + +/* -------------------------------------------------------------------------- */ + +template +class TypedParameterInterface : public Parameter{ + +public: + + TypedParameterInterface(const std::string & name, const default_val & def): + Parameter(name){ + is_set = false; + this->def = def; + }; + + virtual void parse(std::stringstream & sstr){ + sstr >> this->val; + if (sstr.fail()) SURFACE_FATAL("could not parse " << this->name); + std::cerr << this->name << " = " << this->val << std::endl; + this->is_set = true; + }; + + operator std::string(){ + std::stringstream sstr; + T tmp = *this; + sstr << tmp; + return sstr.str(); + }; + + operator T(){ + if (is_set) return val; + if (def.is_set) return def.val; + else SURFACE_FATAL("option '" << name << "' has no default: must be set"); + }; + + virtual std::string getStringDefault(){ + std::stringstream sstr; + if (def.is_set) sstr << def.val; + return sstr.str(); + } + +protected: + + T val; + default_val def; + bool is_set; +}; + +/* -------------------------------------------------------------------------- */ + +template <> +class TypedParameterInterface : public Parameter{ + +public: + + TypedParameterInterface(const std::string & name, const default_val & def): + Parameter(name){ + is_set = false; + this->def = def; + }; + + virtual void parse(std::stringstream & sstr){ + sstr >> this->val; + std::cerr << this->name << " = " << this->val << std::endl; + this->is_set = true; + }; + + operator std::string(){ + if (is_set) return val; + if (def.is_set) return def.val; + else SURFACE_FATAL("option '" << name << "' has no default: must be set"); + }; + + virtual std::string getStringDefault(){ + std::stringstream sstr; + if (def.is_set) sstr << def.val; + return sstr.str(); + } + +protected: + + std::string val; + default_val def; + bool is_set; +}; + + +/* -------------------------------------------------------------------------- */ + + + +template +class TypedParameter : public TypedParameterInterface{ + +public: + + TypedParameter(const std::string & name, const default_val & def): + TypedParameterInterface(name,def){}; + +}; + +/* -------------------------------------------------------------------------- */ + +template <> +class TypedParameter : public TypedParameterInterface{ + +public: + + TypedParameter(const std::string & name, const default_val & def): + TypedParameterInterface(name,def){ + + }; + + + virtual void parse(std::stringstream & sstr){ + if (sstr.eof()) return; + + std::string str_cpy = sstr.str().substr(sstr.tellg()); + std::stringstream sstr_cpy(str_cpy); + + std::string mot; + sstr_cpy >> mot; + if (mot == "False" || mot == "false") + val = false; + else if (mot == "True" || mot == "true") + val = true; + else { + if (! def.is_set) SURFACE_FATAL("default must be provided for unregistered option " << name); + val = def.val; + if (val == true) val = false; + else val = true; + } + std::cerr << this->name << " = " << val << std::endl; + is_set = true; + }; + + operator std::string(){ + if (val) return "true"; + else return "false"; + }; + + virtual std::string getStringDefault(){ + std::stringstream sstr; + if (def.is_set) { + if (def.val) sstr << "true"; + else sstr << "false"; + } + return sstr.str(); + } + + +}; + +/* -------------------------------------------------------------------------- */ + + + +class Parser { + + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ +public: + + Parser(){ + this->addParameter("help","Get Usage information",false); + }; + virtual ~Parser(){ + for (auto p: this->parameters) delete p.second; + }; + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ +public: + + template + void addParameter(const std::string & name, + const std::string & help, + const default_val def = default_val()); + + + template + void addParameter(const std::string & name, + const std::string & help,const T & def); + + + + std::string usage(); + void parse(int argc,char ** argv); + void parse(const std::string & line); + + std::string makeFilename(const std::string & prefix = "", + const std::string & extension = "txt"); + + Parameter & get(const std::string & name){ + if (parameters.count(name) == 0) + SURFACE_FATAL("unregistered option " << name); + return *parameters[name]; + }; + + /* ------------------------------------------------------------------------ */ + /* Accessors */ + /* ------------------------------------------------------------------------ */ +public: + + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ +private: + + std::map parameters; + std::string prog_name; +}; + +/* -------------------------------------------------------------------------- */ + +template +void Parser::addParameter(const std::string & name, const std::string & help, + const default_val def){ + + TypedParameter * p = new TypedParameter(name,def); + p->setHelp(help); + this->parameters[name] = p; +} +/* -------------------------------------------------------------------------- */ + +template +void Parser::addParameter(const std::string & name, const std::string & help, + const T & def){ + + TypedParameter * p = new TypedParameter(name,default_val(def)); + p->setHelp(help); + this->parameters[name] = p; +} +/* -------------------------------------------------------------------------- */ + +void Parser::parse(int argc, char ** argv){ + std::string line; + this->prog_name = argv[0]; + for (int i = 1; i < argc; ++i) { + line += argv[i]; + if (i+1 != argc) line += " "; + } + this->parse(line); +} + +/* -------------------------------------------------------------------------- */ +void Parser::parse(const std::string & line){ + std::stringstream sstr(line); + + while (sstr.good()){ + std::string word; + sstr >> word; + + + if (word.find("--") == 0){ + std::string option = word.substr(2); + if (parameters.count(option) == 0){ + SURFACE_FATAL("'" << option << "' is not a valid option" << std::endl + << this->usage()); + } + if (option == "help") + SURFACE_FATAL("\n\n\n" + this->usage()); + + parameters[option]->parse(sstr); + } + } +} + + +/* -------------------------------------------------------------------------- */ +std::string Parser::makeFilename(const std::string & prefix, + const std::string & extension){ + + std::stringstream sstr; + if (prefix != "") sstr << prefix; + else sstr << "general"; + + std::map::iterator it = parameters.begin(); + std::map::iterator end = parameters.end(); + + while (it != end){ + std::string name = it->first; + std::string val = *(it->second); + if (name != "help") + sstr << "-" << name << "-" << val; + ++it; + } + sstr << "." << extension; + return sstr.str(); +} + + +/* -------------------------------------------------------------------------- */ + +std::string Parser::usage(){ + std::map::iterator it = parameters.begin(); + std::map::iterator end = parameters.end(); + + std::stringstream sstr; + sstr << "Usage: " << this->prog_name << " --option1 val1 ... --optionN valN ..." + << std::endl << std::endl << "Options:" << std::endl; + while (it != end){ + std::string name = it->first; + std::string help = it->second->getHelp(); + sstr << "\t" << "--" << std::left << std::setw(30) << name; + std::string def = it->second->getStringDefault(); + if (def != "") { + std::string def_str = "(default '" + def + "')"; + sstr << std::setw(20) << def_str; + } + else sstr << std::setw(20) << ""; + sstr << " " << help << std::endl; + ++it; + } + return sstr.str(); +} + diff --git a/src/surface.cpp b/src/surface.cpp new file mode 100644 index 0000000..d938115 --- /dev/null +++ b/src/surface.cpp @@ -0,0 +1,415 @@ +/* -------------------------------------------------------------------------- */ +#include +#include +#include +#include +#include +#include +/* -------------------------------------------------------------------------- */ +#include "surface.hh" +#include "surface_statistics.hh" +/* -------------------------------------------------------------------------- */ +#ifdef USING_IOHELPER +#include "dumper_paraview.hh" +#endif +/* -------------------------------------------------------------------------- */ +std::string fname = "surface_height.pdf"; +/* -------------------------------------------------------------------------- */ + + + +template +void Surface::expandByLinearInterpolation() { + UInt n = this->size(); + Surface * old_s = new Surface(n,1.); + int new_n = n*2; + *old_s = *this; + this->setGridSize(new_n); + for (UInt i=0; i +void Surface::expandByShannonInterpolation(int factor) { + + this->FFTTransform(); + 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->at(i,j); + } + + for (UInt i = n/2; i < n; ++i) + for (UInt j = 0; j < n/2; ++j) { + s(N-n+i,j) = this->at(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->at(i,j); + } + + for (UInt i = 0; i < n/2; ++i) + for (UInt j = n/2; j < n; ++j) { + s(i,N-n+j) = this->at(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->at(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; iat(2*i,j*2) = s(i,j); + +// // do shannon interpolation +// int rcut = 64; + +// //interpolate lines +// 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 n) i1 = new_n - i1; + UInt j1 = j; + if (j1 > n) j1 = new_n - j1; + if (i == n || j == n) { + this->at(i,j) = 0.; + continue; + } + this->at(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->at(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->at(i,j) = s(i,j); + } + } +} +/* -------------------------------------------------------------------------- */ + +template +void Surface::contractByIgnoringMidPoints() { + UInt n = this->size(); + Surface s(*this); + this->setGridSize(n/2); + + for (UInt i=0; iat(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 = NULL; + // 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 +Surface::Surface(UInt a, Real L) : Map2dSquare(a,L){ + this->setGridSize(a); +} + +/* -------------------------------------------------------------------------- */ +template +Surface::~Surface(){ +} + +/* -------------------------------------------------------------------------- */ + +// void Surface::copy(Surface & s){ +// this->n = s.n; +// this->L = s.L; +// this->heights = s.heights; +// } + +/* -------------------------------------------------------------------------- */ +template +void Surface::recenterHeights(){ + UInt n = this->size(); + Real zmean = SurfaceStatistics::computeAverage(*this); + + for (UInt i = 0 ; i < n*n ; ++i) + this->at(i) = this->at(i) - zmean; +} + +/* -------------------------------------------------------------------------- */ +template +void Surface::generateWhiteNoiseSurface(Surface & sources, long random_seed){ + + //set the random gaussian generator + std::mt19937 gen(random_seed); + std::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; +template class Surface; diff --git a/src/surface.hh b/src/surface.hh new file mode 100644 index 0000000..c4b6cd2 --- /dev/null +++ b/src/surface.hh @@ -0,0 +1,61 @@ +/* -------------------------------------------------------------------------- */ +#ifndef __SURFACE_HH__ +#define __SURFACE_HH__ +/* -------------------------------------------------------------------------- */ +#include +#include +#include +#include +#include +/* -------------------------------------------------------------------------- */ +#include "map_2d_square.hh" +/* -------------------------------------------------------------------------- */ + +template +class Surface : public Map2dSquare { + + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ + + public: + + Surface(UInt a, Real L); + ~Surface(); + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ + + //! 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 + using Map2d::operator=; + + + static void generateWhiteNoiseSurface(Surface & surface, long random_seed); + +}; + +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +#include "surface_complex.hh" +/* -------------------------------------------------------------------------- */ + + +#endif /* __SURFACE_HH__ */ diff --git a/src/surface_complex.hh b/src/surface_complex.hh new file mode 100644 index 0000000..7ba48ab --- /dev/null +++ b/src/surface_complex.hh @@ -0,0 +1,132 @@ +#ifndef SURFACE_COMPLEX_H +#define SURFACE_COMPLEX_H +/* -------------------------------------------------------------------------- */ + +template +class SurfaceComplex : public Map2dSquare > { + +public: + + SurfaceComplex(UInt a, Real L):Map2dSquare >(a,L){} + SurfaceComplex(Surface & s); + + SurfaceComplex & operator=(const Surface & s); + SurfaceComplex & operator=(const SurfaceComplex & s); + + //! make a surface real by taking norm as real part and imaginary 0 + void makeItRealBySquare(); + //! make it real by summing the imaginary and real parts + void makeItRealBySum(); + //! make a surface real by taking norm as real part and imaginary 0 + void makeItRealByAbs(); + //! get real part + Surface real() const; + //! get imaginary part + Surface imag() const; + + // set all the members of the map to a given value + using Map2d >::operator=; + +}; + +/* -------------------------------------------------------------------------- */ + +template +SurfaceComplex & SurfaceComplex::operator=(const Surface & s){ + this->setGridSize(s.size()); + UInt size = s.size()*s.size(); + for (UInt i = 0; i < size; i++) { + this->at(i) = s(i); + } + return *this; +} +/* -------------------------------------------------------------------------- */ + +template +SurfaceComplex & SurfaceComplex::operator=(const SurfaceComplex & s){ + this->setGridSize(s.size()); + UInt size = s.size()*s.size(); + for (UInt i = 0; i < size; i++) { + this->at(i) = s(i); + } + return *this; +} + + +/* -------------------------------------------------------------------------- */ + + +template +Surface SurfaceComplex::real()const{ + Surface res(this->size(),this->getL()); + UInt n = this->size(); + for (UInt i = 0 ; i < n ; ++i) + for (UInt j = 0 ; j < n ; ++j){ + res(i,j) = this->at(i,j).real(); + } + return res; +} +/* -------------------------------------------------------------------------- */ + + +template +Surface SurfaceComplex::imag()const{ + Surface res(this->size(),this->getL()); + UInt n = this->size(); + for (UInt i = 0 ; i < n ; ++i) + for (UInt j = 0 ; j < n ; ++j){ + res(i,j) = this->at(i,j).imag(); + } + return res; +} + +/* -------------------------------------------------------------------------- */ +template +void SurfaceComplex::makeItRealBySquare(){ + UInt n = this->size(); + for (UInt i = 0 ; i < n ; ++i) + for (UInt j = 0 ; j < n ; ++j){ + Real norm = std::norm(this->at(i,j)); + this->at(i,j) = norm; + } +} + + +/* -------------------------------------------------------------------------- */ +template +void SurfaceComplex::makeItRealByAbs(){ + UInt n = this->size(); + for (UInt i = 0 ; i < n ; ++i) + for (UInt j = 0 ; j < n ; ++j){ + Real abs = std::abs(this->at(i,j)); + this->at(i,j) = abs; + } +} + +/* -------------------------------------------------------------------------- */ +template +void SurfaceComplex::makeItRealBySum(){ + UInt n = this->size(); + for (UInt i = 0 ; i < n*n ; ++i){ + this->at(i) = this->at(i).real() + this->at(i).imag(); + } +} + +/* -------------------------------------------------------------------------- */ +template +SurfaceComplex::SurfaceComplex(Surface & surface): + Map2dSquare >(surface.size(),surface.getL()){ + UInt n = this->size(); + + for (UInt i = 0; i < n*n; i++) { + this->at(i) = surface(i); + } + +} + +/* -------------------------------------------------------------------------- */ + + + + +#endif /* SURFACE_COMPLEX_H */ diff --git a/src/surface_generator.cpp b/src/surface_generator.cpp new file mode 100644 index 0000000..10c79c0 --- /dev/null +++ b/src/surface_generator.cpp @@ -0,0 +1,107 @@ +/* -------------------------------------------------------------------------- */ +#include +#include +#include +/* -------------------------------------------------------------------------- */ +#include "surface_generator.hh" +#include "surface_generator_voss.hh" +#include "surface_generator_filter.hh" +#include "surface_generator_filter_bessel.hh" +#include "surface_generator_filter_fft.hh" +#include "surface_generator_crenel.hh" +#include "surface_generator_ellipsoid.hh" +#include "surface_statistics.hh" +/* -------------------------------------------------------------------------- */ +using namespace std; +/* -------------------------------------------------------------------------- */ +/* Sort functions */ +int sortAscend(const void * a, const void * b) { + return ( *(int*)a - *(int*)b ); +} +/* -------------------------------------------------------------------------- */ + + +int sortDescend(const void * a, const void * b) { + return ( *(int*)b - *(int*)a ); +} +/* -------------------------------------------------------------------------- */ +/* Check if a number is a power of two */ +int isPowerOfTwo (unsigned int x) +{ + return ((x != 0) && ((x & (~x + 1)) == x)); +} + +/* -------------------------------------------------------------------------- */ + + +SurfaceGenerator::SurfaceGenerator(const string & inputfile): surface(NULL) { + configfile = inputfile; + +} + +/* -------------------------------------------------------------------------- */ + +SurfaceGenerator::SurfaceGenerator(): + rms(0.), random_seed(0),configfile(""),surface(NULL),gridsize(0) { +} + +/* -------------------------------------------------------------------------- */ + +void SurfaceGenerator::Init() { + + if (configfile != ""){ + + ifstream fp(configfile.c_str()); + //double layerthickness; + if (fp.is_open() == false) { + SURFACE_FATAL("Could not read the file " << configfile); + } + else + cout << "Reading options from the file " << configfile << std::endl; + + /* Parse the input file */ + parseInputFile(fp); + + /* close the file */ + fp.close(); + + } + + /* Post-process grid size */ + if (!isPowerOfTwo(gridsize)) { + SURFACE_FATAL("Grid size should be a power of two and is " << gridsize); + } + + surface = new Surface(gridsize,1.); + /* Post-process random seed */ + //RandomSeed = makeseed(RandomSeed); + + return; +} +/* -------------------------------------------------------------------------- */ + + +// Real SurfaceGenerator::roughness(Real d) { +// //return d*(2*uniform(&RandomSeed)-1); +// return d*(gaussian(&RandomSeed)); +// } +/* -------------------------------------------------------------------------- */ + + + +Real SurfaceGenerator::constrainRMS(){ + int n = surface->size(); + // Real avg = SurfaceStatistics::computeAverage(*surface); + Real measured_rms = SurfaceStatistics::computeStdev(*surface); + + std::cerr << "actual rms is " << rms << endl; + /* shift to center to mean value */ + for (int i = 0 ; i < n ; ++i) + for (int j = 0 ; j < n ; ++j){ + surface->at(i,j) *= rms/measured_rms; + } + return rms/measured_rms; +} + +/* -------------------------------------------------------------------------- */ + diff --git a/src/surface_generator.hh b/src/surface_generator.hh new file mode 100644 index 0000000..10c513b --- /dev/null +++ b/src/surface_generator.hh @@ -0,0 +1,121 @@ +/** + * @file surface_generator.hh + * + * @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 Akantu. If not, see . + * + */ + +/* -------------------------------------------------------------------------- */ +#ifndef SURFACE_GENERATOR_H +#define SURFACE_GENERATOR_H +/* -------------------------------------------------------------------------- */ +#include "surface.hh" +#include +#include +#include +#include + +/* -------------------------------------------------------------------------- */ +inline void trim(std::string & to_trim) { + size_t first = to_trim.find_first_not_of(" \t"); + if (first != std::string::npos) { + size_t last = to_trim.find_last_not_of(" \t"); + to_trim = to_trim.substr(first, last - first + 1); + } else to_trim = ""; +} +/* -------------------------------------------------------------------------- */ + + +class SurfaceGenerator { + +public: + + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ + + //! constructor : takes a config file as input + SurfaceGenerator(const std::string & inputfile); + //! default constructor + SurfaceGenerator(); + //! default destructor + virtual ~SurfaceGenerator(){ + delete surface; + }; + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ + + //! Build surface profile (array of heights) + virtual Surface & buildSurface()=0; + virtual void Init(); + Real constrainRMS(); + + protected: + + virtual void parseInputFile(std::ifstream & fp)=0; + template inline void readInput(const std::string & arg, const std::string & key, T & value); + + /* ------------------------------------------------------------------------ */ + /* Accessors */ + /* ------------------------------------------------------------------------ */ + +public: + + int & getGridSize(){return gridsize;}; + void setGridSize(int gsz){this->gridsize = gsz;}; + Real & getRMS(){return rms;}; + long & getRandomSeed(){return random_seed;}; + + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ + + protected: + + Real rms; /* The RMS for the rough surface */ + long random_seed; /* A random seed */ + std::string configfile; + Surface * surface; + int gridsize; + +}; + +/* -------------------------------------------------------------------------- */ + + +template +inline void SurfaceGenerator::readInput(const std::string & line, const std::string & key, T & value){ + std::string arg; + std::stringstream str(line); + str >> arg; + trim(arg); + if (key == arg){ + str >> value; + } +} +/* -------------------------------------------------------------------------- */ + + + +#endif diff --git a/src/surface_generator_crenel.cpp b/src/surface_generator_crenel.cpp new file mode 100644 index 0000000..906ec57 --- /dev/null +++ b/src/surface_generator_crenel.cpp @@ -0,0 +1,65 @@ +/* -------------------------------------------------------------------------- */ +#include "surface_generator_crenel.hh" +#include +#include +#include +/* -------------------------------------------------------------------------- */ +using namespace std; +/* -------------------------------------------------------------------------- */ + + +SurfaceGeneratorCrenel::SurfaceGeneratorCrenel(const string & inputfile): + SurfaceGenerator(inputfile){ +} + +/* -------------------------------------------------------------------------- */ + + +void SurfaceGeneratorCrenel::Init(){ + SurfaceGenerator::Init(); +} +/* -------------------------------------------------------------------------- */ + + +void SurfaceGeneratorCrenel::parseInputFile(ifstream & fp){ + + int gridsize; + string line; + while (! fp.eof() ) + { + getline (fp,line); + size_t pos = line.find("#"); //remove the comment + line = line.substr(0, pos); + trim(line); // remove unnecessary spaces + + /* Read all options one by one */ + readInput(line, "gridsize" , gridsize); + readInput(line, "c" , c); + readInput(line, "div_crenel", div_crenel); + } + + return; +} +/* -------------------------------------------------------------------------- */ + + + +Surface & SurfaceGeneratorCrenel::buildSurface(){ + UInt n = surface->size(); + + for (UInt i = 0 ; i < n ; ++i) + for (UInt j = 0 ; j < n ; ++j){ + int sub_n = n/div_crenel; + int sub_i = i%sub_n; + int sub_j = j%sub_n; + int sub_c = c/div_crenel; + + if (fabs(sub_i-sub_n/2) < sub_c/2 && + fabs(sub_j-sub_n/2) < sub_c/2){ + surface->at(i,j) = 1.; + } + else surface->at(i,j) = 0.; + } + return *surface; +} + diff --git a/src/surface_generator_crenel.hh b/src/surface_generator_crenel.hh new file mode 100644 index 0000000..f745098 --- /dev/null +++ b/src/surface_generator_crenel.hh @@ -0,0 +1,27 @@ +#ifndef SURFACE_GENERATOR_CRENEL_H +#define SURFACE_GENERATOR_CRENEL_H + +/* -------------------------------------------------------------------------- */ +#include "surface_generator.hh" +/* -------------------------------------------------------------------------- */ + +class SurfaceGeneratorCrenel : public virtual SurfaceGenerator { + public: + + //! constructor : takes a config file as input + SurfaceGeneratorCrenel(const std::string & inputfile); + Surface & buildSurface(); + void Init(); + + + void parseInputFile(std::ifstream & fp); + + protected: + + + Real c; + int div_crenel; + +}; + +#endif diff --git a/src/surface_generator_ellipsoid.cpp b/src/surface_generator_ellipsoid.cpp new file mode 100644 index 0000000..15c39d4 --- /dev/null +++ b/src/surface_generator_ellipsoid.cpp @@ -0,0 +1,59 @@ +/* -------------------------------------------------------------------------- */ +#include "surface_generator_ellipsoid.hh" +/* -------------------------------------------------------------------------- */ +#include +#include +#include +/* -------------------------------------------------------------------------- */ + +SurfaceGeneratorEllipsoid::SurfaceGeneratorEllipsoid(const std::string & inputfile): + SurfaceGenerator(inputfile){ +} +/* -------------------------------------------------------------------------- */ + +void SurfaceGeneratorEllipsoid::Init(){ + SurfaceGenerator::Init(); +} +/* -------------------------------------------------------------------------- */ + +void SurfaceGeneratorEllipsoid::parseInputFile(std::ifstream & fp){ + + std::string line; + int gridsize; + + while (! fp.eof() ) + { + getline (fp,line); + size_t pos = line.find("#"); //remove the comment + line = line.substr(0, pos); + trim(line); // remove unnecessary spaces + + /* Read all options one by one */ + readInput(line, "gridsize" , gridsize); + readInput(line, "centerx" , centerx ); + readInput(line, "centery" , centery ); + readInput(line, "step" , step ); + readInput(line, "radiusx" , radiusx ); + readInput(line, "radiusy" , radiusy ); + readInput(line, "scale" , scale ); + } + + return; +} + + +Surface & SurfaceGeneratorEllipsoid::buildSurface(){ + int n = surface->size(); + + for (int i = 0 ; i < n ; ++i){ + for (int j = 0 ; j < n ; ++j){ + Real x = ((i - centerx)*step)/radiusx; + Real y = ((j - centery)*step)/radiusy; + surface->at(i+j*n) = 1 - x*x -y*y; + surface->at(i+j*n) *= scale; + } + } + + return *surface; +} + diff --git a/src/surface_generator_ellipsoid.hh b/src/surface_generator_ellipsoid.hh new file mode 100644 index 0000000..31a0fa1 --- /dev/null +++ b/src/surface_generator_ellipsoid.hh @@ -0,0 +1,34 @@ +#ifndef __SURFACE_GENERATOR_ELLIPSOID_H__ +#define __SURFACE_GENERATOR_ELLIPSOID_H__ +/* -------------------------------------------------------------------------- */ +#include "surface_generator.hh" +/* -------------------------------------------------------------------------- */ + + + +class SurfaceGeneratorEllipsoid : public virtual SurfaceGenerator { + public: + + //! constructor : takes a config file as input + SurfaceGeneratorEllipsoid(const std::string & inputfile); + Surface & buildSurface(); + void Init(); + + void parseInputFile(std::ifstream & fp); + + protected: + + + Real centerx; + Real centery; + Real radiusx; + Real radiusy; + Real scale; + Real step; + +}; + + + + +#endif /* __SURFACE_GENERATOR_ELLIPSOID_H__ */ diff --git a/src/surface_generator_filter.cpp b/src/surface_generator_filter.cpp new file mode 100644 index 0000000..5119fde --- /dev/null +++ b/src/surface_generator_filter.cpp @@ -0,0 +1,126 @@ +/* -------------------------------------------------------------------------- */ +#include "surface_generator_filter.hh" +#include +#include +/* -------------------------------------------------------------------------- */ + + +SurfaceGeneratorFilter::SurfaceGeneratorFilter(const std::string & inputfile): + SurfaceGenerator(inputfile){ + + h_coeff = NULL; + sources = NULL; + surface_spectral = NULL; + white_noise_FFT = NULL; + h_coeff_power = NULL; + +} + +/* -------------------------------------------------------------------------- */ + +SurfaceGeneratorFilter::SurfaceGeneratorFilter(){ + h_coeff = NULL; + sources = NULL; + surface_spectral = NULL; + white_noise_FFT = NULL; + h_coeff_power = NULL; +} + +/* -------------------------------------------------------------------------- */ + +SurfaceGeneratorFilter::~SurfaceGeneratorFilter(){ + delete white_noise_FFT; + delete surface_spectral; +} + +/* -------------------------------------------------------------------------- */ + + +void SurfaceGeneratorFilter::Init(){ + SurfaceGenerator::Init(); +} + +/* -------------------------------------------------------------------------- */ + +void SurfaceGeneratorFilter::applyFilterOnSource(){ + std::cerr << "resize surface" << std::endl; + if (surface_spectral == NULL) + surface_spectral = new SurfaceComplex(surface->size(),surface->getL()); + else surface_spectral->setGridSize(surface->size()); + std::cerr << "do full product in fourier space" << std::endl; + surface_spectral->fullProduct(*white_noise_FFT,*h_coeff_power); + std::cerr << "fourier transform filter spectrum" << std::endl; + surface_spectral->FFTITransform(*surface); +} +/* -------------------------------------------------------------------------- */ + + +void SurfaceGeneratorFilter::generateWhiteNoiseFFT(){ + white_noise_FFT = new SurfaceComplex(*sources); + white_noise_FFT->FFTTransform(); + // white_noise_FFT->dumpToParaview("white noise FFT",NO_REPLICATION); +} + +/* -------------------------------------------------------------------------- */ + + +void SurfaceGeneratorFilter::generateHFFT(){ + SurfaceComplex h_coeff_FFT(*h_coeff); + // fourier transform it + h_coeff_FFT.FFTTransform(); + // copy it to power spectrum + *h_coeff_power = h_coeff_FFT; + // make it real so that applicable filter is constructed + h_coeff_power->makeItRealByAbs(); +} +/* -------------------------------------------------------------------------- */ + + +Surface & SurfaceGeneratorFilter::buildSurface(){ + + if (surface == NULL) SURFACE_FATAL("Init function was not called"); + + int n = surface->size(); + + if (white_noise_FFT == NULL){ + // create the random source + sources = new Surface(n,1.); + Surface::generateWhiteNoiseSurface(*sources,random_seed); + fprintf(stderr,"build FFT of white noise\n"); + generateWhiteNoiseFFT(); + delete (sources); + } + + fprintf(stderr,"build filter coefficients\n"); + computeFilterCoefficients(); + if (h_coeff_power == NULL) { + generateHFFT(); + } + // s->setHeights(h_coeff_power); + // h_coeff_power->dumpToParaview("h_coeff_power",NO_REPLICATION); + + fprintf(stderr,"apply filter on white noise\n"); + applyFilterOnSource(); + + delete h_coeff_power; + + fprintf(stderr,"recenter arround mean the surface"); + surface->recenterHeights(); + constrainRMS(); + + // s->setHeights(heights); + //s->SetHeights(sources); + //s->SetHeights(h); + + + return *surface; +} + +/* -------------------------------------------------------------------------- */ + +void SurfaceGeneratorFilter::clearSource(){ + if (white_noise_FFT != NULL){ + delete white_noise_FFT; + white_noise_FFT = NULL; + } +} diff --git a/src/surface_generator_filter.hh b/src/surface_generator_filter.hh new file mode 100644 index 0000000..5e8d382 --- /dev/null +++ b/src/surface_generator_filter.hh @@ -0,0 +1,58 @@ +#ifndef SURFACE_GENERATOR_FILTER_H +#define SURFACE_GENERATOR_FILTER_H +/* -------------------------------------------------------------------------- */ +#include "surface_generator.hh" +/* -------------------------------------------------------------------------- */ + +class SurfaceGeneratorFilter : public virtual SurfaceGenerator { + + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ + + public: + + //! constructor : takes a config file as input + SurfaceGeneratorFilter(const std::string & inputfile); + //! default constructor + SurfaceGeneratorFilter(); + //! destructor + ~SurfaceGeneratorFilter(); + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ + + Surface & buildSurface(); + void Init(); + + //! clear the random surface + void clearSource(); + + protected: + + virtual void computeFilterCoefficients()=0; + void applyFilterOnSource(); + void generateWhiteNoiseFFT(); + void generateHFFT(); + + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ + +protected: + + //! filter coefficients + Surface * h_coeff; + //! white noise + Surface * sources; + //! cutofffrequency + Real alpha; + + SurfaceComplex * surface_spectral; + SurfaceComplex * white_noise_FFT; + SurfaceComplex * h_coeff_power; + +}; + +#endif diff --git a/src/surface_generator_filter_bessel.cpp b/src/surface_generator_filter_bessel.cpp new file mode 100644 index 0000000..daf8897 --- /dev/null +++ b/src/surface_generator_filter_bessel.cpp @@ -0,0 +1,128 @@ +/* -------------------------------------------------------------------------- */ +#include "surface_generator_filter_bessel.hh" +#include +#include +/* -------------------------------------------------------------------------- */ + + +SurfaceGeneratorFilterBessel::SurfaceGeneratorFilterBessel(const std::string & inputfile): + SurfaceGenerator(inputfile),SurfaceGeneratorFilter(inputfile){ + +} + +/* -------------------------------------------------------------------------- */ + + +Real SurfaceGeneratorFilterBessel::besselFunction1(Real x){ + Real ax,z; + Real xx,y,ans,ans1,ans2; + if ((ax=fabs(x)) < 8.0) { //Direct rational approximation. + y=x*x; + ans1=x*(72362614232.0+y*(-7895059235.0+y*(242396853.1 + +y*(-2972611.439+y*(15704.48260+y*(-30.16036606)))))); + ans2=144725228442.0+y*(2300535178.0+y*(18583304.74 + +y*(99447.43394+y*(376.9991397+y*1.0)))); + ans=ans1/ans2; + } else { //Fitting function (6.5.9). + z=8.0/ax; + y=z*z; + xx=ax-2.356194491; + ans1=1.0+y*(0.183105e-2+y*(-0.3516396496e-4 + +y*(0.2457520174e-5+y*(-0.240337019e-6)))); + ans2=0.04687499995+y*(-0.2002690873e-3 + +y*(0.8449199096e-5+y*(-0.88228987e-6 + +y*0.105787412e-6))); + ans=sqrt(0.636619772/ax)*(cos(xx)*ans1-z*sin(xx)*ans2); + if (x < 0.0) ans = -ans; + } + return ans; +} + +// Real SurfaceGeneratorFilterBessel::besselFunction1(Real x,int order){ +// Real res = 0; +// Real sign = 1; +// Real x_2p = 1; +// Real p_factorial = 1; +// Real two_power2p = 1; +// for (int p = 0 ; p < order ; ++p){ +// res += sign*x_2p/two_power2p/p_factorial/p_factorial/(p+1); +// /* fprintf(stderr,"(p = %d) adding %e = %e * %e / %e / %e ^2 / %d => %e (x=%e)\n", +// p, +// sign*x_2p/two_power2p/p_factorial/p_factorial/(p+1), +// sign, +// x_2p, +// two_power2p, +// p_factorial, +// p+1, res,x); +// */ +// sign *= -1; +// x_2p *= x*x; +// two_power2p *= 4; +// p_factorial *= p+1; +// } +// if (isnan(res) || isinf(res)) { +// fprintf(stderr,"bessel function computation failed %.15e %d %.15e\n",x,order,res); +// exit(-1); +// } +// return res*(x/2); +// } + +inline Real sinc(Real x){ + return sin(M_PI*x)/M_PI/x; +} +/* -------------------------------------------------------------------------- */ + + +Real SurfaceGeneratorFilterBessel::lanczosFunction(Real x,int N){ + if (fabs(x) < N) return sinc(2*x/N); + return 0; +} +/* -------------------------------------------------------------------------- */ + + +void SurfaceGeneratorFilterBessel::computeFilterCoefficients(){ + int n = surface->size(); + h_coeff = new Surface(n,1.); + for (int i = 0 ; i < n ; ++i) + for (int j = 0 ; j < n ; ++j){ + Real A; + if (i == 0 && j == 0){ + A = 1; + } + else + A = sqrt(i*i+j*j); + Real x = 2.*M_PI*alpha*A; + Real J1 = besselFunction1(x); + (*h_coeff)(i,j) = alpha*1.6*J1/A*lanczosFunction(A,n);//*alpha + // h[i+j*n] = lanczosFunction(A,n/2); + if (isnan((*h_coeff)(i,j)) || isinf((*h_coeff)(i,j))) + { + fprintf(stderr,"h computation failed %.15e %.15e %.15e\n", + alpha,J1,sqrt(i*i+j*j)); + exit(-1); + } + } +} + +/* -------------------------------------------------------------------------- */ + +void SurfaceGeneratorFilterBessel::parseInputFile(std::ifstream & fp) { + + std::string line; + int gridsize; + + while (! fp.eof() ) + { + getline (fp,line); + size_t pos = line.find("#"); //remove the comment + line = line.substr(0, pos); + trim(line); // remove unnecessary spaces + + /* Read all options one by one */ + readInput(line, "seed" , random_seed); + readInput(line, "gridsize", gridsize ); + readInput(line, "alpha" , alpha ); + } + + return; +} diff --git a/src/surface_generator_filter_bessel.hh b/src/surface_generator_filter_bessel.hh new file mode 100644 index 0000000..33d46c1 --- /dev/null +++ b/src/surface_generator_filter_bessel.hh @@ -0,0 +1,26 @@ +#ifndef SURFACE_GENERATOR_FILTER_BESSEL_H +#define SURFACE_GENERATOR_FILTER_BESSEL_H +/* -------------------------------------------------------------------------- */ +#include "surface_generator.hh" +#include "surface_generator_filter.hh" +/* -------------------------------------------------------------------------- */ + +class SurfaceGeneratorFilterBessel : public virtual SurfaceGeneratorFilter { + public: + + //! constructor : takes a config file as input + SurfaceGeneratorFilterBessel(const std::string & inputfile); + + protected: + + void parseInputFile(std::ifstream & fp); + void computeFilterCoefficients(); + Real besselFunction1(Real x); + Real lanczosFunction(Real x,int order); + + //! cutofffrequency + Real alpha; + +}; + +#endif diff --git a/src/surface_generator_filter_fft.cpp b/src/surface_generator_filter_fft.cpp new file mode 100644 index 0000000..837752b --- /dev/null +++ b/src/surface_generator_filter_fft.cpp @@ -0,0 +1,123 @@ +/* -------------------------------------------------------------------------- */ +#include "surface_generator_filter_fft.hh" +#include "surface_statistics.hh" +/* -------------------------------------------------------------------------- */ +#include +#include +#include +#include +/* -------------------------------------------------------------------------- */ + + +SurfaceGeneratorFilterFFT::SurfaceGeneratorFilterFFT(const std::string & inputfile): + SurfaceGenerator(inputfile),SurfaceGeneratorFilter(inputfile){ + +} +/* -------------------------------------------------------------------------- */ + + +SurfaceGeneratorFilterFFT::SurfaceGeneratorFilterFFT(){ +} + +/* -------------------------------------------------------------------------- */ + +complex SurfaceGeneratorFilterFFT::computeFractalPSDProfile(int i, int j){ + Real q = sqrt(i*i+j*j); + complex value(Real(0.),Real(0.)); + if (q < q0) value = 0.; + else if (q <= q1) value = 1.; + else if (q > q2) value = 0.; + else value = pow(q/q1,-2.*(hurst+1)); + return value; +} +/* -------------------------------------------------------------------------- */ + + + +void SurfaceGeneratorFilterFFT::buildCorrelationInput(){ + int n = surface->size(); + // all entries are set to zero automatically + Surface power_input(n,1.); + + std::cout << "rms: " << rms << " , hurst: " << hurst << " , q0: " << q0 << " , q1: " << q1 << " , q2: " << q2 << std::endl; + + + power_input(0,0) = 0.; + + for (int i = 1 ; i < n/2 ; ++i) + for (int j = 1 ; j < n/2 ; ++j){ + + complex value = computeFractalPSDProfile(i,j); + power_input(i,j) = value.real(); + power_input(n-i,n-j) = value.real(); + power_input(n-i,j) = value.real(); + power_input(i,n-j) = value.real(); + } + + // external line (i or j == 0) + for (int i = 1 ; i < n/2 ; ++i){ + complex value = computeFractalPSDProfile(i,0); + power_input(i,0) = value.real(); + power_input(0,i) = value.real(); + power_input(0,n-i) = value.real(); + power_input(n-i,0) = value.real(); + value = computeFractalPSDProfile(i,n/2); + power_input(i,n/2) = value.real(); + power_input(n-i,n/2) = value.real(); + power_input(n/2,i) = value.real(); + power_input(n/2,n-i) = value.real(); + } + { + power_input(n/2,n/2) = computeFractalPSDProfile(n/2,n/2).real(); + power_input(0,n/2) = computeFractalPSDProfile(0,n/2).real(); + power_input(n/2,0) = computeFractalPSDProfile(n/2,0).real(); + } + + power_input.dumpToParaview("power_spectrum_input"); + + + Real average_spectrum = SurfaceStatistics::computeAverageAmplitude(*white_noise_FFT); + std::cout << "white noise average spectrum is " << average_spectrum << std::endl; + + + // compute fourier transform of filter coefficients + h_coeff_power = new SurfaceComplex(n,1.); + Real C = average_spectrum; + + for (int i = 0 ; i < n ; ++i) + for (int j = 0 ; j < n ; ++j){ + h_coeff_power->at(i,j) = sqrt(power_input(i,j)/C); + } +} +/* -------------------------------------------------------------------------- */ + + +void SurfaceGeneratorFilterFFT::computeFilterCoefficients(){ + buildCorrelationInput(); +} +/* -------------------------------------------------------------------------- */ + + +/* Parse an input file */ +void SurfaceGeneratorFilterFFT::parseInputFile(std::ifstream & fp) { + std::string line; + + while (! fp.eof() ) + { + getline (fp,line); + size_t pos = line.find("#"); //remove the comment + line = line.substr(0, pos); + trim(line); // remove unnecessary spaces + + /* Read all options one by one */ + readInput(line, "seed" , random_seed); + readInput(line, "gridsize", gridsize ); + readInput(line, "rms" , rms ); + readInput(line, "l0" , q0 ); + readInput(line, "l1" , q1 ); + readInput(line, "l2" , q2 ); + readInput(line, "hurst" , hurst ); + } + + return; +} diff --git a/src/surface_generator_filter_fft.hh b/src/surface_generator_filter_fft.hh new file mode 100644 index 0000000..f198a80 --- /dev/null +++ b/src/surface_generator_filter_fft.hh @@ -0,0 +1,41 @@ +#ifndef SURFACE_GENERATOR_FILTER_FFT_H +#define SURFACE_GENERATOR_FILTER_FFT_H +/* -------------------------------------------------------------------------- */ +#include "surface_generator.hh" +#include "surface_generator_filter.hh" +/* -------------------------------------------------------------------------- */ + + +class SurfaceGeneratorFilterFFT : public virtual SurfaceGeneratorFilter { + public: + + //! constructor : takes a config file as input + SurfaceGeneratorFilterFFT(const std::string & inputfile); + //! can construct a generator with default values + SurfaceGeneratorFilterFFT(); + + //! get high frequency cut + int & getQ2(){return q2;}; + //! get low frequency cut + int & getQ0(){return q0;}; + //! get roll frequency cut + int & getQ1(){return q1;}; + //! get hurst + Real & getHurst(){return hurst;}; + + + protected: + + void parseInputFile(std::ifstream & fp); + void computeFilterCoefficients(); + void buildCorrelationInput(); + + complex computeFractalPSDProfile(int i, int j); + + int q0; + int q1; + int q2; + Real hurst; +}; + +#endif diff --git a/src/surface_generator_voss.cpp b/src/surface_generator_voss.cpp new file mode 100644 index 0000000..f67157a --- /dev/null +++ b/src/surface_generator_voss.cpp @@ -0,0 +1,192 @@ +/* -------------------------------------------------------------------------- */ +#include "surface_generator_voss.hh" +#include "math.h" +#include +#include +#include "surface_statistics.hh" +/* -------------------------------------------------------------------------- */ +#define TWOPOW(A) (pow(2.0,((Real)(A)))) +/* -------------------------------------------------------------------------- */ +using namespace std; +/* -------------------------------------------------------------------------- */ + + + +SurfaceGeneratorVoss::SurfaceGeneratorVoss(const string & inputfile): + SurfaceGenerator(inputfile){ + +} +/* -------------------------------------------------------------------------- */ + + +void SurfaceGeneratorVoss::Init(){ + SurfaceGenerator::Init(); + int gridsize = surface->size(); + + /* Post-process Hurst exponent */ + if ((Hurst<0) || (Hurst>1)) { + SURFACE_FATAL("Hurst exponent should be between 0.0 and 1.0"); + } + + Nloops = (int)(log(gridsize)/log(2.0)); + + /* Post-process RMS */ + if ((rms < 0) || (fabs(rms) < 1e-10)) { + SURFACE_FATAL("RMS should be larger than zero"); + } + /* Initialize specific lists for the surface algorithm */ + Nsquares = (int *)malloc((gridsize+1)*sizeof(int)); + Ndiamonds = (int *)malloc((gridsize+1)*sizeof(int)); + + return; +} + +/* -------------------------------------------------------------------------- */ + + +void SurfaceGeneratorVoss::parseInputFile(ifstream & fp) { + + string line; + int gridsize; + + while (! fp.eof() ) + { + getline (fp,line); + size_t pos = line.find("#"); //remove the comment + line = line.substr(0, pos); + trim(line); // remove unnecessary spaces + + /* Read all options one by one */ + readInput(line, "seed" , random_seed); + readInput(line, "hurst" , Hurst); + readInput(line, "rms" , rms); + readInput(line, "gridsize", gridsize); + + } + + return; +} + +/* -------------------------------------------------------------------------- */ + + +void SurfaceGeneratorVoss::createRoughSurface(Real *err) { + + int i, j, k, p, n; + int nsquares, ndiamonds; + int dns, dnd; + int midx, midy; + int top, bot, lft, rgt; + Real rval, roughparam; + Real curval, newval; + Real min, max, avg, scaling; + + /* Set some variables */ + int gridsize = surface->size(); + n = gridsize+1; + roughparam = 1.0; + + /* Initiate the dynamic arrays */ + for (i=0; iat(i) = 0.0; + } + + /* Put random values on the corner points */ + SURFACE_FATAL("AAAAAAAAAAAAAAAA"); + // rval = roughness(roughparam); + surface->at(0) = rval; + surface->at((n*n)-1) = rval; + surface->at(n-1) = rval; + surface->at((n*n)-n) = rval; + + /* Start the looping */ + for (p=0; pat(Nsquares[i] + n*Nsquares[j] ); + curval += surface->at(Nsquares[i+1] + n*Nsquares[j] ); + curval += surface->at(Nsquares[i] + n*Nsquares[j+1]); + curval += surface->at(Nsquares[i+1] + n*Nsquares[j+1]); + SURFACE_FATAL("AAAAAAAAAAAAAAAA"); + // newval = 0.25*curval + roughness(roughparam); + midx = Nsquares[i+1]-dns/2; + midy = Nsquares[j+1]-dns/2; + surface->at(midx + n*midy) += newval; + } + } + /* Then the edges of the squares */ + ndiamonds = (int) TWOPOW(p+1); + dnd = gridsize/ndiamonds; + Ndiamonds[0] = 0; /* Should be zero always, just to be sure */ + for (i=1; i<(ndiamonds+1); i++) { Ndiamonds[i] = Ndiamonds[i-1]+dnd; } + for (i=0, k=0; i<(ndiamonds+1); i++) { + for (j=0; j<(ndiamonds+1); j++, k++) { + if ((k%2)==1) { + top = Ndiamonds[j]+dnd; top += top<0?gridsize:0; top -= top>gridsize?gridsize:0; + bot = Ndiamonds[j]-dnd; bot += bot<0?gridsize:0; bot -= bot>gridsize?gridsize:0; + lft = Ndiamonds[i]+dnd; lft += lft<0?gridsize:0; lft -= lft>gridsize?gridsize:0; + rgt = Ndiamonds[i]-dnd; rgt += rgt<0?gridsize:0; rgt -= rgt>gridsize?gridsize:0; + curval = 0; + curval += surface->at(rgt + n*(Ndiamonds[j])); + curval += surface->at(lft + n*(Ndiamonds[j])); + curval += surface->at(Ndiamonds[i] + n*(bot) ); + curval += surface->at(Ndiamonds[i] + n*(top) ); + SURFACE_FATAL("AAAAAAAAAAAAAAAA"); + // newval = 0.25*curval + roughness(roughparam); + surface->at(Ndiamonds[i] + n*Ndiamonds[j]) += newval; + } + } + } + /* And now keep things periodic */ + for (i=0; iat(i+n*(n-1)) = surface->at(i); + surface->at((n-1)+n*i) = surface->at(n*i); + } + /* Update roughness parameter */ + roughparam *= TWOPOW(-Hurst); + } + + /* Reformat the grid */ + min = SurfaceStatistics::computeMinimum(*surface); + max = SurfaceStatistics::computeMaximum(*surface); + avg = SurfaceStatistics::computeAverage(*surface); + scaling = rms/(max-min); + for (i=0; i<(n*n); i++) { + surface->at(i) -= avg; + surface->at(i) *= scaling; + } + + /* Error estimate */ + *err = fabs(surface->at(0) - SurfaceStatistics::computeAverage(*surface)); + + return; +} + +Surface & SurfaceGeneratorVoss::buildSurface(){ + + //int i, j, n; + int n; + Real err; + int gridsize = surface->size(); + + /* Allocate the surface arrays */ + n = gridsize+1; + surface = new Surface(n,1.); + // heights = (Real *)allocate(n*n*sizeof(Real),"heights"); + + /* Build the top surface */ + fprintf(stdout,"Building surface...\n"); fflush(stdout); + err = rms; + while (err>(rms/4)) { createRoughSurface(&err); } + + return *surface; +} diff --git a/src/surface_generator_voss.hh b/src/surface_generator_voss.hh new file mode 100644 index 0000000..29f2455 --- /dev/null +++ b/src/surface_generator_voss.hh @@ -0,0 +1,28 @@ +#ifndef SURFACE_GENERATOR_VOSS_H +#define SURFACE_GENERATOR_VOSS_H +/* -------------------------------------------------------------------------- */ +#include "surface_generator.hh" +/* -------------------------------------------------------------------------- */ + +class SurfaceGeneratorVoss : public virtual SurfaceGenerator { + public: + + //! constructor : takes a config file as input + SurfaceGeneratorVoss(const std::string & inputfile); + //! Build surface profile (array of heights) + Surface & buildSurface(); + void Init(); + + protected: + + void parseInputFile(std::ifstream & fp); + + + void createRoughSurface(Real *err); + + int Nloops; /* Number of loops during creation */ + Real Hurst; /* Hurst parameter for rough surface */ + int *Nsquares, *Ndiamonds; /* Specific lists for surface algorithm */ +}; + +#endif diff --git a/src/surface_statistics.hh b/src/surface_statistics.hh new file mode 100644 index 0000000..909d4f1 --- /dev/null +++ b/src/surface_statistics.hh @@ -0,0 +1,666 @@ +#ifndef __SURFACE_STATISTICS_HH__ +#define __SURFACE_STATISTICS_HH__ +/* -------------------------------------------------------------------------- */ +#include "surface.hh" +#include +/* -------------------------------------------------------------------------- */ + + +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 UInt computeAverage(const Surface & s, + UInt epsilon=0){SURFACE_FATAL("TO IMPLEMENT");}; + + inline static unsigned long computeAverage(const Surface & s, + unsigned long epsilon=0){SURFACE_FATAL("TO IMPLEMENT");}; + + + inline static Real computeAverage(const Surface & s, + Real epsilon= -1.*std::numeric_limits::max()){ + return computeAverage(s,epsilon); + } + + template + inline static T computeAverage(const Surface & s, + T epsilon= -1.*std::numeric_limits::max()); + inline static Real computeStdev(const Surface & s, Real epsilon=-1. * std::numeric_limits::max()); + + 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=-1*std::numeric_limits::max()); + + 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 Real computeAverageAmplitude(const SurfaceComplex & surface); + + + //! sum all heights + inline static Real computeSum(const Surface & surface); + //! compute auto correlation + inline static Surface computeAutocorrelation(Surface & surface); + //! compute powerspectrum + inline static SurfaceComplex computePowerSpectrum(Surface & surface); + + +}; + + +/* -------------------------------------------------------------------------- */ +/* inline functions */ +/* -------------------------------------------------------------------------- */ + +//#include "surface_statistics_inline_impl.cc" + +/* -------------------------------------------------------------------------- */ + +template +std::vector +SurfaceStatistics::computeDistribution(const Surface & 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 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::max() ) + max_heights = computeMaximum(surface); + if (min_value == std::numeric_limits::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 << " ::max(); + 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 +SurfaceStatistics::computeSpectralDistribution(const Surface & 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 distrib_fft(n_bins); + const int N = n_bins; + Real L = max_value - min_value; + + for (int k = 0 ; k < N ; ++k) distrib_fft[k] = 0.; + + 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; + } + for (int k = 1 ; k < N ; ++k) distrib_fft[k] /= n*n; + + + distrib_fft[0] = std::polar(1.,0.); + + 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 + + for (int k = 0 ; k < N ; ++k) { + distrib_fft[k] = std::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 distrib; + distrib.resize(N); + for (int k = 0 ; k < N ; ++k) { + distrib[k] = std::conj(distrib_fft[k]); + } + + return distrib; + +} +/* -------------------------------------------------------------------------- */ + + +Real SurfaceStatistics::computeAverageAmplitude(const Surface & surface){ + Real average_amplitude = 0; + UInt n = surface.size(); + for (UInt i = 0 ; i < n ; ++i) + for (UInt j = 0 ; j < n ; ++j) + average_amplitude += std::abs(surface(i,j)); + + average_amplitude *= 1./n/n; + return average_amplitude; +} +/* -------------------------------------------------------------------------- */ + +Real SurfaceStatistics::computeAverageAmplitude(const SurfaceComplex & surface){ + Real average_amplitude = 0; + UInt n = surface.size(); + for (UInt i = 0 ; i < n ; ++i) + for (UInt j = 0 ; j < n ; ++j) + average_amplitude += std::abs(surface(i,j)); + + average_amplitude *= 1./n/n; + return average_amplitude; +} + +/* -------------------------------------------------------------------------- */ + +Real SurfaceStatistics::computeContactArea(const Surface & surface) { + Real L = surface.getL(); + return SurfaceStatistics::computeContactAreaRatio(surface)*L*L; +} + + +/* -------------------------------------------------------------------------- */ +Real SurfaceStatistics::computeContactAreaRatio(const Surface & surface) { + UInt area = 0; + UInt n = surface.size(); + + for (UInt i = 0; i 1e-10) + area++; + } + } + return area/Real(n*n); +} + + + + +/* -------------------------------------------------------------------------- */ + +Surface SurfaceStatistics::computeAutocorrelation(Surface & surface){ + SurfaceComplex correlation_heights = computePowerSpectrum(surface); + correlation_heights.FFTITransform(); + return correlation_heights.real(); +} +/* -------------------------------------------------------------------------- */ + + +SurfaceComplex SurfaceStatistics::computePowerSpectrum(Surface & surface){ + SurfaceComplex power_spectrum(surface); + power_spectrum.FFTTransform(); + + UInt n = power_spectrum.size(); + Real factor = 1./(n*n); + for (UInt i = 0 ; i < n ; ++i) + for (UInt j = 0 ; j < n ; ++j) + power_spectrum(i,j) *= factor; + + power_spectrum.makeItRealBySquare(); + return power_spectrum; +} + +/* -------------------------------------------------------------------------- */ +template +T SurfaceStatistics::computeAverage(const Surface & surface, T epsilon){ + + Real avg = 0.0; + UInt cpt = 0; + UInt n = surface.size(); + + 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 & surface, + Real avg, Real std){ + Real skw = 0.0; + UInt n = surface.size(); + + 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 & surface, + Real avg, Real std){ + + Real kur=0.0; + UInt n = surface.size(); + + 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 & surface){ + Real _max = -1. * std::numeric_limits::max(); + UInt n = surface.size(); + for (UInt i = 0; i < n*n; i++) { + _max = std::max(surface(i),_max); + } + return _max; +} +/* -------------------------------------------------------------------------- */ + +Real SurfaceStatistics::computeMinimum(const Surface & surface){ + Real _min = std::numeric_limits::max(); + UInt n = surface.size(); + + for (UInt i = 0; i < n*n; i++) { + _min = std::min(surface(i),_min); + } + return _min; +} +/* -------------------------------------------------------------------------- */ + + +Real SurfaceStatistics::computeRMSSlope(const Surface & surface){ + + // UInt xl, yl; + UInt xh, yh; + Real avg, slp; + Real gx, gy; + + UInt n = surface.size(); + Surface 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)); + xh = ((i==(n-1))?(k-n+1):(k+1)); + // yl = ((j==0)?(k+n*n-n):(k-n)); + yh = ((j==(n-1))?(k-n*n+n):(k+n)); + + + gx = surface(xh) - surface(k); + gy = surface(yh) - surface(k); + grad(m++) = gx*gx + gy*gy; + } + } + + avg = SurfaceStatistics::computeAverage(grad); + 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 & surface){ + SurfaceComplex power = computePowerSpectrum(surface); + UInt n = surface.size(); + + Real rms_slopes = 0; + for (UInt i = 1 ; i < n/2 ; ++i) + for (UInt j = 1 ; j < n/2 ; ++j){ + rms_slopes += 1.*((i*i)+(j*j))*power(i,j).real(); + rms_slopes += 1.*((i*i)+(j*j))*power(n-i,n-j).real(); + rms_slopes += 1.*((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) + 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 += 1.*(i*i)*power(0,i).real(); + rms_slopes += 1.*(i*i)*power(0,n-i).real(); + } + + //internal line (i or j == n/2) + 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 += 0.5*(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 Surface & surface, Real epsilon){ + UInt n = surface.size(); + UInt cpt = 0; + Real std = 0.0; + Real avg = 0.0; + + for (UInt i = 0; i < n*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 & surface){ + SurfaceComplex power = computePowerSpectrum(surface); + Real rms_heights = 0; + UInt n = surface.size(); + + 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 & surface){ + SurfaceComplex power = computePowerSpectrum(surface); + UInt n = surface.size(); + + Real rms_curvatures = 0; + 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) + 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) + 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 & surface, Real eps) { + int perimeter = 0; + UInt n = surface.size(); + + + 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 & surface){ + Real sum = 0.; + UInt n = surface.size(); + + for (UInt i = 0 ; i < n ; ++i) + for (UInt j = 0 ; j < n ; ++j) + sum += surface(i,j); + return sum; +} + +/* -------------------------------------------------------------------------- */ +std::vector SurfaceStatistics::computeMoments(Surface & surface){ + + SurfaceComplex power = computePowerSpectrum(surface); + Real L = surface.getL(); + UInt n = surface.size(); + Real k_factor = 2.*M_PI/L; + + std::vector > 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 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; +} + +/* -------------------------------------------------------------------------- */ + + +#endif /* __SURFACE_STATISTICS_HH__ */ diff --git a/src/surface_timer.cpp b/src/surface_timer.cpp new file mode 100644 index 0000000..bca9bd0 --- /dev/null +++ b/src/surface_timer.cpp @@ -0,0 +1,50 @@ +#include "surface.hh" +/* -------------------------------------------------------------------------- */ +#if defined(USING_TIMER) +/* -------------------------------------------------------------------------- */ +#include +#include +/* -------------------------------------------------------------------------- */ +#include "surface_timer.hh" +/* -------------------------------------------------------------------------- */ +std::map mesT; +std::map nmes; +std::map tstart; +std::map tstop; +/* -------------------------------------------------------------------------- */ +void dumpTimes(UInt proc_number) { + std::stringstream fname; + fname << "perf-" << proc_number; + std::ofstream out(fname.str().c_str()); + out << std::setw(30) << "Operation" << std::setw(5) << " " + << std::setw(20) << "Mean time(s)" << std::setw(5) << " " + << std::setw(20) << "Total time(s)" << std::setw(5) << " " + << std::setw(20) << "Call number" << std::endl; + std::multimap inv; + { + std::map::iterator it = mesT.begin(); + std::map::iterator end = mesT.end(); + for( ; it != end ; ++it){ + Real t = (*it).second.tv_sec + (*it).second.tv_nsec*1e-9; + inv.insert(std::pair(t,(*it).first)); + } + } + std::multimap::reverse_iterator it = inv.rbegin(); + std::multimap::reverse_iterator end = inv.rend(); + for( ; it != end ; ++it){ + std::string & key = (*it).second; + Real t = (*it).first; + UInt n = nmes[key]; + Real t_moy = t/n; + out << std::scientific << std::setprecision(10) + << std::setw(30) << key << std::setw(5) << " " + << std::setw(20) << t_moy << std::setw(5) << " " + << std::setw(20) << t << std::setw(5) << " " + << std::setw(20) << n << std::endl; + } +} +#else + +void dumpTimes(UInt proc_number) {} +#endif +/* -------------------------------------------------------------------------- */ diff --git a/src/surface_timer.hh b/src/surface_timer.hh new file mode 100644 index 0000000..51d3847 --- /dev/null +++ b/src/surface_timer.hh @@ -0,0 +1,44 @@ +/* -------------------------------------------------------------------------- */ +#if defined(TIMER) && defined(USING_TIMER) +/* -------------------------------------------------------------------------- */ +#include +#include +#include +/* -------------------------------------------------------------------------- */ +extern std::map mesT; +extern std::map nmes; +extern std::map tstart; +extern std::map tstop; +/* -------------------------------------------------------------------------- */ +#define SEC_IN_NANOSEC 1000000000 +/* -------------------------------------------------------------------------- */ + +#define STARTTIMER(x) { \ + if (!mesT.count(x)) { \ + mesT[x].tv_sec = 0; \ + mesT[x].tv_nsec = 0; \ + } \ + clock_gettime(CLOCK_REALTIME,&(tstart[x])); \ + } +/* -------------------------------------------------------------------------- */ + +#define STOPTIMER(x) { \ + clock_gettime(CLOCK_REALTIME,&(tstop[x])); \ + mesT[x].tv_sec += (tstop[x].tv_sec - tstart[x].tv_sec); \ + mesT[x].tv_nsec += (tstop[x].tv_nsec - tstart[x].tv_nsec); \ + if (mesT[x].tv_nsec < 0) { \ + --mesT[x].tv_sec; \ + mesT[x].tv_nsec += SEC_IN_NANOSEC; \ + } \ + if (mesT[x].tv_nsec >= SEC_IN_NANOSEC){ \ + ++mesT[x].tv_sec; \ + mesT[x].tv_nsec -= SEC_IN_NANOSEC; \ + } \ + ++nmes[x]; \ + } +/* -------------------------------------------------------------------------- */ +#else +#define STARTTIMER(x) +#define STOPTIMER(x) +#endif +void dumpTimes(UInt proc_number = 0); diff --git a/src/types.hh b/src/types.hh new file mode 100644 index 0000000..c2ae2b7 --- /dev/null +++ b/src/types.hh @@ -0,0 +1,37 @@ +#ifndef SURFACE_TYPES_H +#define SURFACE_TYPES_H +/* -------------------------------------------------------------------------- */ +#include +#include +//#include +/* -------------------------------------------------------------------------- */ +class SurfaceException : public std::exception{ +public: + SurfaceException(const std::string & mesg){ + msg = mesg; + } + + virtual const char* what() const throw(){ + return msg.c_str(); + } + +private: + std::string msg; +}; +/* -------------------------------------------------------------------------- */ +#define SURFACE_FATAL(mesg) { \ + std::stringstream sstr; \ + sstr \ + << __FILE__ \ + << ":" << __LINE__ << ":FATAL: " \ + << mesg << std::endl; \ + std::cerr.flush(); \ + throw SurfaceException(sstr.str()); \ +} +/* -------------------------------------------------------------------------- */ +typedef double Real; +typedef unsigned int UInt; +typedef std::complex complex; +static Real zero_threshold = 1e-14; + +#endif /* SURFACE_TYPES_H */