Skip to content
Snippets Groups Projects
MaterialBuilderTest.h 9.65 KiB
Newer Older
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
//     NScD Oak Ridge National Laboratory, European Spallation Source
//     & Institut Laue - Langevin
// SPDX - License - Identifier: GPL - 3.0 +
#ifndef MANTID_KERNEL_MATERIALBUILDERTEST_H_
#define MANTID_KERNEL_MATERIALBUILDERTEST_H_

#include <cxxtest/TestSuite.h>

#include "MantidKernel/Atom.h"
#include "MantidKernel/EmptyValues.h"
#include "MantidKernel/MaterialBuilder.h"
#include "MantidKernel/NeutronAtom.h"

using Mantid::Kernel::Material;
using Mantid::Kernel::MaterialBuilder;
using Mantid::PhysicalConstants::NeutronAtom;

class MaterialBuilderTest : public CxxTest::TestSuite {
public:
  // This pair of boilerplate methods prevent the suite being created statically
  // This means the constructor isn't called when running other tests
  static MaterialBuilderTest *createSuite() {
    return new MaterialBuilderTest();
  }
  static void destroySuite(MaterialBuilderTest *suite) { delete suite; }

  //----------------------------------------------------------------------------
  // Success tests
  //----------------------------------------------------------------------------
  void test_Build_From_Name_And_Chemical_Formula_Single_Atom() {
    MaterialBuilder builder;
    Material mat = builder.setName("Nickel").setFormula("Ni").build();

    TS_ASSERT_EQUALS(mat.name(), "Nickel");
    TS_ASSERT_DELTA(mat.numberDensity(), 0.0913375, 0.0001);
    TS_ASSERT_DELTA(mat.totalScatterXSection(), 18.5, 0.0001);
    TS_ASSERT_DELTA(mat.absorbXSection(), 4.49, 0.0001);

    // Overrides by provided values
    const double rho(0.12);
    mat = builder.setNumberDensity(rho).build();
    TS_ASSERT_DELTA(mat.numberDensity(), rho, 0.0001);

    double totScatterXSec(18.1);
    mat = builder.setTotalScatterXSection(totScatterXSec).build();
    TS_ASSERT_DELTA(mat.totalScatterXSection(), totScatterXSec, 0.0001);
    double absXSec(4.6);
    mat = builder.setAbsorptionXSection(absXSec).build();
    TS_ASSERT_DELTA(mat.absorbXSection(), absXSec, 0.0001);
    double cohXSec(4.6);
    mat = builder.setCoherentXSection(cohXSec).build();
    TS_ASSERT_DELTA(mat.cohScatterXSection(), cohXSec, 0.0001);
    double incohXSec(4.6);
    mat = builder.setIncoherentXSection(incohXSec).build();
    TS_ASSERT_DELTA(mat.incohScatterXSection(), incohXSec, 0.0001);
  }

  void test_Build_From_Name_And_Chemical_Formula_MultiAtom() {
    MaterialBuilder builder;
    Material mat = builder.setName("Nickel")
                       .setFormula("Al2-O3")
                       .setNumberDensity(0.1)
                       .build();
    TS_ASSERT_DELTA(mat.numberDensity(), 0.1, 0.0001);
    TS_ASSERT_DELTA(mat.totalScatterXSection(), 3.1404, 0.0001);
    TS_ASSERT_DELTA(mat.absorbXSection(), 0.092514, 0.0001);
  }

  void test_Build_From_Atomic_Number() {
    MaterialBuilder builder;
    Material mat = builder.setName("Nickel")
                       .setAtomicNumber(28)
                       .setNumberDensity(0.1)
                       .build();
    // Default isotope
    TS_ASSERT_DELTA(mat.totalScatterXSection(), 18.5, 0.0001);
    TS_ASSERT_DELTA(mat.absorbXSection(), 4.49, 0.0001);

    mat = builder.setName("Ni").setAtomicNumber(28).setMassNumber(58).build();
    // Other isotop
    TS_ASSERT_DELTA(mat.totalScatterXSection(), 26.1, 0.0001);
    TS_ASSERT_DELTA(mat.absorbXSection(), 4.6, 0.0001);
  }

  void test_Build_From_Cross_Sections() {
    MaterialBuilder builder;
    Material mat = builder.setNumberDensity(0.1)
                       .setTotalScatterXSection(2.3)
                       .setCoherentXSection(0.5)
                       .setIncoherentXSection(5.0)
                       .setAbsorptionXSection(0.23)
                       .build();
    TS_ASSERT_EQUALS(mat.chemicalFormula().size(), 1)
    TS_ASSERT_EQUALS(mat.chemicalFormula().front().atom->symbol, "user")
    TS_ASSERT_EQUALS(mat.numberDensity(), 0.1)
    TS_ASSERT_EQUALS(mat.totalScatterXSection(), 2.3)
    TS_ASSERT_EQUALS(mat.cohScatterXSection(), 0.5)
    TS_ASSERT_EQUALS(mat.incohScatterXSection(), 5.0)
    TS_ASSERT_EQUALS(mat.absorbXSection(), 0.23)
  }

  void test_Number_Density_Set_By_Formula_ZParameter_And_Cell_Volume() {
    MaterialBuilder builder;
    auto mat = builder.setName("Nickel")
                   .setFormula("Al2-O3")
                   .setZParameter(6)
                   .setUnitCellVolume(253.54)
                   .build();

    TS_ASSERT_DELTA(mat.numberDensity(), 0.1183245, 0.001);
  }

  void test_Number_Density_Set_By_Formula_MassDensity() {
    MaterialBuilder builder;
    auto mat = builder.setName("Nickel")
                   .setFormula("Al2-O3")
                   .setMassDensity(4)
                   .build();

    TS_ASSERT_DELTA(mat.numberDensity(), 0.0236252 * 5, 0.001);
  }

  void test_Number_Density_Set_By_AtomicNumber_MassDensity() {
    MaterialBuilder builder;
Martyn Gigg's avatar
Martyn Gigg committed
    auto mat =
        builder.setName("Nickel").setAtomicNumber(28).setMassDensity(4).build();

    TS_ASSERT_DELTA(mat.numberDensity(), 0.0410414, 0.001);
  }
  void test_Number_Density_Set_By_AtomicNumber_ZParameter_And_Cell_Volume() {
    MaterialBuilder builder;
    auto mat = builder.setName("Nickel")
                   .setAtomicNumber(28)
                   .setZParameter(6)
                   .setUnitCellVolume(253)
                   .build();

    TS_ASSERT_DELTA(mat.numberDensity(), 0.0237154, 0.001);
  }

  void test_Number_Density_By_Formula_Unit() {
    MaterialBuilder builder;
    const auto material =
        builder.setName("Strange oxide")
            .setFormula("Al2 O3")
            .setNumberDensity(0.23)
            .setNumberDensityUnit(
                MaterialBuilder::NumberDensityUnit::FormulaUnits)
            .build();
    TS_ASSERT_DELTA(material.numberDensity(), (2. + 3.) * 0.23, 1e-12)
  }

  //----------------------------------------------------------------------------
  // Failure tests
  //----------------------------------------------------------------------------
  void test_Empty_Name_Throws_Error_When_Set() {
    MaterialBuilder builder;
    TS_ASSERT_THROWS(builder.setName(""), const std::invalid_argument &);
  }

  void test_Invalid_Formula_Throws_Error_When_Set() {
    MaterialBuilder builder;
    TS_ASSERT_THROWS(builder.setFormula(""), const std::invalid_argument &);
    TS_ASSERT_THROWS(builder.setFormula("Al-2"), const std::invalid_argument &);
  }

  void test_Setting_Neither_ChemicalFormula_And_AtomicNumber_Throws_Error() {
    MaterialBuilder builder;
Samuel Jones's avatar
Samuel Jones committed
    TS_ASSERT_THROWS(builder.setName("Nickel").build(),
                     const std::runtime_error &);
  }

  void test_Setting_Both_ChemicalFormula_And_AtomicNumber_Throws_Error() {
    MaterialBuilder builder;
    TS_ASSERT_THROWS(builder.setFormula("Al2-O3").setAtomicNumber(28),
                     const std::runtime_error &);
    TS_ASSERT_THROWS(builder.setAtomicNumber(28).setFormula("Al2-O3"),
                     const std::runtime_error &);
  }

  void test_Setting_ZParameter_UnitCell_And_MassDensity_Throws_Error() {
    MaterialBuilder builder;
    TS_ASSERT_THROWS(builder.setMassDensity(4).setZParameter(6),
                     const std::runtime_error &);
    TS_ASSERT_THROWS(builder.setMassDensity(4).setUnitCellVolume(250.),
                     const std::runtime_error &);

    TS_ASSERT_THROWS(builder.setZParameter(6).setMassDensity(4),
                     const std::runtime_error &);
    TS_ASSERT_THROWS(builder.setUnitCellVolume(6).setMassDensity(4),
                     const std::runtime_error &);

  void test_MultiAtom_with_no_number_density_throws() {
    MaterialBuilder builder;
    builder.setName("Nickel").setFormula("Al2-O3");
    TS_ASSERT_THROWS_EQUALS(
        builder.build(), const std::runtime_error &e, std::string(e.what()),
        "The number density could not be determined. Please "
        "provide the number density, ZParameter and unit "
        "cell volume or mass density.")

  void test_User_Defined_Material_Without_NumberDensity_Throws() {
    MaterialBuilder builder;
    builder = builder.setTotalScatterXSection(2.3)
                  .setCoherentXSection(0.5)
                  .setIncoherentXSection(5.0)
                  .setAbsorptionXSection(0.23);
    TS_ASSERT_THROWS(builder.build(), const std::runtime_error &)
  }

  void test_User_Defined_Material_Without_TotalScatterXSection_Throws() {
    MaterialBuilder builder;
    builder = builder.setNumberDensity(0.1)
                  .setCoherentXSection(0.5)
                  .setIncoherentXSection(5.0)
                  .setAbsorptionXSection(0.23);
    TS_ASSERT_THROWS(builder.build(), const std::runtime_error &)
  }

  void test_User_Defined_Material_Without_CoherentXSection_Throws() {
    MaterialBuilder builder;
    builder = builder.setNumberDensity(0.1)
                  .setTotalScatterXSection(2.3)
                  .setIncoherentXSection(5.0)
                  .setAbsorptionXSection(0.23);
    TS_ASSERT_THROWS(builder.build(), const std::runtime_error &)
  }

  void test_User_Defined_Material_Without_IncoherentXSection_Throws() {
    MaterialBuilder builder;
    builder = builder.setNumberDensity(0.1)
                  .setTotalScatterXSection(2.3)
                  .setCoherentXSection(5.0)
                  .setAbsorptionXSection(0.23);
    TS_ASSERT_THROWS(builder.build(), const std::runtime_error &)
  }

  void test_User_Defined_Material_Without_AbsorptionXSection_Throws() {
    MaterialBuilder builder;
    builder = builder.setNumberDensity(0.1)
                  .setTotalScatterXSection(2.3)
                  .setCoherentXSection(5.0)
                  .setIncoherentXSection(5.0);
    TS_ASSERT_THROWS(builder.build(), const std::runtime_error &)
};

#endif /* MANTID_KERNEL_MATERIALBUILDERTEST_H_ */