static SBMLDocument *checkedReadSBMLFromString(const char* xml) { SBMLDocument *doc = readSBMLFromString(xml); if (doc) { if (doc->getModel() == 0) { // fatal error SBMLErrorLog *log = doc->getErrorLog(); string errors = log ? log->toString() : " NULL SBML Error Log"; delete doc; throw_llvm_exception("Fatal SBML error, no model, errors in sbml document: " + errors); } else if (doc->getNumErrors() > 0) { SBMLErrorLog *log = doc->getErrorLog(); string errors = log ? log->toString() : " NULL SBML Error Log"; Log(rr::Logger::LOG_WARNING) << "Warning, errors found in sbml document: " + errors; } } else { delete doc; throw_llvm_exception("readSBMLFromString returned NULL, no further information available"); } return doc; }
const LLVMModelDataSymbols::SpeciesReferenceInfo& LLVMModelDataSymbols::getNamedSpeciesReferenceInfo(const std::string& id) const { StringRefInfoMap::const_iterator i = namedSpeciesReferenceInfo.find(id); if (i != namedSpeciesReferenceInfo.end()) { return i->second; } else { throw_llvm_exception(id + " is not a named SpeciesReference"); return *(SpeciesReferenceInfo*)(0); // shutup eclipse warnings } }
llvm::Value* ModelInitialValueStoreSymbolResolver::storeSymbolValue( const std::string& symbol, llvm::Value *value) { assert(value); ModelDataIRBuilder mdbuilder(modelData, modelDataSymbols, builder); if (modelDataSymbols.isIndependentInitFloatingSpecies(symbol)) { const Species *species = model->getSpecies(symbol); assert(species); Value *amt = 0; // only amounts are stored, convert to conc if required if (species->getHasOnlySubstanceUnits()) { amt = value; } else { // have a conc, need to convert to amt Value *comp = resolver.loadSymbolValue(species->getCompartment()); amt = builder.CreateFMul(value, comp, symbol + "_amt"); } assert(amt); return mdbuilder.createInitFloatSpeciesAmtStore(symbol, amt); } else if (modelDataSymbols.isIndependentInitCompartment(symbol)) { return mdbuilder.createInitCompStore(symbol, value); } string msg = "The symbol \'"; msg += symbol; msg += "\' is not physically stored in the ModelData structure, " "it either does not exists or is defined by an assigment rule (hence it " "is not a terminal symbol)"; throw_llvm_exception(msg); return 0; }
static void createLibraryFunction(llvm::LibFunc::Func funcId, llvm::FunctionType *funcType, Module* module) { TargetLibraryInfo targetLib; if (targetLib.has(funcId)) { Function::Create(funcType, Function::ExternalLinkage, targetLib.getName(funcId), module); } else { string msg = "native target does not have library function for "; msg += targetLib.getName(funcId); throw_llvm_exception(msg); } }
llvm::Value* ModelDataLoadSymbolResolver::loadSymbolValue( const std::string& symbol, const llvm::ArrayRef<llvm::Value*>& args) { ModelDataIRBuilder mdbuilder(modelData, modelDataSymbols, builder); /*************************************************************************/ /* time */ /*************************************************************************/ if (symbol.compare(SBML_TIME_SYMBOL) == 0) { Value *timeEP = mdbuilder.createGEP(Time); Value *time = builder.CreateLoad(timeEP, SBML_TIME_SYMBOL); return time; } /*************************************************************************/ /* Function */ /*************************************************************************/ { Value *funcVal = FunctionResolver(*this, model, builder).loadSymbolValue(symbol, args); if (funcVal) { return funcVal; } } /*************************************************************************/ /* AssignmentRule */ /*************************************************************************/ { SymbolForest::ConstIterator i = modelSymbols.getAssigmentRules().find( symbol); if (i != modelSymbols.getAssigmentRules().end()) { recursiveSymbolPush(symbol); Value* result = ASTNodeCodeGen(builder, *this).codeGen(i->second); recursiveSymbolPop(); return result; } } /*************************************************************************/ /* Species */ /*************************************************************************/ const Species *species = model->getSpecies(symbol); if (species) { Value *amt = 0; if (modelDataSymbols.isIndependentFloatingSpecies(symbol)) { amt = mdbuilder.createFloatSpeciesAmtLoad(symbol, symbol + "_amt"); } else if (modelDataSymbols.isIndependentBoundarySpecies(symbol)) { amt = mdbuilder.createBoundSpeciesAmtLoad(symbol, symbol + "_amt"); } else if(modelDataSymbols.hasRateRule(symbol)) { amt = mdbuilder.createRateRuleValueLoad(symbol, symbol + "_amt"); } else { string msg = string("the symbol ") + symbol + string(" appeared to " "be a species, but it could not be found as an independent " "species or rate rule"); throw_llvm_exception(msg); } assert(amt); // now we have an amount, check to see if we need to convert to conc if (species->getHasOnlySubstanceUnits()) { return amt; } else { // expect a concentration, need to convert amt to conc, // so we need to get the compartment its in, but these // can vary also... Value *comp = loadSymbolValue(species->getCompartment()); return builder.CreateFDiv(amt, comp, symbol + "_conc"); } } if (modelDataSymbols.isIndependentCompartment(symbol)) { return mdbuilder.createCompLoad(symbol); } if (modelDataSymbols.isIndependentGlobalParameter(symbol)) { return mdbuilder.createGlobalParamLoad(symbol); } if (modelDataSymbols.hasRateRule(symbol)) { // species conc / amt has already been taken care of at this point return mdbuilder.createRateRuleValueLoad(symbol); } if (modelDataSymbols.isNamedSpeciesReference(symbol)) { const LLVMModelDataSymbols::SpeciesReferenceInfo &info = modelDataSymbols.getNamedSpeciesReferenceInfo(symbol); Value *value = mdbuilder.createStoichiometryLoad(info.row, info.column, symbol); if (info.type == LLVMModelDataSymbols::MultiReactantProduct) { string msg = "mutable stochiometry for species which appear " "multiple times in a single reaction is not currently " "supported, species reference id: "; msg += symbol; throw_llvm_exception(msg); } if (info.type == LLVMModelDataSymbols::Reactant) { // its consumed in the reaction, so has a negative in the stoich // matrix Value *negOne = ConstantFP::get(builder.getContext(), APFloat(-1.0)); negOne->setName("neg_one"); value = builder.CreateFMul(negOne, value, "neg_" + symbol); } return value; } /*************************************************************************/ /* Reaction Rate */ /*************************************************************************/ const Reaction* reaction = model->getReaction(symbol); if (reaction) { return loadReactionRate(reaction); } string msg = "the symbol \'"; msg += symbol; msg += "\' is not physically stored in the ModelData structure, " "it either does not exists or is defined by an assigment rule (hence it " "is not a terminal symbol)"; throw_llvm_exception(msg); return 0; }
llvm::Value* ModelDataStoreSymbolResolver::storeSymbolValue( const std::string& symbol, llvm::Value *value) { assert(value); ModelDataIRBuilder mdbuilder(modelData, modelDataSymbols, builder); /*************************************************************************/ /* AssignmentRule */ /*************************************************************************/ // can not store anything with an assigment rule, these are determined // by other independent elements. if (modelDataSymbols.hasAssignmentRule(symbol)) { throw_llvm_exception("Attempt to store a value in symbol \"" + symbol + "\" which is defined by an assignemnt rule"); } /*************************************************************************/ /* Species */ /*************************************************************************/ const Species *species = model->getSpecies(symbol); if (species) { Value *amt = 0; // only amounts are stored, convert to conc if required if (species->getHasOnlySubstanceUnits()) { amt = value; } else { // have a conc, need to convert to amt Value *comp = resolver.loadSymbolValue(species->getCompartment()); amt = builder.CreateFMul(value, comp, symbol + "_amt"); } assert(amt); // now look where we need to store it if (modelDataSymbols.isIndependentFloatingSpecies(symbol)) { return mdbuilder.createFloatSpeciesAmtStore(symbol, amt); } else if (modelDataSymbols.isIndependentBoundarySpecies(symbol)) { return mdbuilder.createBoundSpeciesAmtStore(symbol, amt); } else if(modelDataSymbols.hasRateRule(symbol)) { return mdbuilder.createRateRuleValueStore(symbol, amt); } else { string msg = string("the symbol ") + symbol + string(" appeared to " "be a species, but it could not be found as an independent " "species or rate rule"); throw_llvm_exception(msg); return 0; } } // at this point, we have already taken care of the species amount / // conc conversion, rest are just plain stores. if (modelDataSymbols.hasRateRule(symbol)) { return mdbuilder.createRateRuleValueStore(symbol, value); } else if (modelDataSymbols.isIndependentCompartment(symbol)) { return mdbuilder.createCompStore(symbol, value); } else if (modelDataSymbols.isIndependentGlobalParameter(symbol)) { return mdbuilder.createGlobalParamStore(symbol, value); } else if (modelDataSymbols.isNamedSpeciesReference(symbol)) { const LLVMModelDataSymbols::SpeciesReferenceInfo &info = modelDataSymbols.getNamedSpeciesReferenceInfo(symbol); if (info.type == LLVMModelDataSymbols::MultiReactantProduct) { string msg = "mutable stochiometry for species which appear " "multiple times in a single reaction is not currently " "supported, species reference id: "; msg += symbol; throw_llvm_exception(msg); } if (info.type == LLVMModelDataSymbols::Reactant) { // its consumed in the reaction, so has a negative in the stoich // matrix Value *negOne = ConstantFP::get(builder.getContext(), APFloat(-1.0)); negOne->setName("neg_one"); value = builder.CreateFMul(negOne, value, "neg_" + symbol); } return mdbuilder.createStoichiometryStore(info.row, info.column, value); } string msg = "The symbol \'"; msg += symbol; msg += "\' is not physically stored in the ModelData structure, " "it either does not exists or is defined by an assigment rule (hence it " "is not a terminal symbol)"; throw_llvm_exception(msg); return 0; }
ModelGeneratorContext::ModelGeneratorContext(std::string const &sbml, unsigned options) : ownedDoc(0), doc(0), symbols(0), modelSymbols(0), errString(new string()), context(0), executionEngine(0), module(0), builder(0), functionPassManager(0), options(options), moietyConverter(0) { try { ownedDoc = checkedReadSBMLFromString(sbml.c_str()); if (options & rr::ModelGenerator::CONSERVED_MOIETIES) { if ((rr::Config::getInt(rr::Config::ROADRUNNER_DISABLE_WARNINGS) & rr::Config::ROADRUNNER_DISABLE_WARNINGS_CONSERVED_MOIETY) == 0) { Log(Logger::LOG_NOTICE) << "performing conserved moiety conversion"; } // check if already conserved doc if (rr::conservation::ConservationExtension::isConservedMoietyDocument(ownedDoc)) { doc = ownedDoc; } else { moietyConverter = new rr::conservation::ConservedMoietyConverter(); if (moietyConverter->setDocument(ownedDoc) != LIBSBML_OPERATION_SUCCESS) { throw_llvm_exception("error setting conserved moiety converter document"); } if (moietyConverter->convert() != LIBSBML_OPERATION_SUCCESS) { throw_llvm_exception("error converting document to conserved moieties"); } doc = moietyConverter->getDocument(); SBMLWriter sw; char* convertedStr = sw.writeToString(doc); Log(Logger::LOG_INFORMATION) << "***************** Conserved Moiety Converted Document ***************"; Log(Logger::LOG_INFORMATION) << convertedStr; Log(Logger::LOG_INFORMATION) << "*********************************************************************"; free(convertedStr); } } else { doc = ownedDoc; } symbols = new LLVMModelDataSymbols(doc->getModel(), options); modelSymbols = new LLVMModelSymbols(getModel(), *symbols); // initialize LLVM // TODO check result InitializeNativeTarget(); context = new LLVMContext(); // Make the module, which holds all the code. module = new Module("LLVM Module", *context); builder = new IRBuilder<>(*context); // engine take ownership of module EngineBuilder engineBuilder(module); engineBuilder.setErrorStr(errString); executionEngine = engineBuilder.create(); addGlobalMappings(); createLibraryFunctions(module); ModelDataIRBuilder::createModelDataStructType(module, executionEngine, *symbols); initFunctionPassManager(); } catch(const std::exception&) { // we might have allocated memory in a failed ctor, // clean it up here. // destructors are not called on *this* class when exception is raised // in the ctor. cleanup(); throw; } }
ModelGeneratorContext::ModelGeneratorContext(libsbml::SBMLDocument const *doc, unsigned options) : ownedDoc(0), doc(0), symbols(new LLVMModelDataSymbols(doc->getModel(), options)), modelSymbols(new LLVMModelSymbols(getModel(), *symbols)), errString(new string()), context(0), executionEngine(0), module(0), builder(0), functionPassManager(0), options(options), moietyConverter(0) { try { if (options & rr::ModelGenerator::CONSERVED_MOIETIES) { Log(Logger::LOG_NOTICE) << "performing conserved moiety conversion"; moietyConverter = new rr::conservation::ConservedMoietyConverter(); if (moietyConverter->setDocument(doc) != LIBSBML_OPERATION_SUCCESS) { throw_llvm_exception("error setting conserved moiety converter document"); } if (moietyConverter->convert() != LIBSBML_OPERATION_SUCCESS) { throw_llvm_exception("error converting document to conserved moieties"); } this->doc = moietyConverter->getDocument(); SBMLWriter sw; char* convertedStr = sw.writeToString(doc); Log(Logger::LOG_INFORMATION) << "***************** Conserved Moiety Converted Document ***************"; Log(Logger::LOG_INFORMATION) << convertedStr; Log(Logger::LOG_INFORMATION) << "*********************************************************************"; delete convertedStr; } else { this->doc = doc; } symbols = new LLVMModelDataSymbols(doc->getModel(), options); modelSymbols = new LLVMModelSymbols(getModel(), *symbols); // initialize LLVM // TODO check result InitializeNativeTarget(); context = new LLVMContext(); // Make the module, which holds all the code. module = new Module("LLVM Module", *context); builder = new IRBuilder<>(*context); // engine take ownership of module EngineBuilder engineBuilder(module); //engineBuilder.setEngineKind(EngineKind::JIT); engineBuilder.setErrorStr(errString); executionEngine = engineBuilder.create(); addGlobalMappings(); createLibraryFunctions(module); ModelDataIRBuilder::createModelDataStructType(module, executionEngine, *symbols); initFunctionPassManager(); } catch(const std::exception&) { cleanup(); throw; } }
llvm::Value* ModelInitialValueSymbolResolver::loadSymbolValue( const std::string& symbol, const llvm::ArrayRef<llvm::Value*>& args) { ModelDataIRBuilder mdbuilder(modelData, modelDataSymbols, builder); /*************************************************************************/ /* time */ /*************************************************************************/ if (symbol.compare(SBML_TIME_SYMBOL) == 0) { return ConstantFP::get(builder.getContext(), APFloat(0.0)); } /*************************************************************************/ /* Function */ /*************************************************************************/ { Value *funcVal = FunctionResolver(*this, model, builder).loadSymbolValue(symbol, args); if (funcVal) { return funcVal; } } /*************************************************************************/ /* Initial AssignmentRule */ /*************************************************************************/ { SymbolForest::ConstIterator i = modelSymbols.getInitialAssignmentRules().find(symbol); if (i != modelSymbols.getInitialAssignmentRules().end()) { recursiveSymbolPush(symbol); Value* result = ASTNodeCodeGen(builder, *this).codeGen(i->second); recursiveSymbolPop(); return result; } } /*************************************************************************/ /* AssignmentRule */ /*************************************************************************/ if (!modelDataSymbols.isConservedMoietySpecies(symbol)) { SymbolForest::ConstIterator i = modelSymbols.getAssigmentRules().find(symbol); if (i != modelSymbols.getAssigmentRules().end()) { return ASTNodeCodeGen(builder, *this).codeGen(i->second); } } if (modelDataSymbols.isIndependentInitFloatingSpecies(symbol)) { const Species *species = model->getSpecies(symbol); assert(species); Value *amt = mdbuilder.createInitFloatSpeciesAmtLoad(symbol, symbol + "_amt"); // now we have an amount, check to see if we need to convert to conc if (species->getHasOnlySubstanceUnits()) { return amt; } else { // expect a concentration, need to convert amt to conc, // so we need to get the compartment its in, but these // can vary also... Value *comp = loadSymbolValue(species->getCompartment()); return builder.CreateFDiv(amt, comp, symbol + "_conc"); } } else if (modelDataSymbols.isIndependentCompartment(symbol)) { return mdbuilder.createInitCompLoad(symbol); } /*************************************************************************/ /* Initial Value */ /*************************************************************************/ { SymbolForest::ConstIterator i = modelSymbols.getInitialValues().find(symbol); if (i != modelSymbols.getInitialValues().end()) { return ASTNodeCodeGen(builder, *this).codeGen(i->second); } } /*************************************************************************/ /* Reaction Rate */ /*************************************************************************/ const Reaction* reaction = model->getReaction(symbol); if (reaction) { return loadReactionRate(reaction); } string msg = "Could not find requested symbol \'"; msg += symbol; msg += "\' in the model"; throw_llvm_exception(msg); return 0; }
ExecutableModel* LLVMModelGenerator::createModel(const std::string& sbml, uint options) { bool forceReCompile = options & LoadSBMLOptions::RECOMPILE; string md5; if (!forceReCompile) { // check for a chached copy md5 = rr::getMD5(sbml); if (options & LoadSBMLOptions::CONSERVED_MOIETIES) { md5 += "_conserved"; } ModelPtrMap::const_iterator i; SharedModelPtr sp; cachedModelsMutex.lock(); if ((i = cachedModels.find(md5)) != cachedModels.end()) { sp = i->second.lock(); } cachedModelsMutex.unlock(); // we could have recieved a bad ptr, a model could have been deleted, // in which case, we should have a bad ptr. if (sp) { Log(Logger::LOG_DEBUG) << "found a cached model for " << md5; return new LLVMExecutableModel(sp, createModelData(*sp->symbols, sp->random)); } else { Log(Logger::LOG_TRACE) << "no cached model found for " << md5 << ", creating new one"; } } SharedModelPtr rc(new ModelResources()); ModelGeneratorContext context(sbml, options); rc->evalInitialConditionsPtr = EvalInitialConditionsCodeGen(context).createFunction(); rc->evalReactionRatesPtr = EvalReactionRatesCodeGen(context).createFunction(); rc->getBoundarySpeciesAmountPtr = GetBoundarySpeciesAmountCodeGen(context).createFunction(); rc->getFloatingSpeciesAmountPtr = GetFloatingSpeciesAmountCodeGen(context).createFunction(); rc->getBoundarySpeciesConcentrationPtr = GetBoundarySpeciesConcentrationCodeGen(context).createFunction(); rc->getFloatingSpeciesConcentrationPtr = GetFloatingSpeciesConcentrationCodeGen(context).createFunction(); rc->getCompartmentVolumePtr = GetCompartmentVolumeCodeGen(context).createFunction(); rc->getGlobalParameterPtr = GetGlobalParameterCodeGen(context).createFunction(); rc->evalRateRuleRatesPtr = EvalRateRuleRatesCodeGen(context).createFunction(); rc->getEventTriggerPtr = GetEventTriggerCodeGen(context).createFunction(); rc->getEventPriorityPtr = GetEventPriorityCodeGen(context).createFunction(); rc->getEventDelayPtr = GetEventDelayCodeGen(context).createFunction(); rc->eventTriggerPtr = EventTriggerCodeGen(context).createFunction(); rc->eventAssignPtr = EventAssignCodeGen(context).createFunction(); rc->evalVolatileStoichPtr = EvalVolatileStoichCodeGen(context).createFunction(); rc->evalConversionFactorPtr = EvalConversionFactorCodeGen(context).createFunction(); if (options & LoadSBMLOptions::READ_ONLY) { rc->setBoundarySpeciesAmountPtr = 0; rc->setBoundarySpeciesConcentrationPtr = 0; rc->setFloatingSpeciesConcentrationPtr = 0; rc->setCompartmentVolumePtr = 0; rc->setFloatingSpeciesAmountPtr = 0; rc->setGlobalParameterPtr = 0; } else { rc->setBoundarySpeciesAmountPtr = SetBoundarySpeciesAmountCodeGen( context).createFunction(); rc->setBoundarySpeciesConcentrationPtr = SetBoundarySpeciesConcentrationCodeGen(context).createFunction(); rc->setFloatingSpeciesConcentrationPtr = SetFloatingSpeciesConcentrationCodeGen(context).createFunction(); rc->setCompartmentVolumePtr = SetCompartmentVolumeCodeGen(context).createFunction(); rc->setFloatingSpeciesAmountPtr = SetFloatingSpeciesAmountCodeGen( context).createFunction(); rc->setGlobalParameterPtr = SetGlobalParameterCodeGen(context).createFunction(); } if (options & LoadSBMLOptions::MUTABLE_INITIAL_CONDITIONS) { rc->getFloatingSpeciesInitConcentrationsPtr = GetFloatingSpeciesInitConcentrationCodeGen(context).createFunction(); rc->setFloatingSpeciesInitConcentrationsPtr = SetFloatingSpeciesInitConcentrationCodeGen(context).createFunction(); rc->getFloatingSpeciesInitAmountsPtr = GetFloatingSpeciesInitAmountCodeGen(context).createFunction(); rc->setFloatingSpeciesInitAmountsPtr = SetFloatingSpeciesInitAmountCodeGen(context).createFunction(); rc->getCompartmentInitVolumesPtr = GetCompartmentInitVolumeCodeGen(context).createFunction(); rc->setCompartmentInitVolumesPtr = SetCompartmentInitVolumeCodeGen(context).createFunction(); rc->getGlobalParameterInitValuePtr = GetGlobalParameterInitValueCodeGen(context).createFunction(); rc->setGlobalParameterInitValuePtr = SetGlobalParameterInitValueCodeGen(context).createFunction(); } else { rc->getFloatingSpeciesInitConcentrationsPtr = 0; rc->setFloatingSpeciesInitConcentrationsPtr = 0; rc->getFloatingSpeciesInitAmountsPtr = 0; rc->setFloatingSpeciesInitAmountsPtr = 0; rc->getCompartmentInitVolumesPtr = 0; rc->setCompartmentInitVolumesPtr = 0; rc->getGlobalParameterInitValuePtr = 0; rc->setGlobalParameterInitValuePtr = 0; } // if anything up to this point throws an exception, thats OK, because // we have not allocated any memory yet that is not taken care of by // something else. // Now that everything that could have thrown would have thrown, we // can now create the model and set its fields. LLVMModelData *modelData = createModelData(context.getModelDataSymbols(), context.getRandom()); uint llvmsize = ModelDataIRBuilder::getModelDataSize(context.getModule(), &context.getExecutionEngine()); if (llvmsize != modelData->size) { std::stringstream s; s << "LLVM Model Data size " << llvmsize << " is different from " << "C++ size of LLVM ModelData, " << modelData->size; LLVMModelData_free(modelData); Log(Logger::LOG_FATAL) << s.str(); throw_llvm_exception(s.str()); } // * MOVE * the bits over from the context to the exe model. context.stealThePeach(&rc->symbols, &rc->context, &rc->executionEngine, &rc->random, &rc->errStr); if (!forceReCompile) { // check for a chached copy, another thread could have // created one while we were making ours... ModelPtrMap::const_iterator i; SharedModelPtr sp; cachedModelsMutex.lock(); // whilst we have it locked, clear any expired ptrs for (ModelPtrMap::const_iterator j = cachedModels.begin(); j != cachedModels.end();) { if (j->second.expired()) { Log(Logger::LOG_DEBUG) << "removing expired model resource for hash " << md5; j = cachedModels.erase(j); } else { ++j; } } if ((i = cachedModels.find(md5)) == cachedModels.end()) { Log(Logger::LOG_DEBUG) << "could not find existing cached resource " "resources, for hash " << md5 << ", inserting new resources into cache"; cachedModels[md5] = rc; } cachedModelsMutex.unlock(); } return new LLVMExecutableModel(rc, modelData); }
void LLVMModelDataSymbols::initReactions(const libsbml::Model* model) { // get the reactions const ListOfReactions *reactions = model->getListOfReactions(); for (uint i = 0; i < reactions->size(); i++) { const Reaction *reaction = reactions->get(i); reactionsMap.insert(StringUIntPair(reaction->getId(), i)); // go through the reaction reactants and products to know how much to // allocate space for the stochiometry matrix. // all species that participate in reactions must be floating. const ListOfSpeciesReferences *reactants = reaction->getListOfReactants(); for (uint j = 0; j < reactants->size(); j++) { const SimpleSpeciesReference *r = reactants->get(j); if (isValidSpeciesReference(r, "reactant")) { // at this point, we'd better have a floating species uint speciesIdx = getFloatingSpeciesIndex(r->getSpecies()); stoichColIndx.push_back(i); stoichRowIndx.push_back(speciesIdx); stoichIds.push_back(r->isSetId() ? r->getId() : ""); stoichTypes.push_back(Reactant); if(r->isSetId() && r->getId().length() > 0) { if (namedSpeciesReferenceInfo.find(r->getId()) == namedSpeciesReferenceInfo.end()) { SpeciesReferenceInfo info = {speciesIdx, i, Reactant, r->getId()}; namedSpeciesReferenceInfo[r->getId()] = info; } else { string msg = "Species Reference with id "; msg += r->getId(); msg += " appears more than once in the model"; throw_llvm_exception(msg); } } } } const ListOfSpeciesReferences *products = reaction->getListOfProducts(); for (uint j = 0; j < products->size(); j++) { const SimpleSpeciesReference *p = products->get(j); // products had better be in the stoich matrix. if (isValidSpeciesReference(p, "product")) { uint speciesIdx = getFloatingSpeciesIndex(p->getSpecies()); stoichColIndx.push_back(i); stoichRowIndx.push_back(speciesIdx); stoichIds.push_back(p->isSetId() ? p->getId() : ""); stoichTypes.push_back(Product); if (p->isSetId() && p->getId().length() > 0) { if (namedSpeciesReferenceInfo.find(p->getId()) == namedSpeciesReferenceInfo.end()) { SpeciesReferenceInfo info = { speciesIdx, i, Product, p->getId()}; namedSpeciesReferenceInfo[p->getId()] = info; } else { string msg = "Species Reference with id "; msg += p->getId(); msg += " appears more than once in the model"; throw_llvm_exception(msg); } } } } } }
void LLVMModelDataSymbols::initFloatingSpecies(const libsbml::Model* model, bool computeAndAssignConsevationLaws) { const ListOfSpecies *species = model->getListOfSpecies(); list<string> indFltSpecies; list<string> depFltSpecies; // get the floating species and set thier compartments ls::LibStructural structural(model); poco_information(getLogger(), "performed structural analysis on model: " + structural.getAnalysisMsg()); // reorder by linearly independent first, then linearly dependent vector<string> reorderedList = computeAndAssignConsevationLaws ? structural.getReorderedSpecies() : structural.getSpecies(); linearlyIndependentFloatingSpeciesSize = structural.getNumIndSpecies(); // figure out 'fully' indendent flt species -- those without rules. for (uint i = 0; i < reorderedList.size(); ++i) { // just make sure its a valid species const string& sid = reorderedList[i]; const Species *s = 0; assert((s = species->get(sid)) && !s->getBoundaryCondition()); if (computeAndAssignConsevationLaws && i <= linearlyIndependentFloatingSpeciesSize && !isIndependentElement(sid)) { string msg = "structural analysis determined that " + sid + " is linearly independent, but it has has rules " "(assignment or rate) determining its dynamics."; throw_llvm_exception(msg); } if (isIndependentElement(sid)) { indFltSpecies.push_back(sid); } else { depFltSpecies.push_back(sid); } } // stuff the species in the map for (list<string>::const_iterator i = indFltSpecies.begin(); i != indFltSpecies.end(); ++i) { uint si = floatingSpeciesMap.size(); floatingSpeciesMap[*i] = si; } for (list<string>::const_iterator i = depFltSpecies.begin(); i != depFltSpecies.end(); ++i) { uint si = floatingSpeciesMap.size(); floatingSpeciesMap[*i] = si; } // finally set how many ind species we've found independentFloatingSpeciesSize = indFltSpecies.size(); if (Logger::PRIO_INFORMATION <= getLogger().getLevel()) { LoggingBuffer log(Logger::PRIO_INFORMATION, __FILE__, __LINE__); log.stream() << "found " << indFltSpecies.size() << " independent and " << depFltSpecies.size() << " dependent floating species." << endl; log.stream() << "linearly independent species: " << linearlyIndependentFloatingSpeciesSize << endl; vector<string> ids = getFloatingSpeciesIds(); for (uint i = 0; i < ids.size(); ++i) { log.stream() << "floating species [" << i << "] = \'" << ids[i] << "\'" << endl; } } }