Skip to content
Snippets Groups Projects
Commit 2a3a182d authored by Wuttke, Joachim's avatar Wuttke, Joachim
Browse files

[physman3] Ingest several internal reports into DevRef ()

Merging branch 'physman3'  into 'main'.

See merge request !1657
parents 4a04edf4 4563dcb1
No related branches found
No related tags found
1 merge request!1657Ingest several internal reports into DevRef
Pipeline #100931 passed
Showing
with 9833 additions and 539 deletions
No preview for this file type
......@@ -21,14 +21,12 @@
% makeindex -s nomencl.ist $T.nlo -o $T.nls
% xelatex $T
\documentclass[a4paper,11pt,fleqn]{report}\usepackage[final]{graphicx}
%\documentclass[a4paper,11pt,fleqn,draft]{report}\usepackage[final]{graphicx}
%\documentclass[a4paper,11pt,fleqn]{report}\usepackage[final]{graphicx}
\documentclass[a4paper,11pt,fleqn,draft]{report}\usepackage[final]{graphicx}
%\documentclass[a4paper,11pt,fleqn,draft]{report}\usepackage[draft]{graphicx}
\def\shorttitle{BornAgain Developers Reference}
\def\longtitle{\shorttitle\\ Physics and Numerics}
\def\authors{Joachim Wuttke and other BornAgain developers}
\def\version{20x}
\input{Setup}
......@@ -41,14 +39,14 @@
\tableofcontents\cleardoublepage
\include{Preface}
%\include{Preface}
\pagemode{\thechapter}
\include{Scattering}
\include{Multilayers}
\include{Roughness}
\include{Polarized}
%\include{Assemblies}
%\include{Roughness}
%\include{PolarizedScattering}
\include{Instrument}
%\appendix %\addtocontents{toc}{\protect\setcounter{tocdepth}{1}}
......
......@@ -242,10 +242,10 @@ through the following steps:
\end{array}
\end{equation}
\Note{\indent Transforming detector images
Transforming detector images
from pixel coordinates into the $q_y$,~$q_z$~plane is not implemented in \BornAgain,
and not on our agenda.
We would, however, like to hear about use cases.}
We would, however, like to hear about use cases.
When simulating and fitting experimental data with \BornAgain,
detector images remain unchanged.
......
......@@ -89,8 +89,10 @@
\hyphenation{
Born-Again
equi-dis-tant
Laz-za-ri
MacOS
nano-par-ti-cle nano-par-ti-cles
para-crys-tal
Schrö-ding-er
wave-num-ber}
wave-num-ber
Wuttke}
This diff is collapsed.
This diff is collapsed.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% BornAgain Developers Reference
%%
%% homepage: http://www.bornagainproject.org
%%
%% copyright: Forschungszentrum Jülich GmbH 2015
%%
%% license: Creative Commons CC-BY-SA
%%
%% authors: Scientific Computing Group at MLZ Garching
%% C. Durniak, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\chapter{Polarized GISAS} \label{SPol}
In this chapter,
we generalize our treatment of wave propagation and
grazing-incidence small-angle scattering
to polarized neutrons.
\index{Neutron!polarized}
\index{Polarization!neutron}
We therefore need to study spinor wave equations,
in contrast to the scalar theory of the previous chapter.
\MissingSection
\iffalse
%===============================================================================
\section{Polarized neutrons}\label{Snpol}
%===============================================================================
\Work{This is preliminary and incomplete material waiting for revision and extension}
%===============================================================================
\subsection{Wave equation and propagation within one layer}
%===============================================================================
%\cite{Deak_ppt, PhysRevB.76.224420, Deak2001113, PhysRevB.53.6158}.
%\cite{RevModPhys.23.287}
To allow for polarization-dependent interactions,
we replace the squared index of refraction $n^2$
by $1+\uu\chi$, where $\uu\chi$ is a $2\times 2$ susceptibility matrix.
The wave equation \cref{EHomoK} for layer~$l$ becomes
\begin{equation}\label{Ewaveqp}
(\Delta +K^2 +K^2 \uu\chi_l) \u\psi(\r)= 0,
\end{equation}
where $\u\psi(\r)$ is a two-component spinor wavefunction,
with components $\psi_\UP(\r)$ and~$\psi_\DN(\r)$.
At interfaces between layers,
both spinor components of $\u\psi(\r)$ and $\Nabla\u\psi(\r)$
must evolve continuously.
The reasons for the factorization \cref{Ekpar} still apply,
and so we can write
\begin{equation}\label{Ewave3p}
\u\psi(\r) = \u\psi(z) \e^{i \k_\parallel\r_\parallel}.
\end{equation}
As before, $\k_\parallel$ is constant across layers.
The wave equation~\cref{Ewaveqp} reduces to
\begin{equation}\label{Ewavezp}
\left(\partial_z^2 + K^2 + K^2\uu\chi_l - k_\parallel^2 \right) \u\psi(z) = 0.
\end{equation}
We abbreviate
\begin{equation}
\uu H_l \coloneqq K^2(1+\uu\chi_l)-k_\parallel^2
\end{equation}
so that the wave equation becomes simply
\begin{equation}\label{Ewaveqp2}
\left(\partial_z^2 + \uu H_l\right) \u\psi(z) = 0.
\end{equation}
The solution is
\begin{equation}\label{Epsizp}
\u\psi_l(z)
= \sum_{k=1}^2 \u x_{l k}\left(\alpha_{l k}\e^{i p_{l k}(z-z_k)}
+ \beta_{l k}\e^{-i p_{l k}(z-z_k)}\right),
\end{equation}
where the $\u x_{l k}$ are eigenvectors of $\uu H_l$
with eigenvalues $p_{l k}^2$:
\begin{equation}
\left( -p_{l k}^2 + \uu H_l \right) \u x_{l k} = 0
\;\text{ for }\;l=1,2.
\end{equation}
In a reproducible algorithm,
the eigenvectors $\u x_{l k}$ must be chosen according to some arbitrary
normalization rule,
for instance
\begin{equation}
|\u x_{l k}|=1,\quad x_{il\UP} \text{ real and nonnegative}.
\end{equation}
Similarly,
a rule is needed how to handle the case of one degenerate eigenvalue,
which includes in particular the case of scalar interactions.
%-------------------------------------------------------------------------------
\subsection{Wave propagation across layers}
%-------------------------------------------------------------------------------
Generalizing \Cref{Sacrolay},
we introduce the coefficient vector
\begin{equation}
c_l \coloneqq {(\alpha_{l1}, \alpha_{l2}, \beta_{l1}, \beta_{l2})}^\text{T}.
\end{equation}
To match solutions for neighboring layers,
continuity is requested for both spinorial components
of $\u\psi$ and $\Nabla\u\psi$.
We have at the bottom of layer~$l$
\begin{equation}\label{EFcFDcp}
F_l c_l = F_{l+1} D_{l+1} c_{l+1},
\end{equation}
where the matrices are
\begin{equation}
F_l \coloneqq \left(\begin{array}{cccc}
x_{i1\UP} &x_{i2\UP} &x_{i1\UP} &x_{i2\UP} \\
x_{i1\DN} &x_{i2\DN} &x_{i1\DN} &x_{i2\DN} \\
x_{i1\UP}p_{l1}&x_{i2\UP}p_{l2}&-x_{i1\UP}p_{l1}&-x_{i2\UP}p_{l2}\\
x_{i1\DN}p_{l1}&x_{i2\DN}p_{l2}&-x_{i1\DN}p_{l1}&-x_{i2\DN}p_{l2}
\end{array}\right)
\end{equation}
and
\begin{equation}
D_l \coloneqq \text{diag}(\delta_{l1}, \delta_{l2}, \delta_{l1}^*, \delta_{l2}^*)
\end{equation}
with the phase factor
\begin{equation}
\delta_{l k} \coloneqq \e^{ip_{l k}d_k}.
\end{equation}
Note that matrix $F_l$ has the block form
\begin{equation}
F_l
=\left(\begin{array}{ll}\uu x_l&\hphantom{-}\uu x_l\\[1ex]
\uu x_l\; \uu P_l&-\uu x_l\; \uu P_l\end{array}\right)
= \uu x_l \cdot
\left(\begin{array}{cc}\uu 1&\uu 1\\[1ex]
\uu P_l&-\uu P_l\end{array}\right),
\end{equation}
with
\begin{equation}
\uu x_l \coloneqq
\left(\u x_{l1}, \u x_{l2}\right),
\quad
\uu P_l \coloneqq
\text{diag}\left(p_{l1},p_{l2}\right).
\end{equation}
This facilitates the computation of the inverse
\begin{equation}
F_l^{-1}
= \frac{1}{2}
\left(\begin{array}{cc}\uu 1&\hphantom{-}\uu P_l^{-1}\\[1.2ex]
\uu 1 &-\uu P_l^{-1}\end{array}\right)
\cdot\uu x_l^{-1},
\end{equation}
which is needed for the transfer matrix $M_l$,
defined as in \cref{EMil}.
With the new meaning of $c_l$ and $M_l$,
the recursion \cref{EcMc} and the explicit solution~\cref{EAtildel}
hold as derived above.
To resolve~\cref{Eci} for the reflected amplitudes $\alpha_{0l}$
as function of the incident amplitudes $\beta_{0l}$,
we choose the notations
\begin{equation}
\u\alpha_l
\coloneqq \left(\begin{array}{c}\alpha_{l1}\\\alpha_{l2}\end{array}\right),\quad
\u\beta_l
\coloneqq \left(\begin{array}{c}\beta_{l1}\\\beta_{l2}\end{array}\right),\quad
M\coloneqq M_1 ... M_N % TODO restore \cdots
\eqqcolon \left(\begin{array}{cc}\uu m_{11}&\uu m_{12}\\
\uu m_{21}&\uu m_{22}\end{array}\right),
\end{equation}
where the $\uu m_{l k}$ are $2\times2$ matrices.
Eq.~\cref{Eci} then takes the form
\begin{equation}
\left(\begin{array}{c}\u\alpha_{0}\\\u\beta_{0}\end{array}\right)
=
\left(\begin{array}{cc}\uu m_{11}&\uu m_{12}\\
\uu m_{21}&\uu m_{22}\end{array}\right)
\left(\begin{array}{c}\u{0}\\\u\beta_{N}\end{array}\right),
\end{equation}
which immediately yields
\begin{equation}
\u\alpha_0 = \uu m_{12}\,\uu m_{22}^{-1}\,\u\beta_0.
\end{equation}
\fi
......@@ -21,7 +21,7 @@ For information about BornAgain,
see the reference paper Pospelov et al 2020 \cite{PoHB20}
and the web docs at \url{https://www.bornagainproject.org}.
This reference provides some of theory behind the code.
This reference provides some of the theory behind the code.
It is principally targetted at fellow developers.
Mathematical notations are explained in the symbol index, page~\pageref{Snomencl}.
This diff is collapsed.
......@@ -24,18 +24,12 @@
\chaptermark{Scattering}%
\index{Elastic scattering|seealso{Cross section}}%
This chapter provides a self-contained introduction
into the theory of neutron and X-ray scattering,
This chapter introduces the formalism to described neutron and X-ray propagation
and scattering,
as needed for the analysis of grazing-incidence small-angle scattering (GISAS) experiments.
\index{Grazing-incidence small-angle scattering}%
\index{Scattering!grazing incidence|see{Grazing-incidence small-angle scattering}}%
\index{GISAS|see{Grazing-incidence small-angle scattering}}%
In \Cref{Swave},
a generic wave equation is derived.
In \Cref{SDWBA},
it is solved in first-order distorted-wave Born approximation (DWBA).
\index{DWBA|see {Distorted-wave Born approximation}}%
\index{Distorted-wave Born approximation}%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Wave propagation}\label{Swave}
......
......@@ -383,15 +383,11 @@
{\marginSymbolLarge{fig/icons/Arbeiten.png}{TODO}}
\defineBox{boxWarn}{boxxWarn}{magenta!40}{magenta}
{\marginSymbolLarge{fig/icons/Achtung.png}{WARN}}
\defineBox{boxNote}{boxxNote}{yellow!33}{yellow}{{}}
\defineBox{boxEmph}{boxxEmph}{green!20}{green}{{}}
\def\Warn#1{\begin{boxWarn}#1\end{boxWarn}}
\def\Work#1{\begin{boxWork}#1\end{boxWork}}
\def\Note#1{\begin{boxNote}#1\end{boxNote}}
\def\MissingSection{\begin{boxWork}\ldots\ to be written \ldots\end{boxWork}}
\def\MissingSection{\Work{to be written \ldots}}
%-------------------------------------------------------------------------------
% Hyper ref and clever ref
......
......@@ -26,7 +26,7 @@
Work in progress\\[2ex]
Last updated \today\\\vfill
\large
\authors\\[10mm]
edited by Joachim Wuttke\\[10mm]
\large
Scientific Computing Group\\[.2ex]
J\"ulich Centre for Neutron Science\\[.2ex]
......@@ -42,14 +42,20 @@ Forschungszentrum J\"ulich GmbH
% Back of title page.
\thispagestyle{empty}
For information about BornAgain,
see the reference paper Pospelov et al 2020 \cite{PoHB20}
and the web docs at \url{https://www.bornagainproject.org}.
This reference provides some of the theory behind the code.
It is principally targetted at fellow developers.
~\vfill
\noindent
\begin{tabular}{@{}p{.25\textwidth}@{}p{.75\textwidth}@{}}
Homepage: &\url{http://www.bornagainproject.org}\\[2ex]
%Homepage: &\url{http://www.bornagainproject.org}\\[2ex]
Copyright: &Forschungszentrum Jülich GmbH 2013--\the\year\\[2ex]
Licenses: &Software: GNU General Public License version 3 or higher\\
&Documentation: Creative Commons CC-BY-SA\\[2ex]
Authors: &\authors\\
License: &Creative Commons CC-BY-SA\\[2ex]
Editor: &Joachim Wuttke\\[2ex]
Authors: &BornAgain developers, see git log\\
&Scientific Computing Group\\
&at Heinz Maier-Leibnitz Zentrum (MLZ) Garching\\[2ex]
Disclaimer: &Software and documentation are work in progress.\\
......
This diff is collapsed.
This diff is collapsed.
......@@ -383,14 +383,9 @@ double ReSample::sliceBottomZ(size_t i) const
return m_stack.at(i).low();
}
bool ReSample::containsMagneticMaterial() const
{
return m_polarized;
}
bool ReSample::polarizing() const
{
return containsMagneticMaterial() || m_sample.externalField() != R3{};
return m_polarized || m_sample.externalField() != R3{};
}
bool ReSample::hasRoughness() const
......@@ -403,14 +398,14 @@ bool ReSample::hasRoughness() const
Fluxes ReSample::fluxesIn(const R3& k) const
{
if (m_polarized)
if (polarizing())
return Compute::SpecularMagnetic::fluxes(m_stack, k, true);
return Compute::SpecularScalar::fluxes(m_stack, k);
}
Fluxes ReSample::fluxesOut(const R3& k) const
{
if (m_polarized)
if (polarizing())
return Compute::SpecularMagnetic::fluxes(m_stack, -k, false);
return Compute::SpecularScalar::fluxes(m_stack, -k);
}
......
......@@ -49,7 +49,6 @@ public:
const OwningVector<const ReLayout>& relayouts() const;
double sliceTopZ(size_t i) const;
double sliceBottomZ(size_t i) const;
bool containsMagneticMaterial() const;
bool polarizing() const; //!< Contains magnetic material, or nonzero magnetic field
bool hasRoughness() const;
const MultiLayer& sample() const { return m_sample; }
......
......@@ -59,13 +59,6 @@ SliceStack SliceStack::setBField(const R3& externalField)
return *this;
}
bool SliceStack::containsMagneticMaterial() const
{
return std::any_of(this->cbegin(), this->cend(), [](const Slice& slice) -> bool {
return slice.material().isMagneticMaterial();
});
}
const LayerRoughness* SliceStack::bottomRoughness(size_t i_slice) const
{
if (i_slice + 1 < size())
......
......@@ -48,7 +48,6 @@ public:
SliceStack setBField(const R3& externalField);
bool containsMagneticMaterial() const;
const LayerRoughness* bottomRoughness(size_t i_slice) const;
RoughnessModel roughnessModel() const { return m_roughness_model; }
......
......@@ -183,7 +183,7 @@ Fluxes Compute::SpecularMagnetic::fluxes(const SliceStack& slices, const R3& k,
ASSERT(slices.size() == kz.size());
Fluxes result;
for (auto& coeff : ::computeFlux(slices, kz, slices.roughnessModel(), forward))
for (const MatrixFlux& coeff : ::computeFlux(slices, kz, slices.roughnessModel(), forward))
result.emplace_back(new MatrixFlux(coeff));
return result;
......
......@@ -13,8 +13,6 @@
// ************************************************************************************************
#include "Resample/Specular/ComputeFluxScalar.h"
#include <numbers>
using std::numbers::pi;
#include "Base/Math/Functions.h"
#include "Base/Util/Assert.h"
#include "Resample/Flux/ScalarFlux.h"
......@@ -22,7 +20,8 @@ using std::numbers::pi;
#include "Resample/Slice/SliceStack.h"
#include "Sample/Interface/LayerRoughness.h"
#include "Sample/Multilayer/Layer.h"
#include <stdexcept>
#include <numbers>
using std::numbers::pi;
namespace {
......@@ -86,21 +85,20 @@ std::vector<Spinor> computeTR(const SliceStack& slices, const std::vector<comple
}
// Calculate transmission/refraction coefficients t_r for each layer, from bottom to top.
TR[X[N - 1]] = {1.0, 0.0};
// Starting from TR[X[N - 1]] = {1.0, 0.0} as set above.
std::vector<complex_t> factors(N - 1);
for (size_t i = N - 1; i > 0; i--) {
size_t jthis = X[i - 1];
size_t jlast = X[i];
const size_t jthis = X[i - 1];
const size_t jlast = X[i];
const auto* roughness = slices.bottomRoughness(jthis); // TODO verify
const double sigma = roughness ? roughness->sigma() : 0.;
const auto [mp, mm] = transition(kz[jthis], kz[jlast], sigma, r_model);
const auto [slp, slm] = transition(kz[jthis], kz[jlast], sigma, r_model);
const complex_t delta = exp_I(kz[jthis] * slices[jthis].thicknessOr0());
complex_t S = delta / (mp + mm * TR[jlast].v);
factors[i - 1] = S;
TR[jthis].v = delta * (mm + mp * TR[jlast].v) * S;
const complex_t f = delta / (slp + slm * TR[jlast].v);
factors[i - 1] = f;
TR[jthis].v = delta * (slm + slp * TR[jlast].v) * f;
}
// Now correct all amplitudes by dividing by the remaining factors in forward direction.
......@@ -126,7 +124,7 @@ Fluxes Compute::SpecularScalar::fluxes(const SliceStack& slices, const R3& k)
std::vector<complex_t> kz = Compute::Kz::computeReducedKz(slices, k);
ASSERT(slices.size() == kz.size());
const std::vector<Spinor> TR = computeTR(slices, kz, slices.roughnessModel(), top_exit);
const std::vector<Spinor> TR = ::computeTR(slices, kz, slices.roughnessModel(), top_exit);
Fluxes result;
for (size_t i = 0; i < kz.size(); ++i)
......@@ -153,7 +151,7 @@ complex_t Compute::SpecularScalar::topLayerR(const SliceStack& slices,
if (const auto* const roughness = slices.bottomRoughness(i - 1))
sigma = roughness->sigma();
const auto [mp, mm] = transition(kz[i - 1], kz[i], sigma, r_model);
const auto [mp, mm] = ::transition(kz[i - 1], kz[i], sigma, r_model);
const complex_t delta = exp_I(kz[i - 1] * slices[i - 1].thicknessOr0());
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment