/
Material.h
208 lines (179 loc) · 8.23 KB
/
Material.h
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2007 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source,
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
#pragma once
//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include "MantidKernel/AttenuationProfile.h"
#include "MantidKernel/NeutronAtom.h"
#include "MantidKernel/PhysicalConstants.h"
#include <boost/optional/optional.hpp>
#include <memory>
#include <string>
#include <vector>
// Forward Declares
namespace NeXus {
class File;
}
namespace Mantid {
namespace PhysicalConstants {
class Atom;
}
namespace Kernel {
class AttenuationProfile;
/**
A material is defined as being composed of a given element, defined as a
PhysicalConstants::NeutronAtom, with the following properties:
<UL>
<LI>temperature (Kelvin)</LI>
<LI>pressure (KPa) </LI>
<LI>number density (nAtoms / Angstrom^3)</LI>
</UL>
To understand how the effective scattering information is calculated, see
Sears, Varley F. "Neutron scattering lengths and cross sections." Neutron
news 3.3 (1992): 26-37. To highlight a point that may be missed, the
absorption is the only quantity that is wavelength dependent.
*/
class MANTID_KERNEL_DLL Material final {
public:
/// Structure to hold the information for a parsed chemical formula
struct FormulaUnit final {
std::shared_ptr<PhysicalConstants::Atom> atom;
double multiplicity;
FormulaUnit(std::shared_ptr<PhysicalConstants::Atom> atom, const double multiplicity);
FormulaUnit(const PhysicalConstants::Atom &atom, const double multiplicity);
};
using ChemicalFormula = std::vector<FormulaUnit>;
static ChemicalFormula parseChemicalFormula(const std::string &chemicalSymbol);
/// Default constructor. Required for other parts of the code to
/// function correctly. The material is considered "empty"
Material();
/// Construct a material from a known element, with optional
/// temperature and pressure
explicit Material(std::string name, const ChemicalFormula &formula, const double numberDensity,
const double packingFraction = 1, const double temperature = 300,
const double pressure = PhysicalConstants::StandardAtmosphere);
explicit Material(std::string name, const PhysicalConstants::NeutronAtom &atom, const double numberDensity,
const double packingFraction = 1, const double temperature = 300,
const double pressure = PhysicalConstants::StandardAtmosphere);
/// Virtual destructor.
virtual ~Material() = default;
/// Allow an explicit attenuation profile to be loaded onto the material
/// that overrides the standard linear absorption coefficient
void setAttenuationProfile(AttenuationProfile attenuationOverride);
void setXRayAttenuationProfile(AttenuationProfile attenuationProfile);
/// Returns the name of the material
const std::string &name() const;
const Material::ChemicalFormula &chemicalFormula() const;
/** @name Material properties */
//@{
/// Get the number density
double numberDensity() const;
/// Get the effective number density
double numberDensityEffective() const;
/// Get the packing fraction
double packingFraction() const;
/// The total number of atoms in the formula
double totalAtoms() const;
/// Get the temperature
double temperature() const;
/// Get the pressure
double pressure() const;
/// Get the coherent scattering cross section for a given wavelength in barns.
double cohScatterXSection() const;
/// Get the incoherent cross section for a given wavelength in barns.
double incohScatterXSection() const;
/// Return the total scattering cross section for a given wavelength in barns.
double totalScatterXSection() const;
/// Get the absorption cross section at a given wavelength in barns.
double absorbXSection(const double lambda = PhysicalConstants::NeutronAtom::ReferenceLambda) const;
double attenuationCoefficient(const double lambda) const;
/// Compute the attenuation at a given wavelength over the given distance
double attenuation(const double distance,
const double lambda = PhysicalConstants::NeutronAtom::ReferenceLambda) const;
/// Compute the x-ray attenuation at a given energy over the given distance
double xRayAttenuation(const double distance, const double energy) const;
/**
* Returns the linear coefficient of absorption for the material in units of
* cm^-1
* this should match the implementation of the iterator version
*/
double linearAbsorpCoef(const double lambda = PhysicalConstants::NeutronAtom::ReferenceLambda) const;
/**
* Returns the linear coefficient of absorption for the material in units of
* cm^-1
* this should match the implementation of the scalar version
*/
std::vector<double> linearAbsorpCoef(std::vector<double>::const_iterator lambdaBegin,
std::vector<double>::const_iterator lambdaEnd) const;
/// Get the coherent scattering length for a given wavelength in fm
double cohScatterLength(const double lambda = PhysicalConstants::NeutronAtom::ReferenceLambda) const;
/// Get the incoherent length for a given wavelength in fm
double incohScatterLength(const double lambda = PhysicalConstants::NeutronAtom::ReferenceLambda) const;
/// Return the total scattering length for a given wavelength in fm
double totalScatterLength(const double lambda = PhysicalConstants::NeutronAtom::ReferenceLambda) const;
/// Get the coherent scattering length for a given wavelength in fm
double cohScatterLengthReal(const double lambda = PhysicalConstants::NeutronAtom::ReferenceLambda) const;
/// Get the coherent scattering length for a given wavelength in fm
double cohScatterLengthImg(const double lambda = PhysicalConstants::NeutronAtom::ReferenceLambda) const;
/// Get the incoherent length for a given wavelength in fm
double incohScatterLengthReal(const double lambda = PhysicalConstants::NeutronAtom::ReferenceLambda) const;
/// Get the incoherent length for a given wavelength in fm
double incohScatterLengthImg(const double lambda = PhysicalConstants::NeutronAtom::ReferenceLambda) const;
/**
* Get the coherent scattering length squared, \f$<b>^2\f$, for a given
* wavelength
* in \f$fm^2\f$.
*/
double cohScatterLengthSqrd(const double lambda = PhysicalConstants::NeutronAtom::ReferenceLambda) const;
/**
* Get the incoherent length squared, \f$<b>^2\f$, for a given wavelength in
* \f$fm^2\f$.
*/
double incohScatterLengthSqrd(const double lambda = PhysicalConstants::NeutronAtom::ReferenceLambda) const;
/**
* Return the total scattering length squared, \f$<b^2>\f$, for a given
* wavelength
* in \f$fm^2\f$.
*/
double totalScatterLengthSqrd(const double lambda = PhysicalConstants::NeutronAtom::ReferenceLambda) const;
//@}
void saveNexus(::NeXus::File *file, const std::string &group) const;
void loadNexus(::NeXus::File *file, const std::string &group);
bool hasValidXRayAttenuationProfile();
private:
/// Update the total atom count
void countAtoms();
/// Update the linear absorption x section (by wavelength)
void calculateLinearAbsorpXSectionByWL();
/// Update the total scatter x section
void calculateTotalScatterXSection();
/// Material name
std::string m_name;
/// The normalized chemical formula
ChemicalFormula m_chemicalFormula;
/// Total number of atoms
double m_atomTotal;
/// Number density in atoms per A^-3
double m_numberDensity;
/// Packing fraction should be between 0 and 2
double m_packingFraction;
/// Temperature
double m_temperature;
/// Pressure
double m_pressure;
double m_linearAbsorpXSectionByWL;
double m_totalScatterXSection;
boost::optional<AttenuationProfile> m_attenuationOverride;
boost::optional<AttenuationProfile> m_xRayAttenuationProfile;
};
/// Typedef for a shared pointer
using Material_sptr = std::shared_ptr<Material>;
/// Typedef for a shared pointer to a const object
using Material_const_sptr = std::shared_ptr<const Material>;
} // namespace Kernel
} // namespace Mantid