File: ReParticle.cpp

package info (click to toggle)
bornagain 23.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 103,936 kB
  • sloc: cpp: 423,131; python: 40,997; javascript: 11,167; awk: 630; sh: 318; ruby: 173; xml: 130; makefile: 51; ansic: 24
file content (135 lines) | stat: -rw-r--r-- 5,129 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      Resample/Particle/ReParticle.cpp
//! @brief     Implements class interface ReParticle.
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#include "Resample/Particle/ReParticle.h"
#include "Base/Type/Span.h"
#include "Base/Util/Assert.h"
#include "Base/Vector/WavevectorInfo.h" // debug
#include "Sample/Material/Material.h"
#include "Sample/Material/MaterialFactoryFuncs.h"
#include "Sample/Particle/IFormfactor.h"
#include "Sample/Scattering/Rotations.h"

ReParticle::ReParticle(const std::optional<size_t>& i_layer, const IFormfactor* ff,
                       const Material* material, const Material* ambient_material,
                       const R3* position, const RotMatrix* rotMatrix)
    : IReParticle(i_layer)
    , m_ff(ff)
    , m_material(material)
    , m_ambient_material(ambient_material)
    , m_position(position)
    , m_rot_matrix(rotMatrix)
{
}

ReParticle::ReParticle(const IFormfactor* ff, const R3* position, const RotMatrix* rot)
    : ReParticle({}, ff, nullptr, nullptr, position, rot)
{
}

ReParticle::~ReParticle() = default;

ReParticle* ReParticle::clone() const
{
    return new ReParticle(i_layer(), m_ff->clone(),
                          m_material ? new Material(*m_material) : nullptr,
                          m_ambient_material ? new Material(*m_ambient_material) : nullptr,
                          m_position ? new R3(*m_position) : nullptr,
                          m_rot_matrix ? new RotMatrix(*m_rot_matrix) : nullptr);
}

void ReParticle::setMaterial(const Material& material)
{
    m_material = std::make_unique<Material>(material);
}

void ReParticle::setAmbientMaterial(const Material& ambient_material)
{
    m_ambient_material = std::make_unique<Material>(ambient_material);
}

double ReParticle::volume() const
{
    return m_ff->volume();
}

double ReParticle::radialExtension() const
{
    return m_ff->radialExtension();
}

complex_t ReParticle::theFF(const WavevectorInfo& wavevectors) const
{
    WavevectorInfo wavevectors2 =
        m_rot_matrix ? wavevectors.transformed(m_rot_matrix->Inverse()) : wavevectors;
    complex_t result = m_ff->theFF(wavevectors2);
    if (m_material && m_ambient_material)
        result = (m_material->scalarSubtrSLD(wavevectors2)
                  - m_ambient_material->scalarSubtrSLD(wavevectors2))
                 * result;
    return result * phaseFactor(wavevectors, m_position.get());
}

SpinMatrix ReParticle::thePolFF(const WavevectorInfo& wavevectors) const
{
    WavevectorInfo wavevectors2 =
        m_rot_matrix ? wavevectors.transformed(m_rot_matrix->Inverse()) : wavevectors;
    SpinMatrix result = m_ff->thePolFF(wavevectors2);
    if (m_material && m_ambient_material) {
        // the conjugated linear part of time reversal operator T
        // (T=UK with K complex conjugate operator and U is linear)
        SpinMatrix time_reverse_conj(0, 1, -1, 0);
        // the interaction and time reversal taken together:
        SpinMatrix V_eff = time_reverse_conj
                           * (m_material->polarizedSubtrSLD(wavevectors2)
                              - m_ambient_material->polarizedSubtrSLD(wavevectors2));
        result *= V_eff;
    }
    return result * phaseFactor(wavevectors, m_position.get());
}

Span ReParticle::zSpan() const
{
    RotMatrix transform = m_rot_matrix ? *m_rot_matrix : RotMatrix();
    std::unique_ptr<const IRotation> total_rotation(IRotation::createRotation(transform));
    Span span = m_ff->spanZ(total_rotation.get());
    if (m_position)
        return span + m_position->z();
    return span;
}

bool ReParticle::contains(const R3& position) const
{
    return m_ff->contains(position);
}

bool ReParticle::consideredEqualTo(const IReParticle& ire) const
{
    if (const auto* re = dynamic_cast<const ReParticle*>(&ire)) {
        bool same_material = (!m_material && !re->material())
                             || (m_material && re->material() && (*m_material == *re->material()));
        bool same_ambient = (!m_ambient_material && !re->ambientMaterial())
                            || (m_ambient_material && re->ambientMaterial()
                                && (*m_ambient_material == *re->ambientMaterial()));
        bool same_rotation =
            (!m_rot_matrix && !re->rotMatrix())
            || (m_rot_matrix && re->rotMatrix() && (*m_rot_matrix == *re->rotMatrix()));
        bool same_ff = (m_ff && re->ff() && m_ff->isEqualTo(re->ff()));

        // translated position is not compared here, this is intentional
        return IReParticle::consideredEqualTo(ire) && same_ff && same_material && same_ambient
               && same_rotation;
    }
    return false;
}