bool CMathObject::createIntensiveValueExpression(const CMetab * pSpecies, CMathContainer & container) { bool success = true; // mConc = *mpValue / mpCompartment->getValue() * mpModel->getNumber2QuantityFactor(); CObjectInterface * pNumber = NULL; CObjectInterface * pCompartment = NULL; if (mIsInitialValue) { pNumber = pSpecies->getInitialValueReference(); pCompartment = pSpecies->getCompartment()->getInitialValueReference(); } else { pNumber = pSpecies->getValueReference(); pCompartment = pSpecies->getCompartment()->getValueReference(); } std::ostringstream Infix; Infix.imbue(std::locale::classic()); Infix.precision(16); Infix << container.getModel().getNumber2QuantityFactor(); Infix << "*"; Infix << pointerToString(container.getMathObject(pNumber)->getValuePointer()); Infix << "/"; Infix << pointerToString(container.getMathObject(pCompartment)->getValuePointer());; CExpression E("IntensiveValueExpression", &container); success &= E.setInfix(Infix.str()); pdelete(mpExpression); mpExpression = new CMathExpression(E, container, !mIsInitialValue); compileExpression(); return success; }
CMathExpression::CMathExpression(const CExpression & src, CMathContainer & container, const bool & replaceDiscontinuousNodes): CEvaluationTree(src.getObjectName(), &container, CEvaluationTree::MathExpression), mPrerequisites() { clearNodes(); // Create a converted copy of the existing expression tree. mpRootNode = container.copyBranch(src.getRoot(), replaceDiscontinuousNodes); compile(); }
bool CMathObject::compileTotalMass(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); 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; for (; it != end; ++it) { const C_FLOAT64 & Multiplicity = it->first; if (First || Multiplicity < 0.0) { Infix << Multiplicity; } else { Infix << "+" << Multiplicity; } First = false; Infix << "*"; Infix << pointerToString(container.getMathObject(it->second->getValueReference())->getValuePointer()); } CExpression E("TotalMass", &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::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 << pDensity->getCN(); Infix << ">*<"; Infix << pCompartment->getCN(); Infix << ">"; CExpression E("ExtensiveValueExpression", &container); success &= E.setInfix(Infix.str()); 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; }
CMathExpression::CMathExpression(const CFunction & src, const CCallParameters< C_FLOAT64 > & callParameters, CMathContainer & container, const bool & replaceDiscontinuousNodes): CEvaluationTree(src.getObjectName(), &container, CEvaluationTree::MathExpression), mPrerequisites() { clearNodes(); // Deal with the different function types switch (src.getType()) { case CEvaluationTree::Function: case CEvaluationTree::PreDefined: case CEvaluationTree::UserDefined: { // Create a vector of CEvaluationNodeObject for each variable CMath::Variables< CEvaluationNode * > Variables; CCallParameters< C_FLOAT64 >::const_iterator it = callParameters.begin(); CCallParameters< C_FLOAT64 >::const_iterator end = callParameters.end(); for (; it != end; ++it) { Variables.push_back(createNodeFromValue(it->value)); } // Create a converted copy of the existing expression tree. mpRootNode = container.copyBranch(src.getRoot(), Variables, replaceDiscontinuousNodes); // Deleted the created variables CMath::Variables< CEvaluationNode * >::iterator itVar = Variables.begin(); CMath::Variables< CEvaluationNode * >::iterator endVar = Variables.end(); for (; itVar != endVar; ++itVar) { pdelete(*itVar); } } break; case CEvaluationTree::MassAction: { // We build a mass action expression based on the call parameters. CCallParameters< C_FLOAT64 >::const_iterator it = callParameters.begin(); // Handle the case we were have an invalid number of call parameters. if (callParameters.size() < 2) { mpRootNode = NULL; } else { // We always have reactants const C_FLOAT64 * pK = it->value; ++it; const CCallParameters< C_FLOAT64 > * pSpecies = it->vector; ++it; CEvaluationNode * pPart = createMassActionPart(pK, pSpecies); if (callParameters.size() < 4) { mpRootNode = pPart; } else { mpRootNode = new CEvaluationNodeOperator(CEvaluationNode::S_MINUS, "-"); mpRootNode->addChild(pPart); pK = it->value; ++it; pSpecies = it->vector; ++it; pPart = createMassActionPart(pK, pSpecies); mpRootNode->addChild(pPart); } } } break; case CEvaluationTree::MathExpression: case CEvaluationTree::Expression: // This cannot happen and is only here to satisfy the compiler. break; } compile(); }