Exemple #1
0
void CellmlFile::retrieveCmetaIdsFromCellmlElement(iface::cellml_api::CellMLElement *pElement)
{
    // Keep track of the given CellML element's cmeta:id

    QString cmetaId = QString::fromStdWString(pElement->cmetaId());

    if (!cmetaId.isEmpty())
        mUsedCmetaIds << cmetaId;

    // Do the same for all the child elements of the given CellML element

    ObjRef<iface::cellml_api::CellMLElementSet> childElements = pElement->childElements();
    ObjRef<iface::cellml_api::CellMLElementIterator> childElementsIter = childElements->iterate();

    try {
        for (ObjRef<iface::cellml_api::CellMLElement> childElement = childElementsIter->next();
             childElement; childElement = childElementsIter->next()) {
            retrieveCmetaIdsFromCellmlElement(childElement);
        }
    } catch (...) {
        // Note: we should never reach this point, but it may still happen if a
        //       CellML file contains a child element that is not known to the
        //       CellML API. We are taking the view that this is a limitation of
        //       the CellML API and shouldn't therefore generate an error for
        //       something that should have been working fine in the first
        //       place...
    }
}
Exemple #2
0
void CellmlFileRuntime::retrieveDaeCodeInformation(iface::cellml_api::Model *pModel)
{
    // Get a code generator bootstrap and create a DAE code generator

    ObjRef<iface::cellml_services::CodeGeneratorBootstrap> codeGeneratorBootstrap = CreateCodeGeneratorBootstrap();
    ObjRef<iface::cellml_services::IDACodeGenerator> codeGenerator = codeGeneratorBootstrap->createIDACodeGenerator();

    // Generate some code for the model

    try {
        mDaeCodeInformation = codeGenerator->generateIDACode(pModel);

        // Check that the code generation went fine

        checkCodeInformation(mDaeCodeInformation);
    } catch (iface::cellml_api::CellMLException &exception) {
        couldNotGenerateModelCodeIssue(Core::formatMessage(QString::fromStdWString(exception.explanation)));
    } catch (...) {
        unknownProblemDuringModelCodeGenerationIssue();
    }

    // Check the outcome of the DAE code generation

    if (mIssues.count())
        resetDaeCodeInformation();
}
double SingleCellViewSimulation::requiredMemory()
{
    // Determine and return the amount of required memory to run our simulation
    // Note #1: we return the amount as a double rather than a qulonglong (as we
    //          do when retrieving the total/free amount of memory available;
    //          see [OpenCOR]/src/plugins/misc/Core/src/coreutils.cpp) in case a
    //          simulation requires an insane amount of memory...
    // Note #2: the 1 is for mPoints in SingleCellViewSimulationResults...

    iface::cellml_services::CellMLCompiledModel*
        compModel(mData->isDAETypeSolver() ?
                  static_cast<iface::cellml_services::CellMLCompiledModel*>
                  (mRuntime->daeCompiledModel()) :
                  static_cast<iface::cellml_services::CellMLCompiledModel*>
                  (mRuntime->odeCompiledModel()));
    ObjRef<iface::cellml_services::CodeInformation> codeInfo
        (compModel->codeInformation());

    // This is not very accurate at all, because the solver caches a lot more
    // information about the problem being solved, some of it bigger than any
    // of the below (e.g. Jacobian matricies. Given the solver dependence of
    // this size, I'm not sure this function is that useful.
    return 
        size() *
        (1 + codeInfo->constantIndexCount() + codeInfo->rateIndexCount() * 3 +
         codeInfo->algebraicIndexCount())
        * sizeof(double);
}
Exemple #4
0
QStringList CellmlFileRuntime::componentHierarchy(iface::cellml_api::CellMLElement *pElement)
{
    // Make sure that we have a given element

    if (!pElement)
        return QStringList();

    // Try to retrieve the component that owns the given element, unless the
    // given element is a component itself (which will be the case when we come
    // here through recursion)

    ObjRef<iface::cellml_api::CellMLComponent> component = QueryInterface(pElement);
    ObjRef<iface::cellml_api::CellMLElement> parent = pElement->parentElement();
    ObjRef<iface::cellml_api::CellMLComponent> parentComponent = QueryInterface(parent);

    if (!component && !parentComponent) {
        // The element isn't a component and neither is its parent, so it
        // doesn't have a hierarchy

        return QStringList();
    }

    // Recursively retrieve the component hierarchy of the given element's
    // encapsulation parent, if any

    ObjRef<iface::cellml_api::CellMLComponent> componentEncapsulationParent = component?component->encapsulationParent():parentComponent->encapsulationParent();

    return componentHierarchy(componentEncapsulationParent) << QString::fromStdWString(component?component->name():parentComponent->name());
}
//! (static)
std::pair<bool, ObjRef> loadAndExecute(Runtime & runtime, const std::string & filename) {
	ObjRef script;
	try {
		script = loadScriptFile(filename);
	} catch (Exception * error) {
		std::cerr << "\nError occurred while loading file '" << filename << "':\n" << error->toString() << std::endl;
		return std::make_pair(false, error);
	}
	bool success = true;
	ObjRef result;
	try {
		runtime.executeObj(script.get());
		result = runtime.getResult();
		if(runtime.getState() == Runtime::STATE_EXCEPTION) {
			std::cout << "\nException caught (1):\n" << result.toString() << std::endl;
			success = false;
		}
	} catch (Object * o) {
		result = o;
		std::cout << "\nException caught (2):\n" << result.toString() << std::endl;
		success = false;
	} catch (...) {
		std::cout << "\nCaught unknown C++ exception." << std::endl;
		success = false;
	}
	return std::make_pair(success, result);
}
Exemple #6
0
QString CellmlFile::xmlBase()
{
    // Return the CellML file's base URI

    if (load()) {
        ObjRef<iface::cellml_api::URI> baseUri = mModel->xmlBase();

        return QString::fromStdWString(baseUri->asText());
    } else {
        return QString();
    }
}
Exemple #7
0
bool CellmlFile::load()
{
    // Check whether the file is already loaded and without any issues

    if (!mLoadingNeeded)
        return mIssues.isEmpty();

    // Consider the file loaded
    // Note: even when we can't load the file, we still consider it 'loaded'
    //       since we at least tried to load it, so unless the file gets
    //       modified (and we are to reload it), we are 'fine'...

    mLoadingNeeded = false;

    // Try to load the model

    if (!doLoad(mFileName, QString(), &mModel, mIssues))
        return false;

    // Retrieve all the RDF triples associated with the model and initialise our
    // list of original RDF triples

    ObjRef<iface::cellml_api::RDFRepresentation> rdfRepresentation = mModel->getRDFRepresentation(L"http://www.cellml.org/RDF/API");

    if (rdfRepresentation) {
        mRdfApiRepresentation = QueryInterface(rdfRepresentation);

        if (mRdfApiRepresentation) {
            mRdfDataSource = mRdfApiRepresentation->source();
            ObjRef<iface::rdf_api::TripleSet> rdfTriples = mRdfDataSource->getAllTriples();
            ObjRef<iface::rdf_api::TripleEnumerator> rdfTriplesEnumerator = rdfTriples->enumerateTriples();

            for (ObjRef<iface::rdf_api::Triple> rdfTriple = rdfTriplesEnumerator->getNextTriple();
                 rdfTriple; rdfTriple = rdfTriplesEnumerator->getNextTriple()) {
                mRdfTriples << new CellmlFileRdfTriple(this, rdfTriple);
            }

            mRdfTriples.updateOriginalRdfTriples();
        }
    }

    // Determine which cmeta:ids are currently in use, be they in the various
    // CellML elements or RDF triples

    retrieveCmetaIdsFromCellmlElement(mModel);

    foreach (CellmlFileRdfTriple *rdfTriple, mRdfTriples)
        mUsedCmetaIds << rdfTriple->metadataId();

    mUsedCmetaIds.removeDuplicates();

    return true;
}
void SingleCellViewSimulationData::startNextRepeat()
{
    mCurrentRepeat++;
    if (mCurrentRepeat >= solverProperties()["nrepeats"].toInt()) {
        emit simulationComplete();
        return;
    }

    if (mCurrentRepeat == 0)
      mStatesWhenRun = mStates;
    else
      mStates = mStatesWhenRun;

    newIntegrationRun();

    if (!mIntegrationRun)
        return;

    mState = SingleCellViewSimulationData::SIMSTATE_WAITING_RESULTS;

    iface::cellml_services::CellMLCompiledModel*
        compModel(isDAETypeSolver() ?
                  static_cast<iface::cellml_services::CellMLCompiledModel*>
                  (mRuntime->daeCompiledModel()) :
                  static_cast<iface::cellml_services::CellMLCompiledModel*>
                  (mRuntime->odeCompiledModel()));
    ObjRef<iface::cellml_services::CodeInformation> codeInfo
        (compModel->codeInformation());

    mResultReceiver = new ResultListener(mIntegrationRun, codeInfo->rateIndexCount(),
                                         codeInfo->algebraicIndexCount());
    mResultReceiver->delay(mDelay);

    mIntegrationRun->setStepSizeControl(mSolverProperties["absTol"].toDouble(),
                                        mSolverProperties["relTol"].toDouble(),
                                        1.0, // Scaling factor: states
                                        1.0, // Scaling factor: rates
                                        mSolverProperties["maxStep"].toDouble());
    mIntegrationRun->setResultRange(mStartingPoint, mEndingPoint,
                                    10000.0 // Maximum density of points in bvar, as an upper bound on the number
                                            // of points returned.
                                   );
    mIntegrationRun->setProgressObserver(mResultReceiver);

    QObject::connect(mResultReceiver, SIGNAL(constantsAvailable(const QList<double>)), this, SIGNAL(constantsAvailable(const QList<double>)));
    QObject::connect(mResultReceiver, SIGNAL(solveDone()), this, SLOT(startNextRepeat()));
    QObject::connect(mResultReceiver, SIGNAL(solveFailure(QString)), this, SIGNAL(simulationFailed(QString)));
    QObject::connect(mResultReceiver, SIGNAL(solvePointAvailable(double,QList<double>,QList<double>,QList<double>)), this, SIGNAL(simulationDataAvailable(double,QList<double>,QList<double>,QList<double>)));

    setupOverrides();
    mIntegrationRun->start();
}
//! (static)
std::pair<bool, ObjRef> loadAndExecute(Runtime & runtime, const std::string & filename) {
	try {
		ObjRef result = _loadAndExecute(runtime,filename);
		ObjRef exitResult = runtime.fetchAndClearExitResult();
		return std::make_pair(true,exitResult.isNotNull() ? exitResult : result);
	} catch (Object * error) {
		std::ostringstream os;
		os << "Error occurred while loading file '" << filename << "':\n" << error->toString() << std::endl;
		runtime.log(Logger::LOG_ERROR,os.str());
		return std::make_pair(false, error);
	}
//	}catch(...){
//		std::cout << "\nCaught unknown C++ exception." << std::endl;
//		return std::make_pair(false, result.detachAndDecrease());
}
Exemple #10
0
bool CellmlFileManager::canLoadFileContents(const QString &pFileContents) const
{
    // Try to load the CellML file contents

    ObjRef<iface::cellml_api::CellMLBootstrap> cellmlBootstrap = CreateCellMLBootstrap();
    ObjRef<iface::cellml_api::DOMModelLoader> modelLoader = cellmlBootstrap->modelLoader();
    ObjRef<iface::cellml_api::Model> model;

    try {
        model = modelLoader->createFromText(pFileContents.toStdWString());

        return true;
    } catch (iface::cellml_api::CellMLException &) {
        return false;
    }
}
void
CDA_CellMLElement::addEventListener
(
 const std::wstring& aType,
 iface::events::EventListener* aListener,
 bool aUseCapture
)
  throw(std::exception&)
{
  // Only bubbling is supported, as these events can't be cancelled.
  if (aUseCapture)
    throw iface::cellml_api::CellMLException(L"Only bubbling events are supported.");

  int32_t event = FindEventByName(aType);
  // Unknown events are silently ignored, as per the DOM Events specification.
  if (event == -1)
    return;

  // Find the adaptor, if there is one...
  ListenerToAdaptor_t::iterator i = mListenerToAdaptor.find(aListener);

  ObjRef<CDA_CellMLElementEventAdaptor> adaptor;

  if (i == mListenerToAdaptor.end())
  {
    // We add a refcount, putting the total to 2...
    adaptor = new CDA_CellMLElementEventAdaptor(this, aListener);
    // One refcount is used for the map, the other belongs to the ObjRef and
    // will be automatically dropped.
    mListenerToAdaptor.insert(std::pair<iface::events::EventListener*,
                              CDA_CellMLElementEventAdaptor*>
                              (aListener, adaptor)
                             );
  }
  else
    adaptor = (*i).second;

  try
  {
    adaptor->newEventType(event);
  }
  catch (std::exception& e)
  {
    adaptor->considerDestruction();
    throw e;
  }
}
std::wstring CompactorReport::getReport() const
{
    std::wstringstream report;
    report << L"Model Compaction Report\n"
           << L"=======================\n\n";
    if (! mErrorMessage.empty()) report << L"Error message: " << mErrorMessage << L"\n\n";
    std::wstring indent = L"";
    if (mVariableForCompaction.size() > 0)
    {
        report << L"Some variables have not been compacted.\n"
               << L"Uncompacted variables are given below.\n\n";
        for (size_t i=0; i<mVariableForCompaction.size(); ++i)
        {
            ObjRef<iface::cellml_api::CellMLVariable> variable = mVariableForCompaction[i].first;
            ObjRef<iface::cellml_api::CellMLVariable> srcVariable = mVariableForCompaction[i].second;
            std::wstring modelUri = variable->modelElement()->base_uri()->asText();
            std::wstring srcModelUri = srcVariable->modelElement()->base_uri()->asText();
            for (size_t j=0;j<i;++j) indent += L"\t";
            report << indent << L"Compaction requested for variable: " << modelUri << L" # "
                   << variable->componentName() << L" / "
                   << variable->name() << L";\n" << indent << L"with the actual source variable being: "
                   << srcModelUri << L" # " << srcVariable->componentName() << L" / " << srcVariable->name() << L"\n";
        }
    }
    report.flush();
    return report.str();
}
/*! Tries to locate the given __filename__ with the current searchPath set in the runtime.
	@return the path to the file or the original __filename__ if the file could not be found.	*/
static std::string findFile(Runtime & runtime, const std::string & filename){
	static const StringId seachPathsId("__searchPaths");

	std::string file(IO::condensePath(filename));
	if( IO::getEntryType(file)!=IO::TYPE_FILE ){
		if(Array * searchPaths = dynamic_cast<Array*>(runtime.getAttribute(seachPathsId).getValue())){
			for(ERef<Iterator> itRef=searchPaths->getIterator();!itRef->end();itRef->next()){
				ObjRef valueRef = itRef->value();
				std::string s(IO::condensePath(valueRef.toString()+'/'+filename));
				if( IO::getEntryType(s)==IO::TYPE_FILE ){
					file = s;
					break;
				}
			}
		}
	}
	return file;
}
/*! Tries to locate the given __filename__ with the current searchPath set in the runtime.
	@return the path to the file or the original __filename__ if the file could not be found.	*/
static std::string findFile(Runtime & runtime, const std::string & filename){
	static const identifierId seachPathsId=stringToIdentifierId("__searchPaths");

	std::string file(FileUtils::condensePath(filename));
	if( FileUtils::isFile(file)!=1 ){
		if(Array * searchPaths = dynamic_cast<Array*>(runtime.getAttribute(seachPathsId))){
			for(ERef<Iterator> itRef=searchPaths->getIterator();!itRef->end();itRef->next()){
				ObjRef valueRef = itRef->value();
				std::string s(FileUtils::condensePath(valueRef.toString()+"/"+filename));
				if( FileUtils::isFile(s)==1 ){
					file = s;
					break;
				}
			}
		}
	}
	return file;
}
Exemple #15
0
bool CellmlFile::doLoad(const QString &pFileName, const QString &pFileContents,
                        ObjRef<iface::cellml_api::Model> *pModel,
                        CellmlFileIssues &pIssues)
{
    // Make sure that pIssues is empty

    pIssues.clear();

    // Get a bootstrap object and its model loader

    ObjRef<iface::cellml_api::CellMLBootstrap> cellmlBootstrap = CreateCellMLBootstrap();
    ObjRef<iface::cellml_api::DOMModelLoader> modelLoader = cellmlBootstrap->modelLoader();

    // Try to create the model

    try {
        if (pFileContents.isEmpty())
            *pModel = modelLoader->loadFromURL(QUrl::fromPercentEncoding(QUrl::fromLocalFile(pFileName).toEncoded()).toStdWString());
        else
            *pModel = modelLoader->createFromText(pFileContents.toStdWString());
    } catch (iface::cellml_api::CellMLException &exception) {
        // Something went wrong with the loading of the model

        if (pFileContents.isEmpty()) {
            pIssues << CellmlFileIssue(CellmlFileIssue::Error,
                                       QObject::tr("the model could not be loaded (%1)").arg(Core::formatMessage(QString::fromStdWString(exception.explanation))));
        } else {
            pIssues << CellmlFileIssue(CellmlFileIssue::Error,
                                       QObject::tr("the model could not be created (%1)").arg(Core::formatMessage(QString::fromStdWString(exception.explanation))));
        }

        return false;
    }

    // Update the base URI, should the CellML file be a remote one or its
    // contents be directly passed onto us

    Core::FileManager *fileManagerInstance = Core::FileManager::instance();
    ObjRef<iface::cellml_api::URI> baseUri = (*pModel)->xmlBase();

    if (fileManagerInstance->isRemote(pFileName)) {
        // We are dealing with a remote file, so its XML base value should point
        // to its remote location

        baseUri->asText(fileManagerInstance->url(pFileName).toStdWString());
    } else if (!pFileContents.isEmpty()) {
        // We are dealing with a file which contents was directly passed onto
        // us, so its XML base value should point to its actual location

        baseUri->asText(pFileName.toStdWString());
    }

    return true;
}
bool isCellmlFile(const QString &pFileName)
{
    // If the given file is already managed by our CellML file manager, then we
    // consider that it's still a CellML file (even though it may not be a
    // CellML file anymore after having been edited and saved, but in this case
    // it's good to keep considering the file as a CellML file, so that the user
    // can continue editing it for example)

    QString nativeFileName = Core::nativeCanonicalFileName(pFileName);

    if (CellMLSupport::CellmlFileManager::instance()->cellmlFile(nativeFileName))
        return true;

    // The given file is not managed by our CellML file manager, so check
    // whether it's a new file and, if so, consider it as a CellML file

    if (Core::FileManager::instance()->isNew(nativeFileName))
        return true;

    // Check whether we are dealing with an empty file or a file that contains
    // spaces of sorts and, if not, whether we can load it using the CellML API

    QString fileContents;

    if (Core::readTextFromFile(nativeFileName, fileContents)) {
        if (fileContents.trimmed().isEmpty())
            return true;

        ObjRef<iface::cellml_api::CellMLBootstrap> cellmlBootstrap = CreateCellMLBootstrap();
        ObjRef<iface::cellml_api::DOMModelLoader> modelLoader = cellmlBootstrap->modelLoader();
        ObjRef<iface::cellml_api::Model> model;

        try {
            model = modelLoader->createFromText(fileContents.toStdWString());

            return true;
        } catch (iface::cellml_api::CellMLException &) {
            return false;
        }
    } else {
        return false;
    }
}
Exemple #17
0
			Util::GenericAttribute * convertFromEScript(const EScript::ObjPtr & object) override {
				// is a Number?
				EScript::Number * n = dynamic_cast<EScript::Number *> (object.get());
				if (n != nullptr) {
					return GenericAttribute::createNumber(n->getValue());
				}

				// is a Bool?
				EScript::Bool * b = dynamic_cast<EScript::Bool *> (object.get());
				if (b != nullptr) {
					return GenericAttribute::createBool(b->toBool());
				}

				// is a String?
				EScript::String * s = dynamic_cast<EScript::String *> (object.get());
				if (s != nullptr) {
					return GenericAttribute::createString(s->getString());
				}

				// is an Array?
				EScript::Array * a = dynamic_cast<EScript::Array *> (object.get());
				if (a != nullptr) {
					auto gl = new Util::GenericAttributeList;
					for (ERef<EScript::Iterator> i = a->getIterator(); !i->end(); i->next()) {
						ObjRef value = i->value();
						gl->push_back(convertEScriptObjectToGenericAttribute(value));
					}
					return gl;
				}
				// is a Map?
				EScript::Map * m = dynamic_cast<EScript::Map *> (object.get());
				if (m != nullptr) {
					auto gm = new Util::GenericAttributeMap;
					for (ERef<EScript::Iterator> i = m->getIterator(); !i->end(); i->next()) {
						ObjRef key = i->key();
						ObjRef value = i->value();
						gm->setValue(key->toString(), convertEScriptObjectToGenericAttribute(value));
					}
					return gm;
				}

				return nullptr;
			}
 void operator= (const ObjRef<U>& newAssign)
 {
     T* nap = newAssign.getPointer();
     if (mPtr == nap)
         return;
     if (mPtr)
         mPtr->release_ref();
     mPtr = nap;
     if (mPtr != NULL)
         mPtr->add_ref();
 }
void SingleCellViewSimulationData::setupOverrides()
{
    iface::cellml_services::CellMLCompiledModel*
        compModel(isDAETypeSolver() ?
                  static_cast<iface::cellml_services::CellMLCompiledModel*>
                  (mRuntime->daeCompiledModel()) :
                  static_cast<iface::cellml_services::CellMLCompiledModel*>
                  (mRuntime->odeCompiledModel()));
    ObjRef<iface::cellml_services::CodeInformation> codeInfo
        (compModel->codeInformation());
    
    for (unsigned int i = 0; i < codeInfo->constantIndexCount(); i++)
        if (mInitialConstants[i] != mConstants[i])
            mIntegrationRun->setOverride(iface::cellml_services::CONSTANT,
                                         i, mConstants[i]);
    for (unsigned int i = 0; i < codeInfo->rateIndexCount(); i++)
        if (mInitialStates[i] != mStates[i])
            mIntegrationRun->setOverride(iface::cellml_services::STATE_VARIABLE,
                                         i, mStates[i]);
}
int CellmlModelDefinition::loadModelFromString(const std::string &ms)
{
    std::cout << "Creating CellML Model Definition from the given model string"
              << std::endl;
    mUrl = "";
    std::wstring msW = s2ws(ms);
    ObjRef<iface::cellml_api::CellMLBootstrap> cb = CreateCellMLBootstrap();
    ObjRef<iface::cellml_api::DOMModelLoader> ml = cb->modelLoader();
    int code;
    try
    {
        ObjRef<iface::cellml_api::Model> model = ml->createFromText(msW);
        model->fullyInstantiateImports();
        // we have a model, so we can start grabbing hold of the CellML API objects
        mCapi = new CellmlApiObjects();
        mCapi->model = model;
        code = instantiateCellmlApiObjects();
    }
    catch (...)
    {
      std::wcerr << L"Error loading model from string." << std::endl;
      return -1;
    }
    return code;
}
int CellmlModelDefinition::loadModel(const std::string &url)
{
    std::cout << "Creating CellML Model Definition from the URL: "
              << url << std::endl;
    mUrl = url;
    if (mUrl.empty()) return -1;
    std::wstring urlW = s2ws(url);
    ObjRef<iface::cellml_api::CellMLBootstrap> cb = CreateCellMLBootstrap();
    ObjRef<iface::cellml_api::DOMModelLoader> ml = cb->modelLoader();
    int code;
    try
    {
        ObjRef<iface::cellml_api::Model> model = ml->loadFromURL(urlW);
        model->fullyInstantiateImports();
        // we have a model, so we can start grabbing hold of the CellML API objects
        mCapi = new CellmlApiObjects();
        mCapi->model = model;
        code = instantiateCellmlApiObjects();
    }
    catch (...)
    {
      std::wcerr << L"Error loading model: " << urlW << std::endl;
      return -1;
    }
    return code;
}
//! ---|> [Object]
Object * ForeachControl::execute(Runtime & rt) {
	ERef<Iterator> itRef=dynamic_cast<Iterator *>(rt.executeObj(arrayExpressionRef.get()));
	if(!rt.assertNormalState(this) || itRef.isNull())
		return NULL;

	ObjRef resultRef;

	while (!itRef->end()) {
		if (keyVar)
			rt.assignToVariable(keyVar,itRef->key());
		if (valueVar)
			rt.assignToVariable(valueVar,itRef->value());

		if(!actionRef.isNull()){
			try {
				resultRef=rt.executeObj(actionRef.get());
			} catch (Object * e) {
				std::cout << "###"<<e<<itRef->key();
				throw(e);
			}
			if(!rt.checkNormalState()){
				if(rt.getState()==Runtime::STATE_BREAKING){
					rt.resetState();
					break;
				}else if(rt.getState()==Runtime::STATE_CONTINUE){
					rt.resetState();
				}else{
					return NULL;
				}
			}
		}

		itRef->next();
	}
	return resultRef.detachAndDecrease();
}
ObjRef<iface::cellml_api::CellMLVariable> findLocalVariable(CellmlApiObjects* capi, const std::string& variableId)
{
    if (!(capi->cevas))
    {
        std::cerr << "CellMLModelDefinition::findLocalVariable -- missing CeVAS object?" << std::endl;
        return NULL;
    }
    // find named variable - in local components only!
    CVpair cv = splitName(variableId);
    if ((cv.first.length() == 0) || (cv.second.length() == 0)) return NULL;
    //std::cout << "Component name: " << cv.first << "; variable name: " << cv.second << std::endl;
    ObjRef<iface::cellml_api::CellMLComponentSet> components = capi->model->localComponents();
    ObjRef<iface::cellml_api::CellMLComponent> component = components->getComponent(s2ws(cv.first));
    if (!component)
    {
        std::cerr << "CellMLModelDefinition::findLocalVariable -- unable to find local component: " << cv.first << std::endl;
        return NULL;
    }
    ObjRef<iface::cellml_api::CellMLVariableSet> variables = component->variables();
    ObjRef<iface::cellml_api::CellMLVariable> variable = variables->getVariable(s2ws(cv.second));
    if (!variable)
    {
        std::cerr << "CellMLModelDefinition::findLocalVariable -- unable to find variable: " << cv.first << " / "
                  << cv.second << std::endl;
        return NULL;
    }
    // get source variable
    ObjRef<iface::cellml_services::ConnectedVariableSet> cvs = capi->cevas->findVariableSet(variable);
    ObjRef<iface::cellml_api::CellMLVariable> v = cvs->sourceVariable();
    if (!v)
    {
        std::cerr << "CellMLModelDefinition::findLocalVariable -- unable get source variable for variable: "
                  << cv.first << " / " << cv.second << std::endl;
        return NULL;
    }
    return v;
}
CellmlFileRdfTripleElement::CellmlFileRdfTripleElement(iface::rdf_api::Node *pRdfNode) :
    mId(QString()),
    mUriReference(QString()),
    mLexicalForm(QString()),
    mLanguage(QString()),
    mDataTypeUri(QString())
{
    // Check which interface is supported by the node and initialise it in case
    // it supports the rdf_api::URIReference, rdf_api::PlainLiteral or
    // rdf_api::TypedLiteral interface

    ObjRef<iface::rdf_api::URIReference> uriReference = QueryInterface(pRdfNode);

    if (uriReference) {
        // The rdf_api::URIReference interface is supported, so initialise the
        // triple element using that interface

        mType = UriReference;

        mUriReference = QString::fromStdWString(uriReference->URI()).trimmed();
    } else {
        ObjRef<iface::rdf_api::PlainLiteral> plainLiteral = QueryInterface(pRdfNode);

        if (plainLiteral) {
            // The rdf_api::PlainLiteral interface is supported, so initialise
            // the triple element using that interface

            mType = PlainLiteral;

            mLexicalForm = QString::fromStdWString(plainLiteral->lexicalForm()).trimmed();
            mLanguage    = QString::fromStdWString(plainLiteral->language()).trimmed();
        } else {
            ObjRef<iface::rdf_api::TypedLiteral> typedLiteral = QueryInterface(pRdfNode);

            if (typedLiteral) {
                // The rdf_api::TypedLiteral interface is supported, so
                // initialise the triple element using that interface

                mType = TypedLiteral;

                mLexicalForm = QString::fromStdWString(typedLiteral->lexicalForm()).trimmed();
                mDataTypeUri = QString::fromStdWString(typedLiteral->datatypeURI()).trimmed();
            } else {
                // The node doesn't support any interface, so initialise the
                // triple element using its id
                // Note: the id returned by the CellML API will look something
                //       like
                //
                //          7EQ?;?Y?A?w???A
                //
                //       This is clearly not user-friendly, so we generate and
                //       use our own id instead...

                static QMap<QString, QString> ids;
                static int counter = 0;

                QString id = QString::fromStdString(pRdfNode->objid()).trimmed();

                mType = Id;

                mId = ids.value(id);

                if (mId == QString()) {
                    // There is no id value for the current id, so generate one
                    // and keep track of it

                    mId = QString("id_%1").arg(++counter, 9, 10, QChar('0'));

                    ids.insert(id, mId);
                }
            }
        }
    }

    // Keep track of the RDF triple element's value as a string, which is based
    // on its type

    switch (mType) {
    case UriReference:
        mAsString = mUriReference;

        break;
    case PlainLiteral:
        mAsString = mLexicalForm+" ["+mLanguage+"]";

        break;
    case TypedLiteral:
        mAsString = mLexicalForm+" ["+mDataTypeUri+"]";

        break;
    default:
        // Id

        mAsString = mId;
    }
}
void
WriteCode(iface::cellml_services::CodeInformation* cci, uint32_t useida)
{
  iface::cellml_services::ModelConstraintLevel mcl =
    cci->constraintLevel();
  if (mcl == iface::cellml_services::UNDERCONSTRAINED)
  {
    ObjRef<iface::cellml_services::ComputationTarget> ctMissingIV(cci->missingInitial());
    if (ctMissingIV != NULL)
    {
      ObjRef<iface::cellml_api::CellMLVariable> v = ctMissingIV->variable();
      std::wstring n = v->name();
      std::wstring c = v->componentName();
      std::wstring str;
      uint32_t deg = ctMissingIV->degree();
      if (deg != 0)
      {
        str += L"d^";
        wchar_t buf[20];
        any_swprintf(buf, 20, L"%u", deg);
        str += buf;
        str += L"/dt^";
        str += buf;
        str += L" ";
      }
      str += n;
      str += L" (in ";
      str += c;
      str += L")\n";
      printf("/* Model is underconstrained due to missing initial_value on %S\n", str.c_str());
    }
    else
    {
      printf("/* Model is underconstrained.\n"
             " * List of undefined targets follows...\n");
      iface::cellml_services::ComputationTargetIterator* cti = cci->iterateTargets();
      iface::cellml_services::ComputationTarget* ct;
      std::vector<std::wstring> messages;
      while (true)
      {
        ct = cti->nextComputationTarget();
        if (ct == NULL)
          break;
        if (ct->type() != iface::cellml_services::FLOATING)
        {
          ct->release_ref();
          continue;
        }
        iface::cellml_api::CellMLVariable* v = ct->variable();
        std::wstring n = v->name();
        std::wstring c = v->componentName();
        std::wstring str = L" * * ";
        uint32_t deg = ct->degree();
        if (deg != 0)
        {
          str += L"d^";
          wchar_t buf[20];
          any_swprintf(buf, 20, L"%u", deg);
          str += buf;
          str += L"/dt^";
          str += buf;
          str += L" ";
        }
        str += n;
        str += L" (in ";
        str += c;
        str += L")\n";
        messages.push_back(str);
        v->release_ref();
      ct->release_ref();
      }
      cti->release_ref();
      // Sort the messages...
      std::sort(messages.begin(), messages.end());
      std::vector<std::wstring>::iterator msgi;
      for (msgi = messages.begin(); msgi != messages.end(); msgi++)
        printf("%S", (*msgi).c_str());
      printf(" */\n");
    }
    return;
  }
  else if (mcl == iface::cellml_services::OVERCONSTRAINED)
  {
    printf("/* Model is overconstrained.\n"
           " * List variables defined at time of error follows...\n");
    iface::cellml_services::ComputationTargetIterator* cti = cci->iterateTargets();
    iface::cellml_services::ComputationTarget* ct;
    std::vector<std::wstring> messages;
    while (true)
    {
      ct = cti->nextComputationTarget();
      if (ct == NULL)
        break;
      if (ct->type() == iface::cellml_services::FLOATING)
      {
        ct->release_ref();
        continue;
      }
      iface::cellml_api::CellMLVariable* v = ct->variable();
      std::wstring n = v->name();
      std::wstring str = L" * * ";
      uint32_t deg = ct->degree();
      if (deg != 0)
      {
        str += L"d^";
        wchar_t buf[20];
        any_swprintf(buf, 20, L"%u", deg);
        str += buf;
        str += L"/dt^";
        str += buf;
        str += L" ";
      }
      str += n;
      str += L"\n";
      messages.push_back(str);
      v->release_ref();
      ct->release_ref();
    }
    cti->release_ref();

    // Sort the messages...
    std::sort(messages.begin(), messages.end());
    std::vector<std::wstring>::iterator msgi;
    for (msgi = messages.begin(); msgi != messages.end(); msgi++)
      printf("%S", (*msgi).c_str());

    // Get flagged equations...
    iface::mathml_dom::MathMLNodeList* mnl = cci->flaggedEquations();
    printf(" * Extraneous equation was:\n");
    iface::dom::Node* n = mnl->item(0);
    mnl->release_ref();
    iface::dom::Element* el =
      reinterpret_cast<iface::dom::Element*>(n->query_interface("dom::Element"));
    n->release_ref();

    std::wstring cmeta = el->getAttribute(L"id");
    if (cmeta == L"")
      printf(" *   <equation with no cmeta ID>\n");
    else
      printf(" *   %S\n", cmeta.c_str());

    n = el->parentNode();
    el->release_ref();

    if (n != NULL)
    {
      el = reinterpret_cast<iface::dom::Element*>
        (n->query_interface("dom::Element"));
      n->release_ref();

      cmeta = el->getAttribute(L"id");
      if (cmeta == L"")
        printf(" *   in <math with no cmeta ID>\n");
      else
        printf(" *   in math with cmeta:id %S\n", cmeta.c_str());

      el->release_ref();
    }

    printf(" */\n");
    return;
  }
  else if (mcl == iface::cellml_services::UNSUITABLY_CONSTRAINED)
  {
    printf("/* Model is unsuitably constrained (i.e. would need capabilities"
           " beyond those of the CCGS to solve).\n"
           " * The status of variables at time of error follows...\n");
    iface::cellml_services::ComputationTargetIterator* cti = cci->iterateTargets();
    iface::cellml_services::ComputationTarget* ct;
    std::vector<std::wstring> messages;
    while (true)
    {
      ct = cti->nextComputationTarget();
      if (ct == NULL)
        break;
      std::wstring str = L" * * ";
      if (ct->type() == iface::cellml_services::FLOATING)
        str += L" Undefined: ";
      else
        str += L" Defined: ";

      uint32_t deg = ct->degree();
      if (deg != 0)
      {
        str += L"d^";
        wchar_t buf[20];
        any_swprintf(buf, 20, L"%u", deg);
        str += buf;
        str += L"/dt^";
        str += buf;
        str += L" ";
      }
      iface::cellml_api::CellMLVariable* v = ct->variable();
      std::wstring n = v->name();
      str += n;
      str += L"\n";
      messages.push_back(str);
      v->release_ref();
      ct->release_ref();
    }
    cti->release_ref();

    // Sort the messages...
    std::sort(messages.begin(), messages.end());
    std::vector<std::wstring>::iterator msgi;
    for (msgi = messages.begin(); msgi != messages.end(); msgi++)
      printf("%S", (*msgi).c_str());

    printf(" */\n");
    return;
  }

  printf("/* Model is correctly constrained.\n");
  iface::mathml_dom::MathMLNodeList* mnl = cci->flaggedEquations();
  uint32_t i, l = mnl->length();
  if (l == 0)
    printf(" * No equations needed Newton-Raphson evaluation.\n");
  else
    printf(" * The following equations needed Newton-Raphson evaluation:\n");

  std::vector<std::wstring> messages;
  for (i = 0; i < l; i++)
  {
    iface::dom::Node* n = mnl->item(i);
    iface::dom::Element* el =
      reinterpret_cast<iface::dom::Element*>(n->query_interface("dom::Element"));
    n->release_ref();

    std::wstring cmeta = el->getAttribute(L"id");
    std::wstring str;
    if (cmeta == L"")
      str += L" *   <equation with no cmeta ID>\n";
    else
    {
      str += L" *   ";
      str += cmeta;
      str += L"\n";
    }

    n = el->parentNode();
    el->release_ref();

    el = reinterpret_cast<iface::dom::Element*>
      (n->query_interface("dom::Element"));
    n->release_ref();

    cmeta = el->getAttribute(L"id");
    if (cmeta == L"")
      str += L" *   in <math with no cmeta ID>\n";
    else
    {
      str += L" *   in math with cmeta:id ";
      str += cmeta;
      str += L"\n";
    }
    el->release_ref();

    messages.push_back(str);
  }
  mnl->release_ref();

  // Sort the messages...
  std::sort(messages.begin(), messages.end());
  std::vector<std::wstring>::iterator msgi;
  for (msgi = messages.begin(); msgi != messages.end(); msgi++)
    printf("%S", (*msgi).c_str());
  
  printf(" * The rate and state arrays need %u entries.\n", cci->rateIndexCount());
  printf(" * The algebraic variables array needs %u entries.\n", cci->algebraicIndexCount());
  printf(" * The constant array needs %u entries.\n", cci->constantIndexCount());
  printf(" * Variable storage is as follows:\n");
  
  messages.clear();
  iface::cellml_services::ComputationTargetIterator* cti = cci->iterateTargets();
  while (true)
  {
    iface::cellml_services::ComputationTarget* ct = cti->nextComputationTarget();
    if (ct == NULL)
      break;
    iface::cellml_api::CellMLVariable* v = ct->variable();
    iface::cellml_api::CellMLElement* el = v->parentElement();
    iface::cellml_api::CellMLComponent* c =
      reinterpret_cast<iface::cellml_api::CellMLComponent*>
      (el->query_interface("cellml_api::CellMLComponent"));
    el->release_ref();

    std::wstring str;
    std::wstring vn = v->name(), cn = c->name();
    str += L" * * Target ";
    uint32_t deg = ct->degree();
    if (deg != 0)
    {
      str += L"d^";
      wchar_t buf[20];
      any_swprintf(buf, 20, L"%u", deg);
      str += buf;
      str += L"/dt^";
      str += buf;
      str += L" ";
    }
    str += vn;
    str += L" in component ";
    str += cn;
    str += L"\n";

    c->release_ref();
    v->release_ref();

    str += L" * * * Variable type: ";
    str += TypeToString(ct->type());
    str += L"\n * * * Variable index: ";
    wchar_t buf[40];
    any_swprintf(buf, 40, L"%u\n", ct->assignedIndex());
    str += buf;

    str += L" * * * Variable storage: ";
    std::wstring vsn = ct->name();
    str += vsn;
    str += '\n';

    ct->release_ref();

    messages.push_back(str);
  }
  cti->release_ref();

  // Sort the messages...
  std::sort(messages.begin(), messages.end());
  for (msgi = messages.begin(); msgi != messages.end(); msgi++)
    printf("%S", (*msgi).c_str());

  printf(" */\n");

  std::wstring frag = cci->functionsString();
  printf("%S", frag.c_str());

  // Now start the code...
  frag = cci->initConstsString();
  printf("void SetupFixedConstants(double* CONSTANTS, double* RATES, double* STATES)\n{\n%S}\n", frag.c_str());

  frag = cci->variablesString();
  printf("void EvaluateVariables(double VOI, double* CONSTANTS, double* RATES, double* STATES, double* ALGEBRAIC)\n"
         "{\n%S}\n", frag.c_str());

  if (useida)
  {
    iface::cellml_services::IDACodeInformation* icci
      = reinterpret_cast<iface::cellml_services::IDACodeInformation*>(cci->query_interface("cellml_services::IDACodeInformation"));

    frag = icci->essentialVariablesString();
    printf("void EvaluateEssentialVariables(double VOI, double* CONSTANTS, double* RATES, double* STATES, double* ALGEBRAIC)\n"
           "{\n%S}\n", frag.c_str());

    frag = cci->ratesString();
    printf("void ComputeResiduals(double VOI, double* STATES, double* RATES, double* CONSTANTS, "
           "double* ALGEBRAIC)\n"
           "{\n%S}\n", frag.c_str());

    frag = icci->stateInformationString();
    printf("void SetupStateInfo(double * SI)\n{\n%S}\n", frag.c_str());

    frag = icci->rootInformationString();
    printf("void RootInformation()\n{\n%S}\n", frag.c_str());

    icci->release_ref();
  }
  else
  {
    frag = cci->ratesString();
    printf("void ComputeRates(double VOI, double* STATES, double* RATES, double* CONSTANTS, "
           "double* ALGEBRAIC)\n"
           "{\n%S}\n", frag.c_str());
  }
}
int main(int argc, char** argv)
{
  try
  {
    std::wstring modelURL
      (L"http://models.cellml.org/workspace/hodgkin_huxley_1952/@@rawfile/949cd4d3/hodgkin_huxley_1952.cellml");

    // Create a CellML Bootstrap and a model loader.
    ObjRef<iface::cellml_api::CellMLBootstrap> bootstrap(CreateCellMLBootstrap());
    ObjRef<iface::cellml_api::DOMModelLoader> loader(bootstrap->modelLoader());

    // Load a CellML model.
    ObjRef<iface::cellml_api::Model> hhModel
      (loader->loadFromURL(modelURL));

    // Request a RDF/API capable RDF representation...
    ObjRef<iface::cellml_api::RDFRepresentation> rr(hhModel->getRDFRepresentation(L"http://www.cellml.org/RDF/API"));
    ObjRef<iface::rdf_api::RDFAPIRepresentation> rrHH(QueryInterface(rr));

    // Retrieve the DataSource. Note: Changes to the data source are not pushed back
    // to the model until the source attribute is set on the rrHH again.
    ObjRef<iface::rdf_api::DataSource> dsHH(rrHH->source());

    // Get the resource corresponding to the cmeta:id on the model. Note that
    // cmetaId can return the empty string, which you should check for in
    // production code, if there is no cmeta:id
    ObjRef<iface::rdf_api::URIReference> hhModelRef
      (dsHH->getURIReference(bootstrap->makeURLAbsolute(modelURL, L"#" + hhModel->cmetaId())));

#ifdef DUMP_ALL_TRIPLES_FIRST
    {
      ObjRef<iface::rdf_api::TripleSet> ts(dsHH->getAllTriples());
      ObjRef<iface::rdf_api::TripleEnumerator> te(ts->enumerateTriples());
      while (true)
      {
        ObjRef<iface::rdf_api::Triple> t(te->getNextTriple());
        if (t == NULL)
          break;

        displayTriple(t);
      }
    }
#endif

    ObjRef<iface::rdf_api::URIReference> pmid(dsHH->getURIReference(L"http://www.cellml.org/bqs/1.0#Pubmed_id"));
    // Note: Calls like this could fail with an exception if there was no pubmed ID - production code should check.
    ObjRef<iface::rdf_api::Triple> t(hhModelRef->getTripleOutOfByPredicate(pmid));
    ObjRef<iface::rdf_api::Node> n(t->object());
    ObjRef<iface::rdf_api::Literal> lPMID(QueryInterface(n));
    if (lPMID != NULL) // It will be null if for some reason it isn't a literal...
      std::wcout << L"Model pubmed ID: " << lPMID->lexicalForm() << std::endl;

    ObjRef<iface::rdf_api::URIReference> bqsReference(dsHH->getURIReference(L"http://www.cellml.org/bqs/1.0#reference"));
    ObjRef<iface::rdf_api::TripleSet> ts(hhModelRef->getTriplesOutOfByPredicate(bqsReference));
    ObjRef<iface::rdf_api::TripleEnumerator> te(ts->enumerateTriples());
    while (true)
    {
      t = te->getNextTriple();
      if (t == NULL) break;
      ObjRef<iface::rdf_api::Resource> r(QueryInterface(t->object()));
      if (r == NULL) continue;
      std::wcout << L"Found a resource description:" << std::endl;
      try
      {
        t = r->getTripleOutOfByPredicate(pmid);
        n = t->object();
        lPMID = QueryInterface(n);
        if (lPMID != NULL)
          std::wcout << L"  Reference pubmed ID: " << lPMID->lexicalForm() << std::endl;
      }
      catch(...) {}
      // Look up the subject...
      ObjRef<iface::rdf_api::URIReference> subject(dsHH->getURIReference(L"http://purl.org/dc/elements/1.1/subject"));
      ts = r->getTriplesOutOfByPredicate(subject);
      ObjRef<iface::rdf_api::TripleEnumerator> te2 = ts->enumerateTriples();
      while (true)
      {
        t = te2->getNextTriple();
        if (t == NULL)
          break;
        n = t->object();
        r = QueryInterface(n);
        if (r == NULL)
          continue;
        std::wcout << "  Subject:" << std::endl;
        ObjRef<iface::rdf_api::URIReference> subjectType(dsHH->getURIReference(L"http://www.cellml.org/bqs/1.0#subject_type"));
        ts = r->getTriplesOutOfByPredicate(subjectType);
        ObjRef<iface::rdf_api::TripleEnumerator> te3 = ts->enumerateTriples();
        t = te3->getNextTriple();
        if (t)
        {
          n = t->object();
          ObjRef<iface::rdf_api::Literal> l(QueryInterface(n));
          std::wcout << "    Subject Type=" << l->lexicalForm() << std::endl;
        }
        ObjRef<iface::rdf_api::URIReference> value(dsHH->getURIReference(L"http://www.w3.org/1999/02/22-rdf-syntax-ns#value"));
        ts = r->getTriplesOutOfByPredicate(value);
        te3 = ts->enumerateTriples();

        t = te3->getNextTriple();
        if (t == NULL) continue;
        n = t->object();
        r = QueryInterface(n);
        if (r == NULL) continue;
        ObjRef<iface::rdf_api::Container> cont(r->correspondingContainer());

        // Add a new entry to the container first...
        ObjRef<iface::rdf_api::PlainLiteral> newPL(dsHH->getPlainLiteral(L"Newly created label", L"en"));
        cont->appendChild(newPL);

        // Delete any labels that match 'giant axon'...
        ObjRef<iface::rdf_api::NodeIterator> ni(cont->iterateChildren());
        while (true)
        {
          ObjRef<iface::rdf_api::Node> n(ni->getNextNode());
          if (n == NULL)
            break;
          ObjRef<iface::rdf_api::Literal> l(QueryInterface(n));
          if (l == NULL)
            continue;
          if (l->lexicalForm() == L"giant axon")
            // The false means don't renumber immediately. This leaves the
            // container with gaps...
            cont->removeChild(l, false);
        }
        cont->renumberContainer(); // Remove the gaps.

        displayContainer(cont, L"    ");
      }
    }
  }
  catch (iface::cellml_api::CellMLException&)
  {
    std::wcout << L"A CellMLException was raised. In production code, you would normally have more "
               << L"exception handlers to work out exactly where the problem occurred. This program "
               << L"avoids that for simplicity, to make the normal control flow easier to understand. "
               << L"The most likely cause is a network problem retrieving the hardcoded model URL."
               << std::endl;
    return 1;
  }
  catch (iface::rdf_api::RDFProcessingError&)
  {
    std::wcout << L"An RDFProcessingError was raised. In production code, you would normally have more "
               << L"exception handlers to work out exactly where the problem occurred. This program "
               << L"avoids that for simplicity, to make the normal control flow easier to understand."
               << std::endl;
    return 2;
  }
  return 0;
}
Exemple #27
0
void CellmlFileRuntime::update()
{
    // Reset the runtime's properties

    reset(true, true);

    // Check that the model is either a 'simple' ODE model or a DAE model
    // Note #1: we don't check whether a model is valid, since all we want is to
    //          update its runtime (which has nothing to do with editing or even
    //          validating a model), so if it can be done then great otherwise
    //          tough luck (so to speak)...
    // Note #2: in order to do so, we need to get a 'normal' code generator (as
    //          opposed to an IDA, i.e. DAE, code generator) since if the model
    //          is correctly constrained, then we can check whether some of its
    //          equations were flagged as needing a Newton-Raphson evaluation,
    //          in which case we would be dealing with a DAE model...
    // Note #3: ideally, there would be a more convenient way to determine the
    //          type of a model, but there isn't...

    iface::cellml_api::Model *model = mCellmlFile->model();

    if (!model)
        return;

    // Retrieve the model's type
    // Note: this can be done by checking whether some equations were flagged
    //       as needing a Newton-Raphson evaluation...

    retrieveOdeCodeInformation(model);

    if (!mOdeCodeInformation)
        return;

    ObjRef<iface::mathml_dom::MathMLNodeList> flaggedEquations = mOdeCodeInformation->flaggedEquations();

    mModelType = flaggedEquations->length()?CellmlFileRuntime::Dae:CellmlFileRuntime::Ode;

    // If the model is of DAE type, then we don't want the ODE-specific code
    // information, but the DAE-specific code one

    ObjRef<iface::cellml_services::CodeInformation> genericCodeInformation;

    if (mModelType == CellmlFileRuntime::Ode) {
        genericCodeInformation = mOdeCodeInformation;
    } else {
        retrieveDaeCodeInformation(model);

        if (!mDaeCodeInformation)
            return;

        genericCodeInformation = mDaeCodeInformation;
    }

    // Retrieve the number of constants, states/rates, algebraic and conditional
    // variables in the model
    // Note: this is to avoid having to go through the ODE/DAE code information
    //       an unnecessary number of times when we want to retrieve either of
    //       those numbers (e.g. see
    //       SingleCellViewSimulationResults::addPoint())...

    if (mModelType == CellmlFileRuntime::Ode) {
        mConstantsCount   = mOdeCodeInformation->constantIndexCount();
        mStatesRatesCount = mOdeCodeInformation->rateIndexCount();
        mAlgebraicCount   = mOdeCodeInformation->algebraicIndexCount();
        mCondVarCount     = 0;
    } else {
        mConstantsCount   = mDaeCodeInformation->constantIndexCount();
        mStatesRatesCount = mDaeCodeInformation->rateIndexCount();
        mAlgebraicCount   = mDaeCodeInformation->algebraicIndexCount();
        mCondVarCount     = mDaeCodeInformation->conditionVariableCount();
    }

    // Determine whether the model imports some components
    // Note #1: a model that only imports units will clearly not affect our
    //          model's variables, hence such a model won't be relevant for our
    //          mapping below...
    // Note #2: a model cannot be fully instantiated if it imports an empty
    //          component or a component with unmapped variables, so we don't
    //          need to worry about this type of model...

    ObjRef<iface::cellml_api::CellMLImportSet> imports = model->imports();
    ObjRef<iface::cellml_api::CellMLImportIterator> importsIter = imports->iterateImports();
    bool hasComponentImports = false;

    for (ObjRef<iface::cellml_api::CellMLImport> import = importsIter->nextImport();
         import; import = importsIter->nextImport()) {
        ObjRef<iface::cellml_api::ImportComponentSet> importComponents = import->components();

        if (importComponents->length()) {
            hasComponentImports = true;

            break;
        }
    }

    // If the model contains some imports then we want to to go through the
    // variables defined or referenced in our main CellML file and do a mapping
    // between the source of a variable and a variable in the main CellML file
    // Note: indeed, when it comes to CellML 1.1 files, we only want to list the
    //       parameters that are either defined or referenced in our main CellML
    //       file. Not only does it make sense, but also only the parameters
    //       listed in a main CellML file can be referenced in SED-ML...

    QMap<iface::cellml_api::CellMLVariable *, iface::cellml_api::CellMLVariable *> mainVariables = QMap<iface::cellml_api::CellMLVariable *, iface::cellml_api::CellMLVariable *>();
    ObjRef<iface::cellml_api::CellMLComponentSet> localComponents = model->localComponents();
    ObjRef<iface::cellml_api::CellMLComponentIterator> localComponentsIter = localComponents->iterateComponents();

    if (hasComponentImports) {
        for (ObjRef<iface::cellml_api::CellMLComponent> component = localComponentsIter->nextComponent();
             component; component = localComponentsIter->nextComponent()) {
            ObjRef<iface::cellml_api::CellMLVariableSet> variables = component->variables();
            ObjRef<iface::cellml_api::CellMLVariableIterator> variablesIter = variables->iterateVariables();

            for (ObjRef<iface::cellml_api::CellMLVariable> variable = variablesIter->nextVariable();
                 variable; variable = variablesIter->nextVariable()) {
                ObjRef<iface::cellml_api::CellMLVariable> sourceVariable = variable->sourceVariable();

                mainVariables.insert(sourceVariable, variable);
            }
        }
    }

    // Go through all our computation targets and determine which ones are
    // referenced in our main CellML file, and sort them by component and
    // variable name

    ObjRef<iface::cellml_services::ComputationTargetIterator> computationTargetIter = genericCodeInformation->iterateTargets();

    for (ObjRef<iface::cellml_services::ComputationTarget> computationTarget = computationTargetIter->nextComputationTarget();
         computationTarget; computationTarget = computationTargetIter->nextComputationTarget()) {
        // Make sure that our computation target is defined or referenced in our
        // main CellML file, if it has imports

        ObjRef<iface::cellml_api::CellMLVariable> variable = computationTarget->variable();
        iface::cellml_api::CellMLVariable *mainVariable = mainVariables.value(variable);
        iface::cellml_api::CellMLVariable *realVariable = mainVariable?mainVariable:variable.getPointer();

        if (   hasComponentImports && !mainVariable
            &&  (computationTarget->type() != iface::cellml_services::VARIABLE_OF_INTEGRATION)) {
            continue;
        }

        // Determine the type of our computation target

        CellmlFileRuntimeParameter::ParameterType parameterType;

        switch (computationTarget->type()) {
        case iface::cellml_services::VARIABLE_OF_INTEGRATION:
            parameterType = CellmlFileRuntimeParameter::Voi;

            break;
        case iface::cellml_services::CONSTANT:
            // We are dealing with a constant, but the question is whether that
            // constant is a 'proper' constant, a 'computed' constant or even a
            // rate, and this can be determined by checking whether the computed
            // target has an initial value or even a degree
            // Note: a state variable that is initialised using the initial
            //       value of another variable will have its rate considered as
            //       a constant. However, when it comes to the GUI, we really
            //       want it to be seen as a rate hence we check for the degree
            //       of the computed target...

            if (QString::fromStdWString(variable->initialValue()).isEmpty()) {
                // The computed target doesn't have an initial value, so it must
                // be a 'computed' constant

                parameterType = CellmlFileRuntimeParameter::ComputedConstant;
            } else if (computationTarget->degree()) {
                // The computed target has a degree, so it is effectively a rate

                parameterType = CellmlFileRuntimeParameter::Rate;
            } else {
                // The computed target has an initial value, so it must be a
                // 'proper' constant

                parameterType = CellmlFileRuntimeParameter::Constant;
            }

            break;
        case iface::cellml_services::STATE_VARIABLE:
        case iface::cellml_services::PSEUDOSTATE_VARIABLE:
            parameterType = CellmlFileRuntimeParameter::State;

            break;
        case iface::cellml_services::ALGEBRAIC:
            // We are dealing with either a 'proper' algebraic variable or a
            // rate variable
            // Note: if the variable's degree is equal to zero, then we are
            //       dealing with a 'proper' algebraic variable otherwise we
            //       are dealing with a rate variable...

            if (computationTarget->degree())
                parameterType = CellmlFileRuntimeParameter::Rate;
            else
                parameterType = CellmlFileRuntimeParameter::Algebraic;

            break;
        case iface::cellml_services::FLOATING:
            parameterType = CellmlFileRuntimeParameter::Floating;

            break;
        case iface::cellml_services::LOCALLY_BOUND:
            parameterType = CellmlFileRuntimeParameter::LocallyBound;

            break;
        }

        // Keep track of our computation target, should its type be of interest

        if (   (parameterType != CellmlFileRuntimeParameter::Floating)
            && (parameterType != CellmlFileRuntimeParameter::LocallyBound)) {
            CellmlFileRuntimeParameter *parameter = new CellmlFileRuntimeParameter(QString::fromStdWString(realVariable->name()),
                                                                                   computationTarget->degree(),
                                                                                   QString::fromStdWString(realVariable->unitsName()),
                                                                                   componentHierarchy(realVariable),
                                                                                   parameterType,
                                                                                   computationTarget->assignedIndex());

            if (parameterType == CellmlFileRuntimeParameter::Voi)
                mVariableOfIntegration = parameter;

            if (!hasComponentImports || (realVariable == mainVariable))
                mParameters << parameter;
        }
    }

    std::sort(mParameters.begin(), mParameters.end(), sortParameters);

    // Generate the model code

    QString modelCode = QString();
    QString functionsString = QString::fromStdWString(genericCodeInformation->functionsString());

    if (!functionsString.isEmpty()) {
        // We will need to solve at least one NLA system

        mAtLeastOneNlaSystem = true;

        modelCode +=  "struct rootfind_info\n"
                      "{\n"
                      "    double aVOI;\n"
                      "\n"
                      "    double *aCONSTANTS;\n"
                      "    double *aRATES;\n"
                      "    double *aSTATES;\n"
                      "    double *aALGEBRAIC;\n"
                      "\n"
                      "    int *aPRET;\n"
                      "};\n"
                      "\n"
                      "extern void doNonLinearSolve(char *, void (*)(double *, double *, void*), double *, int *, int, void *);\n"
                      "\n"
                     +functionsString.replace("do_nonlinearsolve(", QString("doNonLinearSolve(\"%1\", ").arg(address()))
                     +"\n";

        // Note: we rename do_nonlinearsolve() to doNonLinearSolve() because
        //       CellML's CIS service already defines do_nonlinearsolve(), yet
        //       we want to use our own non-linear solve routine defined in our
        //       Compiler plugin. Also, we add a new parameter to all our calls
        //       to doNonLinearSolve() so that doNonLinearSolve() can retrieve
        //       the correct instance of our NLA solver...
    }

    // Retrieve the body of the function that initialises constants and extract
    // the statements that are related to computed variables (since we want to
    // be able to recompute those whenever the user modifies a parameter)
    // Note: ideally, we wouldn't have to do that, but the CellML API doesn't
    //       distinguish between 'proper' and 'computed' constants...
    //       (See https://tracker.physiomeproject.org/show_bug.cgi?id=3499)

    static const QRegularExpression InitializationStatementRegEx = QRegularExpression("^(CONSTANTS|RATES|STATES)\\[\\d*\\] = [+-]?\\d*\\.?\\d+([eE][+-]?\\d+)?;$");

    QStringList initConstsList = cleanCode(genericCodeInformation->initConstsString()).split("\n");
    QString initConsts = QString();
    QString compCompConsts = QString();

    foreach (const QString &initConst, initConstsList) {
        // Add the statement either to our list of 'proper' constants or
        // 'computed' constants

        if (InitializationStatementRegEx.match(initConst).hasMatch())
            initConsts += (initConsts.isEmpty()?QString():"\n")+initConst;
        else
            compCompConsts += (compCompConsts.isEmpty()?QString():"\n")+initConst;
    }

    modelCode += functionCode("int initializeConstants(double *CONSTANTS, double *RATES, double *STATES)",
                              initConsts, true);
    modelCode += "\n";
    modelCode += functionCode("int computeComputedConstants(double *CONSTANTS, double *RATES, double *STATES)",
                              compCompConsts, true);
    modelCode += "\n";

    // Retrieve the body of the remaining functions

    if (mModelType == CellmlFileRuntime::Ode) {
        modelCode += functionCode("int computeOdeRates(double VOI, double *CONSTANTS, double *RATES, double *STATES, double *ALGEBRAIC)",
                                  cleanCode(mOdeCodeInformation->ratesString()));
        modelCode += "\n";
        modelCode += functionCode("int computeOdeVariables(double VOI, double *CONSTANTS, double *RATES, double *STATES, double *ALGEBRAIC)",
                                  cleanCode(genericCodeInformation->variablesString()));
    } else {
        modelCode += functionCode("int computeDaeEssentialVariables(double VOI, double *CONSTANTS, double *RATES, double *OLDRATES, double *STATES, double *OLDSTATES, double *ALGEBRAIC, double *CONDVAR)",
                                  cleanCode(mDaeCodeInformation->essentialVariablesString()));
        modelCode += "\n";
        modelCode += functionCode("int computeDaeResiduals(double VOI, double *CONSTANTS, double *RATES, double *OLDRATES, double *STATES, double *OLDSTATES, double *ALGEBRAIC, double *CONDVAR, double *resid)",
                                  cleanCode(mDaeCodeInformation->ratesString()));
        modelCode += "\n";
        modelCode += functionCode("int computeDaeRootInformation(double VOI, double *CONSTANTS, double *RATES, double *OLDRATES, double *STATES, double *OLDSTATES, double *ALGEBRAIC, double *CONDVAR)",
                                  cleanCode(mDaeCodeInformation->rootInformationString()));
        modelCode += functionCode("int computeDaeStateInformation(double *SI)",
                                  cleanCode(mDaeCodeInformation->stateInformationString()));
        modelCode += "\n";
        modelCode += functionCode("int computeDaeVariables(double VOI, double *CONSTANTS, double *RATES, double *STATES, double *ALGEBRAIC, double *CONDVAR)",
                                  cleanCode(genericCodeInformation->variablesString()));
    }

    // Check whether the model code contains a definite integral, otherwise
    // compute it and check that everything went fine

    if (modelCode.contains("defint(func")) {
        mIssues << CellmlFileIssue(CellmlFileIssue::Error,
                                   QObject::tr("definite integrals are not yet supported"));
    } else if (!mCompilerEngine->compileCode(modelCode)) {
        mIssues << CellmlFileIssue(CellmlFileIssue::Error,
                                   mCompilerEngine->error());
    }

    // Keep track of the ODE/DAE functions, but only if no issues were reported

    if (mIssues.count()) {
        reset(true, false);
    } else {
        // Add the symbol of any required external function, if any

        if (mAtLeastOneNlaSystem)
            llvm::sys::DynamicLibrary::AddSymbol("doNonLinearSolve",
                                                 (void *) (intptr_t) doNonLinearSolve);

        // Retrieve the ODE/DAE functions

        mInitializeConstants = (InitializeConstantsFunction) (intptr_t) mCompilerEngine->getFunction("initializeConstants");

        mComputeComputedConstants = (ComputeComputedConstantsFunction) (intptr_t) mCompilerEngine->getFunction("computeComputedConstants");

        if (mModelType == CellmlFileRuntime::Ode) {
            mComputeOdeRates     = (ComputeOdeRatesFunction) (intptr_t) mCompilerEngine->getFunction("computeOdeRates");
            mComputeOdeVariables = (ComputeOdeVariablesFunction) (intptr_t) mCompilerEngine->getFunction("computeOdeVariables");
        } else {
            mComputeDaeEssentialVariables = (ComputeDaeEssentialVariablesFunction) (intptr_t) mCompilerEngine->getFunction("computeDaeEssentialVariables");
            mComputeDaeResiduals          = (ComputeDaeResidualsFunction) (intptr_t) mCompilerEngine->getFunction("computeDaeResiduals");
            mComputeDaeRootInformation    = (ComputeDaeRootInformationFunction) (intptr_t) mCompilerEngine->getFunction("computeDaeRootInformation");
            mComputeDaeStateInformation   = (ComputeDaeStateInformationFunction) (intptr_t) mCompilerEngine->getFunction("computeDaeStateInformation");
            mComputeDaeVariables          = (ComputeDaeVariablesFunction) (intptr_t) mCompilerEngine->getFunction("computeDaeVariables");
        }

        // Make sure that we managed to retrieve all the ODE/DAE functions

        bool functionsOk =    mInitializeConstants
                           && mComputeComputedConstants;

        if (mModelType == CellmlFileRuntime::Ode) {
            functionsOk =    functionsOk
                          && mComputeOdeRates
                          && mComputeOdeVariables;
        } else {
            functionsOk =    functionsOk
                          && mComputeDaeEssentialVariables
                          && mComputeDaeResiduals
                          && mComputeDaeRootInformation
                          && mComputeDaeStateInformation
                          && mComputeDaeVariables;
        }

        if (!functionsOk) {
            mIssues << CellmlFileIssue(CellmlFileIssue::Error,
                                       QObject::tr("an unexpected problem occurred while trying to retrieve the model functions"));

            reset(true, false);
        }
    }
}
 ObjRef(const ObjRef<T>& aPtr)
 {
     mPtr = aPtr.getPointer();
     if (mPtr != NULL)
         mPtr->add_ref();
 }
template<class T, class U> bool
operator!=(const ObjRef<T>& lhs, const ObjRef<U>& rhs)
{
    return (lhs.getPointer() != rhs.getPointer());
}
QStringList CellmlFileRuntime::componentHierarchy(iface::cellml_api::CellMLElement *pElement)
{
    // Make sure that we have a given element

    if (!pElement)
        return QStringList();

    // Try to retrieve the component that owns the given element, unless the
    // given element is a component itself (which will be the case when we come
    // here through recursion)

    ObjRef<iface::cellml_api::CellMLComponent> component = QueryInterface(pElement);

    ObjRef<iface::cellml_api::CellMLElement> parent = pElement->parentElement();
    ObjRef<iface::cellml_api::CellMLComponent> parentComponent = QueryInterface(parent);

    if (!component && !parentComponent) {
        // The element isn't a component and neither is its parent, so it
        // doesn't have a hierarchy

        return QStringList();
    }

    // Check whether this is an imported component and, if so, retrieve its
    // imported name

    QString componentName = QString::fromStdWString(component?component->name():parentComponent->name());

    ObjRef<iface::cellml_api::CellMLElement> componentParent = component?component->parentElement():parentComponent->parentElement();
    ObjRef<iface::cellml_api::CellMLElement> componentParentParent = componentParent->parentElement();

    if (componentParentParent) {
        // The given element comes from or is an imported component, so go
        // through our different imported components and look for the one we are
        // after

        ObjRef<iface::cellml_api::CellMLImport> import = QueryInterface(componentParentParent);
        ObjRef<iface::cellml_api::ImportComponentSet> importComponents = import->components();
        ObjRef<iface::cellml_api::ImportComponentIterator> importComponentsIter = importComponents->iterateImportComponents();

        for (ObjRef<iface::cellml_api::ImportComponent> importComponent = importComponentsIter->nextImportComponent();
             importComponent; importComponent = importComponentsIter->nextImportComponent()) {
            if (!componentName.compare(QString::fromStdWString(importComponent->componentRef()))) {
                // This is the imported component we are after, so retrieve its
                // imported name

                componentName = QString::fromStdWString(importComponent->name());

                break;
            }
        }
    }

    // Recursively retrieve the component hierarchy of the given element's
    // encapsulation parent, if any

    ObjRef<iface::cellml_api::CellMLComponent> componentEncapsulationParent = component?component->encapsulationParent():parentComponent->encapsulationParent();

    return componentHierarchy(componentEncapsulationParent) << componentName;
}