// Read the documentation to learn more about C++ code generator // versioning. // %X% %Q% %Z% %W% // CGroupBase #include // AddComponent #include // SumComponent #include #include #include #include #include #include #include // Class SumComponent const string SumComponent::NORM = "norm"; SumComponent::SumComponent(const SumComponent &right) : Component(right), m_foldedPhotonFlux(right.m_foldedPhotonFlux), m_foldedPhotonFluxErr(right.m_foldedPhotonFluxErr) { Parameter* p (right.parameter(NORM)); if (p) parameterSet().push_back(p); } SumComponent::SumComponent (CGroupBase* p) : Component(p), m_foldedPhotonFlux(), m_foldedPhotonFluxErr() { index(0); } SumComponent::SumComponent (const AddComponent& right) : Component(right), m_foldedPhotonFlux(), m_foldedPhotonFluxErr() { // don't want the deep copy of the AddComponent's parameters - only want a // reference to the AddComponent's norm parameter. // Parameter* p (right.parameter("norm")); //p->setParent(componentBase()); parameterSet().push_back(right.parameter(NORM)); // DON'T assume the index number of the generating component. // (But, there should still be some relation between the SumComponent // and the AddComponent it's built on, to assist things that // want to use the SumComponents built by Model::makeSourceComponents // as opposed to the SumComponents generated during the fit // calculations. Therefore, lets just multiply by minus one. index(-right.index()); } SumComponent::~SumComponent() { } SumComponent* SumComponent::clone (CGroupBase* p) const { SumComponent* cloned = new SumComponent(*this); cloned->setParent(p); return cloned; } void SumComponent::calculate (bool saveComponentFlux, bool frozen) { const XSModExpTree& master = root()->compGroupTree(); XSModExpTree::const_iterator a(master.begin()); XSModExpTree::const_iterator b(master.end()); // find the ComponentGroup with the right name. while (a != b && (*a)->groupFlux()->name() != name()) ++a; (*a)->calculate(saveComponentFlux,frozen); debugPrint(tcout,"\nModel Output SumComponent::calculate() "); } SumComponent& SumComponent::operator += (const SumComponent& right) { UniquePhotonContainer::const_iterator rp = right.uniquePhotonArray().begin(); UniquePhotonContainer::const_iterator rpEnd = right.uniquePhotonArray().end(); while (rp != rpEnd) { const UniqueEnergy* uniqueEng = rp->first; const RealArray& rightHandFlux = right.uniquePhotonArray(uniqueEng); RealArray& leftHandFlux = uniquePhotonArray(uniqueEng); // rightHandFlux could be empty if for example it's coming from // a renorm calculation and it has a non-frozen norm param. if (rightHandFlux.size()) { if (leftHandFlux.size() != rightHandFlux.size()) { leftHandFlux.resize(rightHandFlux.size(),0.); } leftHandFlux += rightHandFlux; if (right.isError()) { RealArray& lErr = uniquePhotonErrArray(uniqueEng); if (!isError()) { lErr.resize(rightHandFlux.size(),0.); error(true); } if (lErr.size() != right.uniquePhotonErrArray(uniqueEng).size()) { throw RedAlert("SumComponent: Error array size mismatch"); } lErr += right.uniquePhotonErrArray(uniqueEng) ; } else { // make sure photonErrArray exists even if there is // no error vector, or just leave alone if there is // already one if (!isError()) uniquePhotonErrArray(uniqueEng).resize(0); } } ++rp; } return *this; } SumComponent SumComponent::operator + (const SumComponent& right) const { SumComponent __tmp(*this); return __tmp += right; } void SumComponent::copy (const Component& right) { if ( typeid(*this) != typeid(right) ) throw RedAlert("*** Programmer Error: copying to wrong type ***"); SumComponent __temp(static_cast(right)); swap(__temp); } SumComponent& SumComponent::operator *= (const MulComponent& right) { UniquePhotonContainer::const_iterator p = uniquePhotonArray().begin(); UniquePhotonContainer::const_iterator pEnd = uniquePhotonArray().end(); while (p != pEnd) { // mulFactor might have size zero in some instances, such as during // computation of the frozen norm elements of a model during renorm. const UniqueEnergy* uniqueEng = p->first; RealArray& flux = uniquePhotonArray(uniqueEng); const RealArray& mulFactor = right.uniquePhotonArray(uniqueEng); if (flux.size()) { flux *= mulFactor; if ( isError() ) { uniquePhotonErrArray(uniqueEng) *= (mulFactor * mulFactor); } if (right.isError()) { if ( !isError()) { uniquePhotonErrArray(uniqueEng) .resize(flux.size(),0.); isError(true); } uniquePhotonErrArray(uniqueEng) += flux*flux*right.uniquePhotonErrArray(uniqueEng); } } ++p; } return *this; } SumComponent SumComponent::operator * (const MulComponent& right) const { SumComponent __tmp(*this); __tmp *= right; return __tmp; } bool SumComponent::isNested () const { return parent()->nested(); } void SumComponent::normalize () { // SumComponents with the name "SUM" are temporaries. static const string SUM("SUM"); if ( name() != SUM ) { UniquePhotonContainer normFlux(uniquePhotonArray()); Real x (norm()); UniquePhotonContainer::iterator i (normFlux.begin()); UniquePhotonContainer::iterator iEnd (normFlux.end()); while ( i != iEnd) { (i->second) *= x; ++i; } setUniquePhotonArray(normFlux); if ( isError()) { UniquePhotonContainer normFluxError (uniquePhotonErrArray()); UniquePhotonContainer::iterator i (normFluxError.begin()); UniquePhotonContainer::iterator iEnd (normFluxError.end()); Real x2 (x*x); while ( i != iEnd) { (i->second) *= x2; ++i; } setUniquePhotonErrArray( normFluxError ); } } } Real SumComponent::norm () const { return parameter(NORM)->value(); } void SumComponent::savePhotonArray (bool setSaveFlag) { // switch this operation off for nested subgroups. Will be done in the 'children'. } void SumComponent::restorePhotonArray () { // switch this operation off for nested subgroups. Will be done in the 'children'. } void SumComponent::swap (Component& right) { Component::swap(right); SumComponent& that = static_cast(right); std::swap(m_foldedPhotonFlux,that.m_foldedPhotonFlux); std::swap(m_foldedPhotonFluxErr,that.m_foldedPhotonFluxErr); } void SumComponent::registerSelf () const { // do nothing in this version -- base class version registers parameters // in the Global ModelContainer list. } void SumComponent::saveUniquePhotonArray (bool setSaveFlag) { // switch this operation off for nested subgroups. Will be done in the 'children'. } void SumComponent::restoreUniquePhotonArray () { // switch this operation off for nested subgroups. Will be done in the 'children'. } void SumComponent::fillPhotonArrays () { // The purpose of this function is to copy the unique photon arrays // into a container where they are now 1-to-1 with spectra. This // means creating duplicate arrays when more than 1 spectra make use // of a UniqueEnergy. clearPhotonArrays(); const std::set& energies = getUniqueEnergies(); std::set::const_iterator itEngs = energies.begin(); std::set::const_iterator itEngsEnd = energies.end(); while (itEngs != itEngsEnd) { const UniqueEnergy* uniqueEng = *itEngs; const RealArray& uniqueFlux = uniquePhotonArray(uniqueEng); const RealArray& uniqueFluxErr = uniquePhotonErrArray(uniqueEng); std::set::const_iterator itSpec = uniqueEng->clientSpectra().begin(); std::set::const_iterator itSpecEnd = uniqueEng->clientSpectra().end(); while (itSpec != itSpecEnd) { size_t specNum = *itSpec; // Remember, this does an insert into m_photonArray. RealArray& insertedArray = m_photonArray[specNum]; RealArray& insertedErrArray = m_photonErrArray[specNum]; insertedArray.resize(uniqueFlux.size()); insertedErrArray.resize(uniqueFluxErr.size()); insertedArray = uniqueFlux; insertedErrArray = uniqueFluxErr; ++itSpec; } ++itEngs; } } void SumComponent::clearPhotonArrays () { m_photonArray.clear(); m_photonErrArray.clear(); } const RealArray& SumComponent::photonArray (size_t spectrumNumber) const { ArrayContainer::const_iterator it = m_photonArray.find(spectrumNumber); if (it != m_photonArray.end()) { return it->second; } else { std::ostringstream oss; oss << "SumComponent: Attempting to access non-existing spectrum " << spectrumNumber << " in photon array" ; throw RedAlert(oss.str()); } } const RealArray& SumComponent::photonErrArray (size_t spectrumNumber) const { ArrayContainer::const_iterator it = m_photonErrArray.find(spectrumNumber); if (it != m_photonErrArray.end()) { return it->second; } else { std::ostringstream oss; oss << "SumComponent: Attempting to access non-existing spectrum " << spectrumNumber << " in photon error array" ; throw RedAlert(oss.str()); } } // Additional Declarations