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(); }
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()); } }