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) {
53 fun.setParameter(
"IB21", 0.0);
54 fun.fixParameter(
"IB21");
58void setSymmetryC2(API::IFunction &fun) {
60 fun.unfixParameter(
"B20");
61 fun.unfixParameter(
"B40");
62 fun.unfixParameter(
"B60");
64 free(fun,
"B22", REAL_PARAM_PART);
66 free(fun,
"B42", IMAG_PARAM_PART);
68 free(fun,
"B44", IMAG_PARAM_PART);
70 free(fun,
"B62", IMAG_PARAM_PART);
72 free(fun,
"B64", IMAG_PARAM_PART);
74 free(fun,
"B66", IMAG_PARAM_PART);
78void setSymmetryC2v(API::IFunction &fun) {
80 fun.unfixParameter(
"B20");
81 fun.unfixParameter(
"B40");
82 fun.unfixParameter(
"B60");
84 free(fun,
"B22", REAL_PARAM_PART);
86 free(fun,
"B42", REAL_PARAM_PART);
88 free(fun,
"B44", REAL_PARAM_PART);
90 free(fun,
"B62", REAL_PARAM_PART);
92 free(fun,
"B64", REAL_PARAM_PART);
94 free(fun,
"B66", REAL_PARAM_PART);
98void setSymmetryC4(API::IFunction &fun) {
100 fun.unfixParameter(
"B20");
101 fun.unfixParameter(
"B40");
102 fun.unfixParameter(
"B60");
108 free(fun,
"B44", REAL_PARAM_PART);
112 free(fun,
"B64", IMAG_PARAM_PART);
118void setSymmetryD4(API::IFunction &fun) {
120 fun.unfixParameter(
"B20");
121 fun.unfixParameter(
"B40");
122 fun.unfixParameter(
"B60");
128 free(fun,
"B44", REAL_PARAM_PART);
132 free(fun,
"B64", REAL_PARAM_PART);
138void setSymmetryC3(API::IFunction &fun) {
140 fun.unfixParameter(
"B20");
141 fun.unfixParameter(
"B40");
142 fun.unfixParameter(
"B60");
147 free(fun,
"B43", REAL_PARAM_PART);
151 free(fun,
"B63", IMAG_PARAM_PART);
154 free(fun,
"B66", IMAG_PARAM_PART);
158void setSymmetryD3(API::IFunction &fun) {
160 fun.unfixParameter(
"B20");
161 fun.unfixParameter(
"B40");
162 fun.unfixParameter(
"B60");
167 free(fun,
"B43", REAL_PARAM_PART);
171 free(fun,
"B63", REAL_PARAM_PART);
174 free(fun,
"B66", REAL_PARAM_PART);
178void setSymmetryC6(API::IFunction &fun) {
180 fun.unfixParameter(
"B20");
181 fun.unfixParameter(
"B40");
182 fun.unfixParameter(
"B60");
194 free(fun,
"B66", REAL_PARAM_PART);
198void setSymmetryT(API::IFunction &fun) {
200 fun.setParameter(
"B20", 0.0);
201 fun.fixParameter(
"B20");
202 fun.unfixParameter(
"B40");
203 fun.unfixParameter(
"B60");
209 free(fun,
"B44", REAL_PARAM_PART);
213 free(fun,
"B64", REAL_PARAM_PART);
216 fun.tie(
"B44",
"5*B40");
217 fun.tie(
"B64",
"-21*B60");
221const std::map<std::string, std::function<void(API::IFunction &)>> SYMMETRY_MAP{
223 {
"C1", setSymmetryC1},
224 {
"Ci", setSymmetryC1},
226 {
"C2", setSymmetryC2},
227 {
"Cs", setSymmetryC2},
228 {
"C2h", setSymmetryC2},
230 {
"C2v", setSymmetryC2v},
231 {
"D2", setSymmetryC2v},
232 {
"D2h", setSymmetryC2v},
234 {
"C4", setSymmetryC4},
235 {
"S4", setSymmetryC4},
236 {
"C4h", setSymmetryC4},
238 {
"D4", setSymmetryD4},
239 {
"C4v", setSymmetryD4},
240 {
"D2d", setSymmetryD4},
241 {
"D4h", setSymmetryD4},
243 {
"C3", setSymmetryC3},
244 {
"S6", setSymmetryC3},
246 {
"D3", setSymmetryD3},
247 {
"C3v", setSymmetryD3},
248 {
"D3d", setSymmetryD3},
250 {
"C6", setSymmetryC6},
251 {
"C3h", setSymmetryC6},
252 {
"C6h", setSymmetryC6},
253 {
"D6", setSymmetryC6},
254 {
"C6v", setSymmetryC6},
255 {
"D3h", setSymmetryC6},
256 {
"D6h", setSymmetryC6},
259 {
"Td", setSymmetryT},
260 {
"Th", setSymmetryT},
262 {
"Oh", setSymmetryT}};
299 declareParameter(
"IB21", 0.0,
"Imaginary part of the B21 field parameter.");
300 declareParameter(
"IB22", 0.0,
"Imaginary part of the B22 field parameter.");
301 declareParameter(
"IB41", 0.0,
"Imaginary part of the B41 field parameter.");
302 declareParameter(
"IB42", 0.0,
"Imaginary part of the B42 field parameter.");
303 declareParameter(
"IB43", 0.0,
"Imaginary part of the B43 field parameter.");
304 declareParameter(
"IB44", 0.0,
"Imaginary part of the B44 field parameter.");
305 declareParameter(
"IB61", 0.0,
"Imaginary part of the B61 field parameter.");
306 declareParameter(
"IB62", 0.0,
"Imaginary part of the B62 field parameter.");
307 declareParameter(
"IB63", 0.0,
"Imaginary part of the B63 field parameter.");
308 declareParameter(
"IB64", 0.0,
"Imaginary part of the B64 field parameter.");
309 declareParameter(
"IB65", 0.0,
"Imaginary part of the B65 field parameter.");
310 declareParameter(
"IB66", 0.0,
"Imaginary part of the B66 field parameter.");
312 setSymmetryC1(*
this);
326 throw std::runtime_error(
"Ion name must be specified.");
329 auto ionIter = ION_2_NRE.find(ion);
330 if (ionIter == ION_2_NRE.end()) {
338 if (ion.size() > 1 && std::isdigit(ion[1])) {
341 auto J2 = std::stof(ion.substr(1)) * 2.;
343 throw std::out_of_range(
"");
345 if (
fabs(J2 - (
int)J2) < 0.001) {
350 }
catch (
const std::invalid_argument &) {
351 throw std::runtime_error(
"Invalid value '" + ion.substr(1) +
"' of J passed to CrystalFieldPeaks.");
352 }
catch (
const std::out_of_range &) {
353 throw std::runtime_error(
"Value of J: '" + ion.substr(1) +
"' passed to CrystalFieldPeaks is too big.");
359 throw std::runtime_error(
"Unknown ion name '" + ion +
"' passed to CrystalFieldPeaks.");
362 nre = ionIter->second;
431 if (
name ==
"Symmetry") {
432 auto symmIter = SYMMETRY_MAP.find(attr.
asString());
433 if (symmIter == SYMMETRY_MAP.end()) {
434 throw std::runtime_error(
"Unknown symmetry passed to CrystalFieldPeaks: " + attr.
asString());
436 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