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);
}
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();
}
std::string generateCodeForModel(CellmlApiObjects* capi,
                                 std::map<std::string, unsigned char>& variableTypes,
                                 std::map<std::string, std::map<unsigned char, int> >& variableIndices,
                                 int numberOfInputs, int numberOfStates)
{
    std::stringstream code;
    std::string codeString;
    if (! (capi && capi->codeInformation))
    {
        std::cerr << "CellML Model Definition::generateCodeForModel: missing model implementation?" << std::endl;
        return "";
    }
    // We need to regenerate the code information to make use of the flagged variables.
    ObjRef<iface::cellml_services::CodeGeneratorBootstrap> cgb = CreateCodeGeneratorBootstrap();
    ObjRef<iface::cellml_services::CodeGenerator> cg = cgb->createCodeGenerator();
    // catch any exceptions from the CellML API
    try
    {
        // annotate the source variables in the model with the code-names based on existing annotations
        for (unsigned int i=0; i < capi->cevas->length(); i++)
        {
            ObjRef<iface::cellml_services::ConnectedVariableSet> cvs = capi->cevas->getVariableSet(i);
            ObjRef<iface::cellml_api::CellMLVariable> sv = cvs->sourceVariable();
            std::string currentId = getVariableUniqueId(sv);
            std::map<std::string, unsigned char>::iterator typeit(variableTypes.find(currentId));
            if (typeit != variableTypes.end())
            {
                std::wstringstream ename;
                // here we assign an array and index based on the "primary" purpose of the variable. Later
                // we will add in secondary purposes.
                unsigned char vType = typeit->second;
                if (vType & csim::StateType)
                {
                    ename << L"CSIM_STATE[" << variableIndices[currentId][csim::StateType] << L"]";
                }
                else if (vType & csim::IndependentType)
                {
                    // do nothing, but stop input and output annotations
                }
                else if (vType & csim::InputType)
                {
                    ename << L"CSIM_INPUT[" << variableIndices[currentId][csim::InputType] << L"]";
                }
                else if (vType & csim::OutputType)
                {
                    ename << L"CSIM_OUTPUT[" << variableIndices[currentId][csim::OutputType] << L"]";
                }
                capi->annotations->setStringAnnotation(sv, L"expression", ename.str());

                if (vType & csim::StateType)
                {
                    ename.str(L"");
                    ename.clear();
                    ename << L"CSIM_RATE[" << variableIndices[currentId][csim::StateType] << L"]";
                    capi->annotations->setStringAnnotation(sv, L"expression_d1", ename.str());
                }
            }
        }
        cg->useCeVAS(capi->cevas);
        cg->useAnnoSet(capi->annotations);
        ObjRef<iface::cellml_services::CodeInformation> cci = cg->generateCode(capi->model);
        std::wstring m = cci->errorMessage();
        if (m != L"")
        {
            std::cerr << "CellML Model Definition::generateCodeForModel: error generating code?" << std::endl;
            return "";
        }
        iface::cellml_services::ModelConstraintLevel mcl = cci->constraintLevel();
        if (mcl == iface::cellml_services::UNDERCONSTRAINED)
        {
            std::cerr << "Model is underconstrained" << std::endl;
            return "";
        }
        else if (mcl == iface::cellml_services::OVERCONSTRAINED)
        {
            std::cerr << "Model is overconstrained" << std::endl;
            return "";
        }
        else if (mcl == iface::cellml_services::UNSUITABLY_CONSTRAINED)
        {
            std::cerr << "Model is unsuitably constrained" << std::endl;
            return "";
        }
        std::cout << "Model is correctly constrained" << std::endl;
        // create the code in the format we know how to handle
        code << "//#include <math.h>\n"
        /* required functions */
             << "double fabs(double x);\n"
             << "double acos(double x);\n"
             << "double acosh(double x);\n"
             << "double atan(double x);\n"
             << "double atanh(double x);\n"
             << "double asin(double x);\n"
             << "double asinh(double x);\n"
             << "double acos(double x);\n"
             << "double acosh(double x);\n"
             << "double asin(double x);\n"
             << "double asinh(double x);\n"
             << "double atan(double x);\n"
             << "double atanh(double x);\n"
             << "double ceil(double x);\n"
             << "double cos(double x);\n"
             << "double cosh(double x);\n"
             << "double tan(double x);\n"
             << "double tanh(double x);\n"
             << "double sin(double x);\n"
             << "double sinh(double x);\n"
             << "double exp(double x);\n"
             << "double floor(double x);\n"
             << "double pow(double x, double y);\n"
             << "double factorial(double x);\n"
             << "double log(double x);\n"
             << "double arbitrary_log(double x, double base);\n"
             << "double gcd_pair(double a, double b);\n"
             << "double lcm_pair(double a, double b);\n"
             << "double gcd_multi(unsigned int size, ...);\n"
             << "double lcm_multi(unsigned int size, ...);\n"
             << "double multi_min(unsigned int size, ...);\n"
             << "double multi_max(unsigned int size, ...);\n"
             << "void NR_MINIMISE(double(*func)"
                "(double VOI, double *C, double *R, double *S, double *A),"
                "double VOI, double *C, double *R, double *S, double *A, "
                "double *V);\n";
        std::wstring frag = cci->functionsString();
        code << ws2s(frag);

        int nAlgebraic = cci->algebraicIndexCount();
        int nConstants = cci->constantIndexCount();

        code << "\n\nvoid csim_rhs_routine(double VOI, double* CSIM_STATE, double* CSIM_RATE, double* CSIM_OUTPUT, "
             << "double* CSIM_INPUT)\n{\n\n"
             << "double DUMMY_ASSIGNMENT;\n"
             << "double CONSTANTS["
             << nConstants
             << "], ALGEBRAIC["
             << nAlgebraic
             << "];\n\n";

        /* initConsts - all variables which aren't state variables but have
         *              an initial_value attribute, and any variables & rates
         *              which follow.
         */
        code << ws2s(cci->initConstsString());

        /* rates      - All rates which are not static.
         */
        code << ws2s(cci->ratesString());

        /* variables  - All variables not computed by initConsts or rates
         *  (i.e., these are not required for the integration of the model and
         *   thus only need to be called for output or presentation or similar
         *   purposes)
         */
        code << ws2s(cci->variablesString());

        // add in the setting of any outputs that are not already defined
        for (unsigned int i=0; i < capi->cevas->length(); i++)
        {
            ObjRef<iface::cellml_services::ConnectedVariableSet> cvs = capi->cevas->getVariableSet(i);
            ObjRef<iface::cellml_api::CellMLVariable> sv = cvs->sourceVariable();
            std::string currentId = getVariableUniqueId(sv);
            std::map<std::string, unsigned char>::iterator typeit(variableTypes.find(currentId));
            if (typeit != variableTypes.end())
            {
                unsigned char vType = typeit->second;
                if (vType & csim::OutputType)
                {
                    if (vType & csim::StateType)
                        code << "CSIM_OUTPUT[" << variableIndices[currentId][csim::OutputType]
                                << "] = CSIM_STATE[" << variableIndices[currentId][csim::StateType]
                                   << "];\n";
                    else if (vType & csim::InputType)
                        code << "CSIM_OUTPUT[" << variableIndices[currentId][csim::OutputType]
                                << "] = CSIM_INPUT[" << variableIndices[currentId][csim::InputType]
                                   << "];\n";
                    else if (vType & csim::IndependentType)
                        code << "CSIM_OUTPUT[" << variableIndices[currentId][csim::OutputType]
                                << "] = VOI;\n";
                }
            }
        }

        // close the subroutine
        code << "\n\n}//csim_rhs_routine()\n\n";

        // and now clear out initialisation of state variables and known variables from
        // the RHS routine.
        codeString = clearCodeAssignments(code.str(), "CSIM_STATE", numberOfStates);
        codeString = clearCodeAssignments(codeString, "CSIM_INPUT", numberOfInputs);

        // and finally create the initialisation routine
        std::stringstream initRoutine;
        initRoutine << "\nvoid csim_initialise_routine(double* CSIM_STATE, double* CSIM_OUTPUT, double* CSIM_INPUT)\n{\n";
        // FIXME: this doesn't need to be in the interface?
        initRoutine << "double CSIM_RATES[" << numberOfStates << "];\n";
        initRoutine << "double CONSTANTS[" << nConstants << "];\n";
        initRoutine << ws2s(cci->initConstsString());
        initRoutine << "\n}\n";

        codeString += initRoutine.str();
    }
    catch (...)
    {
        std::cerr << "CellML Model Definition::generateCodeForModel: something went wrong generating code?" << std::endl;
        return "";
    }
    return codeString;
}
void SingleCellViewSimulationData::initialValuesIn()
{
    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());

    mState = SingleCellViewSimulationData::SIMSTATE_GOT_IV;

    if (mDidReset)
    {
      mInitialConstants.clear();
      mInitialConstants.reserve(codeInfo->constantIndexCount());
      mInitialStates.clear();
      mInitialStates.reserve(codeInfo->rateIndexCount());
    }

    mConstants.clear();
    mConstants.reserve(codeInfo->constantIndexCount());

    std::cout << "Computed " << mIVGrabber->consts().size() << " constants and "
              << mIVGrabber->states().size() << " initial values." << std::endl;
        

    for (std::vector<double>::iterator i = mIVGrabber->consts().begin();
         i != mIVGrabber->consts().end(); i++) {
        if (mDidReset)
            mInitialConstants << *i;
        mConstants << *i;
    }

    std::vector<double>& computedData = mIVGrabber->states();
    mStates.clear();
    mStates.reserve(codeInfo->rateIndexCount());
    for (unsigned int i = 0; i < codeInfo->rateIndexCount(); i++) {
        double v = computedData[1 + i];
        if (mDidReset)
            mInitialStates << v;
        mStates << v;
    }

    mRates.clear();
    mRates.reserve(codeInfo->rateIndexCount());
    const unsigned int rateOffset = codeInfo->rateIndexCount() + 1;
    for (unsigned int i = 0; i < codeInfo->rateIndexCount(); i++) {
      mRates << computedData[rateOffset + i];
    }
    
    mAlgebraic.clear();
    mAlgebraic.reserve(codeInfo->algebraicIndexCount());
    const unsigned int algebraicOffset = codeInfo->rateIndexCount() * 2 + 1;
    for (unsigned int i = 0; i < codeInfo->algebraicIndexCount(); i++) {
      mAlgebraic << computedData[algebraicOffset + i];
    }

    emit updated();
    emit modified(this, !mDidReset);
}