22 InterferenceFunction2DParaCrystal::InterferenceFunction2DParaCrystal(
const Lattice2D& lattice,
 
   23                                                                      double damping_length,
 
   28     setName(
"Interference2DParaCrystal");
 
   30     setDomainSizes(domain_size_1, domain_size_2);
 
   31     registerParameter(
"DampingLength", &m_damping_length).setUnit(
"nm").setNonnegative();
 
   32     registerParameter(
"DomainSize1", &m_domain_sizes[0]).setUnit(
"nm").setNonnegative();
 
   33     registerParameter(
"DomainSize2", &m_domain_sizes[1]).setUnit(
"nm").setNonnegative();
 
   43 InterferenceFunction2DParaCrystal::InterferenceFunction2DParaCrystal(
double length_1,
 
   44                                                                      double length_2, 
double alpha,
 
   46                                                                      double damping_length)
 
   52 InterferenceFunction2DParaCrystal::~InterferenceFunction2DParaCrystal() = 
default;
 
   57                                                       m_domain_sizes[0], m_domain_sizes[1]);
 
   58     ret->setPositionVariance(m_position_var);
 
   60         ret->setProbabilityDistributions(*m_pdf1, *m_pdf2);
 
   61     ret->setIntegrationOverXi(m_integrate_xi);
 
   72     m_pdf1.reset(pdf_1.clone());
 
   73     registerChild(m_pdf1.get());
 
   74     m_pdf2.reset(pdf_2.clone());
 
   75     registerChild(m_pdf2.get());
 
   83     m_damping_length = damping_length;
 
   88     double area = m_lattice->unitCellArea();
 
   89     return area == 0.0 ? 0.0 : 1.0 / area;
 
   94     return std::vector<const INode*>() << m_pdf1 << m_pdf2 << m_lattice;
 
   97 double InterferenceFunction2DParaCrystal::iff_without_dw(
const kvector_t q)
 const 
  102         return interferenceForXi(m_lattice->rotationAngle());
 
  103     return RealIntegrator().integrate([&](
double xi) -> 
double { 
return interferenceForXi(xi); },
 
  108 void InterferenceFunction2DParaCrystal::setLattice(
const Lattice2D& lattice)
 
  110     m_lattice.reset(lattice.clone());
 
  111     registerChild(m_lattice.get());
 
  122                                                 double domain_size_1, 
double domain_size_2)
 
  125         SquareLattice(lattice_length), damping_length, domain_size_1, domain_size_2);
 
  126     result->setIntegrationOverXi(
true);
 
  138                                                    double domain_size_1, 
double domain_size_2)
 
  141         HexagonalLattice(lattice_length, 0.), damping_length, domain_size_1, domain_size_2);
 
  142     result->setIntegrationOverXi(
true);
 
  152     m_domain_sizes[0] = size_1;
 
  153     m_domain_sizes[1] = size_2;
 
  156 void InterferenceFunction2DParaCrystal::transformToPrincipalAxes(
double qx, 
double qy, 
double gamma,
 
  157                                                                  double delta, 
double& q_pa_1,
 
  158                                                                  double& q_pa_2)
 const 
  160     q_pa_1 = qx * std::cos(gamma) + qy * std::sin(gamma);
 
  161     q_pa_2 = qx * std::cos(gamma + delta) + qy * std::sin(gamma + delta);
 
  165 double InterferenceFunction2DParaCrystal::interferenceForXi(
double xi)
 const 
  168     double rx = interference1D(m_qx, m_qy, xi, 0);
 
  169     double ry = interference1D(m_qx, m_qy, xi + m_lattice->latticeAngle(), 1);
 
  174 double InterferenceFunction2DParaCrystal::interference1D(
double qx, 
double qy, 
double xi,
 
  179             "InterferenceFunction2DParaCrystal::" 
  180             "interference1D() -> Error! Index of interference function " 
  181             "probability must be < 2");
 
  182     if (!m_pdf1 || !m_pdf2)
 
  184             "InterferenceFunction2DParaCrystal::" 
  185             "interference1D() -> Error! Probability distributions for " 
  186             "interference function not properly initialized");
 
  188     double length = index ? m_lattice->length2() : m_lattice->length1();
 
  189     int n = 
static_cast<int>(std::abs(m_domain_sizes[index] / length));
 
  190     double nd = 
static_cast<double>(n);
 
  191     complex_t fp = FTPDF(qx, qy, xi, index);
 
  193         return ((1.0 + fp) / (1.0 - fp)).real();
 
  194     if (std::norm(1.0 - fp) < std::numeric_limits<double>::epsilon())
 
  197     if (std::abs(1.0 - fp) * nd < 2e-4) {
 
  198         complex_t intermediate =
 
  199             (nd - 1.0) / 2.0 + (nd * nd - 1.0) * (fp - 1.0) / 6.0
 
  200             + (nd * nd * nd - 2.0 * nd * nd - nd + 2.0) * (fp - 1.0) * (fp - 1.0) / 24.0;
 
  201         return 1.0 + 2.0 * intermediate.real();
 
  204     if (std::abs(fp) == 0.0
 
  205         || std::log(std::abs(fp)) * nd < std::log(std::numeric_limits<double>::min()))
 
  208         tmp = std::pow(fp, n);
 
  209     complex_t intermediate = fp / (1.0 - fp) - fp * (1.0 - tmp) / nd / (1.0 - fp) / (1.0 - fp);
 
  210     return 1.0 + 2.0 * intermediate.real();
 
  213 complex_t InterferenceFunction2DParaCrystal::FTPDF(
double qx, 
double qy, 
double xi,
 
  216     double length = (index ? m_lattice->length2() : m_lattice->length1());
 
  219     double qa = qx * length * std::cos(xi) + qy * length * std::sin(xi);
 
  220     complex_t phase = 
exp_I(qa);
 
  223     double gamma = xi + pdf->gamma();
 
  224     double delta = pdf->
delta();
 
  225     transformToPrincipalAxes(qx, qy, gamma, delta, qp1, qp2);
 
  226     double amplitude = pdf->
evaluate(qp1, qp2);
 
  227     complex_t result = phase * amplitude;
 
  228     if (m_damping_length != 0.0)
 
  229         result *= std::exp(-length / m_damping_length);
 
  233 std::vector<double> InterferenceFunction2DParaCrystal::domainSizes()
 const 
  235     return {m_domain_sizes[0], m_domain_sizes[1]};
 
  243     m_integrate_xi = integrate_xi;
 
  244     m_lattice->setRotationEnabled(!m_integrate_xi); 
 
  247 const Lattice2D& InterferenceFunction2DParaCrystal::lattice()
 const 
  250         throw std::runtime_error(
"InterferenceFunction2DParaCrystal::lattice() -> Error. " 
  251                                  "No lattice defined.");
 
complex_t exp_I(complex_t z)
Returns exp(I*z), where I is the imaginary unit.
 
Defines many exception classes in namespace Exceptionss.
 
Defines classes RealIntegrator, ComplexIntegrator.
 
Defines class InterferenceFunction2DParaCrystal.
 
Defines class ParameterPool.
 
Defines class RealParameter.
 
T y() const
Returns y-component in cartesian coordinate system.
 
T x() const
Returns x-component in cartesian coordinate system.
 
Interface for two-dimensional distributions in Fourier space.
 
double delta() const
Angle in direct space between X- and Y-axis of distribution.
 
virtual double evaluate(double qx, double qy) const =0
evaluate Fourier transformed distribution for q in X,Y coordinates the original distribution (in real...
 
Pure virtual base class of interference functions.
 
Interference function of a 2D paracrystal.
 
double getParticleDensity() const override final
If defined by this interference function's parameters, returns the particle density (per area).
 
void setProbabilityDistributions(const IFTDistribution2D &pdf_1, const IFTDistribution2D &pdf_2)
Sets the probability distributions (Fourier transformed) for the two lattice directions.
 
static InterferenceFunction2DParaCrystal * createHexagonal(double lattice_length, double damping_length, double domain_size_1, double domain_size_2)
Creates hexagonal lattice.
 
void setIntegrationOverXi(bool integrate_xi)
Enables/disables averaging over the lattice rotation angle.
 
InterferenceFunction2DParaCrystal * clone() const override final
Returns a clone of this ISample object.
 
void setDampingLength(double damping_length)
Sets the damping length.
 
static InterferenceFunction2DParaCrystal * createSquare(double lattice_length, double damping_length, double domain_size_1, double domain_size_2)
Creates square lattice.
 
void setDomainSizes(double size_1, double size_2)
Sets the sizes of coherence domains.
 
std::vector< const INode * > getChildren() const override final
Returns a vector of children (const).
 
To integrate a real function of a real variable.