27 #include <boost/locale.hpp>    29 using boost::locale::conv::utf_to_utf;
    35     string readToken(istream& mdlFile, 
char delim, 
bool appendDelim=
false)
    40         if (c[0]==delim || c[0]==
'~' || c[0]==
'|')
    53           if (mdlFile>>
GetUtf8Char(c) &&  (c[0]==
'\n'||c[0]==
'\r'))
    64     {
return c>0x7f || isalnum(c) || c==
'\'' || c==
'$';}
    72       auto xx=utf_to_utf<uint32_t>(x);
    73       basic_string<uint32_t> result;
    75       bool quoted=
false, lastWS=
false, inIdentifier=
false;
    78           if (i==
'"' &&lastNonWS!=
'\\')
    83               if (!inIdentifier && result.back()==
'.')
    84                 result.erase(result.end()-1);
    88           if (!quoted && !inIdentifier && isalpha(i))
    90           if (!quoted && inIdentifier && !
identifierChar(i) && !isspace(i) && i!=
'_')
    93               if (result.back()==
'.')
    94                 result.erase(result.end()-1);
    98           if (!isspace(i) && i!=
'_')
   102               basic_string<uint32_t> exprTkGoodChar;
   104                 exprTkGoodChar=utf_to_utf<uint32_t>(
".u"+to_string(i)+
".");
   113                     result+=exprTkGoodChar;
   120                       result+=exprTkGoodChar;
   126                   result+=exprTkGoodChar;
   133       return utf_to_utf<char>(result);
   144       {
"arccos",{
"(x)",
"acos(x)"}},
   145       {
"arcsin",{
"(x)",
"asin(x)"}},
   146       {
"arctan",{
"(x)",
"atan(x)"}},
   147       {
"gammaLn",{
"(x)",
"gammaLn(x)"}},
   148       {
"integer",{
"(x)",
"floor(x)"}},
   149       {
"ifThenElse",{
"(x,y,z)",
"x? y: z"}},
   150       {
"ln",{
"(x)",
"log(x)"}},
   151       {
"log",{
"(x,y)",
"log(x)/log(y)"}},
   152       {
"modulo",{
"(x,y)",
"x%y"}},
   153       {
"power",{
"(x,y)",
"x^y"}},
   154       {
"pulse",{
"(x,y)",
"(time>=x)*(time<x+y)"}},
   155       {
"pulseTrain",{
"(s,b,r,e)",
"tm:=time%r; (time<e)*(time>=s)*(tm<((s+b)%r))*(tm>=(s%r))"}},
   156       {
"quantum",{
"(x,y)",
"floor(x/y)"}},
   157       {
"ramp",{
"(s,a,b)",
"var t1:=min(a,b); var t2:=max(a,b); (clamp(t1,time,t2)-t1)*s"}},
   158       {
"step",{
"(x,y)",
"y*(time>=x)"}},
   159       {
"xidz",{
"(x,y,z)",
"var r:=y/z; isfinite(r)? r: x"}},
   160       {
"zidz",{
"(x,y)",
"var r:=y/z; isfinite(r)? r:0"}}
   164     regex 
identifier(R
"([A-Za-z][A-Za-z0-9._]*[A-Za-z0-9_])");   171           const VariablePtr rhs(VariableBase::flow, definition);
   174             group.addWire(rhs->ports(0).lock(), port);
   179       group.addItem(
function); 
   180       for (
auto& i: function->symbolNames())
   190         group.addWire(function->ports(0), port);
   195       const regex lookupPairsPattern(R
"((\[[^\]]*\],)?(\(.*\)))");   197       map<double,double> xData;   198       if (regex_match(data,match,lookupPairsPattern))
   200           const regex extractHead(R
"(\(([^,]*),([^)]*)\)(,(\(.*\)))*)");   202           for (
auto d=match[2].
str(); regex_match(d, match, extractHead); d=match[4])
   203             xData[stod(match[1])]=stod(match[2]);
   207           vector<double> xyData;
   208           for (
size_t offs=0; offs<data.size(); ++offs)
   209             xyData.push_back(stod(data.substr(offs),&offs));
   210           if (xyData.size()%2!=0)
   211             throw runtime_error(
"Odd amount of data specified");
   212           for (
size_t i=0; i<xyData.size()/2; ++i)
   213             xData[xyData[i]]=xyData[i+xyData.size()/2];
   215       auto f=make_shared<Group>();
   219       const VariablePtr dataVar(VariableType::flow,
"data");
   221       dataVar->moveTo(
f->x()-50,
f->y()-20);
   224       gather->moveTo(
f->x()+30,
f->y()-10);
   225       const VariablePtr inVar(VariableType::flow,
"in"), outVar(VariableType::flow,
"out");
   228       f->inVariables.push_back(inVar);
   229       f->outVariables.push_back(outVar);
   230       f->addWire(*dataVar, *gather, 1);
   231       f->addWire(*
f->inVariables[0], *gather, 2);
   232       f->addWire(*gather, *
f->outVariables[0], 1);
   234       XVector xVals(
"0",{Dimension::value,
""});
   235       auto& tensorInit=dataVar->vValue()->tensorInit;
   237         xVals.push_back(i.first);
   238       Hypercube hc; hc.xvectors.push_back(std::move(xVals));
   239       tensorInit.hypercube(std::move(hc));
   241       assert(tensorInit.size()==xData.size());
   242       auto j=tensorInit.begin();
   246       *dataVar->vValue()=tensorInit;
   252     set<string> integrationVariables;
   253     const regex integ(R
"(\s*integ\s*\(([^,]*),([^,]*)\))");   254     const regex number(R
"(\d*\.?\d+[Ee]?\d*)");   255     const regex unitFieldPattern(R
"(([^\[\]]*)(\[.*\])?)");   256     const regex sliderSpecPattern(R
"(\[([^,]*),?([^,]*),?([^,]*)\])");   257     const regex lookupPattern(R
"(([^(]*)\((.*)\))");   262     string currentMDLGroup;
   265         if (isspace(c[0])) 
continue;
   271               throw runtime_error(
"only UTF-8 file encoding is supported");
   290         string nameStr=
readToken(mdlFile,
'=',
true );
   291         const string name=
collapseWS(
trimWS(c+nameStr.substr(0,nameStr.length()-1)));
   292         if (name.substr(0,9)==R
"(\\\---///)")   295         if (nameStr.back()==
'=')
   298         switch (definition[0])
   301             definition.erase(definition.begin());
   307         regex_match(unitField,match,unitFieldPattern);
   308         const string units=
trimWS(match[1]);
   316         if (currentMDLGroup==
".Control")
   318             if (name==
"timeStep")
   321                 if (regex_match(definition,match,number))
   322                   simParms.
stepMax=stod(definition);
   324             if (!regex_match(definition,match,number)) 
continue;
   325             if (name==
"initialTime") simParms.
t0=stod(definition);
   326             if (name==
"finalTime") simParms.
tmax=stod(definition);
   329         if (regex_match(name,match,lookupPattern))
   331         else if (regex_match(definition,match,integ))
   333             auto intOp=
new IntOp;
   334             group.addItem(intOp);
   335             intOp->description(name);
   336             intOp->detailedText(comments);
   337             auto& v=intOp->intVar;
   338             integrationVariables.insert(name);
   339             auto integrand=match[1].str();
   342             auto init=match[2].str();
   355             v->detailedText(comments);
   358         else if (regex_match(definition,match,number))
   360             const VariablePtr v(VariableBase::parameter, name);
   368             v->detailedText(comments);
   369             if (
auto vv=v->vValue())
   371                 if (regex_match(sliderSpec,match,sliderSpecPattern))
   374                     for (
size_t i=1; i<=match.size(); ++i) spec.push_back(match[i]);
   375                     if (!spec.empty() && regex_match(spec[0],match,number))
   376                       vv->sliderMin=stod(spec[0]);
   378                       vv->sliderMin=0.1*stod(definition);
   379                     if (spec.size()>1 && regex_match(spec[1],match,number))
   380                       vv->sliderMax=stod(spec[1]);
   382                       vv->sliderMax=10*stod(definition);
   383                     if (spec.size()>2 && regex_match(spec[2],match,number))
   384                       vv->sliderStep=stod(spec[2]);
   386                 vv->adjustSliderBounds();
   399             v->detailedText(comments);
 
shared_ptr class for polymorphic operation objects. Note, you may assume that this pointer is always ...
 
string readToken(istream &mdlFile, char delim, bool appendDelim=false)
 
map< string, FunctionDef > venSimFunctions
 
set< string > functionsAdded
 
void readMdl(Group &group, Simulation &simParms, istream &mdlFile)
import a Vensim mdl file into group, also populating simParms from the control block ...
 
std::string trimWS(const std::string &s)
 
std::string str(T x)
utility function to create a string representation of a numeric type 
 
void defineLookupFunction(Group &group, const std::string &name, const std::string &data)
 
void addDefinitionToPort(Group &group, const shared_ptr< Port > &port, const string &name, const string &definition)
 
string collapseWS(const string &x)
 
bool identifierChar(int c)
 
regex identifier(R"([A-Za-z][A-Za-z0-9._]*[A-Za-z0-9_])")