20const std::map<std::string, int> ION_2_NRE{{
"Ce", 1}, {
"Pr", 2}, {
"Nd", 3}, {
"Pm", 4}, {
"Sm", 5},
21 {
"Eu", 6}, {
"Gd", 7}, {
"Tb", 8}, {
"Dy", 9}, {
"Ho", 10},
22 {
"Er", 11}, {
"Tm", 12}, {
"Yb", 13}};
24const bool REAL_PARAM_PART =
true;
25const bool IMAG_PARAM_PART =
false;
27void fixx(API::IFunction &fun,
const std::string &par) {
28 fun.setParameter(par, 0.0);
29 fun.fixParameter(par);
30 const std::string ipar =
"I" + par;
31 fun.setParameter(ipar, 0.0);
32 fun.fixParameter(ipar);
35void free(API::IFunction &fun,
const std::string &par,
bool realOnly) {
36 fun.unfixParameter(par);
37 const std::string ipar =
"I" + par;
39 fun.setParameter(ipar, 0.0);
40 fun.fixParameter(ipar);
42 fun.unfixParameter(ipar);
47void setSymmetryC1(API::IFunction &fun) {
49 auto i = fun.parameterIndex(
"B20");
50 for (; i < fun.nParams(); ++i) {
56void setSymmetryC2(API::IFunction &fun) {
58 fun.unfixParameter(
"B20");
59 fun.unfixParameter(
"B40");
60 fun.unfixParameter(
"B60");
62 free(fun,
"B22", REAL_PARAM_PART);
64 free(fun,
"B42", IMAG_PARAM_PART);
66 free(fun,
"B44", IMAG_PARAM_PART);
68 free(fun,
"B62", IMAG_PARAM_PART);
70 free(fun,
"B64", IMAG_PARAM_PART);
72 free(fun,
"B66", IMAG_PARAM_PART);
76void setSymmetryC2v(API::IFunction &fun) {
78 fun.unfixParameter(
"B20");
79 fun.unfixParameter(
"B40");
80 fun.unfixParameter(
"B60");
82 free(fun,
"B22", REAL_PARAM_PART);
84 free(fun,
"B42", REAL_PARAM_PART);
86 free(fun,
"B44", REAL_PARAM_PART);
88 free(fun,
"B62", REAL_PARAM_PART);
90 free(fun,
"B64", REAL_PARAM_PART);
92 free(fun,
"B66", REAL_PARAM_PART);
96void setSymmetryC4(API::IFunction &fun) {
98 fun.unfixParameter(
"B20");
99 fun.unfixParameter(
"B40");
100 fun.unfixParameter(
"B60");
106 free(fun,
"B44", REAL_PARAM_PART);
110 free(fun,
"B64", IMAG_PARAM_PART);
116void setSymmetryD4(API::IFunction &fun) {
118 fun.unfixParameter(
"B20");
119 fun.unfixParameter(
"B40");
120 fun.unfixParameter(
"B60");
126 free(fun,
"B44", REAL_PARAM_PART);
130 free(fun,
"B64", REAL_PARAM_PART);
136void setSymmetryC3(API::IFunction &fun) {
138 fun.unfixParameter(
"B20");
139 fun.unfixParameter(
"B40");
140 fun.unfixParameter(
"B60");
145 free(fun,
"B43", REAL_PARAM_PART);
149 free(fun,
"B63", IMAG_PARAM_PART);
152 free(fun,
"B66", IMAG_PARAM_PART);
156void setSymmetryD3(API::IFunction &fun) {
158 fun.unfixParameter(
"B20");
159 fun.unfixParameter(
"B40");
160 fun.unfixParameter(
"B60");
165 free(fun,
"B43", REAL_PARAM_PART);
169 free(fun,
"B63", REAL_PARAM_PART);
172 free(fun,
"B66", REAL_PARAM_PART);
176void setSymmetryC6(API::IFunction &fun) {
178 fun.unfixParameter(
"B20");
179 fun.unfixParameter(
"B40");
180 fun.unfixParameter(
"B60");
192 free(fun,
"B66", REAL_PARAM_PART);
196void setSymmetryT(API::IFunction &fun) {
198 fun.setParameter(
"B20", 0.0);
199 fun.fixParameter(
"B20");
200 fun.unfixParameter(
"B40");
201 fun.unfixParameter(
"B60");
207 free(fun,
"B44", REAL_PARAM_PART);
211 free(fun,
"B64", REAL_PARAM_PART);
214 fun.tie(
"B44",
"5*B40");
215 fun.tie(
"B64",
"-21*B60");
219const std::map<std::string, std::function<void(API::IFunction &)>> SYMMETRY_MAP{
221 {
"C1", setSymmetryC1},
222 {
"Ci", setSymmetryC1},
224 {
"C2", setSymmetryC2},
225 {
"Cs", setSymmetryC2},
226 {
"C2h", setSymmetryC2},
228 {
"C2v", setSymmetryC2v},
229 {
"D2", setSymmetryC2v},
230 {
"D2h", setSymmetryC2v},
232 {
"C4", setSymmetryC4},
233 {
"S4", setSymmetryC4},
234 {
"C4h", setSymmetryC4},
236 {
"D4", setSymmetryD4},
237 {
"C4v", setSymmetryD4},
238 {
"D2d", setSymmetryD4},
239 {
"D4h", setSymmetryD4},
241 {
"C3", setSymmetryC3},
242 {
"S6", setSymmetryC3},
244 {
"D3", setSymmetryD3},
245 {
"C3v", setSymmetryD3},
246 {
"D3d", setSymmetryD3},
248 {
"C6", setSymmetryC6},
249 {
"C3h", setSymmetryC6},
250 {
"C6h", setSymmetryC6},
251 {
"D6", setSymmetryC6},
252 {
"C6v", setSymmetryC6},
253 {
"D3h", setSymmetryC6},
254 {
"D6h", setSymmetryC6},
257 {
"Td", setSymmetryT},
258 {
"Th", setSymmetryT},
260 {
"Oh", setSymmetryT}};
297 declareParameter(
"IB21", 0.0,
"Imaginary part of the B21 field parameter.");
298 declareParameter(
"IB22", 0.0,
"Imaginary part of the B22 field parameter.");
299 declareParameter(
"IB41", 0.0,
"Imaginary part of the B41 field parameter.");
300 declareParameter(
"IB42", 0.0,
"Imaginary part of the B42 field parameter.");
301 declareParameter(
"IB43", 0.0,
"Imaginary part of the B43 field parameter.");
302 declareParameter(
"IB44", 0.0,
"Imaginary part of the B44 field parameter.");
303 declareParameter(
"IB61", 0.0,
"Imaginary part of the B61 field parameter.");
304 declareParameter(
"IB62", 0.0,
"Imaginary part of the B62 field parameter.");
305 declareParameter(
"IB63", 0.0,
"Imaginary part of the B63 field parameter.");
306 declareParameter(
"IB64", 0.0,
"Imaginary part of the B64 field parameter.");
307 declareParameter(
"IB65", 0.0,
"Imaginary part of the B65 field parameter.");
308 declareParameter(
"IB66", 0.0,
"Imaginary part of the B66 field parameter.");
310 setSymmetryC1(*
this);
324 throw std::runtime_error(
"Ion name must be specified.");
327 auto ionIter = ION_2_NRE.find(ion);
328 if (ionIter == ION_2_NRE.end()) {
336 if (ion.size() > 1 && std::isdigit(
static_cast<unsigned char>(ion[1]))) {
339 auto J2 = std::stof(ion.substr(1)) * 2.;
341 throw std::out_of_range(
"");
343 if (
fabs(J2 - (
int)J2) < 0.001) {
348 }
catch (
const std::invalid_argument &) {
349 throw std::runtime_error(
"Invalid value '" + ion.substr(1) +
"' of J passed to CrystalFieldPeaks.");
350 }
catch (
const std::out_of_range &) {
351 throw std::runtime_error(
"Value of J: '" + ion.substr(1) +
"' passed to CrystalFieldPeaks is too big.");
357 throw std::runtime_error(
"Unknown ion name '" + ion +
"' passed to CrystalFieldPeaks.");
360 nre = ionIter->second;
429 if (
name ==
"Symmetry") {
430 auto symmIter = SYMMETRY_MAP.find(attr.
asString());
431 if (symmIter == SYMMETRY_MAP.end()) {
432 throw std::runtime_error(
"Unknown symmetry passed to CrystalFieldPeaks: " + attr.
asString());
434 symmIter->second(*
this);
Base class that represents the domain of a function.
A class to store values calculated by a function.
Attribute is a non-fitting parameter.
std::string asString() const
Returns string value if attribute is a string, throws exception otherwise.
virtual Attribute getAttribute(const std::string &name) const
Return a value of attribute attName.
void declareAttribute(const std::string &name, const API::IFunction::Attribute &defaultValue)
Declare a single attribute.
virtual void setAttribute(const std::string &name, const Attribute &)
Set a value to attribute attName.
virtual std::string name() const =0
Returns the function's name.
void setAttributeValue(const std::string &attName, const T &value)
Set an attribute value.
Implements the part of IFunction interface dealing with parameters.
void declareParameter(const std::string &name, double initValue=0, const std::string &description="") override
Declare a new parameter.
double getParameter(size_t i) const override
Get i-th parameter.
size_t size() const
Size of the vector.
void function(const API::FunctionDomain &, API::FunctionValues &) const override
Evaluates the function for all arguments in the domain.
std::string name() const override
Returns the function's name.
CrystalFieldPeaks is a function that calculates crystal field peak positions and intensities.
void calculateEigenSystem(DoubleFortranVector &en, ComplexFortranMatrix &wf, ComplexFortranMatrix &ham, ComplexFortranMatrix &hz, int &nre) const
Calculate the crystal field eigensystem.
void setAttribute(const std::string &name, const Attribute &) override
Perform a castom action when an attribute is set.
CrystalFieldPeaksBase()
Constructor.
Marks code as not implemented yet.
void MANTID_CURVEFITTING_DLL calculateEigensystem(DoubleFortranVector &eigenvalues, ComplexFortranMatrix &eigenvectors, ComplexFortranMatrix &hamiltonian, ComplexFortranMatrix &hzeeman, int nre, const DoubleFortranVector &bmol, const DoubleFortranVector &bext, const ComplexFortranMatrix &bkq, double alpha_euler=0.0, double beta_euler=0.0, double gamma_euler=0.0)
Calculate eigenvalues and eigenvectors of the crystal field hamiltonian.
std::complex< double > ComplexType