Mantid
Loading...
Searching...
No Matches
CrystalFieldFunction.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
15
22
24
25#include <boost/optional.hpp>
26#include <boost/regex.hpp>
27#include <limits>
28#include <memory>
29#include <utility>
30
32
33using namespace CurveFitting;
34using namespace Kernel;
35using namespace API;
36
37DECLARE_FUNCTION(CrystalFieldFunction)
38
39namespace {
40
41const std::string ION_PREFIX("ion");
42const std::string SPECTRUM_PREFIX("sp");
43const std::string BACKGROUND_PREFIX("bg");
44const std::string PEAK_PREFIX("pk");
45
46// Regex for names of attributes/parameters for a particular spectrum
47// Example: sp1.FWHMX
48const boost::regex SPECTRUM_ATTR_REGEX(SPECTRUM_PREFIX + "([0-9]+)\\.(.+)");
49// Regex for names of attributes/parameters for a background
50// Example: bg.A1
51const boost::regex BACKGROUND_ATTR_REGEX(BACKGROUND_PREFIX + "\\.(.+)");
52// Regex for names of attributes/parameters for peaks
53// Example: pk1.PeakCentre
54const boost::regex PEAK_ATTR_REGEX(PEAK_PREFIX + "([0-9]+)\\.(.+)");
55// Regex for names of attributes/parameters for peaks
56// Example: ion1.pk0.PeakCentre
57const boost::regex ION_ATTR_REGEX(ION_PREFIX + "([0-9]+)\\.(.+)");
58// Regex for names of attributes/parameters for physical properties
59// Example: cv.ScaleFactor
60const boost::regex PHYS_PROP_ATTR_REGEX("((ion[0-9]+\\.)?(cv|chi|mh|mt))\\.(.+)");
61
64class Peaks : public CrystalFieldPeaksBase, public API::IFunctionGeneral {
65public:
66 Peaks() : CrystalFieldPeaksBase() {}
67 std::string name() const override { return "Peaks"; }
68 size_t getNumberDomainColumns() const override {
69 throw Exception::NotImplementedError("This method is intentionally not implemented.");
70 }
71 size_t getNumberValuesPerArgument() const override {
72 throw Exception::NotImplementedError("This method is intentionally not implemented.");
73 }
74 void functionGeneral(const API::FunctionDomainGeneral & /*domain*/, API::FunctionValues & /*values*/) const override {
75 throw Exception::NotImplementedError("This method is intentionally not implemented.");
76 }
77 std::vector<size_t> m_IntensityScalingIdx;
78 std::vector<size_t> m_PPLambdaIdxChild;
79 std::vector<size_t> m_PPLambdaIdxSelf;
81 void declareIntensityScaling(size_t nSpec) {
83 m_PPLambdaIdxChild.resize(nSpec, -1);
84 m_PPLambdaIdxSelf.resize(nSpec, -1);
85 for (size_t i = 0; i < nSpec; ++i) {
86 auto si = std::to_string(i);
87 try { // If parameter has already been declared, don't declare it.
88 declareParameter("IntensityScaling" + si, 1.0, "Intensity scaling factor for spectrum " + si);
89 } catch (std::invalid_argument &) {
90 }
91 m_IntensityScalingIdx.emplace_back(parameterIndex("IntensityScaling" + si));
92 }
93 }
94};
95
96} // namespace
97
100 : IFunction(), m_nControlParams(0), m_nControlSourceParams(0), m_dirtyTarget(true) {}
101
102// Evaluates the function
105 if (!m_target) {
106 throw std::logic_error("FunctionGenerator failed to generate target function.");
107 }
108 m_target->function(domain, values);
109}
110
113void CrystalFieldFunction::setSource(IFunction_sptr source) const { m_source = std::move(source); }
114
116 if (!m_target) {
118 }
119 // The call to buildTargetFunction() above may have failed to set m_target.
120 if (!m_target) {
121 throw std::runtime_error("Failed to build target function.");
122 }
123 return m_target->getNumberDomains();
124}
125
126std::vector<IFunction_sptr> CrystalFieldFunction::createEquivalentFunctions() const {
128 std::vector<IFunction_sptr> funs;
129 auto &composite = dynamic_cast<CompositeFunction &>(*m_target);
130 for (size_t i = 0; i < composite.nFunctions(); ++i) {
131 auto fun = composite.getFunction(i);
132 auto cfun = dynamic_cast<CompositeFunction *>(fun.get());
133 if (cfun) {
134 cfun->checkFunction();
135 }
136 funs.emplace_back(fun);
137 }
138 return funs;
139}
140
142void CrystalFieldFunction::setParameter(size_t i, const double &value, bool explicitlySet) {
144 if (i < m_nControlParams) {
145 m_control.setParameter(i, value, explicitlySet);
146 m_dirtyTarget = true;
147 } else if (i < m_nControlSourceParams) {
148 m_source->setParameter(i - m_nControlParams, value, explicitlySet);
149 m_dirtyTarget = true;
150 } else {
152 m_target->setParameter(i - m_nControlSourceParams, value, explicitlySet);
153 }
154}
155
157void CrystalFieldFunction::setParameterDescription(size_t i, const std::string &description) {
159 if (i < m_nControlParams) {
160 m_control.setParameterDescription(i, description);
161 } else if (i < m_nControlSourceParams) {
162 m_source->setParameterDescription(i - m_nControlParams, description);
163 } else {
165 m_target->setParameterDescription(i - m_nControlSourceParams, description);
166 }
167}
168
173 if (i < m_nControlParams) {
174 return m_control.getParameter(i);
175 } else if (i < m_nControlSourceParams) {
176 return m_source->getParameter(i - m_nControlParams);
177 } else {
178 return m_target->getParameter(i - m_nControlSourceParams);
179 }
180}
181
183bool CrystalFieldFunction::hasParameter(const std::string &name) const {
184 try {
186 return true;
187 } catch (std::invalid_argument &) {
188 return false;
189 }
190}
191
193void CrystalFieldFunction::setParameter(const std::string &name, const double &value, bool explicitlySet) {
194 try {
195 auto index = parameterIndex(name);
196 setParameter(index, value, explicitlySet);
197 } catch (std::invalid_argument &) {
198 // Allow ignoring peak parameters: the peak may not exist.
199 boost::smatch match;
200 if (!boost::regex_search(name, match, PEAK_ATTR_REGEX)) {
201 throw;
202 }
203 }
204}
205
207void CrystalFieldFunction::setParameterDescription(const std::string &name, const std::string &description) {
208 auto index = parameterIndex(name);
209 setParameterDescription(index, description);
210}
211
213double CrystalFieldFunction::getParameter(const std::string &name) const {
214 auto index = parameterIndex(name);
215 return getParameter(index);
216}
217
220 if (!m_source) {
221 // This method can be called on an uninitialised function (by tests for
222 // example).
223 // Return 0 so no exception is thrown an it should prevent attemts to access
224 // parameters.
225 return 0;
226 }
229 return m_nControlSourceParams + m_target->nParams();
230}
231
234size_t CrystalFieldFunction::parameterIndex(const std::string &name) const {
237 if (nParams() != m_mapIndices2Names.size()) {
238 makeMaps();
239 }
240 auto found = m_mapNames2Indices.find(name);
241 if (found == m_mapNames2Indices.end()) {
242 throw std::invalid_argument("CrystalFieldFunction parameter not found: " + name);
243 }
244 return found->second;
245}
246
248std::string CrystalFieldFunction::parameterName(size_t i) const {
249 if (i >= nParams()) {
250 throw std::invalid_argument("CrystalFieldFunction's parameter index " + std::to_string(i) + " is out of range " +
252 }
255 if (nParams() != m_mapIndices2Names.size()) {
256 makeMaps();
257 }
258 return m_mapIndices2Names[i];
259}
260
265 if (i < m_nControlParams) {
267 } else if (i < m_nControlSourceParams) {
268 return m_source->parameterDescription(i - m_nControlParams);
269 } else {
270 return m_target->parameterDescription(i - m_nControlSourceParams);
271 }
272}
273
278 if (i < m_nControlParams) {
279 return m_control.isExplicitlySet(i);
280 } else if (i < m_nControlSourceParams) {
281 return m_source->isExplicitlySet(i - m_nControlParams);
282 } else {
283 return m_target->isExplicitlySet(i - m_nControlSourceParams);
284 }
285}
286
288double CrystalFieldFunction::getError(size_t i) const {
291 if (i < m_nControlParams) {
292 return m_control.getError(i);
293 } else if (i < m_nControlSourceParams) {
294 return m_source->getError(i - m_nControlParams);
295 } else {
296 return m_target->getError(i - m_nControlSourceParams);
297 }
298}
299
301double CrystalFieldFunction::getError(const std::string &name) const {
302 auto index = parameterIndex(name);
305 if (index < m_nControlParams) {
306 return m_control.getError(index);
307 } else if (index < m_nControlSourceParams) {
308 return m_source->getError(index - m_nControlParams);
309 } else {
310 return m_target->getError(index - m_nControlSourceParams);
311 }
312}
313
315void CrystalFieldFunction::setError(size_t i, double err) {
318 if (i < m_nControlParams) {
319 m_control.setError(i, err);
320 } else if (i < m_nControlSourceParams) {
321 m_source->setError(i - m_nControlParams, err);
322 } else {
323 m_target->setError(i - m_nControlSourceParams, err);
324 }
325}
326
328void CrystalFieldFunction::setError(const std::string &name, double err) {
329 auto index = parameterIndex(name);
332 if (index < m_nControlParams) {
334 } else if (index < m_nControlSourceParams) {
335 m_source->setError(index - m_nControlParams, err);
336 } else {
337 m_target->setError(index - m_nControlSourceParams, err);
338 }
339}
340
345 if (i < m_nControlParams) {
346 m_control.setParameterStatus(i, status);
347 } else if (i < m_nControlSourceParams) {
348 m_source->setParameterStatus(i - m_nControlParams, status);
349 } else {
350 m_target->setParameterStatus(i - m_nControlSourceParams, status);
351 }
352}
353
358 if (i < m_nControlParams) {
360 } else if (i < m_nControlSourceParams) {
361 return m_source->getParameterStatus(i - m_nControlParams);
362 } else {
363 return m_target->getParameterStatus(i - m_nControlSourceParams);
364 }
365}
366
371 if (ref.getLocalFunction() == this) {
372 return ref.getLocalIndex();
373 }
375 if (index < m_nControlParams) {
376 return index;
377 }
378 index = m_source->getParameterIndex(ref);
379 if (index < m_source->nParams()) {
380 return index + m_nControlParams;
381 }
382 return m_target->getParameterIndex(ref) + m_nControlSourceParams;
383}
384
390}
391
393void CrystalFieldFunction::declareParameter(const std::string & /*name*/, double /*initValue*/,
394 const std::string & /*description*/) {
395 throw Kernel::Exception::NotImplementedError("CrystalFieldFunction cannot have its own parameters.");
396}
397
402 if (!m_attributeNames.empty()) {
403 return;
404 }
405 auto numAttributes = IFunction::nAttributes();
406 for (size_t i = 0; i < numAttributes; ++i) {
408 }
409 auto controlAttributeNames = m_control.getAttributeNames();
410
411 // Lambda function that moves a attribute name from controlAttributeNames
412 // to attNames.
413 auto moveAttributeName = [&](const std::string &name) {
414 auto iterFound = std::find(controlAttributeNames.begin(), controlAttributeNames.end(), name);
415 if (iterFound != controlAttributeNames.end()) {
416 controlAttributeNames.erase(iterFound);
417 m_attributeNames.emplace_back(name);
418 }
419 };
420 // Prepend a prefix to attribute names, ignore NumDeriv attribute.
421 auto prependPrefix = [&](const std::string &prefix, const std::vector<std::string> &names) {
422 for (auto name : names) {
423 if (name.find("NumDeriv") != std::string::npos)
424 continue;
425 name.insert(name.begin(), prefix.begin(), prefix.end());
426 m_attributeNames.emplace_back(name);
427 }
428 };
429 // These names must appear first and in this order in the output vector
430 moveAttributeName("Ions");
431 moveAttributeName("Symmetries");
432 moveAttributeName("Temperatures");
433 moveAttributeName("Background");
434
435 // Only copy the unprefixed attributes - as the loop below will include
436 // And modify the prefixed attributes accordingly
437 std::copy_if(controlAttributeNames.begin(), controlAttributeNames.end(), std::back_inserter(m_attributeNames),
438 [](const auto &name) { return name.find(".") == std::string::npos; });
439 // Get
440 for (size_t iSpec = 0; iSpec < m_control.nFunctions(); ++iSpec) {
441 std::string prefix(SPECTRUM_PREFIX);
442 prefix.append(std::to_string(iSpec)).append(".");
443 auto names = m_control.getFunction(iSpec)->getAttributeNames();
444 for (auto &name : names) {
445 name.insert(name.begin(), prefix.begin(), prefix.end());
446 }
447 m_attributeNames.insert(m_attributeNames.end(), names.begin(), names.end());
448 }
449 // Attributes of physical properties
450 for (size_t iSpec = nSpectra(); iSpec < m_target->nFunctions(); ++iSpec) {
451 auto fun = m_target->getFunction(iSpec).get();
452 auto compositePhysProp = dynamic_cast<CompositeFunction *>(fun);
453 if (compositePhysProp) {
454 // Multi-site case
455 std::string physPropPrefix(compositePhysProp->getFunction(0)->name());
456 physPropPrefix.append(".");
457 for (size_t ion = 0; ion < compositePhysProp->nFunctions(); ++ion) {
458 std::string prefix(ION_PREFIX);
459 prefix.append(std::to_string(ion)).append(".").append(physPropPrefix);
460 auto names = compositePhysProp->getFunction(ion)->getAttributeNames();
461 prependPrefix(prefix, names);
462 }
463 } else {
464 // Single-site
465 std::string prefix(fun->name());
466 prefix.append(".");
467 auto names = fun->getAttributeNames();
468 prependPrefix(prefix, names);
469 }
470 }
471}
472
476 return m_attributeNames.size();
477}
478
480std::vector<std::string> CrystalFieldFunction::getAttributeNames() const {
482 return m_attributeNames;
483}
484
488 auto attRef = getAttributeReference(attName);
489 if (attRef.first == nullptr) {
490 // This will throw an exception because attribute doesn't exist
491 return IFunction::getAttribute(attName);
492 }
493 return attRef.first->getAttribute(attRef.second);
494}
495
497void CrystalFieldFunction::setAttribute(const std::string &attName, const Attribute &attr) {
498 auto attRef = getAttributeReference(attName);
499 if (attRef.first == nullptr) {
500 // This will throw an exception because attribute doesn't exist
501 IFunction::setAttribute(attName, attr);
502 } else if (attRef.first == &m_control) {
504 m_source.reset();
505 }
506 attRef.first->setAttribute(attRef.second, attr);
507 if (attName.find("FWHM") != std::string::npos || attName.find("Background") != std::string::npos) {
508 m_dirtyTarget = true;
509 }
510}
511
513bool CrystalFieldFunction::hasAttribute(const std::string &attName) const {
514 auto attRef = getAttributeReference(attName);
515 if (attRef.first == nullptr) {
516 return false;
517 }
518 return attRef.first->hasAttribute(attRef.second);
519}
520
527std::pair<API::IFunction *, std::string> CrystalFieldFunction::getAttributeReference(const std::string &attName) const {
528 boost::smatch match;
529 if (boost::regex_match(attName, match, SPECTRUM_ATTR_REGEX)) {
530 auto i = std::stoul(match[1]);
531 auto name = match[2].str();
532 if (m_control.nFunctions() == 0) {
534 }
535 if (name == "FWHMX" || name == "FWHMY") {
536 if (i < m_control.nFunctions()) {
537 return std::make_pair(m_control.getFunction(i).get(), name);
538 } else {
539 return std::make_pair(nullptr, "");
540 }
541 }
542 return std::make_pair(nullptr, "");
543 } else if (boost::regex_match(attName, match, PHYS_PROP_ATTR_REGEX)) {
544 auto prop = match[1].str();
545 auto name = match[4].str();
546 auto propIt = m_mapPrefixes2PhysProps.find(prop);
547 if (propIt != m_mapPrefixes2PhysProps.end()) {
548 return std::make_pair(propIt->second.get(), name);
549 }
550 return std::make_pair(nullptr, "");
551 }
552 return std::make_pair(&m_control, attName);
553}
554
557 auto nFuns = m_control.nFunctions();
558 return nFuns;
559}
560
565 auto tie = IFunction::getTie(i);
566 if (tie) {
567 return tie;
568 }
569 if (i < m_nControlParams) {
570 tie = m_control.getTie(i);
571 } else if (i < m_nControlSourceParams) {
572 tie = m_source->getTie(i - m_nControlParams);
573 } else {
574 tie = m_target->getTie(i - m_nControlSourceParams);
575 }
576 return tie;
577}
578
581 // Ignore height ties for Gaussian peaks as component of a CrystalFieldFunction to avoid problems during tie sorting
582 return tie.ownerFunction()->name() == "Gaussian" && tie.parameterName() == "Height" &&
583 tie.asString().find("/Sigma") != std::string::npos;
584}
585
589 auto constraint = IFunction::getConstraint(i);
590 if (constraint == nullptr) {
591 if (i < m_nControlParams) {
592 constraint = m_control.getConstraint(i);
593 } else if (i < m_nControlSourceParams) {
594 constraint = m_source->getConstraint(i - m_nControlParams);
595 } else {
597 constraint = m_target->getConstraint(i - m_nControlSourceParams);
598 }
599 }
600 return constraint;
601}
602
606
610
613 if (!hasAttribute("Background")) {
614 return false;
615 }
616 return !getAttribute("Background").isEmpty();
617}
618
621
624
627 auto composite = dynamic_cast<CompositeFunction *>(m_source.get());
628 if (composite == nullptr) {
629 throw std::logic_error("Source of CrystalFieldFunction is not composite.");
630 }
631 return *composite;
632}
633
636 if (!m_source) {
638 }
639}
640
646 if (!m_parameterResetCache.empty() && m_parameterResetCache.size() == m_source->nParams()) {
647 for (size_t i = 0; i < m_parameterResetCache.size(); ++i) {
648 m_source->setParameter(i, m_parameterResetCache[i]);
649 if (m_fixResetCache[i])
650 m_source->fix(i);
651 }
652 }
653 m_parameterResetCache.clear();
654 m_fixResetCache.clear();
655}
656
659 if (m_dirtyTarget) {
661 }
662 if (!m_target) {
663 throw std::logic_error("CrystalFieldFunction failed to generate target function.");
664 }
665}
666
671 m_dirtyTarget = false;
672 if (isMultiSite()) {
674 } else {
676 }
677 m_attributeNames.clear();
678}
679
682 if (isMultiSpectrum()) {
684 } else {
686 }
687}
688
691 if (isMultiSpectrum()) {
693 } else {
695 }
696}
697
700 auto spectrum = new CompositeFunction;
701 m_target.reset(spectrum);
702 m_target->setAttributeValue("NumDeriv", true);
703 auto bkgdShape = getAttribute("Background").asUnquotedString();
704 bool fixAllPeaks = getAttribute("FixAllPeaks").asBool();
705
706 if (!bkgdShape.empty()) {
707 auto background = API::FunctionFactory::Instance().createInitialized(bkgdShape);
708 spectrum->addFunction(background);
709 }
710
712 FunctionValues values;
713 m_source->function(domain, values);
714
715 if (values.size() == 0) {
716 return;
717 }
718
719 if (values.size() % 2 != 0) {
720 throw std::runtime_error("CrystalFieldPeaks returned odd number of values.");
721 }
722
723 auto xVec = m_control.getAttribute("FWHMX").asVector();
724 auto yVec = m_control.getAttribute("FWHMY").asVector();
725 const auto &FWHMs = m_control.FWHMs();
726 auto defaultFWHM = FWHMs.empty() ? 0.0 : FWHMs[0];
727
728 auto fwhmVariation = getAttribute("FWHMVariation").asDouble();
729 auto peakShape = getAttribute("PeakShape").asString();
730 size_t nRequiredPeaks = getAttribute("NPeaks").asInt();
731 CrystalFieldUtils::buildSpectrumFunction(*spectrum, peakShape, values, xVec, yVec, fwhmVariation, defaultFWHM,
732 nRequiredPeaks, fixAllPeaks);
733}
734
737 auto fun = new MultiDomainFunction;
738 m_target.reset(fun);
739
740 DoubleFortranVector energies;
741 ComplexFortranMatrix waveFunctions;
742 ComplexFortranMatrix hamiltonian;
743 ComplexFortranMatrix hamiltonianZeeman;
744 int nre = 0;
745 auto &peakCalculator = dynamic_cast<CrystalFieldPeaksBase &>(*m_source);
746 peakCalculator.calculateEigenSystem(energies, waveFunctions, hamiltonian, hamiltonianZeeman, nre);
747 hamiltonian += hamiltonianZeeman;
748
749 const auto nSpec = nSpectra();
750 const auto &temperatures = m_control.temperatures();
751 const auto &FWHMs = m_control.FWHMs();
752 const bool addBackground = true;
753 for (size_t i = 0; i < nSpec; ++i) {
754 auto intensityScaling = m_control.getFunction(i)->getParameter("IntensityScaling");
755 fun->addFunction(buildSpectrum(nre, energies, waveFunctions, temperatures[i], FWHMs.size() > i ? FWHMs[i] : 0., i,
756 addBackground, intensityScaling));
757 fun->setDomainIndex(i, i);
758 }
759 const auto &physProps = m_control.physProps();
760 size_t i = nSpec;
761 for (auto &prop : physProps) {
762 auto physPropFun = buildPhysprop(nre, energies, waveFunctions, hamiltonian, prop);
763 fun->addFunction(physPropFun);
764 fun->setDomainIndex(i, i);
765 m_mapPrefixes2PhysProps[prop] = physPropFun;
766 ++i;
767 }
768}
769
772
773 auto spectrum = new CompositeFunction;
774 m_target.reset(spectrum);
775 m_target->setAttributeValue("NumDeriv", true);
776 auto bkgdShape = getAttribute("Background").asUnquotedString();
777 bool fixAllPeaks = getAttribute("FixAllPeaks").asBool();
778
779 if (!bkgdShape.empty()) {
780 auto background = API::FunctionFactory::Instance().createInitialized(bkgdShape);
781 spectrum->addFunction(background);
782 }
783
784 const auto &FWHMs = m_control.FWHMs();
785 auto defaultFWHM = FWHMs.empty() ? 0.0 : FWHMs[0];
786 auto fwhmVariation = getAttribute("FWHMVariation").asDouble();
787 auto peakShape = getAttribute("PeakShape").asString();
788 size_t nRequiredPeaks = getAttribute("NPeaks").asInt();
789 auto xVec = m_control.getAttribute("FWHMX").asVector();
790 auto yVec = m_control.getAttribute("FWHMY").asVector();
791
792 auto &compSource = compositeSource();
793 for (size_t ionIndex = 0; ionIndex < compSource.nFunctions(); ++ionIndex) {
795 FunctionValues values;
796 compSource.getFunction(ionIndex)->function(domain, values);
797
798 if (values.size() == 0) {
799 continue;
800 }
801
802 if (values.size() % 2 != 0) {
803 throw std::runtime_error("CrystalFieldPeaks returned odd number of values.");
804 }
805
806 auto ionSpectrum = std::make_shared<CompositeFunction>();
807 CrystalFieldUtils::buildSpectrumFunction(*ionSpectrum, peakShape, values, xVec, yVec, fwhmVariation, defaultFWHM,
808 nRequiredPeaks, fixAllPeaks);
809 spectrum->addFunction(ionSpectrum);
810 }
811}
812
815 auto multiDomain = new MultiDomainFunction;
816 m_target.reset(multiDomain);
817
818 const auto nSpec = nSpectra();
819 std::vector<CompositeFunction *> spectra(nSpec);
820 for (size_t i = 0; i < nSpec; ++i) {
821 auto spectrum = std::make_shared<CompositeFunction>();
822 spectra[i] = spectrum.get();
823 multiDomain->addFunction(spectrum);
824 multiDomain->setDomainIndex(i, i);
825 }
826 auto &physProps = m_control.physProps();
827 std::vector<CompositeFunction_sptr> compositePhysProps(physProps.size());
828 std::generate(compositePhysProps.begin(), compositePhysProps.end(),
829 []() { return std::make_shared<CompositeFunction>(); });
830
831 auto &compSource = compositeSource();
832 for (size_t ionIndex = 0; ionIndex < compSource.nFunctions(); ++ionIndex) {
833 DoubleFortranVector energies;
834 ComplexFortranMatrix waveFunctions;
835 ComplexFortranMatrix hamiltonian;
836 ComplexFortranMatrix hamiltonianZeeman;
837 int nre = 0;
838 auto &peakCalculator = dynamic_cast<CrystalFieldPeaksBase &>(*compSource.getFunction(ionIndex));
839 peakCalculator.calculateEigenSystem(energies, waveFunctions, hamiltonian, hamiltonianZeeman, nre);
840 hamiltonian += hamiltonianZeeman;
841
842 auto &temperatures = m_control.temperatures();
843 auto &FWHMs = m_control.FWHMs();
844 const bool addBackground = ionIndex == 0;
845 auto ionIntensityScaling = compSource.getFunction(ionIndex)->getParameter("IntensityScaling");
846 for (size_t i = 0; i < nSpec; ++i) {
847 auto spectrumIntensityScaling = m_control.getFunction(i)->getParameter("IntensityScaling");
848 spectra[i]->addFunction(buildSpectrum(nre, energies, waveFunctions, temperatures[i],
849 FWHMs.size() > i ? FWHMs[i] : 0., i, addBackground,
850 ionIntensityScaling * spectrumIntensityScaling));
851 }
852
853 size_t i = 0;
854 for (auto &prop : physProps) {
855 auto physPropFun = buildPhysprop(nre, energies, waveFunctions, hamiltonian, prop);
856 compositePhysProps[i]->addFunction(physPropFun);
857 std::string propName = "ion";
858 propName.append(std::to_string(ionIndex)).append(".").append(prop);
859 m_mapPrefixes2PhysProps[propName] = physPropFun;
860 ++i;
861 }
862 }
863 m_target->checkFunction();
864 size_t i = nSpec;
865 for (auto &propFun : compositePhysProps) {
866 multiDomain->addFunction(propFun);
867 multiDomain->setDomainIndex(i, i);
868 ++i;
869 }
870}
871
880 const ComplexFortranMatrix &waveFunctions, double temperature,
881 FunctionValues &values, double intensityScaling) const {
882 IntFortranVector degeneration;
883 DoubleFortranVector eEnergies;
884 DoubleFortranMatrix iEnergies;
885
886 const double toleranceEnergy = getAttribute("ToleranceEnergy").asDouble();
887 const double toleranceIntensity = getAttribute("ToleranceIntensity").asDouble();
888 DoubleFortranVector eExcitations;
889 DoubleFortranVector iExcitations;
890 calculateIntensities(nre, energies, waveFunctions, temperature, toleranceEnergy, degeneration, eEnergies, iEnergies);
891 calculateExcitations(eEnergies, iEnergies, toleranceEnergy, toleranceIntensity, eExcitations, iExcitations);
892 const auto nPeaks = eExcitations.size();
893 values.expand(2 * nPeaks);
894 for (size_t i = 0; i < nPeaks; ++i) {
895 values.setCalculated(i, eExcitations.get(i));
896 values.setCalculated(i + nPeaks, iExcitations.get(i) * intensityScaling);
897 }
898}
899
911 const ComplexFortranMatrix &waveFunctions, double temperature,
912 double fwhm, size_t iSpec, bool addBackground,
913 double intensityScaling) const {
914 FunctionValues values;
915 calcExcitations(nre, energies, waveFunctions, temperature, values, intensityScaling);
916 const auto fwhmVariation = getAttribute("FWHMVariation").asDouble();
917 const auto peakShape = getAttribute("PeakShape").asString();
918 auto bkgdShape = getAttribute("Background").asUnquotedString();
919 const size_t nRequiredPeaks = getAttribute("NPeaks").asInt();
920 const bool fixAllPeaks = getAttribute("FixAllPeaks").asBool();
921
922 auto spectrum = new CompositeFunction;
923
924 if (addBackground && !bkgdShape.empty()) {
925 if (bkgdShape.find("name=") != 0 && bkgdShape.front() != '(') {
926 bkgdShape = "name=" + bkgdShape;
927 }
928 auto background = API::FunctionFactory::Instance().createInitialized(bkgdShape);
929 spectrum->addFunction(background);
930 }
931
932 auto xVec = m_control.getFunction(iSpec)->getAttribute("FWHMX").asVector();
933 auto yVec = m_control.getFunction(iSpec)->getAttribute("FWHMY").asVector();
934 CrystalFieldUtils::buildSpectrumFunction(*spectrum, peakShape, values, xVec, yVec, fwhmVariation, fwhm,
935 nRequiredPeaks, fixAllPeaks);
936 return IFunction_sptr(spectrum);
937}
938
946 const ComplexFortranMatrix &waveFunctions,
947 const ComplexFortranMatrix &hamiltonian,
948 const std::string &propName) const {
949
950 if (propName == "cv") { // HeatCapacity
951 auto propFun = std::make_shared<CrystalFieldHeatCapacityCalculation>();
952 propFun->setEnergy(energies);
953 return propFun;
954 }
955 if (propName == "chi") { // Susceptibility
956 auto propFun = std::make_shared<CrystalFieldSusceptibilityCalculation>();
957 propFun->setEigensystem(energies, waveFunctions, nre);
958 return propFun;
959 }
960 if (propName == "mh") { // Magnetisation
961 auto propFun = std::make_shared<CrystalFieldMagnetisationCalculation>();
962 propFun->setHamiltonian(hamiltonian, nre);
963 return propFun;
964 }
965 if (propName == "mt") { // MagneticMoment
966 auto propFun = std::make_shared<CrystalFieldMomentCalculation>();
967 propFun->setHamiltonian(hamiltonian, nre);
968 return propFun;
969 }
970
971 throw std::runtime_error("Physical property type not understood: " + propName);
972}
973
981 const ComplexFortranMatrix &waveFunctions,
982 const ComplexFortranMatrix &hamiltonian, API::IFunction &function) const {
983
984 auto propName = function.name();
985
986 if (propName == "cv") { // HeatCapacity
987 auto &propFun = dynamic_cast<CrystalFieldHeatCapacityCalculation &>(function);
988 propFun.setEnergy(energies);
989 } else if (propName == "chi") { // Susceptibility
990 auto &propFun = dynamic_cast<CrystalFieldSusceptibilityCalculation &>(function);
991 propFun.setEigensystem(energies, waveFunctions, nre);
992 } else if (propName == "mh") { // Magnetisation
993 auto &propFun = dynamic_cast<CrystalFieldMagnetisationCalculation &>(function);
994 propFun.setHamiltonian(hamiltonian, nre);
995 } else if (propName == "mt") { // MagneticMoment
996 auto &propFun = dynamic_cast<CrystalFieldMomentCalculation &>(function);
997 propFun.setHamiltonian(hamiltonian, nre);
998 } else {
999 throw std::runtime_error("Physical property type not understood: " + propName);
1000 }
1001}
1002
1005 if (!m_target) {
1007 return;
1008 }
1009 m_dirtyTarget = false;
1010 if (isMultiSite()) {
1012 } else {
1014 }
1015 m_target->checkFunction();
1016}
1017
1020 if (isMultiSpectrum()) {
1022 } else {
1024 }
1025}
1026
1029 if (isMultiSpectrum()) {
1031 } else {
1033 }
1034}
1035
1038 auto fwhmVariation = m_control.getAttribute("FWHMVariation").asDouble();
1039 auto peakShape = m_control.getAttribute("PeakShape").asString();
1040 bool fixAllPeaks = m_control.getAttribute("FixAllPeaks").asBool();
1041 auto xVec = m_control.getAttribute("FWHMX").asVector();
1042 auto yVec = m_control.getAttribute("FWHMY").asVector();
1043 auto &FWHMs = m_control.FWHMs();
1044 auto defaultFWHM = FWHMs.empty() ? 0.0 : FWHMs[0];
1045 size_t indexShift = hasBackground() ? 1 : 0;
1046
1047 FunctionDomainGeneral domain;
1048 FunctionValues values;
1049 m_source->function(domain, values);
1050 m_target->setAttributeValue("NumDeriv", true);
1051 auto &spectrum = dynamic_cast<CompositeFunction &>(*m_target);
1052 CrystalFieldUtils::updateSpectrumFunction(spectrum, peakShape, values, indexShift, xVec, yVec, fwhmVariation,
1053 defaultFWHM, fixAllPeaks);
1054}
1055
1058 DoubleFortranVector energies;
1059 ComplexFortranMatrix waveFunctions;
1060 ComplexFortranMatrix hamiltonian;
1061 ComplexFortranMatrix hamiltonianZeeman;
1062 int nre = 0;
1063 auto &peakCalculator = dynamic_cast<CrystalFieldPeaksBase &>(*m_source);
1064 peakCalculator.calculateEigenSystem(energies, waveFunctions, hamiltonian, hamiltonianZeeman, nre);
1065 hamiltonian += hamiltonianZeeman;
1066 size_t iFirst = hasBackground() ? 1 : 0;
1067
1068 const auto &fun = dynamic_cast<MultiDomainFunction &>(*m_target);
1069 const auto &temperatures = m_control.temperatures();
1070 const auto &FWHMs = m_control.FWHMs();
1071 for (size_t iSpec = 0; iSpec < temperatures.size(); ++iSpec) {
1072 auto intensityScaling = m_control.getFunction(iSpec)->getParameter("IntensityScaling");
1073 updateSpectrum(*fun.getFunction(iSpec), nre, energies, waveFunctions, temperatures[iSpec],
1074 FWHMs.size() > iSpec ? FWHMs[iSpec] : 0., iSpec, iFirst, intensityScaling);
1075 }
1076
1077 for (auto &prop : m_mapPrefixes2PhysProps) {
1078 updatePhysprop(nre, energies, waveFunctions, hamiltonian, *prop.second);
1079 }
1080}
1081
1084 auto fwhmVariation = getAttribute("FWHMVariation").asDouble();
1085 auto peakShape = getAttribute("PeakShape").asString();
1086 bool fixAllPeaks = getAttribute("FixAllPeaks").asBool();
1087 auto xVec = m_control.getAttribute("FWHMX").asVector();
1088 auto yVec = m_control.getAttribute("FWHMY").asVector();
1089 auto &FWHMs = m_control.FWHMs();
1090 auto defaultFWHM = FWHMs.empty() ? 0.0 : FWHMs[0];
1091
1092 size_t spectrumIndexShift = hasBackground() ? 1 : 0;
1093 auto &compSource = compositeSource();
1094 for (size_t ionIndex = 0; ionIndex < compSource.nFunctions(); ++ionIndex) {
1095 FunctionDomainGeneral domain;
1096 FunctionValues values;
1097 compSource.getFunction(ionIndex)->function(domain, values);
1098
1099 auto &ionSpectrum = dynamic_cast<CompositeFunction &>(*m_target->getFunction(ionIndex + spectrumIndexShift));
1100 CrystalFieldUtils::updateSpectrumFunction(ionSpectrum, peakShape, values, 0, xVec, yVec, fwhmVariation, defaultFWHM,
1101 fixAllPeaks);
1102 }
1103}
1104
1107 auto &compSource = compositeSource();
1108 for (size_t ionIndex = 0; ionIndex < compSource.nFunctions(); ++ionIndex) {
1109 DoubleFortranVector energies;
1110 ComplexFortranMatrix waveFunctions;
1111 ComplexFortranMatrix hamiltonian;
1112 ComplexFortranMatrix hamiltonianZeeman;
1113 int nre = 0;
1114 auto &peakCalculator = dynamic_cast<CrystalFieldPeaksBase &>(*compSource.getFunction(ionIndex));
1115 peakCalculator.calculateEigenSystem(energies, waveFunctions, hamiltonian, hamiltonianZeeman, nre);
1116 hamiltonian += hamiltonianZeeman;
1117 size_t iFirst = ionIndex == 0 && hasBackground() ? 1 : 0;
1118
1119 auto &temperatures = m_control.temperatures();
1120 auto &FWHMs = m_control.FWHMs();
1121 auto ionIntensityScaling = compSource.getFunction(ionIndex)->getParameter("IntensityScaling");
1122 for (size_t iSpec = 0; iSpec < temperatures.size(); ++iSpec) {
1123 auto &spectrum = dynamic_cast<CompositeFunction &>(*m_target->getFunction(iSpec));
1124 auto &ionSpectrum = dynamic_cast<CompositeFunction &>(*spectrum.getFunction(ionIndex));
1125 auto spectrumIntensityScaling = m_control.getFunction(iSpec)->getParameter("IntensityScaling");
1126 updateSpectrum(ionSpectrum, nre, energies, waveFunctions, temperatures[iSpec],
1127 FWHMs.size() > iSpec ? FWHMs[iSpec] : 0., iSpec, iFirst,
1128 ionIntensityScaling * spectrumIntensityScaling);
1129 }
1130
1131 std::string prefix("ion");
1132 prefix.append(std::to_string(ionIndex)).append(".");
1133 auto prefixSize = prefix.size();
1134 for (auto prop : m_mapPrefixes2PhysProps) {
1135 if (prop.first.substr(0, prefixSize) == prefix) {
1136 updatePhysprop(nre, energies, waveFunctions, hamiltonian, *prop.second);
1137 }
1138 }
1139 }
1140}
1141
1154 const ComplexFortranMatrix &waveFunctions, double temperature, double fwhm,
1155 size_t iSpec, size_t iFirst, double intensityScaling) const {
1156 const auto fwhmVariation = getAttribute("FWHMVariation").asDouble();
1157 const auto peakShape = getAttribute("PeakShape").asString();
1158 const bool fixAllPeaks = getAttribute("FixAllPeaks").asBool();
1159 auto xVec = m_control.getFunction(iSpec)->getAttribute("FWHMX").asVector();
1160 auto yVec = m_control.getFunction(iSpec)->getAttribute("FWHMY").asVector();
1161
1162 FunctionValues values;
1163 calcExcitations(nre, energies, waveFunctions, temperature, values, intensityScaling);
1164 auto &composite = dynamic_cast<API::CompositeFunction &>(spectrum);
1165 CrystalFieldUtils::updateSpectrumFunction(composite, peakShape, values, iFirst, xVec, yVec, fwhmVariation, fwhm,
1166 fixAllPeaks);
1167}
1168
1171 m_mapNames2Indices.clear();
1172 m_mapIndices2Names.resize(nParams());
1173 if (isMultiSite()) {
1174 if (isMultiSpectrum()) {
1176 } else {
1178 }
1179 } else {
1180 if (isMultiSpectrum()) {
1182 } else {
1184 }
1185 }
1186}
1187
1192size_t CrystalFieldFunction::makeMapsForFunction(const IFunction &fun, size_t iFirst, const std::string &prefix) const {
1193 auto n = fun.nParams();
1194 for (size_t i = 0; i < n; ++i) {
1195 size_t j = i + iFirst;
1196 auto name(prefix);
1197 name.append(fun.parameterName(i));
1200 }
1201 return n;
1202}
1203
1206 size_t i = makeMapsForFunction(*m_source, 0, "");
1207
1208 size_t peakIndex = 0;
1209 // If there is a background it's the first function in m_target
1210 if (hasBackground()) {
1211 auto &background = *m_target->getFunction(0);
1212 i += makeMapsForFunction(background, i, BACKGROUND_PREFIX + ".");
1213 peakIndex = 1;
1214 }
1215 // All other functions are peaks.
1216 for (size_t ip = peakIndex; ip < m_target->nFunctions(); ++ip) {
1217 std::string prefix(PEAK_PREFIX);
1218 prefix.append(std::to_string(ip - peakIndex)).append(".");
1219 i += makeMapsForFunction(*m_target->getFunction(ip), i, prefix);
1220 }
1221}
1222
1225 size_t i = 0;
1226 // Intensity scalings for each spectrum
1227 for (size_t j = 0; j < m_control.nFunctions(); ++j) {
1228 std::string prefix(SPECTRUM_PREFIX);
1229 prefix.append(std::to_string(j)).append(".");
1230 i += makeMapsForFunction(*m_control.getFunction(j), i, prefix);
1231 }
1232 // Crystal field parameters
1233 i += makeMapsForFunction(*m_source, i, "");
1234
1235 size_t peakIndex = 0;
1236 for (size_t iSpec = 0; iSpec < m_target->nFunctions(); ++iSpec) {
1237 if (auto spectrum = dynamic_cast<const CompositeFunction *>(m_target->getFunction(iSpec).get())) {
1238 // This is a normal spectrum
1239 std::string spectrumPrefix(SPECTRUM_PREFIX);
1240 spectrumPrefix.append(std::to_string(iSpec)).append(".");
1241 // If there is a background it's the first function in spectrum
1242 if (hasBackground()) {
1243 auto &background = *spectrum->getFunction(0);
1244 i += makeMapsForFunction(background, i, spectrumPrefix + BACKGROUND_PREFIX + ".");
1245 peakIndex = 1;
1246 }
1247 // All other functions are peaks.
1248 for (size_t ip = peakIndex; ip < spectrum->nFunctions(); ++ip) {
1249 std::string prefix(spectrumPrefix);
1250 prefix.append(PEAK_PREFIX).append(std::to_string(ip - peakIndex)).append(".");
1251 i += makeMapsForFunction(*spectrum->getFunction(ip), i, prefix);
1252 }
1253 } else {
1254 // This is a physical property function
1255 std::string prefix(m_control.physProps()[iSpec - nSpectra()]);
1256 prefix.append(".");
1257 i += makeMapsForFunction(*m_target->getFunction(iSpec), i, prefix);
1258 }
1259 }
1260}
1261
1264 size_t i = 0;
1265 // Intensity scalings for each ion
1266 auto &crystalField = compositeSource();
1267 for (size_t ion = 0; ion < crystalField.nFunctions(); ++ion) {
1268 std::string prefix(ION_PREFIX);
1269 prefix.append(std::to_string(ion)).append(".");
1270 i += makeMapsForFunction(*crystalField.getFunction(ion), i, prefix);
1271 }
1272 // Spectrum split into an optional background and groups of peaks for
1273 // each ion
1274 size_t ionIndex = 0;
1275 // If there is a background it's the first function in spectrum
1276 if (hasBackground()) {
1277 auto &background = *m_target->getFunction(0);
1278 i += makeMapsForFunction(background, i, BACKGROUND_PREFIX + ".");
1279 ionIndex = 1;
1280 }
1281 // All other functions are ion spectra.
1282 for (size_t ion = ionIndex; ion < m_target->nFunctions(); ++ion) {
1283 std::string ionPrefix(ION_PREFIX);
1284 ionPrefix.append(std::to_string(ion - ionIndex)).append(".");
1285 // All other functions are peaks.
1286 auto &spectrum = dynamic_cast<const CompositeFunction &>(*m_target->getFunction(ion));
1287 for (size_t ip = 0; ip < spectrum.nFunctions(); ++ip) {
1288 std::string prefix(ionPrefix);
1289 prefix.append(PEAK_PREFIX).append(std::to_string(ip)).append(".");
1290 i += makeMapsForFunction(*spectrum.getFunction(ip), i, prefix);
1291 }
1292 }
1293}
1294
1297 size_t i = 0;
1298 // Intensity scalings for each spectrum
1299 for (size_t j = 0; j < m_control.nFunctions(); ++j) {
1300 std::string prefix(SPECTRUM_PREFIX);
1301 prefix.append(std::to_string(j)).append(".");
1302 i += makeMapsForFunction(*m_control.getFunction(j), i, prefix);
1303 }
1304 // Intensity scalings for each ion
1305 auto &crystalField = compositeSource();
1306 for (size_t ion = 0; ion < crystalField.nFunctions(); ++ion) {
1307 std::string prefix(ION_PREFIX);
1308 prefix.append(std::to_string(ion)).append(".");
1309 i += makeMapsForFunction(*crystalField.getFunction(ion), i, prefix);
1310 }
1311
1312 // The spectra (background and peak) parameters
1313 for (size_t iSpec = 0; iSpec < nSpectra(); ++iSpec) {
1314 auto &spectrum = dynamic_cast<const CompositeFunction &>(*m_target->getFunction(iSpec));
1315 std::string spectrumPrefix(SPECTRUM_PREFIX);
1316 spectrumPrefix.append(std::to_string(iSpec)).append(".");
1317
1318 // All other functions are ion spectra.
1319 for (size_t ion = 0; ion < crystalField.nFunctions(); ++ion) {
1320 auto &ionSpectrum = dynamic_cast<const CompositeFunction &>(*spectrum.getFunction(ion));
1321 size_t peakIndex = 0;
1322 if (ion == 0 && hasBackground()) {
1323 peakIndex = 1;
1324 std::string prefix(spectrumPrefix);
1325 prefix.append(BACKGROUND_PREFIX).append(".");
1326 i += makeMapsForFunction(*ionSpectrum.getFunction(0), i, prefix);
1327 }
1328 std::string ionPrefix(ION_PREFIX);
1329 ionPrefix.append(std::to_string(ion)).append(".").append(spectrumPrefix);
1330 // All other functions are peaks.
1331 for (size_t ip = peakIndex; ip < ionSpectrum.nFunctions(); ++ip) {
1332 std::string prefix(ionPrefix);
1333 prefix.append(PEAK_PREFIX).append(std::to_string(ip - peakIndex)).append(".");
1334 i += makeMapsForFunction(*ionSpectrum.getFunction(ip), i, prefix);
1335 }
1336 }
1337 }
1338 // The phys prop parameters
1339 for (size_t iSpec = nSpectra(); iSpec < m_target->nFunctions(); ++iSpec) {
1340 auto &spectrum = dynamic_cast<const CompositeFunction &>(*m_target->getFunction(iSpec));
1341 std::string physPropPrefix(spectrum.getFunction(0)->name());
1342 physPropPrefix.append(".");
1343 for (size_t ion = 0; ion < crystalField.nFunctions(); ++ion) {
1344 std::string prefix(ION_PREFIX);
1345 prefix.append(std::to_string(ion)).append(".").append(physPropPrefix);
1346 i += makeMapsForFunction(*spectrum.getFunction(ion), i, prefix);
1347 }
1348 }
1349}
1350
1354 if (!m_source) {
1355 // No function - nothing to cache
1356 m_parameterResetCache.clear();
1357 return;
1358 }
1359 auto np = m_source->nParams();
1360 m_parameterResetCache.resize(np);
1361 m_fixResetCache.resize(np);
1362 for (size_t i = 0; i < np; ++i) {
1363 m_parameterResetCache[i] = m_source->getParameter(i);
1364 m_fixResetCache[i] = m_source->isFixed(i);
1365 }
1366}
1367
1368} // namespace Mantid::CurveFitting::Functions
std::vector< size_t > m_IntensityScalingIdx
std::vector< size_t > m_PPLambdaIdxChild
std::vector< size_t > m_PPLambdaIdxSelf
double value
The value of the point.
Definition: FitMW.cpp:51
#define DECLARE_FUNCTION(classname)
Macro for declaring a new type of function to be used with the FunctionFactory.
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
A composite function is a function containing other functions.
ParameterTie * getTie(size_t i) const override
Get the tie of i-th parameter.
void setParameter(size_t, const double &value, bool explicitlySet=true) override
Set i-th parameter.
size_t getParameterIndex(const ParameterReference &ref) const override
Return parameter index from a parameter reference.
void setParameterDescription(size_t, const std::string &description) override
Set i-th parameter description.
std::size_t nFunctions() const override
Number of functions.
bool isExplicitlySet(size_t i) const override
Checks if a parameter has been set explicitly.
size_t nParams() const override
Total number of parameters.
double getParameter(size_t i) const override
Get i-th parameter.
double getError(size_t i) const override
Get the fitting error for a parameter.
Attribute getAttribute(const std::string &name) const override
Return a value of attribute attName.
std::string parameterDescription(size_t i) const override
Returns the description of parameter i.
IFunction_sptr getFunction(std::size_t i) const override
Returns the pointer to i-th function.
void setError(size_t i, double err) override
Set the fitting error for a parameter.
IConstraint * getConstraint(size_t i) const override
Get constraint of i-th parameter.
ParameterStatus getParameterStatus(size_t i) const override
Get status of parameter.
void checkFunction()
Check the function.
void setParameterStatus(size_t i, ParameterStatus status) override
Change status of parameter.
Represent a domain of a very general type.
Base class that represents the domain of a function.
A class to store values calculated by a function.
size_t size() const
Return the number of values.
void expand(size_t n)
Expand values to a new size, preserve stored values.
void setCalculated(double value)
set all calculated values to same number
An interface to a constraint.
Definition: IConstraint.h:26
Attribute is a non-fitting parameter.
Definition: IFunction.h:282
std::string asUnquotedString() const
Returns a string value that is guarenteed to be unquoted.
Definition: IFunction.cpp:702
std::vector< double > asVector() const
Returns vector<double> if attribute is vector<double>, throws exception otherwise.
Definition: IFunction.cpp:765
int asInt() const
Returns int value if attribute is a int, throws exception otherwise.
Definition: IFunction.cpp:726
std::string asString() const
Returns string value if attribute is a string, throws exception otherwise.
Definition: IFunction.cpp:660
double asDouble() const
Returns double value if attribute is a double, throws exception otherwise.
Definition: IFunction.cpp:739
bool isEmpty() const
Check if a string attribute is empty.
Definition: IFunction.cpp:858
bool asBool() const
Returns bool value if attribute is a bool, throws exception otherwise.
Definition: IFunction.cpp:752
This is an interface to a fitting function - a semi-abstarct class.
Definition: IFunction.h:163
virtual size_t nParams() const =0
Total number of parameters.
virtual Attribute getAttribute(const std::string &name) const
Return a value of attribute attName.
Definition: IFunction.cpp:1394
friend class CompositeFunction
Definition: IFunction.h:699
ParameterStatus
Describe parameter status in relation to fitting: Active: Fit varies such parameter directly.
Definition: IFunction.h:649
virtual void tie(const std::string &parName, const std::string &expr, bool isDefault=false)
Tie a parameter to other parameters (or a constant)
Definition: IFunction.cpp:214
virtual ParameterTie * getTie(size_t i) const
Get the tie of i-th parameter.
Definition: IFunction.cpp:356
virtual void setAttribute(const std::string &name, const Attribute &)
Set a value to attribute attName.
Definition: IFunction.cpp:1409
virtual void setUpForFit()
Set up the function for a fit.
Definition: IFunction.cpp:433
virtual std::vector< std::string > getAttributeNames() const
Returns a list of attribute names.
Definition: IFunction.cpp:1368
virtual std::string attributeName(size_t index) const
Get name of ith attribute.
Definition: IFunction.cpp:1382
virtual std::string parameterName(size_t i) const =0
Returns the name of parameter i.
virtual size_t nAttributes() const
Returns the number of attributes associated with the function.
Definition: IFunction.cpp:1336
virtual IConstraint * getConstraint(size_t i) const
Get constraint of i-th parameter.
Definition: IFunction.cpp:392
A composite function defined on a CompositeDomain.
A reference to a parameter in a function.
std::size_t getLocalIndex() const
Return parameter index in the local function.
IFunction * getLocalFunction() const
Return pointer to the local function.
Ties fitting parameters.
Definition: ParameterTie.h:35
double get(const size_t i) const
Get an element.
size_t size() const
Size of the vector.
const std::vector< double > & temperatures() const
API::IFunction_sptr buildSource()
Build the source function.
void buildControls()
Build control functions for individual spectra.
const std::vector< std::string > & physProps() const
bool hasPhysProperties() const
Check if there are any phys. properties.
bool isMultiSpectrum() const
Is it a multi-spectrum case?
void updateMultiSite() const
Update the target function in a multi site case.
Attribute getAttribute(const std::string &name) const override
Return a value of attribute attName.
std::unordered_map< std::string, size_t > m_mapNames2Indices
Map parameter names to indices.
void updatePhysprop(int nre, const DoubleFortranVector &en, const ComplexFortranMatrix &wf, const ComplexFortranMatrix &ham, API::IFunction &fun) const
Update a physical property function.
API::IFunction_sptr buildPhysprop(int nre, const DoubleFortranVector &en, const ComplexFortranMatrix &wf, const ComplexFortranMatrix &ham, const std::string &propName) const
Build a physical property function.
void checkTargetFunction() const
Update target function if necessary.
API::IFunction_sptr m_source
Function that calculates parameters of the target function.
bool m_dirtyTarget
Flag indicating that updateTargetFunction() is required.
void calcExcitations(int nre, const DoubleFortranVector &en, const ComplexFortranMatrix &wf, double temperature, API::FunctionValues &values, double intensityScaling) const
Calculate excitations at given temperature.
void updateMultiSiteMultiSpectrum() const
Update the target function in a multi site - multi spectrum case.
void updateMultiSiteSingleSpectrum() const
Update the target function in a multi site - single spectrum case.
void makeMapsSingleSiteMultiSpectrum() const
Parameter-index map for single-site multi-spectrum.
std::pair< API::IFunction *, std::string > getAttributeReference(const std::string &attName) const
Get a reference to an attribute.
void updateSpectrum(API::IFunction &spectrum, int nre, const DoubleFortranVector &en, const ComplexFortranMatrix &wf, double temperature, double fwhm, size_t iSpec, size_t iFirst, double intensityScaling) const
Update a function for a single spectrum.
size_t makeMapsForFunction(const IFunction &fun, size_t iFirst, const std::string &prefix) const
Make parameter names from names of a function and map them to indices.
void buildMultiSiteSingleSpectrum() const
Build the target function in a multi site - single spectrum case.
double getParameter(size_t i) const override
Get i-th parameter.
size_t parameterIndex(const std::string &name) const override
Returns the index of parameter name.
std::vector< std::string > m_attributeNames
Attribute names.
void setSource(API::IFunction_sptr source) const
Set the source function.
void setAttribute(const std::string &name, const Attribute &) override
Set a value to attribute attName.
std::vector< std::string > m_mapIndices2Names
Map parameter indices to names.
void makeMapsMultiSiteMultiSpectrum() const
Parameter-index map for multi-site multi-spectrum.
void declareParameter(const std::string &name, double initValue=0, const std::string &description="") override
Declare a new parameter.
API::ParameterTie * getTie(size_t i) const override
Get the tie for i-th parameter.
API::CompositeFunction & compositeSource() const
Get a reference to the source function if it's composite.
std::vector< std::string > getAttributeNames() const override
Returns a list of attribute names.
std::vector< double > m_parameterResetCache
Temporary cache for parameter values during source function resetting.
bool hasParameter(const std::string &name) const override
Check if function has a parameter with this name.
void buildMultiSite() const
Build the target function in a multi site case.
bool hasBackground() const
Check if the spectra have a background.
API::IFunction_sptr buildSpectrum(int nre, const DoubleFortranVector &en, const ComplexFortranMatrix &wf, double temperature, double fwhm, size_t i, bool addBackground, double intensityScaling) const
Build a function for a single spectrum.
bool hasPhysProperties() const
Check if there are any phys. properties.
size_t nSpectra() const
Get number of the number of spectra (excluding phys prop data).
void makeMapsMultiSiteSingleSpectrum() const
Parameter-index map for multi-site single-spectrum.
double getError(size_t i) const override
Get the fitting error for a parameter.
void buildSingleSiteSingleSpectrum() const
Build the target function in a single site - single spectrum case.
void setParameter(size_t, const double &value, bool explicitlySet=true) override
Set i-th parameter.
bool ignoreTie(const API::ParameterTie &tie) const override
Checks if whether tie should be ignored.
bool hasAttribute(const std::string &name) const override
Check if attribute attName exists.
void setUpForFit() override
Set up the function for a fit.
void buildSingleSiteMultiSpectrum() const
Build the target function in a single site - multi spectrum case.
void setError(size_t i, double err) override
Set the fitting error for a parameter.
void checkSourceFunction() const
Build source function if necessary.
bool isMultiSpectrum() const
Check if the function is set up for a multi-spectrum calculations (Multiple temperatures defined)
void buildMultiSiteMultiSpectrum() const
Build the target function in a multi site - multi spectrum case.
size_t getNumberDomains() const override
Get number of domains required by this function.
std::unordered_map< std::string, API::IFunction_sptr > m_mapPrefixes2PhysProps
Map parameter/attribute prefixes to pointers to phys prop functions.
void buildSourceFunction() const
Build the source function.
void makeMaps() const
Make maps between parameter names and indices.
void buildSingleSite() const
Build the target function in a single site case.
void cacheSourceParameters() const
Temporary cache parameter values of the source function if it's initialised.
std::string parameterName(size_t i) const override
Returns the name of parameter i.
size_t m_nControlParams
Cached number of parameters in m_control.
void updateTargetFunction() const
Update the target function.
bool isExplicitlySet(size_t i) const override
Checks if a parameter has been set explicitly.
CrystalFieldControl m_control
Function that creates the source function.
void buildAttributeNames() const
Build and cache the attribute names.
void setParameterStatus(size_t i, ParameterStatus status) override
Change status of parameter.
void updateSingleSite() const
Update the target function in a single site case.
size_t m_nControlSourceParams
Cached number of parameters in m_control and m_source.
void updateSingleSiteMultiSpectrum() const
Update the target function in a single site - multi spectrum case.
void setParameterDescription(size_t, const std::string &description) override
Set i-th parameter description.
API::CompositeFunction_sptr m_target
Function that actually calculates the output.
API::IConstraint * getConstraint(size_t i) const override
Get the i-th constraint.
bool isMultiSite() const
Check if the function is set up for a multi-site calculations.
std::string name() const override
Returns the function's name.
void makeMapsSingleSiteSingleSpectrum() const
Parameter-index map for single-site single-spectrum.
size_t getParameterIndex(const API::ParameterReference &ref) const override
Return parameter index from a parameter reference.
ParameterStatus getParameterStatus(size_t i) const override
Get status of parameter.
std::string parameterDescription(size_t i) const override
Returns the description of parameter i.
void updateSingleSiteSingleSpectrum() const
Update the target function in a single site - single spectrum case.
bool hasPeaks() const
Check if there are peaks (there is at least one spectrum).
size_t nAttributes() const override
Returns the number of attributes associated with the function.
void function(const API::FunctionDomain &domain, API::FunctionValues &values) const override
Evaluate the function.
std::vector< API::IFunction_sptr > createEquivalentFunctions() const override
Split this function (if needed) into a list of independent functions.
size_t nParams() const override
Total number of parameters.
void setHamiltonian(const ComplexFortranMatrix &ham, const int nre)
void setHamiltonian(const ComplexFortranMatrix &ham, const int nre)
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 setEigensystem(const DoubleFortranVector &en, const ComplexFortranMatrix &wf, const int nre)
Marks code as not implemented yet.
Definition: Exception.h:138
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
Definition: IFunction.h:732
size_t updateSpectrumFunction(API::CompositeFunction &spectrum, const std::string &peakShape, const API::FunctionValues &centresAndIntensities, size_t iFirst, const std::vector< double > &xVec, const std::vector< double > &yVec, double fwhmVariation, double defaultFWHM, bool fixAllPeaks)
Update the peaks parameters after recalculationof the crystal field.
size_t buildSpectrumFunction(API::CompositeFunction &spectrum, const std::string &peakShape, const API::FunctionValues &centresAndIntensities, const std::vector< double > &xVec, const std::vector< double > &yVec, double fwhmVariation, double defaultFWHM, size_t nRequiredPeaks, bool fixAllPeaks)
Utility functions to help set up peak functions in a Crystal Field spectrum.
void MANTID_CURVEFITTING_DLL calculateExcitations(const DoubleFortranVector &e_energies, const DoubleFortranMatrix &i_energies, double de, double di, DoubleFortranVector &e_excitations, DoubleFortranVector &i_excitations)
Calculate the excitations (transition energies) and their intensities.
void MANTID_CURVEFITTING_DLL calculateIntensities(int nre, const DoubleFortranVector &energies, const ComplexFortranMatrix &wavefunctions, double temperature, double de, IntFortranVector &degeneration, DoubleFortranVector &e_energies, DoubleFortranMatrix &i_energies)
Calculate the intensities of transitions.
std::string to_string(const wide_integer< Bits, Signed > &n)