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::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]); }
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); }