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 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
|
#include "Base/Const/Units.h"
#include "Base/Vector/RotMatrix.h"
#include "Base/Vector/WavevectorInfo.h"
#include "Sample/Material/MaterialFactoryFuncs.h"
#include "Sample/Material/MaterialUtil.h"
#include "Sample/Scattering/Rotations.h"
#include "Tests/GTestWrapper/google_test.h"
#include <iostream>
#include <numbers>
using std::numbers::pi;
TEST(Material, MaterialConstruction)
{
complex_t material_data = complex_t(0.0, 2.0);
complex_t refIndex = complex_t(1.0 - material_data.real(), material_data.imag());
R3 magnetism = R3(3.0, 4.0, 5.0);
Material material = RefractiveMaterial("MagMaterial", refIndex, magnetism);
EXPECT_EQ(material_data, material.refractiveIndex_or_SLD());
EXPECT_EQ(magnetism, material.magnetization());
Material material2 =
RefractiveMaterial("MagMaterial", material_data.real(), material_data.imag(), magnetism);
EXPECT_EQ(material_data, material2.refractiveIndex_or_SLD());
EXPECT_EQ(magnetism, material2.magnetization());
Material material3 =
MaterialBySLD("MagMaterial", material_data.real(), material_data.imag(), magnetism);
EXPECT_EQ(material_data, material3.refractiveIndex_or_SLD());
EXPECT_EQ(magnetism, material3.magnetization());
R3 default_magnetism = R3{};
Material material4 = RefractiveMaterial("Material", refIndex);
EXPECT_EQ(material_data, material4.refractiveIndex_or_SLD());
EXPECT_EQ(default_magnetism, material4.magnetization());
Material material5 = RefractiveMaterial("Material", material_data.real(), material_data.imag());
EXPECT_EQ(material_data, material5.refractiveIndex_or_SLD());
EXPECT_EQ(default_magnetism, material5.magnetization());
Material material6 = MaterialBySLD("Material", material_data.real(), material_data.imag());
EXPECT_EQ(default_magnetism, material6.magnetization());
}
TEST(Material, MaterialTransform)
{
complex_t material_data = complex_t(1.0, 0.0);
complex_t refIndex = complex_t(1.0 - material_data.real(), material_data.imag());
R3 magnetism = R3(1.0, 0.0, 0.0);
RotationZ transform(90. * Units::deg);
R3 transformed_mag = transform.transformed(magnetism);
Material material = RefractiveMaterial("Material", refIndex, magnetism);
Material material2 = material.rotatedMaterial(transform.rotMatrix());
EXPECT_EQ(material_data, material2.refractiveIndex_or_SLD());
// transformed_mag equals material2.magnetization except on i368:
EXPECT_TRUE(fabs((transformed_mag - material2.magnetization()).x()) < 3e-16);
EXPECT_TRUE(fabs((transformed_mag - material2.magnetization()).y()) < 3e-16);
EXPECT_TRUE(fabs((transformed_mag - material2.magnetization()).z()) < 3e-16);
Material material3 =
MaterialBySLD("Material", material_data.real(), material_data.imag(), magnetism);
Material material4 = material.rotatedMaterial(transform.rotMatrix());
EXPECT_EQ(material_data, material4.refractiveIndex_or_SLD());
// transformed_mag equals material4.magnetization except on i368:
EXPECT_TRUE(fabs((transformed_mag - material4.magnetization()).x()) < 3e-16);
EXPECT_TRUE(fabs((transformed_mag - material4.magnetization()).y()) < 3e-16);
EXPECT_TRUE(fabs((transformed_mag - material4.magnetization()).z()) < 3e-16);
}
TEST(Material, DefaultMaterials)
{
Material material = Vacuum();
const double dummy_wavelength = 1.0;
EXPECT_EQ(material.refractiveIndex_or_SLD(), complex_t());
EXPECT_EQ(material.refractiveIndex_or_SLD(), MaterialBySLD().refractiveIndex_or_SLD());
EXPECT_EQ(material.magnetization(), R3{});
EXPECT_EQ(material.magnetization(), MaterialBySLD().magnetization());
EXPECT_EQ(material.refractiveIndex(dummy_wavelength), complex_t(1.0, 0.0));
EXPECT_EQ(material.refractiveIndex(dummy_wavelength),
MaterialBySLD().refractiveIndex(dummy_wavelength));
EXPECT_TRUE(material.typeID() == Vacuum().typeID());
EXPECT_FALSE(material.typeID() == MaterialBySLD().typeID());
}
TEST(Material, Computation)
{
// Reference data for Fe taken from
// https://sld-calculator.appspot.com
// http://www.ati.ac.at/~neutropt/scattering/table.html
const double bc = 9.45e-6; // nm, bound coherent scattering length
const double abs_cs = 2.56e-10; // nm^2, absorption cross-section for 2200 m/s neutrons
const double basic_wavelength = 0.1798197; // nm, wavelength of 2200 m/s neutrons
const double mol_mass = 55.845; // g/mol, Fe molar mass
const double avog_number = 6.022e23; // mol^{-1}, Avogadro number
const double density = 7.874e-21; // g/nm^3, Fe material density
const double number_density = avog_number * density / mol_mass; // 1/nm^3, Fe number density
const double sld_real = number_density * bc;
const double sld_imag = number_density * abs_cs / (2.0 * basic_wavelength);
const double sq_angstroms = Units::angstrom * Units::angstrom;
const complex_t sld_ref(8.0241e-04, // nm^{-2}, reference data
6.0448e-8); // taken from https://sld-calculator.appspot.com/
// checking input data and reference values are the same
EXPECT_NEAR(2.0 * (sld_ref.real() - sld_real) / (sld_ref.real() + sld_real), 0.0, 1e-3);
EXPECT_NEAR(2.0 * (sld_ref.imag() - sld_imag) / (sld_ref.imag() + sld_imag), 0.0, 1e-3);
const double wl_factor_2200 = basic_wavelength * basic_wavelength / pi;
const double wl_factor_1100 = 4.0 * basic_wavelength * basic_wavelength / pi;
// MaterialBySLD accepts sld in AA^{-2}
Material material = MaterialBySLD("Fe", sld_real * sq_angstroms, sld_imag * sq_angstroms);
complex_t sld_res_2200 = (1.0 - material.refractiveIndex2(basic_wavelength)) / wl_factor_2200;
complex_t sld_res_1100 =
(1.0 - material.refractiveIndex2(2.0 * basic_wavelength)) / wl_factor_1100;
// change the sign of imaginary part according to internal convention
sld_res_2200 = std::conj(sld_res_2200);
sld_res_1100 = std::conj(sld_res_1100);
EXPECT_NEAR(0.0, (sld_ref.real() - sld_res_2200.real()) / sld_ref.real(), 1e-3);
EXPECT_NEAR(0.0, (sld_ref.imag() - sld_res_2200.imag()) / sld_ref.imag(), 1e-3);
EXPECT_NEAR(0.0, (sld_ref.real() - sld_res_1100.real()) / sld_ref.real(), 1e-3);
EXPECT_NEAR(0.0, (sld_ref.imag() - sld_res_1100.imag()) / sld_ref.imag(), 1e-3);
const complex_t refr_index = material.refractiveIndex(2.0 * basic_wavelength);
WavevectorInfo wv_info(C3{}, C3{}, 2.0 * basic_wavelength);
Material material2 =
RefractiveMaterial("Fe", 1.0 - refr_index.real(), std::abs(refr_index.imag()));
const complex_t subtrSLD = material2.scalarSubtrSLD(wv_info);
const complex_t subtrSLDWlIndep = material.scalarSubtrSLD(wv_info);
EXPECT_NEAR(subtrSLD.real(), subtrSLDWlIndep.real(), 1e-10);
EXPECT_NEAR(subtrSLD.imag(), subtrSLDWlIndep.imag(), 1e-10);
}
TEST(Material, AverageRefractiveMaterials)
{
R3 magnetization = R3{1.0, 0.0, 0.0};
const Material material = RefractiveMaterial("Material", 0.5, 0.5, magnetization);
const Admixtures regions = {{OneAdmixture{0.25, material}, OneAdmixture{0.25, material}}};
const Material material_avr = MaterialUtil::averagedMaterial(material, regions);
EXPECT_EQ(material_avr.magnetization(), magnetization);
EXPECT_DOUBLE_EQ(material_avr.refractiveIndex_or_SLD().real(), 0.5);
EXPECT_DOUBLE_EQ(material_avr.refractiveIndex_or_SLD().imag(), 0.5);
EXPECT_TRUE(material_avr.typeID() == MATERIAL_TYPES::RefractiveMaterial);
const Material material3 = MaterialBySLD("Material3", 0.5, 0.5, magnetization);
EXPECT_THROW(MaterialUtil::averagedMaterial(material3, regions), std::runtime_error);
}
TEST(Material, AverageSLDMaterials)
{
R3 magnetization = R3{1.0, 0.0, 0.0};
const Material material = MaterialBySLD("Material", 0.5, 0.5, magnetization);
const Admixtures regions = {{OneAdmixture{0.25, material}, OneAdmixture{0.25, material}}};
const Material material_avr = MaterialUtil::averagedMaterial(material, regions);
EXPECT_EQ(material_avr.magnetization(), magnetization);
EXPECT_DOUBLE_EQ(material_avr.refractiveIndex_or_SLD().real(), 0.5);
EXPECT_DOUBLE_EQ(material_avr.refractiveIndex_or_SLD().imag(), 0.5);
EXPECT_TRUE(material_avr.typeID() == MATERIAL_TYPES::MaterialBySLD);
}
TEST(Material, AverageMixedMaterials)
{
R3 magnetization = R3{1.0, 0.0, 0.0};
const Material material = RefractiveMaterial("Material", 0.5, 0.5, magnetization);
const Admixtures regions = {{OneAdmixture{0.25, material}, OneAdmixture{0.25, material}}};
const Material material3 = MaterialBySLD("Material3", 0.5, 0.5, magnetization);
EXPECT_THROW(MaterialUtil::averagedMaterial(material3, regions), std::runtime_error);
}
TEST(Material, TypeIds)
{
Material material = MaterialBySLD("Material", 1.0, 1.0);
Material material2 = RefractiveMaterial("Material", 1.0, 1.0);
EXPECT_TRUE(material.typeID() == MATERIAL_TYPES::MaterialBySLD);
EXPECT_TRUE(material2.typeID() == MATERIAL_TYPES::RefractiveMaterial);
EXPECT_TRUE(material.typeID() != material2.typeID());
Material material3 = MaterialBySLD("Material", 1.0, 1.0);
EXPECT_TRUE(material.typeID() == material3.typeID());
}
TEST(Material, MaterialComparison)
{
Material material = MaterialBySLD("Material", 1.0, 1.0);
Material material2 = RefractiveMaterial("Material", 1.0, 1.0);
EXPECT_TRUE(material == material);
EXPECT_FALSE(material != material);
EXPECT_FALSE(material == material2);
Material material3 = RefractiveMaterial("Material3", 2.0, 2.0);
EXPECT_FALSE(material3 == material2);
EXPECT_TRUE(material3 != material2);
Material material4 = RefractiveMaterial("Material", 1.0, 1.0, R3{1.0, 2.0, 3.0});
EXPECT_FALSE(material4 == material2);
EXPECT_TRUE(material4 != material2);
EXPECT_FALSE(Vacuum() == MaterialBySLD());
EXPECT_TRUE(Vacuum() != MaterialBySLD());
}
TEST(Material, MaterialCopy)
{
complex_t material_data = complex_t(0.0, 2.0);
complex_t refIndex = complex_t(1.0 - material_data.real(), material_data.imag());
R3 magnetism = R3(3.0, 4.0, 5.0);
Material material = RefractiveMaterial("MagMaterial", refIndex, magnetism);
const Material& copy = material;
EXPECT_EQ(material_data, copy.refractiveIndex_or_SLD());
EXPECT_EQ(magnetism, copy.magnetization());
EXPECT_TRUE(material == copy);
}
|