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.