Newer
Older
Gigg, Martyn Anthony
committed
//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
Janik Zikovsky
committed
#include <stdexcept>
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
using PhysicalConstants::NeutronAtom;
/**
* Construct an "empty" material. Everything returns zero
*/
Material::Material() :
m_name(), m_element(0,0,0.0,0.0,0.0,0.0,0.0,0.0),
m_numberDensity(0.0), m_temperature(0.0), m_pressure(0.0)
Gigg, Martyn Anthony
committed
{
}
Gigg, Martyn Anthony
committed
/**
* Construct a material object
Janik Zikovsky
committed
* @param name :: The name of the material
* @param element :: The element it is composed from
* @param numberDensity :: Density in A^-3
* @param temperature :: The temperature in Kelvin (Default = 300K)
* @param pressure :: Pressure in kPa (Default: 101.325 kPa)
Gigg, Martyn Anthony
committed
*/
Material::Material(const std::string & name, const PhysicalConstants::NeutronAtom& element,
Gigg, Martyn Anthony
committed
const double numberDensity, const double temperature,
const double pressure) :
m_name(name), m_element(element), m_numberDensity(numberDensity),
Gigg, Martyn Anthony
committed
m_temperature(temperature), m_pressure(pressure)
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
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
/**
* Returns the name
* @returns A string containing the name of the material
*/
const std::string & Material::name() const
{
return m_name;
}
/**
* Get the number density
* @returns The number density of the material in A^-3
*/
double Material::numberDensity() const
{
return m_numberDensity;
}
/**
* Get the temperature
* @returns The temperature of the material in Kelvin
*/
double Material::temperature() const
{
return m_temperature;
}
/**
* Get the pressure
* @returns The pressure of the material
*/
double Material::pressure() const
{
return m_pressure;
}
/**
* Get the coherent scattering cross section for a given wavelength.
Gigg, Martyn Anthony
committed
* CURRENTLY this simply returns the value for the underlying element
Janik Zikovsky
committed
* @param lambda :: The wavelength to evaluate the cross section
Gigg, Martyn Anthony
committed
* @returns The value of the coherent scattering cross section at
* the given wavelength
*/
double Material::cohScatterXSection(const double lambda) const
Gigg, Martyn Anthony
committed
{
(void)lambda;
return m_element.coh_scatt_xs;
Gigg, Martyn Anthony
committed
}
/**
* Get the incoherent scattering cross section for a given wavelength
Gigg, Martyn Anthony
committed
* CURRENTLY this simply returns the value for the underlying element
Janik Zikovsky
committed
* @param lambda :: The wavelength to evaluate the cross section
Gigg, Martyn Anthony
committed
* @returns The value of the coherent scattering cross section at
* the given wavelength
*/
double Material::incohScatterXSection(const double lambda) const
Gigg, Martyn Anthony
committed
{
(void)lambda;
return m_element.inc_scatt_xs;
}
/**
* Get the total scattering cross section for a given wavelength
* CURRENTLY this simply returns the value for sum of the incoherent
* and coherent scattering cross sections.
Janik Zikovsky
committed
* @param lambda :: The wavelength to evaluate the cross section
* @returns The value of the total scattering cross section at
* the given wavelength
*/
double Material::totalScatterXSection(const double lambda) const
{
return m_element.tot_scatt_xs;
Gigg, Martyn Anthony
committed
}
/**
* Get the absorption cross section for a given wavelength.
* CURRENTLY This assumes a linear dependence on the wavelength with the reference
* wavelength = NeutronAtom::ReferenceLambda angstroms.
Janik Zikovsky
committed
* @param lambda :: The wavelength to evaluate the cross section
Gigg, Martyn Anthony
committed
* @returns The value of the absoprtioncross section at
* the given wavelength
*/
double Material::absorbXSection(const double lambda) const
Gigg, Martyn Anthony
committed
{
return (m_element.abs_scatt_xs) * (lambda / NeutronAtom::ReferenceLambda);
Gigg, Martyn Anthony
committed
}
Janik Zikovsky
committed
/** Save the object to an open NeXus file.
* @param file :: open NeXus file
* @param group :: name of the group to create
*/
void Material::saveNexus(::NeXus::File * file, const std::string & group) const
{
file->makeGroup(group, "NXdata", 1);
Janik Zikovsky
committed
file->putAttr("version", 1);
file->putAttr("name", m_name);
file->writeData("element_Z", m_element.z_number);
file->writeData("element_A", m_element.a_number);
file->writeData("number_density", m_numberDensity);
file->writeData("temperature", m_temperature);
file->writeData("pressure", m_pressure);
file->closeGroup();
}
/** Load the object from an open NeXus file.
* @param file :: open NeXus file
* @param group :: name of the group to open
*/
void Material::loadNexus(::NeXus::File * file, const std::string & group)
{
file->openGroup(group, "NXdata");
Janik Zikovsky
committed
file->getAttr("name", m_name);
// Find the element
uint16_t element_Z, element_A;
file->readData("element_Z", element_Z);
file->readData("element_A", element_A);
Janik Zikovsky
committed
try {
Janik Zikovsky
committed
m_element = Mantid::PhysicalConstants::getNeutronAtom(element_Z, element_A);
Janik Zikovsky
committed
}
catch (std::runtime_error &)
Janik Zikovsky
committed
{ /* ignore and use the default */ }
Janik Zikovsky
committed
file->readData("number_density", m_numberDensity);
file->readData("temperature", m_temperature);
file->readData("pressure", m_pressure);
file->closeGroup();
}
Material::ChemicalFormula Material::parseChemicalFormula(const std::string chemicalSymbol)
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
209
210
211
212
213
214
const char *s;
s = chemicalSymbol.c_str();
size_t i = 0;
size_t ia = 0;
size_t numberParen = 0;
bool isotope = false;
while (i < chemicalSymbol.length())
{
if (s[i] >= 'A' && s[i]<='Z')
{
std::string buf(s+i, s+i+1);
CF.atoms.push_back(buf);
CF.numberAtoms.push_back(0);
CF.aNumbers.push_back(0);
ia ++;
}
else if (s[i] >= 'a' && s[i]<='z')
{
std::string buf(s+i, s+i+1);
CF.atoms[ia-1].append(buf);
}
else if (s[i] >= '0' && s[i]<='9')
{
if (isotope)
{
size_t ilast = i;
// Number of digits in aNumber
if (CF.aNumbers[ia-1] != 0) ilast -= (int) std::log10 ((double) CF.aNumbers[ia-1]) + 1;
std::string buf(s+ilast, s+i+1);
CF.aNumbers[ia-1] = static_cast<uint16_t>(std::atoi(buf.c_str()));
}
else
{
size_t ilast = i;
// Number of digits in aNumber
if (CF.numberAtoms[ia-1] != 0) ilast -= (int) std::log10 ((double) CF.numberAtoms[ia-1]) + 1;
std::string buf(s+ilast, s+i+1);
CF.numberAtoms[ia-1] = static_cast<uint16_t>(std::atoi(buf.c_str()));
}
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
}
else if (s[i] == '(' || s[i] ==')')
{
isotope = !isotope;
if (s[i] == '(')
{
// next atom
numberParen = ia + 1;
}
else
{
if (ia > numberParen)for (size_t i0 = numberParen - 1; i0 < ia; i0++)
{
// if more than one atom in parenthesis, it is compound
CF.numberAtoms[i0] = CF.aNumbers[i0];
CF.aNumbers[i0] = 0;
}
}
}
else if (s[i] == ' ' || s[i] == '-')
{
// skip it as spacing character
}
else
{
std::stringstream msg;
msg << "Encountered invalid character at position " << i << " in formula \""
<< chemicalSymbol << "\"";
throw std::runtime_error(msg.str());
}
i++;
}
// fix up D -> H2 and number of atoms
for (size_t i=0; i<ia; i++)
if (CF.numberAtoms[i] == 0)
CF.numberAtoms[i] = 1;
if (CF.atoms[i] == "D")
{
CF.atoms[i] = "H";
CF.aNumbers[i] = 2;
}
Gigg, Martyn Anthony
committed
}