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;
}
Esempio n. 10
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;
        }
    }
}