bool CMathObject::compileDependentMass(CMathContainer & container) { bool success = true; // The default value is NaN *mpValue = InvalidValue; // Reset the prerequisites mPrerequisites.clear(); const CMoiety * pMoiety = static_cast< const CMoiety *>(mpDataObject->getObjectParent()); std::ostringstream Infix; Infix.imbue(std::locale::classic()); Infix.precision(16); Infix << pointerToString(container.getMathObject(pMoiety->getTotalNumberReference())->getValuePointer()); std::vector< std::pair< C_FLOAT64, CMetab * > >::const_iterator it = pMoiety->getEquation().begin(); std::vector< std::pair< C_FLOAT64, CMetab * > >::const_iterator end = pMoiety->getEquation().end(); bool First = true; // The first element in the equation is always the dependent species. We can directly update // its value and therefore point mpValue to it. mpValue = (C_FLOAT64 *) container.getMathObject(it->second->getValueReference())->getValuePointer(); ++it; for (; it != end; ++it) { const C_FLOAT64 & Multiplicity = it->first; if (First || Multiplicity >= 0.0) { Infix << "-" << Multiplicity; } else { Infix << "+" << fabs(Multiplicity); } First = false; Infix << "*"; Infix << pointerToString(container.getMathObject(it->second->getValueReference())->getValuePointer()); } CExpression E("DependentMass", &container); success &= E.setInfix(Infix.str()); pdelete(mpExpression); mpExpression = new CMathExpression(E, container, !mIsInitialValue); compileExpression(); return success; }
bool CMathObject::compileParticleFlux(CMathContainer & container) { bool success = true; // The default value is NaN *mpValue = InvalidValue; // Reset the prerequisites mPrerequisites.clear(); const CReaction * pReaction = static_cast< const CReaction * >(mpDataObject->getObjectParent()); // We need to check whether this reaction is a single compartment reaction and scale // it if true. // mParticleFlux = *mUnitScalingFactor * mFlux; // mUnitScalingFactor = & pModel->getQuantity2NumberFactor(); std::ostringstream Infix; Infix.imbue(std::locale::classic()); Infix.precision(16); Infix << container.getModel().getQuantity2NumberFactor(); Infix << "*"; Infix << pointerToString(container.getMathObject(pReaction->getFluxReference())->getValuePointer()); CExpression E("ParticleFluxExpression", &container); success &= E.setInfix(Infix.str()); pdelete(mpExpression); mpExpression = new CMathExpression(E, container, !mIsInitialValue); compileExpression(); return success; }
bool CMathObject::createExtensiveODERateExpression(const CMetab * pSpecies, CMathContainer & container) { bool success = true; std::ostringstream Infix; Infix.imbue(std::locale::classic()); Infix.precision(16); /* mRate = mpModel->getQuantity2NumberFactor() * mpCompartment->getValue() * mpExpression->calcValue(); */ if (!pSpecies->getExpression().empty()) { Infix << container.getModel().getQuantity2NumberFactor(); Infix << "*"; Infix << pointerToString(container.getMathObject(pSpecies->getCompartment()->getValueReference())->getValuePointer()); Infix << "*("; Infix << pSpecies->getExpression(); Infix << ")"; } CExpression E("ExtensiveODERateExpression", &container); success &= E.setInfix(Infix.str()); pdelete(mpExpression); mpExpression = new CMathExpression(E, container, !mIsInitialValue); compileExpression(); return success; }
void CMathReaction::initialize(const CReaction * pReaction, CMathContainer & container) { mpReaction = pReaction; // Sanity Check if (mpReaction == NULL) return; mpParticleFlux = container.getMathObject(mpReaction->getParticleFluxReference()); mpFlux = container.getMathObject(mpReaction->getFluxReference()); mpPropensity = container.getMathObject(mpReaction->getPropensityReference()); mObjectBalance.clear(); mChangedSpecies.clear(); mNumberBalance.resize(mpReaction->getChemEq().getBalances().size()); SpeciesBalance * pStepUpdate = mNumberBalance.array(); CDataVector < CChemEqElement >::const_iterator it = mpReaction->getChemEq().getBalances().begin(); CDataVector < CChemEqElement >::const_iterator end = mpReaction->getChemEq().getBalances().end(); for (; it != end; ++it) { const CMetab * pMetab = it->getMetabolite(); if (pMetab != NULL) { CMathObject * pParticleNumber = container.getMathObject(pMetab->getValueReference()); if (pParticleNumber->getSimulationType() == CMath::SimulationType::Independent || pParticleNumber->getSimulationType() == CMath::SimulationType::Dependent) { mChangedSpecies.insert(pParticleNumber); mObjectBalance.insert(std::pair < const CMathObject *, C_FLOAT64 >(pParticleNumber, it->getMultiplicity())); pStepUpdate->first = (C_FLOAT64 *) pParticleNumber->getValuePointer(); pStepUpdate->second = it->getMultiplicity(); ++pStepUpdate; } } } mNumberBalance.resize(mChangedSpecies.size(), true); }
bool CMathObject::createExtensiveValueExpression(const CMetab * pSpecies, CMathContainer & container) { bool success = true; // mConc * mpCompartment->getValue() * mpModel->getQuantity2NumberFactor(); CObjectInterface * pDensity = NULL; CObjectInterface * pCompartment = NULL; if (mIsInitialValue) { pDensity = pSpecies->getInitialConcentrationReference(); pCompartment = pSpecies->getCompartment()->getInitialValueReference(); } else { pDensity = pSpecies->getConcentrationReference(); pCompartment = pSpecies->getCompartment()->getValueReference(); } std::ostringstream Infix; Infix.imbue(std::locale::classic()); Infix.precision(16); Infix << container.getModel().getQuantity2NumberFactor(); Infix << "*"; Infix << pointerToString(container.getMathObject(pDensity)->getValuePointer()); Infix << "*"; Infix << pointerToString(container.getMathObject(pCompartment)->getValuePointer()); CExpression E("ExtensiveValueExpression", &container); success &= E.setInfix(Infix.str()); pdelete(mpExpression); mpExpression = new CMathExpression(E, container, !mIsInitialValue); compileExpression(); return success; }
bool CMathObject::createIntensiveRateExpression(const CMetab * pSpecies, CMathContainer & container) { bool success = true; /* mConcRate = (mRate * mpModel->getNumber2QuantityFactor() - mConc * mpCompartment->getRate()) / mpCompartment->getValue(); */ std::ostringstream Infix; Infix.imbue(std::locale::classic()); Infix.precision(16); Infix << "("; Infix << pointerToString(container.getMathObject(pSpecies->getRateReference())->getValuePointer()); Infix << "*"; Infix << container.getModel().getNumber2QuantityFactor(); Infix << "-"; Infix << pointerToString(container.getMathObject(pSpecies->getCompartment()->getValueReference())->getValuePointer()); Infix << "*"; Infix << pointerToString(container.getMathObject(pSpecies->getCompartment()->getRateReference())->getValuePointer()); Infix << ")/"; Infix << pointerToString(container.getMathObject(pSpecies->getCompartment()->getValueReference())->getValuePointer()); CExpression E("IntensiveRateExpression", &container); success &= E.setInfix(Infix.str()); pdelete(mpExpression); mpExpression = new CMathExpression(E, container, !mIsInitialValue); compileExpression(); return success; }
bool CMathObject::compileFlux(CMathContainer & container) { bool success = true; // The default value is NaN *mpValue = InvalidValue; // Reset the prerequisites mPrerequisites.clear(); const CReaction * pReaction = static_cast< const CReaction * >(mpDataObject->getObjectParent()); // We need to check whether this reaction is a single compartment reaction and scale it if true. // mFlux = *mScalingFactor * mpFunction->calcValue(mMap.getPointers()); // mScalingFactor = compartment volume or 1 pdelete(mpExpression); mpExpression = new CMathExpression(*pReaction->getFunction(), pReaction->getCallParameters(), container, !mIsInitialValue); if (pReaction->getScalingCompartment() != NULL && pReaction->getEffectiveKineticLawUnitType() == CReaction::ConcentrationPerTime) { CExpression Tmp(mpExpression->getObjectName(), &container); std::string Infix = pointerToString(container.getMathObject(pReaction->getScalingCompartment()->getValueReference())->getValuePointer()) + "*(" + mpExpression->getInfix() + ")"; success &= Tmp.setInfix(Infix); success &= Tmp.compile(); pdelete(mpExpression); mpExpression = new CMathExpression(Tmp, container, false); } compileExpression(); return success; }
bool CMathObject::compilePropensity(CMathContainer & container) { bool success = true; // The default value is NaN *mpValue = InvalidValue; // Reset the prerequisites mPrerequisites.clear(); const CReaction * pReaction = static_cast< const CReaction * >(mpDataObject->getObjectParent()); std::ostringstream Infix; Infix.imbue(std::locale::classic()); Infix.precision(16); // Propensity for reversible reactions must be NaN if (pReaction->isReversible()) { Infix << "NAN"; } else { // Propensity is the same as the flux, but it must now be negative. Infix << "max(0," << pointerToString(container.getMathObject(pReaction->getParticleFluxReference())->getValuePointer()); // Apply correction for deterministic models if (container.getModel().getModelType() == CModel::deterministic) { std::ostringstream Divisor; Divisor.imbue(std::locale::classic()); Divisor.precision(16); const CCopasiVector<CChemEqElement> & Substrates = pReaction->getChemEq().getSubstrates(); CCopasiVector< CChemEqElement >::const_iterator itSubstrate = Substrates.begin(); CCopasiVector< CChemEqElement >::const_iterator endSubstrate = Substrates.end(); bool first = true; for (; itSubstrate != endSubstrate; ++itSubstrate) { const std::string NumberPointer = pointerToString(container.getMathObject(itSubstrate->getMetabolite()->getValueReference())->getValuePointer()); C_FLOAT64 Multiplicity = itSubstrate->getMultiplicity(); Multiplicity -= 1.0; // Nothing to correct if the multiplicity is 1. if (Multiplicity > 2.0 - 100.0 * std::numeric_limits< C_FLOAT64 >::epsilon()) { if (!first) { Divisor << "*"; } first = false; Divisor << NumberPointer << "^" << Multiplicity; } else if (Multiplicity > 1.0 - 100.0 * std::numeric_limits< C_FLOAT64 >::epsilon()) { if (!first) { Divisor << "*"; } first = false; Divisor << NumberPointer; } while (Multiplicity > 1.0 - 100.0 * std::numeric_limits< C_FLOAT64 >::epsilon()) { Infix << "*(" << NumberPointer << "-" << Multiplicity << ")"; Multiplicity -= 1.0; } } if (Divisor.str() != "") { Infix << "/(" << Divisor.str() << ")"; } } Infix << ")"; } CExpression E("PropensityExpression", &container); success &= E.setInfix(Infix.str()); pdelete(mpExpression); mpExpression = new CMathExpression(E, container, !mIsInitialValue); compileExpression(); return success; }
bool CMathObject::compileValue(CMathContainer & container) { bool success = true; // The default value is NaN *mpValue = InvalidValue; // Reset the prerequisites mPrerequisites.clear(); const CModelEntity * pEntity = NULL; const CMetab * pSpecies = NULL; if (mpDataObject != NULL) { pEntity = dynamic_cast< const CModelEntity * >(mpDataObject->getObjectParent()); } // Only species have corresponding properties (extensive vs intensive). if (mEntityType == CMath::Species) { pSpecies = static_cast< const CMetab * >(pEntity); if (mIsIntensiveProperty) { mpCorrespondingProperty = container.getMathObject(pSpecies->getValueReference()); } else { mpCorrespondingProperty = container.getMathObject(pSpecies->getConcentrationReference()); } } if (mIsIntensiveProperty) { switch (mSimulationType) { case CMath::Assignment: success &= createConvertedExpression(pSpecies->getExpressionPtr(), container); break; case CMath::EventTarget: case CMath::Conversion: success &= createIntensiveValueExpression(pSpecies, container); break; case CMath::SimulationTypeUndefined: case CMath::Fixed: case CMath::Time: case CMath::ODE: case CMath::Independent: case CMath::Dependent: success = false; break; } } else { // Species need an additional conversion since the event targets the // intensive property. if (mEntityType == CMath::Species) { success &= createExtensiveValueExpression(pSpecies, container); } switch (mSimulationType) { case CMath::Fixed: case CMath::EventTarget: case CMath::Time: case CMath::ODE: case CMath::Independent: case CMath::Conversion: break; case CMath::Dependent: { // We need to add the dependent number of the moiety as a possible // prerequisite. const CMoiety * pMoiety = pSpecies->getMoiety(); const CMathObject * pDependentNumber = container.getMathObject(pMoiety->getDependentNumberReference()); mPrerequisites.insert(pDependentNumber); } break; case CMath::Assignment: if (pEntity != NULL) { success &= createConvertedExpression(pEntity->getExpressionPtr(), container); } else { compileExpression(); } break; case CMath::SimulationTypeUndefined: success = false; break; } } return success; }
bool CMathObject::compileInitialValue(CMathContainer & container) { bool success = true; // The default value is NaN *mpValue = InvalidValue; // Initial values are taken from the data model if (mpDataObject != NULL) { *mpValue = * (C_FLOAT64 *) mpDataObject->getValuePointer(); } // Reset the prerequisites mPrerequisites.clear(); const CModelEntity * pEntity = dynamic_cast< const CModelEntity * >(mpDataObject->getObjectParent()); const CMetab * pSpecies = NULL; // Only species have corresponding properties (extensive vs intensive). if (mEntityType == CMath::Species) { pSpecies = static_cast< const CMetab * >(pEntity); if (mIsIntensiveProperty) { mpCorrespondingProperty = container.getMathObject(pSpecies->getInitialValueReference()); } else { mpCorrespondingProperty = container.getMathObject(pSpecies->getInitialConcentrationReference()); } } if (mIsIntensiveProperty) { switch (mSimulationType) { case CMath::EventTarget: case CMath::Fixed: case CMath::ODE: case CMath::Independent: case CMath::Dependent: case CMath::Conversion: success &= createIntensiveValueExpression(pSpecies, container); break; case CMath::Assignment: // Extensive Property * Conversion / Compartment Size success &= createConvertedExpression(pSpecies->getInitialExpressionPtr(), container); break; case CMath::Time: case CMath::SimulationTypeUndefined: success = false; break; } } else { switch (mSimulationType) { case CMath::Fixed: break; case CMath::Assignment: if (pEntity != NULL) { success &= createConvertedExpression(pEntity->getInitialExpressionPtr(), container); } else { compileExpression(); } break; case CMath::Conversion: { success &= createExtensiveValueExpression(pSpecies, container); } break; case CMath::SimulationTypeUndefined: case CMath::EventTarget: case CMath::Time: case CMath::ODE: case CMath::Independent: case CMath::Dependent: success = false; break; } } return success; }
bool CMathObject::createExtensiveReactionRateExpression(const CMetab * pSpecies, CMathContainer & container) { bool success = true; std::ostringstream Infix; Infix.imbue(std::locale::classic()); Infix.precision(16); std::string Key = pSpecies->getKey(); bool First = true; CCopasiVectorN< CReaction >::const_iterator it = container.getModel().getReactions().begin(); CCopasiVectorN< CReaction >::const_iterator end = container.getModel().getReactions().end(); for (; it != end; ++it) { const CCopasiVector< CChemEqElement > &Balances = it->getChemEq().getBalances(); CCopasiVector< CChemEqElement >::const_iterator itChem = Balances.begin(); CCopasiVector< CChemEqElement >::const_iterator endChem = Balances.end(); for (; itChem != endChem; ++itChem) if (itChem->getMetaboliteKey() == Key) break; if (itChem != endChem) { const C_FLOAT64 & Multiplicity = itChem->getMultiplicity(); if (First || Multiplicity < 0.0) { if (Multiplicity == std::numeric_limits< C_FLOAT64 >::infinity()) { Infix << "infinity"; } else if (Multiplicity == -std::numeric_limits< C_FLOAT64 >::infinity()) { Infix << "-infinity"; } else { Infix << Multiplicity; } } else { if (Multiplicity == std::numeric_limits< C_FLOAT64 >::infinity()) { Infix << "+infinity"; } else { Infix << "+" << Multiplicity; } } First = false; Infix << "*"; Infix << pointerToString(container.getMathObject(it->getParticleFluxReference())->getValuePointer()); } } CExpression E("ExtensiveReactionExpression", &container); success &= E.setInfix(Infix.str()); pdelete(mpExpression); mpExpression = new CMathExpression(E, container, !mIsInitialValue); compileExpression(); return success; }
bool CMathObject::compileTransitionTime(CMathContainer & container) { bool success = true; // The default value is NaN *mpValue = InvalidValue; // Reset the prerequisites mPrerequisites.clear(); const CMetab * pSpecies = static_cast< const CMetab *>(mpDataObject->getObjectParent()); std::ostringstream Infix; Infix.imbue(std::locale::classic()); Infix.precision(16); switch (pSpecies->getStatus()) { case CModelEntity::ODE: // mTT = *mpValue / fabs(mRate); Infix << "abs("; Infix << pointerToString(container.getMathObject(pSpecies->getValueReference())->getValuePointer()); Infix << "/"; Infix << pointerToString(container.getMathObject(pSpecies->getRateReference())->getValuePointer()); Infix << ")"; break; case CModelEntity::REACTIONS: { std::ostringstream PositiveFlux; PositiveFlux.imbue(std::locale::classic()); PositiveFlux.precision(16); std::ostringstream NegativeFlux; NegativeFlux.imbue(std::locale::classic()); NegativeFlux.precision(16); std::string Key = pSpecies->getKey(); bool First = true; CCopasiVectorN< CReaction >::const_iterator it = container.getModel().getReactions().begin(); CCopasiVectorN< CReaction >::const_iterator end = container.getModel().getReactions().end(); for (; it != end; ++it) { const CCopasiVector< CChemEqElement > &Balances = it->getChemEq().getBalances(); CCopasiVector< CChemEqElement >::const_iterator itChem = Balances.begin(); CCopasiVector< CChemEqElement >::const_iterator endChem = Balances.end(); for (; itChem != endChem; ++itChem) if (itChem->getMetaboliteKey() == Key) break; if (itChem != endChem) { const C_FLOAT64 & Multiplicity = itChem->getMultiplicity(); if (!First) { PositiveFlux << "+"; NegativeFlux << "+"; } PositiveFlux << "max("; NegativeFlux << "min("; if (Multiplicity == std::numeric_limits< C_FLOAT64 >::infinity()) { PositiveFlux << "infinity"; NegativeFlux << "infinity"; } else if (Multiplicity == -std::numeric_limits< C_FLOAT64 >::infinity()) { PositiveFlux << "-infinity"; NegativeFlux << "-infinity"; } else { PositiveFlux << Multiplicity; NegativeFlux << Multiplicity; } PositiveFlux << "*"; NegativeFlux << "*"; PositiveFlux << pointerToString(container.getMathObject(it->getParticleFluxReference())->getValuePointer()); NegativeFlux << pointerToString(container.getMathObject(it->getParticleFluxReference())->getValuePointer()); PositiveFlux << ",0)"; NegativeFlux << ",0)"; First = false; } } if (!First) { Infix << "abs("; Infix << pointerToString(container.getMathObject(pSpecies->getValueReference())->getValuePointer()); Infix << ")/if("; Infix << pointerToString(container.getMathObject(pSpecies->getRateReference())->getValuePointer()); Infix << "<0,-(" << NegativeFlux.str() << ")," << PositiveFlux.str() << ")"; } } break; default: break; } CExpression E("TransitionTimeExpression", &container); success &= E.setInfix(Infix.str()); pdelete(mpExpression); mpExpression = new CMathExpression(E, container, false); compileExpression(); return success; }