diff --git a/Core/FormFactors/inc/FormFactorTetrahedron.h b/Core/FormFactors/inc/FormFactorTetrahedron.h new file mode 100644 index 0000000000000000000000000000000000000000..768007db82cea16cdbdd4c46b38f91648403931c --- /dev/null +++ b/Core/FormFactors/inc/FormFactorTetrahedron.h @@ -0,0 +1,62 @@ +// ************************************************************************** // +// +// BornAgain: simulate and fit scattering at grazing incidence +// +//! @file FormFactors/inc/FormFactorTetrahedron.h +//! @brief Defines class FormFactorTetrahedron +//! +//! @homepage http://apps.jcns.fz-juelich.de/BornAgain +//! @license GNU General Public License v3 or higher (see COPYING) +//! @copyright Forschungszentrum Jülich GmbH 2013 +//! @authors Scientific Computing Group at MLZ Garching +//! @authors C. Durniak, G. Pospelov, W. Van Herck, J. Wuttke +// +// ************************************************************************** // + +#ifndef FORMFACTORTETRAHEDRON_H +#define FORMFACTORTETRAHEDRON_H + + +#include "IFormFactorBorn.h" +#include "IStochasticParameter.h" + +//! Form factor of tetrahedron. + +class BA_CORE_API_ FormFactorTetrahedron : public IFormFactorBorn +{ +public: + //! @brief tetrahedron constructor + //! @param height of tetrahedron + //! @param half_side half of tetrahedron's base + //! @param angle in radians between base and facet + FormFactorTetrahedron(double height, double half_side, double alpha); + + ~FormFactorTetrahedron() {} + virtual FormFactorTetrahedron *clone() const; + + virtual void accept(ISampleVisitor *visitor) const { visitor->visit(this); } + + virtual int getNumberOfStochasticParameters() const { return 3; } + + virtual double getHeight() const { return m_height; } + virtual void setHeight(double height) { m_height = height; } + + virtual double getHalfSide() const { return m_half_side; } + virtual void setHalfSide(double half_side) { m_half_side = half_side; } + + virtual double getAlpha() const { return m_alpha; } + virtual void setAlpha(double alpha) { m_alpha = alpha; } + + virtual complex_t evaluate_for_q(const cvector_t& q) const; + +protected: + virtual void init_parameters(); + +private: + double m_height; + double m_half_side; + double m_alpha; + double m_root3; // Cached value of square root of 3 +}; + +#endif // FORMFACTORTETRAHEDRON_H diff --git a/Core/FormFactors/src/FormFactorBox.cpp b/Core/FormFactors/src/FormFactorBox.cpp index 270c17ac5fd18365baceb03b1e8aa5f5c5d064e3..caf2d63dbb010254692896915ac7ae78aea1a0e4 100644 --- a/Core/FormFactors/src/FormFactorBox.cpp +++ b/Core/FormFactors/src/FormFactorBox.cpp @@ -41,7 +41,7 @@ complex_t FormFactorBox::evaluate_for_q(const cvector_t& q) const void FormFactorBox::init_parameters() { clearParameterPool(); - registerParameter("radius", &m_length); + registerParameter("length", &m_length); registerParameter( "width", & m_width); registerParameter("height", &m_height); } diff --git a/Core/FormFactors/src/FormFactorTetrahedron.cpp b/Core/FormFactors/src/FormFactorTetrahedron.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d6f253effda9f8c3a7ab580e35af34f33cca0c8 --- /dev/null +++ b/Core/FormFactors/src/FormFactorTetrahedron.cpp @@ -0,0 +1,103 @@ +// ************************************************************************** // +// +// BornAgain: simulate and fit scattering at grazing incidence +// +//! @file FormFactors/src/FormFactorTetrahedron.cpp +//! @brief Implements class FormFactorTetrahedron. +//! +//! @homepage http://apps.jcns.fz-juelich.de/BornAgain +//! @license GNU General Public License v3 or higher (see COPYING) +//! @copyright Forschungszentrum Jülich GmbH 2013 +//! @authors Scientific Computing Group at MLZ Garching +//! @authors C. Durniak, G. Pospelov, W. Van Herck, J. Wuttke +// +// ************************************************************************** // + +#include "FormFactorTetrahedron.h" +#include "StochasticDiracDelta.h" +#include "MathFunctions.h" + +FormFactorTetrahedron::FormFactorTetrahedron( + double height, double half_side, double alpha) +{ + setName("FormFactorTetrahedron"); + m_height = height; + m_half_side = half_side; + m_alpha = alpha; + m_root3 = std::sqrt(3.0); + init_parameters(); +} + +void FormFactorTetrahedron::init_parameters() +{ + clearParameterPool(); + registerParameter("height", &m_height); + registerParameter("half_side", &m_half_side); + registerParameter("alpha", &m_alpha); +} + +FormFactorTetrahedron* FormFactorTetrahedron::clone() const +{ + FormFactorTetrahedron *result = + new FormFactorTetrahedron(m_height, m_half_side, m_alpha); + result->setName(getName()); + return result; +} + +complex_t FormFactorTetrahedron::evaluate_for_q(const cvector_t& q) const +{ + double H = m_height; + double R = m_half_side; + double tga = std::tan(m_alpha); + + complex_t qx = q.x(); + complex_t qy = q.y(); + complex_t qz = q.z(); + + complex_t F; + const complex_t im(0,1); + + if (std::abs(qx)==0.0 && std::abs(qy)==0.0) { + complex_t qzH_half = qz*H/2.0; + F = m_root3*R*R*H*std::exp(im*qzH_half)*MathFunctions::Sinc(qzH_half); + } + else { + if (std::abs(qx*qx-3.0*qy*qy)==0.0) { + complex_t qa = 2.*qy/tga + qz/2.; + complex_t qb = - qy/tga + qz/2.; + F = H/2.*m_root3*std::exp(im*2.*qy*R/m_root3)*( + - std::exp(im*qa*H-im*2.*m_root3*qy*R)*MathFunctions::Sinc(qa*H) + + std::exp(im*qb*H)*MathFunctions::Sinc(qb*H)* + ( 1.- 3.*qy/(tga*qb) - im*2.*m_root3*qy*R ) + + 3.*qy/(qb*tga)*std::exp(im*2.*qb*H) + )/( qx*qx ) ; + } else { + + complex_t q1, q2, q3; + double L; + L = 2.*tga*R/m_root3-H; + q3 = (qy/tga - qz/2.); + + if (std::abs(qx)==0.0) { + + F = - 2.*H*MathFunctions::Sinc(q3*H)* + std::exp(im*(q3*L+qz*R*tga/m_root3))/((m_root3*qy*qy)); + + } else { + + q1=(1./2.)*((m_root3*qx-qy)/tga - qz); + q2=(1./2.)*((m_root3*qx+qy)/tga + qz); + + F = -(1. + m_root3*qy/qx)*MathFunctions::Sinc(q1*H)*std::exp(im*q1*L) + -(1. - m_root3*qy/qx)*MathFunctions::Sinc(q2*H)*std::exp(-im*q2*L) + + 2.*MathFunctions::Sinc(q3*H)*std::exp(im*q3*L); + + F = F*H*std::exp(im*qz*R*tga/m_root3)*m_root3/((qx*qx-3.*qy*qy));} + } + } + + return F; +} + + + diff --git a/Doc/UserManual/AppendixListings.tex b/Doc/UserManual/AppendixListings.tex index f7a0780ec4c3cf9014c7c4c899a63812ac67da9b..ae6742e2a5146e84e7feb02ea08fdbe2ee49a880 100644 --- a/Doc/UserManual/AppendixListings.tex +++ b/Doc/UserManual/AppendixListings.tex @@ -6,8 +6,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\section{Python simulation example.} \label{PythonSimulationExampleScript} -Script can be fount at +\section{Python simulation example} \label{PythonSimulationExampleScript} +The following script can be found at \begin{lstlisting}[language=shell, style=commandline] ./Examples/python/simulation/ex001_CylindersAndPrisms/CylindersAndPrisms.py \end{lstlisting} @@ -91,9 +91,9 @@ if __name__ == '__main__': % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage -\section{Python fitting example.} \label{PythonFittingExampleScript} +\section{Python fitting example} \label{PythonFittingExampleScript} -Script can be fount at +The following script can be found at \begin{lstlisting}[language=shell, style=commandline] ./Examples/python/fitting/ex002_FitCylindersAndPrisms/FitCylindersAndPrisms.py \end{lstlisting} diff --git a/Doc/UserManual/Disclaimer.tex b/Doc/UserManual/Disclaimer.tex index df7dc42adbbde6598088a2c2770b7fd7f05b0330..51d8e23f09e2b75b7e59a5d7b62f79b0fb3a58f7 100644 --- a/Doc/UserManual/Disclaimer.tex +++ b/Doc/UserManual/Disclaimer.tex @@ -11,6 +11,6 @@ Disclaimer {\large This manual is under development and does not yet constitute a comprehensive listing of \BornAgain\ features and functionality. -The included information and instructions are subject to substantial change and +The included information and instructions are subject to substantial changes and are provided only as a preview. } diff --git a/Doc/UserManual/Fitting.tex b/Doc/UserManual/Fitting.tex index 790b4c2e51d20416f38107f42f1248d6c6651215..5ffbff8428b8698be72a8584b62ef7d6abdff5cc 100644 --- a/Doc/UserManual/Fitting.tex +++ b/Doc/UserManual/Fitting.tex @@ -8,15 +8,17 @@ fit the numerical model to reference data by modifying a selection of sample parameters from the numerical model. This aspect of the software is discussed in the following chapter. -The chapter starts from the short introduction to the basic concept of data fitting -in \SecRef{FittingGentleIntroducion}. If user is familiar with it, he is welcome to proceed -to the \SecRef{FittingImplementation} containing details of the implementation in -\BornAgain\ . -Advanced fitting techniques, including fine tuning of minimization algorithms, simultaneous fit of different data sets, parameters correlation, are covered in \SecRef{FittingAdvanced}. -\SecRef{FittingExamples} contains Python fitting example with detailed explanations of every fitting step. \SecRef{FittingRightAnswers} contains a few practical advises which might +\SecRef{FittingGentleIntroducion} gives a short introduction to the +basic concepts of data fitting. Users familiar with fitting can +directly proceed to \SecRef{FittingImplementation}, which details the +implementation of fittings in +\BornAgain\ . \Python\ fitting examples with detailed +explanations of every fitting step are given in \SecRef{FittingExamples}. Advanced fitting techniques, including fine tuning of minimization +algorithms, simultaneous fit of different data sets, parameters +correlation, are covered in +\SecRef{FittingAdvanced}. \SecRef{FittingRightAnswers} contains some practical advise which might help the user to get right answers from \BornAgain\ fitting. - \input{FittingGentleIntroduction} \input{FittingImplementation} diff --git a/Doc/UserManual/FittingAdvanced.tex b/Doc/UserManual/FittingAdvanced.tex index 8c9afa25627995d52adb31d52cbdb03ec0558e08..4901b5d9dc8d11ea7f430c4384f81bf7b592e06d 100644 --- a/Doc/UserManual/FittingAdvanced.tex +++ b/Doc/UserManual/FittingAdvanced.tex @@ -1,9 +1,9 @@ -\section {Advanced fitting.} \SecLabel{FittingAdvanced} +\section {Advanced fitting} \SecLabel{FittingAdvanced} -\subsection{Affecting $\chi2$ calculations.} -\subsection{Simultaneous fit of several data sets.} -\subsection{Using fitting strategies.} -\subsection{Masking the real data.} -\subsection{Tuning fitting algorithms.} -\subsection{Fitting with correlated sample parameters.} +\subsection{Affecting $\chi2$ calculations} +\subsection{Simultaneous fits of several data sets} +\subsection{Using fitting strategies} +\subsection{Masking the real data} +\subsection{Tuning fitting algorithms} +\subsection{Fitting with correlated sample parameters} diff --git a/Doc/UserManual/FittingExamples.tex b/Doc/UserManual/FittingExamples.tex index c29a88e335522436c22a496d098f24c144217acf..f6adcb77f6c407e9ec7cea169db4343c07fa0099 100644 --- a/Doc/UserManual/FittingExamples.tex +++ b/Doc/UserManual/FittingExamples.tex @@ -1,25 +1,25 @@ -\section{Basic Python fitting example.} \SecLabel{FittingExamples} +\section{Basic Python fitting example} \SecLabel{FittingExamples} In this section we are going to go through a complete example of -fitting using \BornAgain. Each of the steps will be associated with a -detailed piece of code written in Python. +fitting using \BornAgain. Each step will be associated with a +detailed piece of code written in \Python. The complete listing of -the script is given at the end (see Listing~\ref{PythonFittingExampleScript}). -Script itself can be found at +the script is given in Appendix (see Listing~\ref{PythonFittingExampleScript}). +The script can also be found at \begin{lstlisting}[language=shell, style=commandline] ./Examples/python/fitting/ex002_FitCylindersAndPrisms/FitCylindersAndPrisms.py \end{lstlisting} \noindent -The example uses same sample geometry as in \SecRef{Example1Python}. -It represents cylindrical and -prismatic particles in equal proportion, in an air layer, deposited on a substrate layer, with no interference -between the particles. We consider following parameters to be unkown +This example uses the same sample geometry as in \SecRef{Example1Python}. +Cylindrical and +prismatic particles in equal proportion, in an air layer, are deposited on a substrate layer, with no interference +between the particles. We consider the following parameters to be unkown \begin{itemize} -\item the radius of cylinders -\item the height of cylinders -\item half side length of the prisms' triangular basis -\item the height of prisms +\item the radius of cylinders, +\item the height of cylinders, +\item the half side length of the prisms' triangular basis, +\item the height of prisms. \end{itemize} Our reference data are a ``noisy'' two-dimensional intensity @@ -29,8 +29,8 @@ Then we run our fitting using default minimizer settings starting with a cylinder's height of $4\,{\rm nm}$, a cylinder's radius of $6\,{\rm nm}$, a prism's half side of $6\,{\rm nm}$ and a length equal to $4\,{\rm nm}$. -As a result, fitting procedure is able to restore correct value of $5\,{\rm nm}$ -for all parameters. +As a result, the fitting procedure is able to find the correct value of $5\,{\rm nm}$ +for all four parameters. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -39,7 +39,8 @@ for all parameters. from libBornAgainCore import * from libBornAgainFit import * \end{lstlisting} -We start from importing two \BornAgain\ libraries required to create sample description +We start from importing two \BornAgain\ libraries required to create +the sample description and to run the fitting. @@ -75,13 +76,13 @@ def get_sample(): @\label{script2::get_sample}@ multi_layer.addLayer(substrate_layer) return multi_layer \end{lstlisting} -Function starting at the line ~\ref{script2::get_sample} creates multilayered sample +The function starting at line~\ref{script2::get_sample} creates a multilayered sample with cylinders and prisms using arbitrary $1\,{\rm nm}$ value for all size's of particles. The details about the generation of this multilayered sample are given in \SecRef{Example1Python}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\subsubsection*{Creating the simulation.} +\subsubsection*{Creating the simulation} \begin{lstlisting}[language=python, style=eclipseboxed, firstnumber=35] def get_simulation(): @\label{script2::get_simulation}@ """ @@ -92,13 +93,13 @@ def get_simulation(): @\label{script2::get_simulation}@ simulation.setBeamParameters(1.0*angstrom, 0.2*degree, 0.0*degree) return simulation \end{lstlisting} -Function starting at the line ~\ref{script2::get_simulation} creates -simulation object with beam and detector parameters defined. +The function starting at line~\ref{script2::get_simulation} creates +the simulation object with the definition of the beam and detector parameters. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\subsubsection*{Preparing the fitting pair.} +\subsubsection*{Preparing the fitting pair} \begin{lstlisting}[language=python, style=eclipseboxed, firstnumber=45] def run_fitting(): @\label{script2::run_fitting}@ """ @@ -110,17 +111,20 @@ def run_fitting(): @\label{script2::run_fitting}@ real_data = OutputDataIOFactory.readIntensityData('refdata_fitcylinderprisms.txt') @\label{script2::real_data}@ \end{lstlisting} -Lines ~\ref{script2::setup_simulation1}-~\ref{script2::setup_simulation2} generate +Lines +~\ref{script2::setup_simulation1}-~\ref{script2::setup_simulation2} +generate the sample and simulation description and assign the sample to the simulation. Our reference data are contained in the file \Code{'refdata\_fitcylinderprisms.txt'}. - In our case this reference had been generated by adding noise -on the scattered intensity from a numerical sample with a fixed length of 5~nm of the four fitting + This reference had been generated by adding noise +on the scattered intensity from a numerical sample with a fixed length of 5~nm for the four fitting parameters (\textit{i.e.} the dimensions of the cylinders and prisms). -Line ~\ref{script2::real_data} creates real data object by loading ASCII data from the file. +Line ~\ref{script2::real_data} creates the real data object by loading +the ASCII data from the input file. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\subsubsection*{Setting up \rm\bf{FitSuite}.} +\subsubsection*{Setting up \rm\bf{FitSuite}} \begin{lstlisting}[language=python, style=eclipseboxed, firstnumber=55] fit_suite = FitSuite() @\label{script2::fitsuite1}@ fit_suite.addSimulationAndRealData(simulation, real_data) @\label{script2::fitsuite2}@ @@ -129,8 +133,8 @@ Line ~\ref{script2::real_data} creates real data object by loading ASCII data fr Line ~\ref{script2::fitsuite1} creates a \Code{FitSuite} object which provides the main interface to the minimization kernel of \BornAgain\ . Line ~\ref{script2::fitsuite2} submits simulation description and real data pair to the -subsequent fitting. Line ~\ref{script2::fitsuite3} set up \Code{FitSuite} to print on -the screen the information about fit progress every $10^{{\rm th}}$ iteration. +subsequent fitting. Line ~\ref{script2::fitsuite3} sets up \Code{FitSuite} to print on +the screen the information about fit progress once per 10 iterations. \begin{lstlisting}[language=python, style=eclipseboxed, firstnumber=60] fit_suite.addFitParameter("*FormFactorCylinder/height", 4.*nanometer, 0.01*nanometer, AttLimits.lowerLimited(0.01)) @\label{script2::fitpars1}@ fit_suite.addFitParameter("*FormFactorCylinder/radius", 6.*nanometer, 0.01*nanometer, AttLimits.lowerLimited(0.01)) @@ -144,15 +148,15 @@ radius and the prisms' height and half side length. The syntax of \begin{lstlisting}[language=python, style=eclipse,numbers=none] FitSuite().addFitParameter(<name>, <initial value>, <iteration step>, <limits>) \end{lstlisting} -where \Code{<name>} is the name of sample pool parameters (see \SecRef{WorkingWithSampleParameters} +where \Code{<name>} is the name of the sample pool parameters (see \SecRef{WorkingWithSampleParameters} ) selected as a fitting parameter. Then we input its initial -value and the iteration step used in the minimization process. Finally +value and the iteration step to be used in the minimization process. Finally \Code{<limits>} specify the boundaries of the parameter's value. Here the cylinder's length and prism half side are initially equal to $4\,{\rm nm}$, whereas the cylinder's radius and the prism length are equal to $6\,{\rm nm}$ before the minimization. The -iteration step is equal to $0.01\,{\rm nm}$ and the boundaries are imposed only -on the lower one of $0.01\,{\rm nm}$. +iteration step is equal to $0.01\,{\rm nm}$ and only the lower +boundary is imposed to be equal to $0.01\,{\rm nm}$. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -170,10 +174,12 @@ on the lower one of $0.01\,{\rm nm}$. Line ~\ref{script2::fitresults1} shows the command to start the fitting process. During the fitting the progress will be displayed on the screen. Lines ~\ref{script2::fitresults2}--~\ref{script2::fitresults3} shows different ways of -accessing to fit results. +accessing the fit results. -More details about fitting, access to its results and visualization of fit progress using matplotlib libraries can be learned from detailed example +More details about fitting, access to its results and visualization of +the fit progress using matplotlib libraries can be learned from the +following detailed example \begin{lstlisting}[language=shell, style=commandline] ./Examples/python/fitting/ex002_FitCylindersAndPrisms/FitCylindersAndPrisms_detailed.py \end{lstlisting} diff --git a/Doc/UserManual/FittingGentleIntroduction.tex b/Doc/UserManual/FittingGentleIntroduction.tex index a6317bfba792d52678fe916a6f6a9056f8de48b5..b86df7a3d0da4a3f7eeebc80f923f2fcf7f094b1 100644 --- a/Doc/UserManual/FittingGentleIntroduction.tex +++ b/Doc/UserManual/FittingGentleIntroduction.tex @@ -1,19 +1,19 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\section{Gentle introduction to the data fitting.} \SecLabel{FittingGentleIntroducion} +\section{Gentle introduction to data fitting} \SecLabel{FittingGentleIntroducion} -The aim of this section is to briefly introduce the basic concept of -data fitting, its key terminology and difficulties which might arise in scattering data fit. +The aim of this section is to briefly introduce the basic concepts of +data fitting, its key terminology and difficulties which might arise +when fitting scattering data. Users wanting to find out more about minimization (also called maximization or optimization methods depending on the formulations and objectives) -or looking for more rigorous discussion than provided in this manual -are referred to \cite{Antoniou2007, mntutorial} +or looking for more detailed discussions are referred to \cite{AnLu07, mntutorial} -\subsection{Toy scattering experiment.} +\subsection{Toy scattering experiment} -Fig.~\ref{fig:toyfit_data},left shows scattering intensity map in arbitrary units -as a function of (x,y) of the detector ``measured'' in toy scattering experiment. +Figure~\ref{fig:toyfit_data},left shows a scattering intensity map in arbitrary units +as a function of $(x,y)$, the positions on the detector ``measured'' in this toy scattering experiment. \begin{figure}[!p] \centering @@ -32,36 +32,40 @@ as a function of (x,y) of the detector ``measured'' in toy scattering experiment \end{figure} -Scattering picture presented reminds some of GISAS patterns, nevertheless it is -generated using simple function -$$I(x,y) = G(0.1,~0.01) + \frac{sin(x)}{x} \cdot \frac{sin(y)}{y}$$ -Here $G(0.1, 0.01)$ is a random variable distributed according to the Gaussian distribution -with mean 0.1 and $\sigma=0.01$. -Constant $0.1$ symbolize our experimental background and constant $0.01$ is referred +The scattering picture, similar to some GISAS patterns, has been generated using the simple function +$$I(x,y) = G(0.1,~0.01) + \frac{\sin(x)}{x} \cdot \frac{\sin(y)}{y}$$ +Here $G(0.1, 0.01)$ is a random variable distributed according to a Gaussian distribution +with a mean of 0.1 and a standard deviation $\sigma=0.01$. +Constant $0.1$ symbolizes our experimental background and constant $0.01$ refers to the detector noise. The rest of the formula represents our signal. -Lets define our model, namely specific mathematical function, to which we will fit our toy experimental data. By making an educated guess we assume that scattering intensity observed -in the experiment should be described with the help of $sinc$ functions as follows +Let's define our model, namely specific mathematical functions, to +which we will fit our toy experimental data. By making an educated +guess we assume that the scattering intensity observed +in the experiment should be described by $sinc$ functions as follows \begin{equation} \label{eq:toy_model} f(x,y;p) = p_0 + p_1 \cdot sinc(x - p_2) \cdot sinc(y - p_3) \end{equation} -The model has four parameters: $p_0$ describing background, $p_{1}$ describing signal strength -and $p_2,p_3$ responsible for the peak position. -Fig.~\ref{fig:toyfit_data},right shows the intensity as a function (x,y) calculated according -our model using fixed parameter set $p_0=0,p_1=1,p_2=0,p_3=0$. +The model has four parameters: $p_0$ describes a constant background, +$p_{1}$ describes the signal strength +and $p_2,p_3$ give the peak position along the $x$ and $y$ axis, respectively. +Figure~\ref{fig:toyfit_data},right shows the intensity as a function +of $(x,y)$ calculated using our model and a fixed set of parameters +$p_0=0, p_1=1, p_2=0, p_3=0$. -Two distributions look pretty much the same, however to find exact values of parameters which describe experimental data in the best way, one have to +Two distributions are qualitatively identical. However in order to find the +values of parameters which best describe the experimental data, one has to \begin{itemize} -\item elaborate criteria for the difference between an actual data and its model -\item employ minimization procedure which will minimize that difference +\item define criteria for the difference between the actual data and the model, +\item use a minimization procedure, which will minimize this difference. \end{itemize} \subsection{Objectives} The goal is to obtain the best fit of an observed distribution -to a prediction by modifying a set of parameters from the +to a prediction by modifying a set of parameters from this prediction. This problem can be one or multi-dimensional and also linear or nonlinear. The quantity to minimize is often referred to as the \textit{objective function}, whose expression depends on the @@ -69,7 +73,7 @@ particular method, like the maximum likelihood, the $\chi^2$ minimization or the expected prediction error function. \begin{comment} -\subsubsection*{Maximum of likelihood.} +\subsubsection*{Maximum of likelihood} This is a popular method for parameters' estimations because the maximum likelihood estimators are approximately unbiased and efficient for large data samples, under quite general conditions. @@ -86,90 +90,91 @@ $-\text{ln}(\mathcal{L})$. \subsubsection*{$\chi^2$ or least squares minimization} -A dataset consist of $n$ data pairs $(\mathbf{x_{i}}, a_{i}), i=1,N$ where -$\mathbf{x_{i}}$ is an independent variable and $a_{i}$ is dependent variable, whose -value is found in the measurement $i$. The number $N$ denotes the total -number of measurements. - -In the case of intensity map measured in our toy experiment -and presented in Fig~\ref{fig:toyfit_data}, a variable $a_{i}$ denotes measured intensity, a variable $\mathbf{x_{i}}$ is a vector and correspond to the -$(x_{i}, y_{i})$ coordinates of pixels in our detector while number $N$ corresponds +Performing $N$ measurements generates $N$ pairs of data $(\mathbf{x_{i}}, a_{i}), i=1,N$ where +$\mathbf{x_{i}}$ is an independent variable and $a_{i}$ is a dependent variable, whose +value is found during measurement $i$. + +In the case of the intensity map measured in our toy experiment +and presented in Fig~\ref{fig:toyfit_data}, variable $a_{i}$ denotes +the measured intensity, variable $\mathbf{x_{i}}$ is a vector and +corresponds to the pixel coordinates $(x_{i}, y_{i})$ in our detector while $N$ corresponds to total number of detector pixels. The model function has the form $f(\mathbf{x_{i}},\mathbf{p})$ -where adjustable parameters are held in the vector $\mathbf{p}$. -The least squared method finds the optimum of model function which -fit the data in the best way by searching for the minimum of the sum of squared +where adjustable parameters are held in vector $\mathbf{p}$. +The least squared method finds the optimum of the model function which best +fits the data by searching the minimum of the sum of squared residuals $$ \chi^{2}(\mathbf{p}) = \sum_{i=1}^{N}r_{i}^{2}$$ -where residual is defined as the difference between measured value and the value predicted by the model. +where the residual is defined as the difference between the measured value and the value predicted by the model. $$r = a_{i} - f(\mathbf{x_{i}},\mathbf{p})$$ -In the case of normally distributed variables with the $\sigma^2$ variance +In case of normally distributed variables with a variance $\sigma^2$, the quantity to minimize becomes $$ \chi^{2}(\mathbf{p}) = \frac{1}{d} \sum_{i=1}^{N} \frac{ (a_{i} - f(\mathbf{x_{i}},\mathbf{p}))^2}{\sigma^2} $$ -where $d=N-k$ is number of degree of freedom ($k$ number of free fit parameters). +where $d=N-k$ is number of degree of freedom ($k$ being the number of free fit parameters). \subsubsection*{Maximum of likelihood} to be written \subsubsection*{Minimization algorithms} -There are a large number of minimization algorithms providing a solution to the problem -of minimizing the objective function over the space of parameters of the function. -The minimization starts from initial guess for the parameters provided by the user, -and then evolves iteratively under control of minimization algorithm. The procedural -modifications on the parameters, the objective function, as well as convergence -criterion depend on the method implemented. -Details of particular implementation is beyond the scope of this manual and - interested reader is encouraged to look at outside resources. +There is a large number of algorithms to minimize the objective function over the space of parameters of the function. +The minimization starts from an initial guess for the parameters +provided by the user. Then the process evolves iteratively under the +control of the minimization algorithm. The procedural +modifications on the parameters, the objective function, as well as +the convergence +criteria depend on the method implemented. +Details of all implementations are beyond the scope of this manual. \subsubsection*{Local minima trap} -Finding the global minimum of objective function +Finding the global minimum of the objective function is a general problem in optimization that is unlikely to have an exact and -tractable solution. The problem can be illustrated using our toy experiment. +tractable solution. This issue can be illustrated using our toy experiment. -The theoretical model given by the formula \ref{eq:toy_model} is defined +The theoretical model given by formula \ref{eq:toy_model} is defined in $(x,y)$ space and additionally depends on parameter vector $\mathbf{p}$. The $\chi^2$ -objective function is obtained by the calculation of sum of squared residuals between -measured (Fig.~\ref{fig:toyfit_data}, left) and +objective function is obtained by calculating the sum of squared residuals between +the measured (Fig.~\ref{fig:toyfit_data}, left) and the predicted (Fig.~\ref{fig:toyfit_data}, right) values over $x,y$ space. It is defined -in parameter space $\mathbf{p}$ which have 4 dimensions. +in parameter space $\mathbf{p}$, which have 4 dimensions. -Fig.~\ref{fig:toyfit_chi2} (left) shows $\chi^2$ as a function of -$p_1,p_2$ parameters while parameters $p_0,p_3$ remain fixed. -Fig.~\ref{fig:toyfit_chi2} (right) shows $\chi^2$ as a function of -$p_2,p_3$ parameters while parameters $p_0,p_1$ remain fixed. +Figure~\ref{fig:toyfit_chi2} (left) shows the $\chi^2$ distribution as a function of +parameters $p_1,p_2$ while parameters $p_0,p_3$ remain fixed. +Figure~\ref{fig:toyfit_chi2} (right) shows the $\chi^2$ distribution as a function of +parameters $p_2,p_3$ while parameters $p_0,p_1$ remain fixed. -One can see that given objective function have a strongly pronounced global minimum, -the goal of our search, supplemented by a number of local minima. -The later will provide a hostile environment for the minimization algorithm, causing -poor or slow convergence to single global minimum. +One can see that the given objective function has a strongly +pronounced global minimum, which we aim to determine. In addition the +objective function presents a number of local minima. +The presence of these minima leads to a poor or slow convergence +towards the single global minimum. -\subsection{Terminology.} +\subsection{Terminology} \noindent {\bf Reference data} \\ -Normally just experimental data or might be also simulated data -spoiled with the noise for purpose of testing of minimization algorithms. +In general they are just experimental data or they might be also simulated data +perturbed with some noise for the purpose of testing minimization algorithms. \vspace*{1mm} \noindent {\bf Objective function} \\ -Subject of minimization procedure. +Subject of the minimization procedure. \vspace*{1mm} \noindent {\bf Minimization} \\ -Finding a best available values (i.e. local minimum) of some objective function. +Finding the best available values (i.e. local minimum) of some objective function. \vspace*{1mm} \noindent @@ -179,5 +184,5 @@ Number of data points - number of parameters in the fit. \noindent {\bf Minimizer} \\ -An algorithm which minimize objective function. +Algorithm which minimizes the objective function. diff --git a/Doc/UserManual/FittingImplementation.tex b/Doc/UserManual/FittingImplementation.tex index 4a32b9082dee0be7bad2d7e9b5dd6d394b36e230..c283239ebd8a009bbe9d1e8c0d0fe73e83900c7f 100644 --- a/Doc/UserManual/FittingImplementation.tex +++ b/Doc/UserManual/FittingImplementation.tex @@ -1,20 +1,20 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\section{Implementation in BornAgain.} \SecLabel{FittingImplementation} +\section{Implementation in \BornAgain} \SecLabel{FittingImplementation} Fitting in \BornAgain\ deals with estimating the optimum parameters in the numerical model by minimizing the difference between numerical and reference data using $\chi^2$ or maximum likelihood methods. The features include \begin{itemize} -\item Variety of multidimensional minimization algorithms and strategies. -\item The choice over possible fitting parameters, they properties and correlations. -\item Full control on $\chi^2$ calculations, including application of different normalizations and assignment of different masks and weights to the different areas of reference data. -\item The possibility to fit simultaneously an arbitrary number of data sets. +\item a variety of multidimensional minimization algorithms and strategies. +\item the choice over possible fitting parameters, their properties and correlations. +\item the full control on $\chi^2$ calculations, including applications of different normalizations and assignments of different masks and weights to different areas of reference data. +\item the possibility to fit simultaneously an arbitrary number of data sets. \end{itemize} -Fig. ~\ref{fig:minimization_workflow} shows general work flow of fitting procedure. +Figure ~\ref{fig:minimization_workflow} shows general work flow of a typical fitting procedure. \begin{figure}[htbp] \centering \resizebox{0.99\textwidth}{!}{% @@ -24,48 +24,51 @@ Fitting work flow. } \label{fig:minimization_workflow} \end{figure} -Before running the fitting the user is required to prepare a number of data and to -configure fitting kernel of \BornAgain\ . Necessary stages consist of +Before running the fitting the user is required to prepare some data and to +configure the fitting kernel of \BornAgain\ . The required stages consist in \begin{itemize} -\item Preparing sample and simulation description (multilayer, beam, detector parameters). -\item Choice of fitting parameters. -\item Loading of reference data. -\item Defining minimization settings. +\item Preparing the sample and the simulation description (multilayer, beam, detector parameters). +\item Choosing the fitting parameters. +\item Loading the reference data. +\item Defining the minimization settings. \end{itemize} The class \Code{FitSuite} contains the main functionalities to be used for the fit -and serve as main gate between user and fitting work flow. -The later involve iterations during which +and serves as the main interface between the user and the fitting work flow. +The later involves iterations during which \begin{itemize} -\item The minimizer makes an assumption about optimal sample parameters. +\item The minimizer makes an assumption about the optimal sample parameters. \item These parameters are propagated to the sample. \item The simulation is performed for the given state of the sample. -\item Simulated data (intensities) are propagated to the $\chi^2$ module. -\item The later performs calculation of $\chi^2$-value using simulated and reference data. -\item $\chi^2$-value is propagated to the minimizer which makes new assumption about optimal sample parameters. +\item The simulated data (intensities) are propagated to the $\chi^2$ module. +\item The later calculates $\chi^2$ using the simulated and reference data. +\item The value of $\chi^2$ is propagated to the minimizer, which makes new assumptions about optimal sample parameters. \end{itemize} -Iteration process is going on without user intervention under the control of currently selected minimization algorithm. It stops +The iteration process is going on under the control of the selected minimization +algorithm, without any intervention from the +user. It stops \begin{itemize} -\item when the maximum number of iteration steps has been exceeded -\item when the function's minimum has been reached within the tolerance window -\item if the minimizer could not improve the values of the parameters +\item when the maximum number of iteration steps has been exceeded, +\item when the function's minimum has been reached within the tolerance window, +\item if the minimizer could not improve the values of the parameters. \end{itemize} -After the control is returned to the user application fitting results can be retrieved. -That consist of the best $\chi^2$ value found, corresponding optimal sample parameters and intensity map simulated with this set of parameters. +After the control is returned, fitting results can be retrieved. +They consist in the best $\chi^2$ value found, the corresponding +optimal sample parameters and the intensity map simulated with this set of parameters. Details of \Code{FitSuite} class implementation and description of each interface are given in \SecRef{FitSuiteClass}. The following parts of this section will detail each of -the main stages necessary to run fitting procedure. +the main stages necessary to run a fitting procedure. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\subsection{Preparing sample and simulation description.} +\subsection{Preparing the sample and the simulation description} This step is similar for any simulation using \BornAgain\ (see \SecRef{Simulation}). It consists in first characterizing the geometry of the system: the particles (shapes, sizes, refractive @@ -84,11 +87,14 @@ output detector. \subsection{Choice of parameters to be fitted} In principle, every parameter used in the construction of the sample can be used as a fitting parameter. For example, the particles' -heights, radii or the layer's roughness or thickness could be selected using +heights, radii or the layer's roughness or thickness could be selected +using the parameter pool mechanism. -That mechanism is explained in details in \SecRef{WorkingWithSampleParameters} and it is recommended to read it before proceeding further. +This mechanism is explained in detail in +\SecRef{WorkingWithSampleParameters} and it is therefore recommended +to read it before proceeding any further. -User specifies selected sample parameters as a fit parameter using \Code{FitSuite} +The user specifies selected sample parameters as fit parameters using \Code{FitSuite} and its \Code{addFitParameter} method \begin{lstlisting}[language=shell, style=commandline] @@ -96,12 +102,13 @@ fit_suite = FitSuite() fit_suite.addFitParameter(<name>, <value>, <AttLimits>) \end{lstlisting} -Here the \Code{<name>} correspond to the name of the parameter in the sample's parameter pool. +Here \Code{<name>} corresponds to the parameter name in the sample's parameter pool. By using wildcard's in the parameter name the group of sample parameters, corresponding to the given pattern, can be associated with single fitting parameter and fitted simultaneously to get common optimal value. -The second parameter \Code <value> correspond to the initial value of fitting parameter +The second parameter \Code <value> correspond to the initial value of +the fitting parameter while the third one \Code{<AttLimits>} corresponds to the boundaries imposed on the range of variations of that value. It can be \begin{itemize} @@ -112,59 +119,63 @@ the boundaries imposed on the range of variations of that value. It can be \item \Code{limited(<min\_value>, <max\_value>)}. \end{itemize} where \Code{<min\_value>} and \Code{<max\_value>} are -double values corresponding to the lower and higher boundary respectively. +double values corresponding to the lower and higher boundary, respectively. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\subsection{Associating reference and simulated data.} +\subsection{Associating reference and simulated data} The minimization procedure deals with a pair of reference data (normally associated with experimental data) and the theoretical model (presented by the sample and the simulation descriptions). -We assume that the experimental data is a two-dimensional intensity +We assume that the experimental data are a two-dimensional intensity matrix as function of the output scattering angles $\alpha_f$ and $\phi_f$ (see Fig.~\ref{fig:multil3d}). -The user is required to provide the data in the form of ASCII file containing axes +The user is required to provide the data in the form of an ASCII file +containing an axes binning description and the intensity data itself. \vspace*{2mm} \ImportantPoint{Remark:}{ -We recognize the importance of the support of most common data formats. We are going to provide -this feature in the following releases and welcome user requests on that subject. +We recognize the importance of supporting the most common data formats. We are going to provide +this feature in the following releases and welcome users' requests on this subject. } \vspace*{1mm} -To associate the simulation with the reference data the method \newline +To associate the simulation with the reference data, method \newline \Code{addSimulationAndRealData} has to be used as shown \begin{lstlisting}[language=python, style=eclipseboxed,numbers=none] fit_suite = FitSuite() fit_suite.addSimulationAndRealData(<simulation>, <reference>, <chi2_module>) \end{lstlisting} -here \Code{<simulation>} correspond to the \BornAgain\ simulation object with sample, beam and detector fully defined, \Code{<reference>} correspond to the experimental data object obtained from ASCII file and \Code{<chi2\_module>} is an optional parameter for advanced +Here \Code{<simulation>} corresponds to \BornAgain\ simulation object +with the sample, beam and detector fully defined, \Code{<reference>} +corresponds to the experimental data object obtained from the ASCII file and \Code{<chi2\_module>} is an optional parameter for advanced control of $\chi2$ calculations. -There is a possibility to call given method more than once to submit more than one pair of -\Code{<simulation>, <reference>} to the fitting procedure and so to provide simultaneous fit of -some combined data set. +It is possible to call this given method more than once to submit more than one pair of +\Code{<simulation>, <reference>} to the fitting procedure and so in +order to proceed to simultaneous fits of +some combined data sets. -By using the third \Code{<chi2\_module>} parameter different normalization and weights -can be applied to let the user fully control the way $\chi2$ is calculated. +By using the third \Code{<chi2\_module>} parameter different normalizations and weights +can be applied to let the user in full control of the way $\chi2$ is calculated. This feature will be explained in \SecRef{FittingAdvanced}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\subsection{Minimizer settings.} +\subsection{Minimizer settings} \BornAgain\ contains a variety of minimization engines from \Code{ROOT} and \Code{GSL} libraries. They are listed in Table~\ref{table:fit_minimizers}. By default \Code{Minuit2} minimizer with default settings will be used and no additional configuration needs to be done. -The remainder of this section explains some of the expert setting which can be applied to get better +The remainder of this section explains some of the expert setting, which can be applied to get better fit results. The default minimization algorithm can be changed using @@ -177,7 +188,7 @@ fit_suite.setMinimizer(minimizer) where \Code{<Minimizer name>} and \Code{<algorithm>} can be chosen from the first and second column of Table~\ref{table:fit_minimizers} respectively. -The list of algorithms +The list of minimization algorithms implemented in \BornAgain\ can also be obtained using \Code{MinimizerFactory.printCatalogue()} command. @@ -238,24 +249,25 @@ Algorithm\\ \label{table:fit_minimizers} \end{table} -There are several options common for every minimization algorithms, which can be changed -before minimization starts. They are handled by \Code{MinimizerOptions} class: +There are several options common to every minimization algorithm, which can be changed +before starting the minimization. They are handled by \Code{MinimizerOptions} class: \begin{lstlisting}[language=python, style=eclipseboxed, numbers = none] options = MinimizerOptions() options.setMaxFunctionCalls(10) fit_suite.getMinimizer().setOptions(options) \end{lstlisting} -In given code snippet a number of ``maximum function calls'', namely a number of times the minimizer is allowed to call the simulation, is limited to the 10. The minimizer will take that number into consideration and will try to limit number of iterations by that value. +In the above code snippet, a number of ``maximum function calls'', +namely the maximum number of times the minimizer is allowed to call the simulation, is limited to 10. %The minimizer will take that number into consideration and will try to limit number of iterations by that value. -There is also a number of expert level options common for all minimizers as well -as a number of possibilities to tune individual minimization algorithms. +There are also expert-level options common for all minimizers as well +as a number of options to tune individual minimization algorithms. They will be explained in \SecRef{FittingAdvanced}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\subsection{Running the fitting ant retrieving the results.} +\subsection{Running the fitting ant retrieving the results} After the initial configuration of \Code{FitSuite} has been performed, the fitting can be started using the command @@ -263,12 +275,12 @@ can be started using the command fit_suite.runFit() \end{lstlisting} -Depending on complexity of the sample and number of free sample parameters the fitting -process can go from tenths to thousands of iterations. The results of the fit can +Depending on the complexity of the sample and the number of free sample parameters the fitting +process can count from tenths to thousands of iterations. The results of the fit can be printed on the screen using the command \begin{lstlisting}[language=python, style=eclipseboxed, numbers = none] fit_suite.printResults() \end{lstlisting} -\SecRef{FittingExamples} gives more details about access to fitting results. +\SecRef{FittingExamples} gives more details about how to access the fitting results. diff --git a/Doc/UserManual/FittingRightAnswers.tex b/Doc/UserManual/FittingRightAnswers.tex index 9a4b2ccab046151c33ba8c419af21a1948763018..635b1c281d2fbb68640b87ec5aade936d91976db 100644 --- a/Doc/UserManual/FittingRightAnswers.tex +++ b/Doc/UserManual/FittingRightAnswers.tex @@ -1,36 +1,43 @@ -\section {How to get right answer from fitting.} +\section {How to get the right answer from fitting} \SecLabel{FittingRightAnswers} -As it was already mentioned in \SecRef{FittingGentleIntroducion}, +As it has already been mentioned in \SecRef{FittingGentleIntroducion}, one of the main difficulties in fitting the data with the model is the presence of multiple -local minima in the objective function. The extended list of problems causing fit to failure includes +local minima in the objective function. Many problems can cause the +fit to fail, for example: \begin{itemize} -\item unreliable physical model -\item multiple local minima -\item unphysical behavior of objective function, unphysical regions in parameter space -\item unreliable parameter error calculation in the presence of limits on parameter value -\item often exponential behavior of objective function and corresponding numerical inaccuracies and excessive numerical roundoff in calculation of its value and derivatives -\item large correlations between parameters -\item very different scale of parameters involved in calculation -\item not positive definite error matrix even at minimum +\item an unreliable physical model, +\item multiple local minima, +\item an unphysical behavior of the objective function, unphysical regions + in the parameters space, +\item an unreliable parameter error calculation in the presence of + limits on the parameter value, +\item often an exponential behavior of the objective function and the + corresponding numerical inaccuracies, excessive numerical roundoff + in the calculation of its value and derivatives, +\item large correlations between parameters, +\item very different scales of parameters involved in the calculation, +\item not positive definite error matrix even at minimum. \end{itemize} -Given list, of course, is unrelated only to \BornAgain\ fitting. It remains the same -while fitting the data with any fitting program and any kind of theoretical model. -To address all these difficulties some amount of manual tuning might be necessary. Below we give some recommendations which might help the user to achieve reliable fit results. +The given list, of course, is not only related to \BornAgain\ +fitting. It remains applicable to any fitting program and any kind of theoretical model. +%To address all these difficulties some amount of manual tuning might be necessary. + Below we give some recommendations which might help the user to achieve reliable fit results. -\subsection*{General recommendation} +\subsection*{General recommendations} \begin{itemize} -\item initially choose small number of free fitting parameters -\item eliminate redundand parameters -\item provide a good initial guess for fit parameters -\item start from default minimizer settings and turn to the fine tuning after some experience has been acquired. -\item repeat fit using different starting values for parameters or their limits -\item repeat fit fixing and releasing different groups of parameters -\item use \Code{Minuit2} minimizer with \Code{Migrad} algorithm (default) to get most reliable parameter error estimation -\item try \Code{GSLMultiFit} minimizer or \Code{Minuit2} minimizer with \Code{Fumili} algorithm to get fewer iterations +\item initially choose a small number of free fitting parameters, +\item eliminate redundant parameters, +\item provide a good initial guess for the fit parameters, +\item start from the default minimizer settings and perform some fine tuning after some experience has been acquired, +\item repeat the fit using different starting values for the parameters or their limits, +\item repeat the fit fixing and varying different groups of parameters, +\item use \Code{Minuit2} minimizer with \Code{Migrad} algorithm + (default) to get the most reliable parameter error estimation, +\item try \Code{GSLMultiFit} minimizer or \Code{Minuit2} minimizer with \Code{Fumili} algorithm to get fewer iterations. %\subsection*{Interpretation of errors.} diff --git a/Doc/UserManual/Installation.tex b/Doc/UserManual/Installation.tex index c476227db69de53847de80c39968704f7c0abb1d..3d747418befbfa0af9b568ae115b0d35d684c9a0 100644 --- a/Doc/UserManual/Installation.tex +++ b/Doc/UserManual/Installation.tex @@ -12,27 +12,28 @@ At the moment we support build and installation from source on Unix Platforms (Linux, Mac OS) and -installation using binary installer package on MS Windows 7,8 (see -\SecRef{InstallationUnix} and \SecRef{InstallationWindows}). +installation using binary installer packages on MS Windows 7, 8 (see +\SecRef{InstallationUnix} and \SecRef{InstallationWindows}, respectively). In the next releases we are planning to provide binary installers for Mac OS X and Debian. -We welcome user feedback and/or bug reports related to they installation experience -via \url{http://apps.jcns.fz-juelich.de/redmine/projects/bornagain/issues} +We welcome users feedback and/or bug reports related to their +installation and /or use experience with \BornAgain\ + via \url{http://apps.jcns.fz-juelich.de/redmine/projects/bornagain/issues} -\section{Building and installing on Unix Platforms.} \SecLabel{InstallationUnix} +\section{Building and installing on Unix Platforms} \SecLabel{InstallationUnix} -\BornAgain\ uses \Code{CMake} to configure a build system for compiling and installing the framework. There are three major steps to building \BornAgain\ : +\BornAgain\ uses \Code{CMake} to configure a build system for compiling and installing the framework. There are three major steps to build \BornAgain\ : \begin{enumerate}[1.] -\item Acquire required third-party libraries. -\item Get \BornAgain\ source code. -\item Use \Code{CMake} to build and install software. +\item Acquiring the required third-party libraries. +\item Getting \BornAgain\ source code. +\item Using \Code{CMake} to build and install the software. \end{enumerate} The remainder of this section explains each step in detail. -\subsection{Third-party software.} +\subsection{Third-party software} To successfully build \BornAgain\ a number of prerequisite packages must be installed. \begin{itemize} @@ -41,7 +42,7 @@ To successfully build \BornAgain\ a number of prerequisite packages must be inst \item boost library ($\geq 1.48$) \item GNU scientific library ($\geq 1.15$) \item fftw3 library ($\geq 3.3$) -\item python ($\geq 2.7$, $< 3.0$), python-devel, python-numpy-devel +\item \Python\ ($\geq 2.7$, $< 3.0$), python-devel, python-numpy-devel \end{itemize} \vspace*{2mm} @@ -53,8 +54,9 @@ Other packages are optional \end{itemize} All required packages can be easily installed on most Linux distributions using the system's package -manager. Below we give a few examples for several selected operation systems. Please note, -that other distributions (Fedora, Mint, etc) may have different commands for invoking the package manager and slightly different names of packages (like ``boost'' instead of ``libboost'' etc). Besides that, the installation should be very similar. +manager. Below we give examples for a few selected operation systems. Please note, +that other distributions (Fedora, Mint, etc) may have different +commands for invoking the package manager as well as slightly different names of packages (like ``boost'' instead of ``libboost'' etc). Besides the installation should be very similar. \vspace*{3mm} @@ -63,13 +65,13 @@ that other distributions (Fedora, Mint, etc) may have different commands for inv % --------------- \noindent {\large\bf Ubuntu (12.10, 13.04), Debian (7.1)} \newline -Installing required packages +Installing the required packages \begin{lstlisting}[language=shell, style=commandline] sudo apt-get install git cmake libgsl0-dev libboost-all-dev libfftw3-dev python-dev python-numpy \end{lstlisting} \noindent -Installing optional packages +Installing the optional packages \begin{lstlisting}[language=shell, style=commandline] sudo apt-get install libroot-* root-plugin-* root-system-* ttf-root-installer libeigen3-dev python-matplotlib python-matplotlib-tk \end{lstlisting} @@ -81,19 +83,19 @@ sudo apt-get install libroot-* root-plugin-* root-system-* ttf-root-installer li % --------------- \noindent {\large\bf OpenSuse 12.3} \newline -Adding ``scientific'' repository +Adding the ``scientific'' repository \begin{lstlisting}[language=shell, style=commandline] sudo zypper ar http://download.opensuse.org/repositories/science/openSUSE_12.3 science \end{lstlisting} \noindent -Installing required packages +Installing the required packages \begin{lstlisting}[language=shell, style=commandline] sudo zypper install git-core cmake gsl-devel boost-devel fftw3-devel python-devel python-numpy-devel \end{lstlisting} \noindent -Installing optional packages +Installing the optional packages \begin{lstlisting}[language=shell, style=commandline] sudo zypper install libroot-* root-plugin-* root-system-* root-ttf libeigen3-devel python-matplotlib \end{lstlisting} @@ -110,10 +112,12 @@ sudo zypper install libroot-* root-plugin-* root-system-* root-ttf libeigen3-dev To simplify the installation of third party open-source software on a Mac OS X system we recommend the use of \Code{MacPorts} package manager. The easiest way to install MacPorts is by downloading the \Code{dmg} from \url{www.macports.org/install.php} and running the system's installer. -After the installation new command ``\Code{port}'' will be available in terminal window of your Mac. \ +After the installation new command ``\Code{port}'' will be available +in a terminal window of your Mac. \ + \noindent -Installing required packages +Installing the required packages \begin{lstlisting}[language=shell, style=commandline] sudo port -v selfupdate sudo port install git-core cmake @@ -124,7 +128,7 @@ sudo port install boost -no_single-no_static+python27 \end{lstlisting} \noindent -Installing optional packages +Installing the optional packages \begin{lstlisting}[language=shell, style=commandline] sudo port install py27-matplotlib py27-numpy py27-scipy sudo port install root +fftw3+python27 @@ -134,7 +138,7 @@ sudo port install eigen3 -\subsection{Getting source code} +\subsection{Getting \BornAgain\ source code} \BornAgain\ source can be downloaded at \url{http://apps.jcns.fz-juelich.de/BornAgain} and unpacked with \begin{lstlisting}[language=shell, style=commandline] @@ -152,18 +156,20 @@ git clone git://apps.jcns.fz-juelich.de/BornAgain.git \noindent {\bf\large More about Git} \\ Our Git repository holds two main branches called ``master'' and ``develop''. We consider ``master'' -branch to be the main branch where the source code of HEAD always reflects latest stable release. \Code{git clone} command shown above +branch to be the main branch where the source code of HEAD always +reflects the latest stable release. \Code{git clone} command shown above \begin{enumerate}[1.] \item gives you a source code snapshot corresponding to the latest stable release, \item automatically sets up your local master branch to track our remote master branch, -so you will be able to fetch changes from the remote branch at any time using ``git pull'' command. +so you will be able to fetch changes from the remote branch at any time using \Code{git pull} command. \end{enumerate} -Master branch is updating approximately once per month. +``Master'' branch is updated approximately once per month. % that reflects our release cycle. The second branch, ``develop'' branch, is a snapshot of the current development. This is where any automatic nightly builds are built from. The develop branch is -always expected to work, so to get the most recent features one can switch source code to it by +always expected to work. So in order to get the most recent features +of the source code, one can switch to it by \begin{lstlisting}[language=bash, style=commandline] cd BornAgain git checkout develop @@ -175,9 +181,10 @@ git pull \subsection{Building and installing the code} -\BornAgain\ should be build using \Code{CMake} cross platform build system. -Having third-party libraries installed on the system and \BornAgain\ source code acquired as was explained in -previous sections, type build commands +\BornAgain\ should be built using \Code{CMake} cross platform build system. +Having the third-party libraries installed on your system and +\BornAgain\ source code acquired as explained in the +previous sections, type the build commands \begin{lstlisting}[language=bash, style=commandline] mkdir <build_dir> cd <build_dir> @@ -186,22 +193,23 @@ make \end{lstlisting} \vspace*{3mm} -Here \Code{<source\_dir>} is the name of directory, where \BornAgain\ source code has been -copied, \Code{<install\_dir>} is the directory, where user wants the package -to be installed, and \Code{<build\_dir>} is the directory where building will occur. +Here \Code{<source\_dir>} is the name of the directory, where \BornAgain\ source code has been +copied, \Code{<install\_dir>} is the directory, where you want the package +to be installed, and \Code{<build\_dir>} is the directory where the building will occur. \MakeRemark{About \Code{CMake}}{ -\\Having dedicated directory \Code{<build\_dir>} for build process -is recommended by \Code{CMake}. That allows several builds with different compilers/options from the same source and keeps source directory clean from build remnants. \\ +\\Having a dedicated directory \Code{<build\_dir>} for the build process +is recommended by \Code{CMake}. This allows several builds with +different compilers/options from the same source and keeps the source directory clean from build remnants. \\ } -Compilation process invoked by the command ``make'' lasts about 10 min for an average laptop +The compilation process invoked by the command ``make'' lasts about 10 minutes on an average laptop of 2012 edition. On multi-core machines the compilation time can be decreased by invoking command ``make'' with the parameter ``make -j[N]'', where N is the number of cores. Running functional tests is an optional but recommended step. Command ``make check'' -will compile several additional tests and run them one by one. Every test contains +will compile several additional tests and run them one by one. Each test contains the simulation of a typical GISAS geometry and the comparison on numerical level of simulation results with reference files. Having 100\% tests passed ensures that your local installation is correct. \begin{lstlisting}[language=bash, style=commandline] @@ -214,7 +222,7 @@ Total Test time (real) = 89.19 sec \vspace*{3mm} -The last command ``make install'' copies compiled libraries and some usage examples +The last command ``make install'' copies the compiled libraries and some usage examples into the installation directory. \begin{lstlisting}[language=bash, style=commandline] make install @@ -223,28 +231,28 @@ make install \subsubsection{Troubleshooting} -In the case of complex system setup, with variety of libraries of different versions +In case of a complex system setup, with libraries of different versions scattered across multiple places (\Code{/opt/local}, \Code{/usr} etc.), -you may want to help \Code{CMake} to find libraries in proper place. -In example below -two system variables are defined to force \Code{CMake} to prefer libraries -found in \Code{/opt/local} to other places. +you may want to help \Code{CMake} finding the correct library paths. +In the example below, +two system variables are defined to point \Code{CMake} towards libraries + in \Code{/opt/local} in the first place. \begin{lstlisting}[language=bash, style=commandline] export CMAKE_LIBRARY_PATH=/opt/local/lib:$CMAKE_LIBRARY_PATH export CMAKE_INCLUDE_PATH=/opt/local/include:$CMAKE_INCLUDE_PATH \end{lstlisting} -\subsection{Running first simulation} +\subsection{Running the first simulation} In your installation directory you will find -\begin{lstlisting}[language=bash, style=commandline] +\begin{lstlisting}[language=bash, style=commandline, keywordstyle=\color{black}] ./include - header files for compilation of your C++ program ./lib - libraries to import into python or link with your C++ program ./Examples - directory with examples \end{lstlisting} -Run your first example and enjoy first BornAgain simulation plot. +Run your first example and enjoy the first BornAgain simulation plot. \begin{lstlisting}[language=bash, style=commandline] cd <install_dir>/Examples/python/ex001_CylindersAndPrisms python CylindersAndPrisms.py @@ -253,28 +261,28 @@ python CylindersAndPrisms.py -\section{Installing on Windows Platforms.} \SecLabel{InstallationWindows} +\section{Installing on Windows Platforms} \SecLabel{InstallationWindows} \noindent -{\bf Step I: $~$ installing third party software} \newline +{\bf Step I: $~$ installing the third party software} \newline The current version of \BornAgain\ requires \Code{Python, numpy, matplotlib} -to be installed on the system. If you don't have them already installed, +to be installed on the system. If it is not the case, you can use \Code{PythonXY} installer -at \url{https://code.google.com/p/pythonxy} which, with default installation options, will contain at least these three packages. -The user has to download and install this package before proceeding with -\BornAgain\ installation. +at \url{https://code.google.com/p/pythonxy} which, with the default installation options, contains at least these three packages. +The user has to download and install this package before proceeding to +the installation of \BornAgain. \vspace*{2mm} \noindent -{\bf Step II: $~$ using installation package } \newline -The Windows installation package can be downloaded from \url{http://apps.jcns.fz-juelich.de/BornAgain}. -Double click it to start the installation process, then follow the instructions. +{\bf Step II: $~$ using the installation package } \newline +Windows installation package can be downloaded from \url{http://apps.jcns.fz-juelich.de/BornAgain}. +Double-click on it to start the installation process. And then follow the instructions. \vspace*{2mm} \noindent -{\bf Step IV: $~$ running example} \newline -Run an example by double-clicking on the python script located in the \BornAgain\ installation directory: +{\bf Step IV: $~$ running an example} \newline +Run an example by double-clicking on the \Python\ script located in \BornAgain\ installation directory: \begin{lstlisting}[language=shell, style=commandline] python C:/BornAgain-0.9.1/Examples/python/ex001_CylindersAndPrisms/CylindersAndPrisms.py \end{lstlisting} diff --git a/Doc/UserManual/Introduction.tex b/Doc/UserManual/Introduction.tex index 71757962d250a401a650e14168a60a676693c6a7..d443e4f0c24615461cb3a73651e4c34b7a1fa974 100644 --- a/Doc/UserManual/Introduction.tex +++ b/Doc/UserManual/Introduction.tex @@ -21,7 +21,7 @@ by R. Lazzari \cite{Laz02}. %by R. Lazzari \cite{Laz02}. However, \BornAgain\ also extends this functionality by -supporting an unrestricted number of layers and particles, +supporting the implementation of an unrestricted number of layers and particles, diffuse reflection from rough layer interfaces, particles with inner structures and support for polarized neutrons and magnetic scattering. @@ -29,7 +29,7 @@ Adhering to a strict object-oriented design, \BornAgain\ provides a solid base for future extensions in response to specific user needs. -\BornAgain\ is platform-independent software, +\BornAgain\ is a platform-independent software, with active support for Linux, MacOS and Microsoft Windows. It is a free and open source software provided under terms @@ -45,7 +45,7 @@ please cite this manual as follows: C. Durniak, G. Pospelov, W. Van Herck, J. Wuttke (2013),\newline BornAgain - Software for simulating and fitting X-ray and neutron small-angle scattering at grazing incidence, -version $\langle\ldots\rangle$,\newline +version \UserManualVersionNumber,\newline \url{http://apps.jcns.fz-juelich.de/BornAgain} \end{quote} @@ -68,7 +68,7 @@ A more detailed description of the installation procedure is given in \SecRef{In %while general methodology of simulation with \BornAgain\ and detailed usage examples are %given in \SecRef{Simulation}. %Fitting toolkit provided by the framework are presented in \SecRef{Fitting}. The general methodology of a simulation with \BornAgain\ and detailed simulation usage examples are given in \SecRef{Simulation}. -The fitting toolkit that is provided by the framework, is presented in \SecRef{Fitting}, while +The fitting toolkit, provided by the framework, is presented in \SecRef{Fitting}, while \SecRef{SoftwareArchitecture} provides a brief overview of the software architecture. diff --git a/Doc/UserManual/QuickStart.tex b/Doc/UserManual/QuickStart.tex index 8a6386cb64c51b04792c76346c661131aa68fe45..652106578aa85e7ce8442c6a94775a4d6144ad7e 100644 --- a/Doc/UserManual/QuickStart.tex +++ b/Doc/UserManual/QuickStart.tex @@ -4,8 +4,8 @@ \section{Quick start on Unix Platforms} This section shortly describes how to build and install \BornAgain\ -from source and run the first simulation on Unix Platforms. -More details about installation procedure are given in \SecRef{Installation}. \\ +from source and run the first simulation on Unix Platforms. +Further details about the installation procedure are given in \SecRef{Installation}. \\ \noindent {\bf Step I: $~$ installing third party software} @@ -15,7 +15,7 @@ More details about installation procedure are given in \SecRef{Installation}. \\ \item boost library ($\geq 1.48$) \item GNU scientific library ($\geq 1.15$) \item fftw3 library ($\geq 3.3.1$) -\item python-2.7, python-devel, python-numpy-devel +\item \Python-2.7, python-devel, python-numpy-devel %\item Eigen3 library ($\geq 3.1.0$), optional %\item ROOT framework ($\geq 5.34.00$), optional \end{itemize} @@ -25,7 +25,7 @@ More details about installation procedure are given in \SecRef{Installation}. \\ \noindent {\bf Step II: $~$ getting the source} \newline Download \BornAgain\ source tarball from \url{http://apps.jcns.fz-juelich.de/BornAgain} -or use git repository +or use the following git repository \begin{lstlisting}[language=bash, style=commandline] git clone git://apps.jcns.fz-juelich.de/BornAgain.git \end{lstlisting} @@ -47,7 +47,7 @@ make install \noindent -{\bf Step IV: $~$ running example} +{\bf Step IV: $~$ running an example} \begin{lstlisting}[language=shell, style=commandline] cd <install_dir>/Examples/python/ex001_CylindersAndPrisms python CylindersAndPrisms.py @@ -58,34 +58,36 @@ python CylindersAndPrisms.py \section{Quick start on Windows Platforms} \noindent -{\bf Step I: $~$ installing third party software} \newline +{\bf Step I: $~$ installing the third party software} \newline The current version of \BornAgain\ requires \Code{Python, numpy, matplotlib} to be installed on the system. If you don't have them already installed, -you can use \Code{PythonXY} installer -at \url{https://code.google.com/p/pythonxy} which, with default installation options, will contain at least these three packages. -\BornAgain\ installation. +you can use \Code{PythonXY} installer available +at \url{https://code.google.com/p/pythonxy} which, with default installation options, contains at least these three packages. +%\BornAgain\ installation. \vspace*{2mm} \noindent -{\bf Step II: $~$ using installation package } \newline -The Windows installation package can be downloaded from \url{http://apps.jcns.fz-juelich.de/BornAgain}. -Double click it to start installation process, then follow instructions. +{\bf Step II: $~$ using the installation package } \newline +Windows installation package can be downloaded from \url{http://apps.jcns.fz-juelich.de/BornAgain}. +Double-click on it to start the installation process. Then follow the instructions. \vspace*{2mm} \noindent -{\bf Step III: $~$ running example} \newline -Run an example simulation by double-clicking on the python script located in the \BornAgain\ installation directory: +{\bf Step III: $~$ running the example} \newline +Run an example simulation by double-clicking on the \Python\ script located in the \BornAgain\ installation directory: \begin{lstlisting}[language=shell, style=commandline] python C:/BornAgain-0.9.1/Examples/python/ex001_CylindersAndPrisms/CylindersAndPrisms.py \end{lstlisting} \section{Getting help} -Users of the software who encounter a problem in the installation of the framework or in running a simulation can use a web based issue tracking system -at \url{http://apps.jcns.fz-juelich.de/redmine/projects/bornagain/issues} to provide a bug -report. The same system can be used for requests for new features. -The system is open for all users in read mode, while -submitting of bug reports and feature requests are possible only after a simple registration +Users of the software who encounter problems during the installation +of the framework or during the run of a simulation can use the web-based issue tracking system +at +\url{http://apps.jcns.fz-juelich.de/redmine/projects/bornagain/issues} +to report a bug. The same system can be used to request new features. +This system is open for all users in read mode, while +submitting bug reports and feature requests are possible only after a simple registration procedure. diff --git a/Doc/UserManual/Simulation.tex b/Doc/UserManual/Simulation.tex index 58ffedea33f089fa98a28084b09f7b29996ea8f7..7856f644c671e9f8019e0175e1e8a0aa794f8dcb 100644 --- a/Doc/UserManual/Simulation.tex +++ b/Doc/UserManual/Simulation.tex @@ -7,7 +7,7 @@ A simulation of GISAXS using \BornAgain\ consists of following steps: \item define materials by specifying name and refractive index, \item define embedded particles by specifying shape, size, constituting material, interference function, -\item define layers by specifiying thickness, roughness, material +\item define layers by specifying thickness, roughness, material, \item include particles in layers, specifying density, position, orientation, \item assemble a multilayered sample, \item specify input beam and detector characteristics, @@ -18,9 +18,9 @@ A simulation of GISAXS using \BornAgain\ consists of following steps: %\noindent The sample is built from object oriented building blocks and can be %instead of loading data files. \noindent -User defines all these steps using \BornAgain\ API in Python script and then run -the simulation by executing the script in Python interpreter. -More information about general software architecture and \BornAgain\ internal design +User defines all these steps using \BornAgain\ API in \Python\ script and then run +the simulation by executing the script in \Python\ interpreter. +More information about the general software architecture and \BornAgain\ internal design are given in \SecRef{SoftwareArchitecture}. @@ -32,7 +32,7 @@ are given in \SecRef{SoftwareArchitecture}. surface and pointing upwards. The $x$-axis is perpendicular to the plane of the detector and the $y$-axis is along it. The input and the scattered output beams are each characterized by two angles -$\alpha_i$, $\phi_i$ and $\alpha_f$, $\phi_f$ respectively. Our choice of orientation for the +$\alpha_i$, $\phi_i$ and $\alpha_f$, $\phi_f$, respectively. Our choice of orientation for the angles $\alpha_i$ and $\alpha_f$ is so that they are positive as shown in \reffig{multil3d}. \\ \begin{figure}[h] @@ -40,7 +40,7 @@ angles $\alpha_i$ and $\alpha_f$ is so that they are positive as shown in \reffi \includegraphics[clip=, width=120mm]{Figures/multilayer3d3.eps} \caption[Representation of the scattering geometry.]{Representation of the scattering geometry. $n_j$ is the refractive index of layer $j$ and $\alpha_i$ and $\phi_i$ are the incident - angle of the wave propagating. $\alpha_f$ is the exit angle with respect to the sample's surface and + angles of the wave propagating. $\alpha_f$ is the exit angle with respect to the sample's surface and $\phi_f$ is the scattering angle with respect to the scattering plane. } \label{fig:multil3d} @@ -56,7 +56,7 @@ perpendicular to the $z$-axis. There is also no limitation to the number of layers that could be defined in \BornAgain. Note that the thickness of the top and bottom layer are not defined. \\ -\ImportantPoint{Remark:}{- Order of the different steps for the simulation: \\ +\ImportantPoint{Remark:}{Order of the different steps for the simulation: \\ When assembling the sample, the layers are defined from top to bottom. So in most cases the first layer will be the air layer.}\\ @@ -67,8 +67,8 @@ bottom. So in most cases the first layer will be the air layer.}\\ radius) to three for an ellipsoid (its three main axis lengths).\\ By placing the particles inside or on top of a layer, we impose their vertical positions, whose -values corresponds to the bottoms of the particles. The in-plane distribution of particles is linked with the way the -particles interfere with each other, which is therefore implemented +values correspond to the bottoms of the particles. The in-plane distribution of particles is linked with the way the +particles interfere with each other. It is therefore implemented when dealing with the interference function. \\ %\ImportantPoint{Remark:}{Depth of particles\\ @@ -94,7 +94,7 @@ parameter like, for example, \Code{20.0*micrometer}. \subsection{Programs} -The examples presented in the next paragraphs are written in Python. For tutorials about this +The examples presented in the next paragraphs are written in \Python. For tutorials about this programming language, the users are referred to \cite{Lut09}. %\noindent Note about the version of C++ and Python to run the examples.\\ diff --git a/Doc/UserManual/SimulationExamples.tex b/Doc/UserManual/SimulationExamples.tex index 5628f0cd790c9af1aa870d389c67313cdc55477e..dc955dba5ddf8ea5fdb0d0251d012e6eaa6c21cd 100644 --- a/Doc/UserManual/SimulationExamples.tex +++ b/Doc/UserManual/SimulationExamples.tex @@ -3,11 +3,11 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%\mysection{Example 1}{Example 1: two types of islands on top of -% substrate without interference.} \SecLabel{Example1Python} +\mysection{Example 1: two types of islands on a substrate without interference}{Example 1: two types of islands on top of + substrate without interference} \SecLabel{Example1Python} -\section{Example 1: two types of islands on top of - substrate without interference.} \SecLabel{Example1Python} +%\section{Example 1: two types of islands on top of +% substrate without interference.} \SecLabel{Example1Python} % \sectionmark{Example 1} @@ -15,13 +15,14 @@ In this example, we simulate the scattering from a mixture of cylindrical and prismatic nanoparticles without any interference between them. These particles are placed in air, on top of a substrate.\\ We are going to go through each step of the -simulation. The Python script specific to each stage will be given at +simulation. The \Python script specific to each stage will be given at the beginning of the description. But for the sake of completeness the full code is given -at the end of this section (Listing~\ref{script_ex1}). \\ +in Appendix~\ref{PythonSimulationExampleScript}. \\ \noindent We start by importing different functions from external -modules (line~\ref{import_lib}), for example NumPy, which -is a fundamental package for scientific computing with Python \cite{s:numpy}. In particular, line~\ref{import_end} +modules (line~\ref{import_lib}), for example \Code{NumPy}, which +is a fundamental package for scientific computing with \Python\ +\cite{s:numpy}. In particular, line~\ref{import_end} imports the features of \BornAgain\ software.\\ \begin{lstlisting}[language=python, style=eclipseboxed,name=ex1,nolol] @@ -32,17 +33,15 @@ from libBornAgainCore import * @\label{import_end}@ %%%%%%%%%%%%% -\myparagraph{\underline{First step:} Defining materials} +\myparagraph{\underline{First step:} Defining the materials} \begin{lstlisting}[language=python, style=eclipseboxed,name=ex1,nolol] def RunSimulation(): @\label{def_function}@ # defining materials @\label{material1}@ mAmbience = MaterialManager.getHomogeneousMaterial("Air", 0.0, 0.0) @\label{material2}@ - mSubstrate = MaterialManager.getHomogeneousMaterial("Substrate", - 6e-6, 2e-8) @\label{material3}@ - mParticle = MaterialManager.getHomogeneousMaterial("Particle", 6e-4, - 2e-8 ) @\label{materialparticle}@ + mSubstrate = MaterialManager.getHomogeneousMaterial("Substrate",6e-6, 2e-8) @\label{material3}@ + mParticle = MaterialManager.getHomogeneousMaterial("Particle", 6e-4, 2e-8) @\label{materialparticle}@ \end{lstlisting} \noindent Line~\ref{def_function} marks the beginning of the @@ -60,7 +59,7 @@ materials using function \Code{getHomogeneousMaterial} from class material associated with its complex refractive index n=1-\Code{delta} +i \Code{beta}. \Code{<material\_name>} is later used when referring to this particular material. The three defined materials in this example are \Code{Air} with a refractive -index of 1 (\Code{delta = beta =0}), a \Code{Substrate} associated with a complex refractive index +index of 1 (\Code{delta = beta = 0}), a \Code{Substrate} associated with a complex refractive index equal to $1-6\times 10^{-6} +i2\times 10^{-8} $, and the material of particles, whose refractive index is \Code{n}$=1-6\times 10^{-4}+i2\times 10^{-8}$.\\\\ %\noindent \underline{Remark:} there is no condition on the choice of \Code{name}. @@ -92,7 +91,7 @@ its radius and height, both equal to 5 nanometers in this particular case (see line~\ref{particlescyl1}). Then we associate this shape with the constituting material as in line~\ref{particlescyl2}.\\ -\noindent The same procedure has been applied for the prism in lines~\ref{particlesprism1} and \ref{particlesprism2} respectively. +\noindent The same procedure has been applied for the prism in lines~\ref{particlesprism1} and \ref{particlesprism2}, respectively. %%%%%%%%%%%%% \myparagraph{\underline{Third step:} Characterizing the layers and assembling the sample} @@ -127,18 +126,18 @@ normalized to the total number of particles. Here we have 50\% of cylinders and 50\% of prisms. \\ \ImportantPoint{Remark:}{Depth of particles\\ -The vertical positions of particles in a layer are given in relative -coordinates. For the top layer, the bottom corresponds to +The vertical positions of the particles in a layer are given in relative +coordinates. For the top layer, the bottom of the layer corresponds to \Code{depth}=0 and negative values would correspond to particles floating above layer 1 since the vertical axis, shown in \reffig{multil3d} is pointing upwards. But for all the other layers, it is the top of the layer which corresponds to \Code{depth}=0.}\\ -\noindent Finally lines~\ref{particlesnointerf} and +\noindent Finally, lines~\ref{particlesnointerf} and \ref{particlesinterf} specify that there is \textbf{no coherent interference} between -the waves scattered by these particles. The intensity is calculated by -the incoherent sum of the scattered waves: $\langle |F_n|^2\rangle$, -where $F_n$ is the form factor associated with the particle of type $n$. The way these waves +the waves scattered by these particles. In this case, the intensity is calculated by +the incoherent sum of the scattered waves: $\langle |F_j|^2\rangle$, +where $F_j$ is the form factor associated with the particle of type $j$. The way these waves interfere imposes the horizontal distribution of the particles as the interference reflects the long or short-range order of the @@ -192,8 +191,7 @@ output detector and running the simulation} \begin{lstlisting}[language=python, style=eclipseboxed,name=ex1,nolol] # run simulation @\label{run1}@ simulation = Simulation() @\label{run2}@ - simulation.setDetectorParameters(100,-1.0*degree, 1.0*degree, - 100, 0.0*degree, 2.0*degree, True) @\label{rundetector}@ + simulation.setDetectorParameters(100,-1.0*degree, 1.0*degree, 100, 0.0*degree, 2.0*degree, True) @\label{rundetector}@ simulation.setBeamParameters(1.0*angstrom, 0.2*degree, 0.0*degree) @\label{runbeam}@ simulation.setSample(multi_layer) @\label{runsample}@ simulation.runSimulation() @\label{runsimul}@ @@ -282,25 +280,27 @@ is associated with the output intensity in arbitrary units. } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\section{Example 2: working with sample parameters.} \SecLabel{WorkingWithSampleParameters} +\section{Example 2: working with sample parameters} \SecLabel{WorkingWithSampleParameters} This section gives additional details about the manipulation of sample parameters -at run time, that is after the sample has already been constructed. -For single simulation this is normally not necessary, however it might be useful -during interactive work when user tries to find optimal sample parameters by -running a series of consequent simulations. -Similarly, this task arises when the theoretical model, presented by the sample and the simulation descriptions, is used for the fitting of real data. -In this case fitting kernel has to be informed about existing sample parameters -and has to have a mechanism for changing values of these parameters to find -they optimal values. - -In \BornAgain\ this is done using so called sample parameter pool mechanism -and we will briefly explain it using example from the previous -\SecRef{Example1Python}. - -Inside \BornAgain\ sample is described by a hierarchical tree of objects. -For the multilayer created in previous section this tree can be graphically -represented as shown in Fig.~\ref{fig:sample_tree}. Similar tree can be printed in Python +during run time; that is after the sample has already been constructed. +For a single simulation this is normally not necessary. However it might be useful +during interactive work when the user tries to find optimal sample parameters by +running a series of simulations. +A similar task also arises when the theoretical model, composed of the +description of the sample and of the simulation, is used for fitting real data. +In this case, the fitting kernel requires a list of the existing sample parameters +and a mechanism for changing the values of these parameters in order to find +their optima. + +In \BornAgain\ this is done using the so-called sample parameter pool +mechanism. We are going to briefly explain this approach using the example +of \SecRef{Example1Python}. + +In \BornAgain\ a sample is described by a hierarchical tree of objects. +For the multilayer created in the previous section this tree can be graphically +represented as shown in Fig.~\ref{fig:sample_tree}. Similar trees can +be printed in a \Python\ session by running \Code{multi\_layer.printSampleTree()} \begin{figure}[p!] @@ -403,24 +403,26 @@ session by running \Code{multi\_layer.printSampleTree()} The top \Code{MultiLayer} object is composed of three children, namely -\Code{Layer \#0, Layer Interface \#0} and \Code{Layer \#1}. Children objects -by turn might also be composed into tree-like structure. For example, -\Code{Layer \#0} contains \Code{ParticleDecoration} object which holds information -related to the two types of particles populating the layer. All numerical values which have been used -during sample construction (thickness of layers, size of particles, roughness parameters) are the part of the same tree structure. +\Code{Layer \#0, Layer Interface \#0} and \Code{Layer \#1}. The +children objects might themselves also be decomposed into tree-like structures. For example, +\Code{Layer \#0} contains \Code{ParticleDecoration} object, which holds information +related to the two types of particles populating the layer. All numerical values used +during the sample construction (thickness of layers, size of particles, roughness parameters) are part of the same tree structure. They are marked in the figure with shaded gray boxes. These values are registered in the sample parameter pool using the name -composed from the names of corresponding nodes of the tree and can be accessed/changed -during run time. For example, the \Code{height} of the cylinders populating first layer can be changed from -current $5~nm$ to $1~nm$ by running the command +composed of the corresponding nodes' names. And they can be accessed/changed +during run time. For example, the \Code{height} of the cylinders +populating the first layer can be changed from the +current value of $5~\rm{nm}$ to $1~\rm{nm}$ by running the command \begin{lstlisting}[language=shell, style=commandline] multi_layer.setParameterValue('/MultiLayer/Layer0/ParticleDecoration/ParticleInfo0/Particle/FormFactorCylinder/height', 1.0) \end{lstlisting} -The user can get names and values of all registered sample's parameters using the command +A list of the names and values of all registered sample's parameters +can be displayed using the command \begin{lstlisting}[language=shell, style=commandline] > multi_layer.printParameters() @@ -441,13 +443,15 @@ The sample contains following parameters ('name':value) '/MultiLayer/crossCorrLength':0 \end{lstlisting} -Wildcards \Code{'*'} can be used to reduce typing or to work on group of parameters. In example below first command will change the height of the cylinders in the same way, as in previous example, while the second line will change simultaneously the height of {\it both} cylinders and prisms. +Wildcards \Code{'*'} can be used to reduce typing or to work on a group +of parameters. In the example below, the first command will change the +height of all cylinders in the same way, as in the previous example. The second line will change simultaneously the height of {\it both} cylinders and prisms. \begin{lstlisting}[language=shell, style=commandline] multi_layer.setParameterValue('*FormFactorCylinder/height', 1.0) multi_layer.setParameterValue('*height', 1.0) \end{lstlisting} -The complete example to this section can be found at +The complete example described in this section can be found at \begin{lstlisting}[language=shell, style=commandline] ./Examples/python/fitting/ex001_SampleParametersIntro/SampleParametersIntro.py \end{lstlisting} diff --git a/Doc/UserManual/SoftwareArchitecture.tex b/Doc/UserManual/SoftwareArchitecture.tex index ef378644ee34e87105d452d6860a7ba0b6a36f1f..ebe2fe85235ce5e3711d8f9a7c933101ef9ada52 100644 --- a/Doc/UserManual/SoftwareArchitecture.tex +++ b/Doc/UserManual/SoftwareArchitecture.tex @@ -2,10 +2,10 @@ \chapter{Software architecture}\SecLabel{SoftwareArchitecture} -\BornAgain\ is written in C++ +\BornAgain\ is written in \Code{C++} and uses an object oriented approach to achieve modularity, extensibility and transparency. -This leads to the task driven rather than command driven approach in +This leads to the task driven rather than the command driven approach in different aspects of the simulation and fitting of GISAS data. The user defines the sample structure, beam and detector characteristics and fit parameters using building @@ -13,17 +13,17 @@ blocks -- \Code{classes} -- defined in core libraries of the framework. These buildings blocks are combined by the user according to his current task using one the following approaches: \begin{itemize} -\item The user creates a Python script with a sample description and simulation settings +\item The user creates a \Python\ script with a sample description and simulation settings using the \BornAgain\ API. -The user then runs the simulation by executing the script in the Python interpreter and assesses the -simulation results using his preferred graphics or analysis library, e.g. Python + numpy + matplotlib. -\item The user may write a standalone C++ application linked to the \BornAgain\ libraries. +The user then runs the simulation by executing the script in the \Python\ interpreter and assesses the +simulation results using his preferred graphics or analysis library, e.g. \Python\ + \Code{numpy} + \Code{matplotlib}. +\item The user may write a standalone \Code{C++} application linked to the \BornAgain\ libraries. \item The user interacts with the framework through a graphical user interface (forthcoming). \end{itemize} The object oriented approach in the software design allows users -to have a much higher level of flexibility in sample construction; it also +to have a much higher level of flexibility in the sample construction; it also decouples the building blocks used in the internal calculations and thereby facilitates the creation of new models, with little or no modification to the existing code. @@ -42,12 +42,16 @@ Structure of \BornAgain\ libraries. The general structure of \BornAgain\ and the way the user interacts with it are shown in Fig.~\ref{fig:two_ratios}. The framework consists of two shared libraries, \Code{libBornAgainCore} and -\Code{libBornAgainFit}. Thanks to the Python interface they can be imported into Python as external modules. The library \Code{libBornAgainCore} contains a number of classes, grouped into several class categories, necessary for the description of a model and running a simulation. +\Code{libBornAgainFit}. Thanks to the \Python\ interface they can be imported into \Python\ as external modules. The library \Code{libBornAgainCore} contains a number of classes, grouped into several class categories, necessary for the description of a model and running a simulation. The library \Code{libBornAgainFit} contains a number of minimization engines and interfaces to them, allowing the user to fit real data with the model previously defined. -\BornAgain\ depends from a few external and well established open-source libraries: boost, GNU scientific library, Eigen and Fast Fourier Transformation libraries. They are required to be present on the system to run \BornAgain\ on Unix Platform. In the case of Windows Platform they will be added to the system automatically during \BornAgain\ installation. Other libraries shown -on the plot (ROOT, matplotlib) are optional. +\BornAgain\ depends from a few external and well established +open-source libraries: \Code{boost}, GNU scientific library, Eigen and +Fast Fourier Transformation libraries. They are required to be +installed on the system to run \BornAgain\ on Unix Platforms. In the +case of Windows Platform they are added to the system automatically during \BornAgain\ installation. Other libraries shown +on the plot (\Code{ROOT}, \Code{matplotlib}) are optional. diff --git a/Doc/UserManual/SoftwareDesignOverview.tex b/Doc/UserManual/SoftwareDesignOverview.tex index ac33eb5495488b836ba718405bfc1db7b034f308..0c8eb0552bab8431b1d2b12a80d20463e02a6368 100644 --- a/Doc/UserManual/SoftwareDesignOverview.tex +++ b/Doc/UserManual/SoftwareDesignOverview.tex @@ -8,7 +8,7 @@ These classes constitute the main interface to the software's users, since they \subsection{The Experiment object} -The Experiment class holds all references to data objects that are needed to perform a simulation. These consist of a sample description, possibly implemented by a builder object, detector and beam parameters and finally, a simulation parameter class that defines the different approximations that can be used during a simulation. Besides getters and setters for these fields, the class also contains a runSimulation() method that will generate an ISimulation object that will perform the actual computations. The class diagram for Experiment is shown in \reffig{exp}. +The \Code{Experiment} class holds all references to data objects that are needed to perform a simulation. These consist in a sample description, possibly implemented by a builder object, detector and beam parameters and finally, a simulation parameter class that defines the different approximations that can be used during a simulation. Besides getters and setters for these fields, the class also contains a \Code{runSimulation()} method that will generate an ISimulation object that will perform the actual computations. The class diagram for \Code{Experiment} is shown in \reffig{exp}. \vspace{8mm} \begin{figure}[H] @@ -96,9 +96,9 @@ This interface and two of its subclasses are sketched in \reffig{isample}. -\subsection{The FitSuite class.} \SecLabel{FitSuiteClass} +\subsection{The FitSuite class} \SecLabel{FitSuiteClass} -\subsection{The IMinimizer class.} \SecLabel{IMinimizerClass} +\subsection{The IMinimizer class} \SecLabel{IMinimizerClass} -\subsection{The MinimizerOptions class.} \SecLabel{MinimizerOptionsClass} +\subsection{The MinimizerOptions class} \SecLabel{MinimizerOptionsClass} diff --git a/Doc/UserManual/UserManual.pdf b/Doc/UserManual/UserManual.pdf index 89f37055e2c9578f48fe63810a7173b3b34d7cf0..a63883ba1fc429186570b9341a921d2abf665480 100644 Binary files a/Doc/UserManual/UserManual.pdf and b/Doc/UserManual/UserManual.pdf differ diff --git a/Doc/UserManual/UserManual.tex b/Doc/UserManual/UserManual.tex index e13df7002c5712cdd345b6279def7efada1ecb15..420fa07f232f98f5ca8d2ca9288abe69ab8dda26 100644 --- a/Doc/UserManual/UserManual.tex +++ b/Doc/UserManual/UserManual.tex @@ -110,6 +110,7 @@ %------------------------------------------------------------------------------- \newcommand{\Code}[1]{\texttt{#1}} \newcommand{\BornAgain}{\Code{BornAgain}}% +\newcommand{\Python}{\Code{Python}}% \newcommand{\IsGISAXS}{\Code{IsGISAXS}}% \newcommand{\SecLabel}[1]{\label{sec:#1}}% \newcommand{\SecRef}[1]{Section~\ref{sec:#1}}% @@ -177,6 +178,9 @@ Forschungszentrum J\"ulich GmbH \input{SoftwareDesignOverview} \appendix \input{AppendixListings} + + + %\input{AppendixPhysics} \bibliographystyle{switch} diff --git a/Doc/UserManual/jw7.bib b/Doc/UserManual/jw7.bib index af2e5ca756b3c8f006f34bbac5003b1c9e28b3e2..1b16d37a53c353bd11a3887e410e585361267de9 100644 --- a/Doc/UserManual/jw7.bib +++ b/Doc/UserManual/jw7.bib @@ -204,6 +204,7 @@ j=zpc, v=4, p=226, y=1889, x="exp-A/T", c="C"} @Art{Arr75, a={D'Arrigo,G}, j=jcp, v=63, p=61, y=1975, x="otp.usound", c="C"} +@Buk{AnLu07, a={Antoniou,A and Lu,W.-S.}, t={Practical Optimization}, f={Springer US}, y=2007} @Art{AsFS00, a={Aschauer,H and Fleischmann,A and Schanzer,C and Steichele,E}, j=pyB, v=283, p=323, y=2000, x="frm2" } @Art{AsAG90, a={Aschauer,R and Asenbaum,A and Gerl,H}, @@ -4975,3 +4976,32 @@ this is delightful reading for a member of the latter community.}} acquired.} } @Any{tau:R7261, a={Wuttke,J and Schir\`o,G and Weik,M and Lohstroh,W}, t={MLZ Experimental Report 7261 (TOFTOF 2013)} } + +% References for BornAgain manual +@Any{MinuitURL, + t = {Minuit user's guide, \url{http://seal.web.cern.ch/seal/documents/minuit/mnusersguide.pdf}} +} + +@Any{GSLMultiMinURL, + t = {\url{http://www.gnu.org/software/gsl/manual/html_node/Multidimensional-Minimization.html}} +} + +@Any{GSLMultiFitURL, + t = {\url{http://www.gnu.org/software/gsl/manual/html_node/Nonlinear-Least_002dSquares-Fitting.html#Nonlinear-Least_002dSquares-Fitting}} +} + +@Any{GSLSimAnURL, + t = {\url{http://www.gnu.org/software/gsl/manual/html_node/Simulated-Annealing.html}} +} + +@Any{mntutorial, + t = {\url{http://seal.web.cern.ch/seal/documents/minuit/mntutorial.pdf}} +} + +@Any{mnerror, +t = {\url{http://seal.web.cern.ch/seal/documents/minuit/mnerror.pdf}} +} + +@Any{minuitv94.1, +t = {\url{http://hep.fi.infn.it/minuit.pdf}} +} \ No newline at end of file diff --git a/Tests/UnitTests/TestCore/FormFactorTest.h b/Tests/UnitTests/TestCore/FormFactorTest.h new file mode 100644 index 0000000000000000000000000000000000000000..46e10f68ae4d0793cf3928c78b6387ec049afeaf --- /dev/null +++ b/Tests/UnitTests/TestCore/FormFactorTest.h @@ -0,0 +1,295 @@ +// ************************************************************************** // +// +// BornAgain: simulate and fit scattering at grazing incidence +// +//! @file FormFactorTest.h +//! @brief Defines unit test for Form factors. +//! +//! @homepage http://apps.jcns.fz-juelich.de/BornAgain +//! @license GNU General Public License v3 or higher (see COPYING) +//! @copyright Forschungszentrum Jülich GmbH 2013 +//! @authors Scientific Computing Group at MLZ Garching +//! @authors C. Durniak, G. Pospelov, W. Van Herck, J. Wuttke +// +// ************************************************************************** // +#ifndef FORMFACTORTEST_H +#define FORMFACTORTEST_H + +#include "FormFactorBox.h" +#include "FormFactorCone.h" +#include "FormFactorCylinder.h" +#include "FormFactorEllipsoid.h" +#include "FormFactorFullSphere.h" +#include "FormFactorParallelepiped.h" +#include "FormFactorPrism3.h" +#include "FormFactorPrism6.h" +#include "FormFactorPyramid.h" +#include "FormFactorSphere.h" +//#include "FormFactorFullSpheroid.h" +//#include "FormFactorHemiSpheroid.h" +#include "FormFactorTetrahedron.h" + +#include "gtest/gtest.h" + +class FormFactorTest : public ::testing::Test +{ + protected: + FormFactorTest(){} + virtual ~FormFactorTest(){} +}; + +// Test form factor of a box +TEST_F(FormFactorTest, Box) +{ + double length = 6.; + double height = 5.; + double width = 7.; + double volume = length*height*width; + + FormFactorBox box(length, width, height); + + EXPECT_EQ(7., box.getWidth()); + EXPECT_EQ(5., box.getHeight()); + EXPECT_EQ(3., box.getRadius()); + EXPECT_EQ(volume, box.getVolume()); + EXPECT_EQ(3, box.getNumberOfStochasticParameters()); + + FormFactorBox *boxclone = box.clone(); + + EXPECT_EQ(7., boxclone->getWidth()); + EXPECT_EQ(5., boxclone->getHeight()); + EXPECT_EQ(3., boxclone->getRadius()); + EXPECT_EQ(volume, boxclone->getVolume()); + EXPECT_EQ(3, boxclone->getNumberOfStochasticParameters()); +} + +// Test form factor of a cone - Check form factor +TEST_F(FormFactorTest, Cone) +{ + double radius = 3.; + double height = 5.; + double alpha = 0.5; + double tan_alpha = std::tan(alpha); + double volume = M_PI/3.*tan_alpha*( + radius*radius*radius + -(radius-height/tan_alpha) + *(radius-height/tan_alpha) + *(radius-height/tan_alpha)); + + FormFactorCone cone(radius, height, alpha); + + EXPECT_EQ(5., cone.getHeight()); + EXPECT_EQ(volume, cone.getVolume()); + EXPECT_EQ((int)3, cone.getNumberOfStochasticParameters()); + + FormFactorCone *coneclone = cone.clone(); + + EXPECT_EQ(5., coneclone->getHeight()); + EXPECT_EQ(volume, coneclone->getVolume()); + EXPECT_EQ((int)3, coneclone->getNumberOfStochasticParameters()); +} + +// Test form factor of a cylinder +TEST_F(FormFactorTest, Cylinder) +{ + double radius = 3.; + double height = 5.; + double volume = M_PI*radius*radius*height; + + FormFactorCylinder cylinder(height,radius); + + EXPECT_EQ(5., cylinder.getHeight()); + EXPECT_EQ(3., cylinder.getRadius()); + EXPECT_EQ(volume, cylinder.getVolume()); + EXPECT_EQ((int)2, cylinder.getNumberOfStochasticParameters()); + + FormFactorCylinder *cylinderclone = cylinder.clone(); + + EXPECT_EQ(5., cylinderclone->getHeight()); + EXPECT_EQ(3., cylinderclone-> getRadius()); + EXPECT_EQ(volume, cylinderclone-> getVolume()); + EXPECT_EQ((int)2, cylinderclone-> getNumberOfStochasticParameters()); +} + +// Test form factor of an ellipsoid - check form factor +TEST_F(FormFactorTest, Ellipsoid) +{ + double radius = 3.; + double width = 5.; + double height = 4; + double alpha = 0.5; + //double volume = ; + + FormFactorEllipsoid ellipsoid(radius, width, height, alpha); + + EXPECT_EQ(4., ellipsoid.getHeight()); + EXPECT_EQ(3., ellipsoid.getRadius()); + EXPECT_EQ(5., ellipsoid.getWidth()); + //EXPECT_EQ(5., ellipsoid.getVolume()); + EXPECT_EQ(2, ellipsoid.getNumberOfStochasticParameters()); + + //FormFactorEllipsoid *ellispoidclone = ellipsoid.clone(); + +} + +// Test form factor of a full sphere +TEST_F(FormFactorTest, FullSphere) +{ + double radius = 5.; + double volume = 4./3.*M_PI*radius*radius*radius; + + FormFactorFullSphere fullsphere(radius); + + EXPECT_EQ(5., fullsphere.getRadius()); + EXPECT_EQ(2.*5., fullsphere.getHeight()); + EXPECT_EQ(volume, fullsphere.getVolume()); + EXPECT_EQ((int)1, fullsphere.getNumberOfStochasticParameters()); + + FormFactorFullSphere *fullsphereclone = fullsphere.clone(); + EXPECT_EQ(5., fullsphereclone->getRadius()); + EXPECT_EQ(2.*5., fullsphereclone->getHeight()); + EXPECT_EQ(volume, fullsphereclone->getVolume()); + EXPECT_EQ((int)1, fullsphereclone->getNumberOfStochasticParameters()); +} + +// Test form factor of a parallelepiped +TEST_F(FormFactorTest, Parallelepiped) +{ + double radius = 11.; + double height = 10.; + double volume = 4.*radius*radius*height; + + FormFactorParallelepiped parallelepiped(height, radius); + + EXPECT_EQ(10., parallelepiped.getHeight()); + EXPECT_EQ(11., parallelepiped.getRadius()); + EXPECT_EQ(volume, parallelepiped.getVolume()); + EXPECT_EQ((int)2, parallelepiped.getNumberOfStochasticParameters()); + + FormFactorParallelepiped *parallelepipedclone = parallelepiped.clone(); + + EXPECT_EQ(10., parallelepipedclone-> getHeight()); + EXPECT_EQ(11., parallelepipedclone-> getRadius()); + EXPECT_EQ(volume, parallelepipedclone-> getVolume()); + EXPECT_EQ((int)2, parallelepipedclone-> getNumberOfStochasticParameters()); +} + +// Test form factor of a prism3 +TEST_F(FormFactorTest, Prism3) +{ + double height = 4.; + double half_side = 3.; + double volume = sqrt(3.)*height*half_side*half_side; + + FormFactorPrism3 prism3(height, half_side); + + EXPECT_EQ(4., prism3.getHeight()); + EXPECT_EQ(3., prism3.getHalfSide()); + EXPECT_EQ(volume, prism3.getVolume()); + EXPECT_EQ((int)2, prism3.getNumberOfStochasticParameters()); + + FormFactorPrism3 *prism3clone = prism3.clone(); + + EXPECT_EQ(double(4.), prism3clone->getHeight()); + EXPECT_EQ(3., prism3clone->getHalfSide()); + EXPECT_EQ(volume, prism3clone->getVolume()); + EXPECT_EQ((int)2, prism3clone->getNumberOfStochasticParameters()); +} + +// Test form factor of a prism6 +TEST_F(FormFactorTest, Prism6) +{ + double height = 4.; + double half_side = 3.; + double volume = 2.*sqrt(3.)*height*half_side*half_side; + + FormFactorPrism6 prism6(height, half_side); + + EXPECT_EQ(4., prism6.getHeight()); + EXPECT_EQ(3., prism6.getHalfSide()); + EXPECT_EQ(volume, prism6.getVolume()); + EXPECT_EQ((int)2, prism6.getNumberOfStochasticParameters()); + + FormFactorPrism6 *prism6clone = prism6.clone(); + + EXPECT_EQ(4., prism6clone->getHeight()); + EXPECT_EQ(3., prism6clone->getHalfSide()); + EXPECT_EQ(volume, prism6clone->getVolume()); + EXPECT_EQ((int)2, prism6clone->getNumberOfStochasticParameters()); +} + +// Test form factor of a pyramid +TEST_F(FormFactorTest, Pyramid) +{ + double height = 4.; + double half_side = 3.; + double alpha = 0.5; + double tga = std::tan(alpha); + double HdivRtga = height/half_side/tga; + double volume = 4./3.*tga*half_side*half_side*half_side*( 1. + - (1. - HdivRtga)*(1. - HdivRtga)*(1. - HdivRtga)); + + FormFactorPyramid pyramid(height, half_side, alpha); + + EXPECT_EQ(4., pyramid.getHeight()); + EXPECT_EQ(3., pyramid.getHalfSide()); + EXPECT_EQ(0.5, pyramid.getAlpha()); + EXPECT_EQ(volume, pyramid.getVolume()); + EXPECT_EQ((int)3, pyramid.getNumberOfStochasticParameters()); + + FormFactorPyramid *pyramidclone = pyramid.clone(); + + EXPECT_EQ(4., pyramidclone->getHeight()); + EXPECT_EQ(3., pyramidclone->getHalfSide()); + EXPECT_EQ(0.5, pyramidclone->getAlpha()); + EXPECT_EQ(volume, pyramidclone->getVolume()); + EXPECT_EQ((int)3, pyramidclone->getNumberOfStochasticParameters()); +} + +// Test form factor of a sphere +TEST_F(FormFactorTest, Sphere) +{ + double radius = 5.; + double height = 3.; + double HdivR = height/radius; + double volume = M_PI/3.*radius*radius*radius + *(3.*HdivR -1. - (HdivR - 1.)*(HdivR - 1.)*(HdivR - 1.)); + + FormFactorSphere sphere(radius, height); + + EXPECT_EQ(3., sphere.getHeight()); + EXPECT_EQ(volume, sphere.getVolume()); + EXPECT_EQ((int)2, sphere.getNumberOfStochasticParameters()); + + FormFactorSphere *sphereclone = sphere.clone(); + + EXPECT_EQ(3., sphereclone->getHeight()); + EXPECT_EQ((int)2, sphereclone->getNumberOfStochasticParameters()); +} + +// Test form factor of a tetrahedron - check form factor +TEST_F(FormFactorTest, Tetrahedron) +{ + double height = 5.; + double half_side = 3.; + double alpha = 0.5; + //double volume = half_side*half_side*height/sqrt(3.); + + FormFactorTetrahedron tetrahedron(height, half_side, alpha); + + EXPECT_EQ(5., tetrahedron.getHeight()); + EXPECT_EQ(3., tetrahedron.getHalfSide()); + EXPECT_EQ(0.5, tetrahedron.getAlpha()); + //EXPECT_EQ(volume, tetrahedron.getVolume()); + EXPECT_EQ((int)3, tetrahedron.getNumberOfStochasticParameters()); + + FormFactorTetrahedron *tetrahedronclone = tetrahedron.clone(); + + EXPECT_EQ(5., tetrahedronclone->getHeight()); + EXPECT_EQ(3., tetrahedronclone->getHalfSide()); + EXPECT_EQ(0.5, tetrahedronclone->getAlpha()); + //EXPECT_EQ(volume, tetrahedronclone->getVolume()); + EXPECT_EQ((int)3, tetrahedronclone->getNumberOfStochasticParameters()); +} + +#endif // FORMFACTORTEST_H