26 const int min_points = 4;
32 setName(
"Interference2DLattice");
42 double alpha,
double xi)
47 InterferenceFunction2DLattice::~InterferenceFunction2DLattice() =
default;
52 ret->setPositionVariance(m_position_var);
53 ret->setIntegrationOverXi(integrationOverXi());
55 ret->setDecayFunction(*m_decay);
81 m_decay.reset(decay.clone());
82 registerChild(m_decay.get());
83 initialize_calc_factors();
86 void InterferenceFunction2DLattice::setIntegrationOverXi(
bool integrate_xi)
88 m_integrate_xi = integrate_xi;
89 m_lattice->setRotationEnabled(!m_integrate_xi);
92 const Lattice2D& InterferenceFunction2DLattice::lattice()
const
95 throw std::runtime_error(
"InterferenceFunction2DLattice::lattice() -> Error. "
96 "No lattice defined.");
102 double area = m_lattice->unitCellArea();
103 return area == 0.0 ? 0.0 : 1.0 / area;
108 return std::vector<const INode*>() << m_decay << m_lattice;
113 initialize_rec_vectors();
114 initialize_calc_factors();
117 double InterferenceFunction2DLattice::iff_without_dw(
const kvector_t q)
const
121 " -> Error! No decay function defined.");
125 return interferenceForXi(m_lattice->rotationAngle());
126 return RealIntegrator().integrate([&](
double xi) ->
double {
return interferenceForXi(xi); },
131 void InterferenceFunction2DLattice::setLattice(
const Lattice2D& lattice)
133 m_lattice.reset(lattice.clone());
134 registerChild(m_lattice.get());
135 initialize_rec_vectors();
138 double InterferenceFunction2DLattice::interferenceForXi(
double xi)
const
141 auto q_frac = calculateReciprocalVectorFraction(m_qx, m_qy, xi);
143 for (
int i = -m_na - 1; i < m_na + 2; ++i) {
144 for (
int j = -m_nb - 1; j < m_nb + 2; ++j) {
145 double qx = q_frac.first + i * m_sbase.m_asx + j * m_sbase.m_bsx;
146 double qy = q_frac.second + i * m_sbase.
m_asy + j * m_sbase.
m_bsy;
147 result += interferenceAtOneRecLatticePoint(qx, qy);
153 double InterferenceFunction2DLattice::interferenceAtOneRecLatticePoint(
double qx,
double qy)
const
157 "InterferenceFunction2DLattice::interferenceAtOneRecLatticePoint"
158 " -> Error! No decay function defined.");
159 double gamma = m_decay->gamma();
160 auto qXY = rotateOrthonormal(qx, qy, gamma);
161 return m_decay->evaluate(qXY.first, qXY.second);
165 std::pair<double, double> InterferenceFunction2DLattice::rotateOrthonormal(
double qx,
double qy,
168 double q_X = qx * std::cos(gamma) + qy * std::sin(gamma);
169 double q_Y = -qx * std::sin(gamma) + qy * std::cos(gamma);
176 std::pair<double, double>
177 InterferenceFunction2DLattice::calculateReciprocalVectorFraction(
double qx,
double qy,
180 double a = m_lattice->length1();
181 double b = m_lattice->length2();
182 double alpha = m_lattice->latticeAngle();
184 double qx_rot = qx * std::cos(xi) + qy * std::sin(xi);
185 double qy_rot = -qx * std::sin(xi) + qy * std::cos(xi);
188 int qa_int =
static_cast<int>(std::lround(a * qx_rot / M_TWOPI));
189 int qb_int =
static_cast<int>(
190 std::lround(b * (qx_rot * std::cos(alpha) + qy_rot * std::sin(alpha)) / M_TWOPI));
192 double qx_frac = qx_rot - qa_int * m_sbase.m_asx - qb_int * m_sbase.m_bsx;
193 double qy_frac = qy_rot - qa_int * m_sbase.
m_asy - qb_int * m_sbase.
m_bsy;
194 return {qx_frac, qy_frac};
198 void InterferenceFunction2DLattice::initialize_rec_vectors()
201 throw std::runtime_error(
"InterferenceFunction2DLattice::initialize_rec_vectors() -> "
202 "Error. No lattice defined yet");
204 BasicLattice base_lattice(m_lattice->length1(), m_lattice->length2(), m_lattice->latticeAngle(),
206 m_sbase = base_lattice.reciprocalBases();
209 void InterferenceFunction2DLattice::initialize_calc_factors()
213 "InterferenceFunction2DLattice::initialize_calc_factors"
214 " -> Error! No decay function defined.");
217 auto q_bounds = m_decay->boundingReciprocalLatticeCoordinates(
218 nmax / m_decay->decayLengthX(), nmax / m_decay->decayLengthY(), m_lattice->length1(),
219 m_lattice->length2(), m_lattice->latticeAngle());
220 m_na =
static_cast<int>(std::lround(q_bounds.first + 0.5));
221 m_nb =
static_cast<int>(std::lround(q_bounds.second + 0.5));
222 m_na = std::max(m_na, min_points);
223 m_nb = std::max(m_nb, min_points);
Defines many exception classes in namespace Exceptionss.
Defines classes RealIntegrator, ComplexIntegrator.
Defines class InterferenceFunction2DLattice.
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 decay function in reciprocal space.
Pure virtual base class of interference functions.
Interference function of a 2D lattice.
void onChange() override final
Action to be taken in inherited class when a parameter has changed.
static InterferenceFunction2DLattice * createSquare(double lattice_length, double xi)
Creates square lattice.
static InterferenceFunction2DLattice * createHexagonal(double lattice_length, double xi)
Creates hexagonal lattice.
std::vector< const INode * > getChildren() const override final
Returns a vector of children (const).
double getParticleDensity() const override final
Returns the particle density associated with this 2d lattice.
InterferenceFunction2DLattice(double length_1, double length_2, double alpha, double xi)
Constructor of two-dimensional interference function.
void setDecayFunction(const IFTDecayFunction2D &decay)
Sets two-dimensional decay function.
InterferenceFunction2DLattice * clone() const override final
Returns a clone of this ISample object.
To integrate a real function of a real variable.
double m_asy
x,y coordinates of a*
double m_bsy
x,y coordinates of b*