Skip to content

Commit

Permalink
-Added register of unit weights for unit parsing to handle individual…
Browse files Browse the repository at this point in the history
… weight settings for each component.

git-svn-id: https://openmodelica.org/svn/OpenModelica/branches/MathCoreOSMC@4182 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
Peter Aronsson committed Aug 24, 2009
1 parent ad4fc72 commit 1be2b65
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 29 deletions.
9 changes: 9 additions & 0 deletions Compiler/DAE.mo
Expand Up @@ -367,6 +367,15 @@ matchcontinue (bindExp,attr)
end matchcontinue;
end addEquationBoundString;

public function getClassList "get list of classes from Var"
input Element v;
output list<Absyn.Path> lst;
algorithm
lst := matchcontinue(v)
case(VAR(pathLst = lst)) then lst;
end matchcontinue;
end getClassList;

public function getBoundStartEquation ""
input VariableAttributes attr;
output Exp.Exp oe;
Expand Down
22 changes: 15 additions & 7 deletions Compiler/Inst.mo
Expand Up @@ -148,6 +148,7 @@ protected import HashTable5;
protected import MMath;
protected import UnitAbsynBuilder;
protected import UnitChecker;
protected import UnitParserExt;

public import UnitAbsyn;

Expand Down Expand Up @@ -1808,6 +1809,7 @@ algorithm
re,prot,inst_dims,impl,graph,instSingleCref)
local list<Mod> tmpModList;
equation
UnitParserExt.checkpoint();
//print(" Instclassdef for: " +& Prefix.printPrefixStr(pre) +& "." +& className +& " mods: " +& Mod.printModStr(mods)+& "\n");
ci_state1 = ClassInf.trans(ci_state, ClassInf.NEWDEF());
els = extractConstantPlusDeps(els,instSingleCref,{},className);
Expand Down Expand Up @@ -1865,6 +1867,7 @@ algorithm
cdefelts_1 = addNomod(cdefelts);
compelts_2 = Util.listFlatten({compelts_2,compelts_1, cdefelts_1});
//Instantiate components


compelts_2_elem = Util.listMap(compelts_2,Util.tuple21);
checkMods = Mod.merge(mods,emods,env4,Prefix.NOPRE());
Expand Down Expand Up @@ -1901,18 +1904,23 @@ algorithm
// but bindings on scalar variables must be considered, therefore passing dae1 separately
(store,ut)= UnitAbsynBuilder.instBuildUnitTerms(env,Util.listFlatten({daetemp,dae2,dae3,dae4,dae5}),dae1,store);

print("built store for "+&className+&"\n");
UnitAbsynBuilder.printInstStore(store);
print("terms for "+&className+&"\n");
UnitAbsynBuilder.printTerms(ut);
//print("built store for "+&className+&"\n");
//UnitAbsynBuilder.printInstStore(store);
//print("terms for "+&className+&"\n");
//UnitAbsynBuilder.printTerms(ut);

UnitAbsynBuilder.registerUnitWeights(cache,env,dae1);

// perform the check
(res,st3) = UnitChecker.check(ut,UnitAbsynBuilder.instGetStore(store));
// updates store so higher up in instance hierarchy can use the results
store = UnitAbsynBuilder.updateInstStore(store,st3);

print("store for "+&className+&"\n");
UnitAbsynBuilder.printInstStore(store);
print("dae1="+&DAE.dumpDebugDAE(DAE.DAE(dae1))+&"\n");
//print("store for "+&className+&"\n");
//UnitAbsynBuilder.printInstStore(store);
//print("dae1="+&DAE.dumpDebugDAE(DAE.DAE(dae1))+&"\n");
UnitParserExt.rollback();
//print("rollback for "+&className+&"\n");
then
(cache,dae,env5,store,csets5,ci_state6,tys,NONE/* no basictype bc*/,NONE,equalityConstraint,graph);

Expand Down
55 changes: 50 additions & 5 deletions Compiler/UnitAbsynBuilder.mo
Expand Up @@ -24,15 +24,60 @@ protected import OptManager;
protected import Interactive;
protected import SCode;

public function registerUnitWeights "traverses all dae variables and adjusts weights depending on defineunits defined
in the scopes of the classLst for each variable"
input Env.Cache cache;
input Env.Env env;
input list<DAE.Element> dae;
protected
list<Absyn.Path> paths; list<SCode.Element> du;
algorithm
paths := Util.listListUnion(Util.listMap(DAE.getMatchingElements(dae,DAE.isVar),DAE.getClassList));
du := Util.listListUnion(Util.listMap1(paths,retrieveUnitsFromEnv,(cache,env)));
registerUnitWeightDefineunits(du);
end registerUnitWeights;

protected function retrieveUnitsFromEnv "help function to registerUnitWeights"
input Absyn.Path p;
input tuple<Env.Cache,Env.Env> tpl;
output list<SCode.Element> du;

algorithm
du := matchcontinue(p,tpl) local
Env.Env env; list<SCode.Element> du;
case(p,tpl) equation
(_,_,env as Env.FRAME(defineUnits = du)::_) = Lookup.lookupClass(Util.tuple21(tpl),Util.tuple22(tpl),p,false);
then du;
case(p,tpl) then {};
end matchcontinue;
end retrieveUnitsFromEnv;

protected function registerUnitWeightDefineunits "help function to registerUnitWeightForClass"
input list<SCode.Element> du;
algorithm
_ := matchcontinue(du)
local String n; Real w;
case(SCode.DEFINEUNIT(name=n,weight = SOME(w))::du) equation
UnitParserExt.registerWeight(n,w);
registerUnitWeightDefineunits(du);
then ();
case(SCode.DEFINEUNIT(name=n,weight = NONE)::du) equation
registerUnitWeightDefineunits(du);
then ();
case(_::du) equation
registerUnitWeightDefineunits(du);
then ();
case({}) then ();

end matchcontinue;
end registerUnitWeightDefineunits;

public function registerUnits "traverses the Absyn.Program and registers all defineunits.
Note: this requires that instantiation is done on a 'total program', so only defineunits that
are referenced in the model are picked up
"
input Absyn.Program prg;
algorithm
print("registerUnits called\n");
((_,_,_)) := Interactive.traverseClasses(prg,NONE,registerUnitInClass,0,false); // defineunits must be in public section.
end registerUnits;

Expand Down Expand Up @@ -64,15 +109,15 @@ algorithm
String exp; Real weight;
case({}) then ();
/* Derived unit with weigth */
case((du as Absyn.DEFINEUNIT(name=_))::elts) equation
{SCode.DEFINEUNIT(name,SOME(exp),SOME(weight))} = SCode.elabElement(du,false);
/*case((du as Absyn.DEFINEUNIT(name=_))::elts) equation
{SCode.DEFINEUNIT(name,SOME(exp),_)} = SCode.elabElement(du,false);
UnitParserExt.addDerivedWeight(name,exp,weight);
registerDefineunits(elts);
then ();
then ();*/

/* Derived unit without weigth */
case((du as Absyn.DEFINEUNIT(name=_))::elts) equation
{SCode.DEFINEUNIT(name,SOME(exp),NONE)} = SCode.elabElement(du,false);
{SCode.DEFINEUNIT(name,SOME(exp),_)} = SCode.elabElement(du,false);
UnitParserExt.addDerived(name,exp);
registerDefineunits(elts);
then ();
Expand Down
15 changes: 15 additions & 0 deletions Compiler/UnitParserExt.mo
Expand Up @@ -36,6 +36,13 @@ public function addBase "adds a base unit without weight"
external "C";
end addBase;

public function registerWeight "registers a weight to be multiplied with the weigth factor of a derived unit"
input String name;
input Real weight;
external "C";
end registerWeight;


public function addDerived "adds a derived unit without weight"
input String name;
input String exp;
Expand All @@ -49,6 +56,14 @@ public function addDerivedWeight "adds a derived unit with weight"
external "C";
end addDerivedWeight;

public function checkpoint "copies all unitparser information to allow changing unit weights locally for a component"
external "C";
end checkPoint;

public function rollback "rollback the copy made in checkPoint call"
external "C";
end rollback;

public function clear "clears the unitparser from stored units"
external "C";
end clear;
Expand Down
28 changes: 14 additions & 14 deletions Compiler/runtime/unitparser.cpp
Expand Up @@ -32,7 +32,7 @@
#include "unitparser.h"
#include <iostream>
#include <sstream>
#ifndef NO_LPLIB
#ifndef NO_LPLIB
#include "lp_lib.h"
#endif

Expand All @@ -53,7 +53,7 @@ Rational::Rational(long numerator, long denominator)
* of ambiguity that needs to be adressed. */
void Rational::rationalize(double r)
{
#ifndef NO_LPLIB
#ifndef NO_LPLIB
const double eps = 1e-6;
double rapp;
long numerator=(long)r;
Expand Down Expand Up @@ -353,9 +353,9 @@ UnitRes UnitParser::addDerivedInternal(const string quantityName, const string u
u.unitSymbol = unitSymbol;
u.prefixAllowed = prefixAllowed;
u.prefixExpo = prefixExpo;
u.scaleFactor = scaleFactor;
u.scaleFactor = scaleFactor;
u.offset = offset;
u.weight = weight;
u.weight = weight;

map<string,Unit>::iterator p = _units.find(unitSymbol);
// Unit already defined?
Expand All @@ -368,11 +368,11 @@ UnitRes UnitParser::addDerivedInternal(const string quantityName, const string u
if(u.equalNoWeight((*p).second)){
Unit u2 =_units[unitSymbol];
u2.weight *= weight;
_units[unitSymbol] = u2;
_units[unitSymbol] = u2;
}
else
return UnitRes(UnitRes::UNITS_DEFINED_WITH_DIFFERENT_EXPR);
}
}
return res;
}

Expand All @@ -383,7 +383,7 @@ void UnitParser::accumulateWeight(const string unitSymbol, double weight)
{
Unit u2 =_units[unitSymbol];
u2.weight *= weight;
_units[unitSymbol] = u2;
_units[unitSymbol] = u2;
}
}

Expand Down Expand Up @@ -421,7 +421,7 @@ string UnitParser::prettyPrintUnit2str(Unit unit)

Unit UnitParser::solveMIP(Unit unit)
{
#ifndef NO_LPLIB
#ifndef NO_LPLIB
int numBaseUnits = _base.size();
int numDerivedUnits=0;
// Counting the derived units by traversing all units
Expand Down Expand Up @@ -500,7 +500,7 @@ Unit UnitParser::solveMIP(Unit unit)
int c2;
/* element 0..numBaseUnits-1*/
for (c2=0; c2 < numBaseUnits;c2++ ) {
double cost=0;
double cost=1;
for (int r2=0; r2 < numBaseUnits; r2++) {
double b = r2 < unit.unitVec.size() ? unit.unitVec[r2].toReal() : 0.0;
cost+= fabs(b - (c2==r2?1:0));
Expand All @@ -512,7 +512,7 @@ Unit UnitParser::solveMIP(Unit unit)
/* elements numBaseUnits .. NU -1 */
c2=numBaseUnits;
for(map<string,Unit>::iterator it=_units.begin(); it != _units.end(); it++) {
double cost=0;
double cost=1;
Unit u = it->second;
if (!u.isBaseUnit()) {
for(int r2=0; r2 < numBaseUnits; r2++) {
Expand All @@ -528,7 +528,7 @@ Unit UnitParser::solveMIP(Unit unit)
}
/* elements NU .. NU+numBaseUnits-1 */
for (int c2=0; c2 < numBaseUnits;c2++ ) {
double cost=0;
double cost=1;
for (int r2=0; r2 < numBaseUnits; r2++) {
double b = r2 < unit.unitVec.size() ? unit.unitVec[r2].toReal() : 0.0;
cost+= fabs(b - (c2==r2?-1:0));
Expand All @@ -540,7 +540,7 @@ Unit UnitParser::solveMIP(Unit unit)
/* elements NU+numBaseUnits .. 2*NU -1 */
c2=numBaseUnits;
for(map<string,Unit>::iterator it=_units.begin(); it != _units.end(); it++) {
double cost=0;
double cost=1;
Unit u = it->second;
if (!u.isBaseUnit()) {
for(int r2=0; r2 < numBaseUnits; r2++) {
Expand Down Expand Up @@ -597,7 +597,7 @@ Unit UnitParser::solveMIP(Unit unit)
prettyUnit.unitVec.push_back(r);
}
}
//cerr << "resulting unit =" << unit2str(prettyUnit) << endl;
//cout << "resulting unit =" << unit2str(prettyUnit) << endl;
retVal = prettyUnit;
} else {
retVal = unit;
Expand All @@ -606,7 +606,7 @@ Unit UnitParser::solveMIP(Unit unit)
delete row;
delete colno;
return retVal;
#else
#else
return unit;
#endif
}
Expand Down
49 changes: 46 additions & 3 deletions Compiler/runtime/unitparserext.cpp
@@ -1,10 +1,18 @@
/* External interface for UnitParserExt module */
#include "unitparser.h"

#include <stack>
using namespace std;



UnitParser* unitParser=0;

stack<UnitParser*> rollbackStack;

#include <iostream>
#include <string>
#include <stack>

using namespace std;

Expand All @@ -27,6 +35,31 @@ RML_BEGIN_LABEL(UnitParserExt__initSIUnits)
}
RML_END_LABEL

RML_BEGIN_LABEL(UnitParserExt__checkpoint)
{
UnitParser *copy = new UnitParser(*unitParser);
rollbackStack.push(unitParser);
unitParser = copy;
RML_TAILCALLK(rmlSC);
}
RML_END_LABEL


RML_BEGIN_LABEL(UnitParserExt__rollback)
{
if (rollbackStack.size() == 0) {
cerr << "Error, rollback on empty stack" << endl;
RML_TAILCALLK(rmlFC);
}
UnitParser * old = rollbackStack.top();
rollbackStack.pop();
delete unitParser;
unitParser=old;
RML_TAILCALLK(rmlSC);
}
RML_END_LABEL


RML_BEGIN_LABEL(UnitParserExt__clear)
{
if (unitParser) delete unitParser;
Expand All @@ -43,10 +76,20 @@ RML_BEGIN_LABEL(UnitParserExt__commit)
RML_END_LABEL


RML_BEGIN_LABEL(UnitParserExt__registerWeight)
{
char * name = RML_STRINGDATA(rmlA0);
double w = rml_prim_get_real(rmlA1);
//cout << "registerWeight(" << name << ", "<<w <<")"<<endl;
unitParser->accumulateWeight(name,w);
RML_TAILCALLK(rmlSC);
}
RML_END_LABEL

RML_BEGIN_LABEL(UnitParserExt__addBase)
{
char * name = (char*) RML_STRINGDATA(rmlA0);
cout << "addBase(" << name << ")"<<endl;
//cout << "addBase(" << name << ")"<<endl;
if (strcmp(name,"kg")==0) {
unitParser->addBase("","",name,false);
} else {
Expand All @@ -60,7 +103,7 @@ RML_BEGIN_LABEL(UnitParserExt__addDerived)
{
char * name = (char*) RML_STRINGDATA(rmlA0);
char * exp = (char*) RML_STRINGDATA(rmlA1);
cout << "addDerived(" << name << ", "<<exp << ")" << endl;
//cout << "addDerived(" << name << ", "<<exp << ")" << endl;
unitParser->addDerived(name,name,name,exp,Rational(0),Rational(1),Rational(0),true);
RML_TAILCALLK(rmlSC);
}
Expand All @@ -71,7 +114,7 @@ RML_BEGIN_LABEL(UnitParserExt__addDerivedWeight)
char * name = (char*) RML_STRINGDATA(rmlA0);
char * exp = (char*) RML_STRINGDATA(rmlA1);
double w = rml_prim_get_real(rmlA2);
cout << "addDerived(" << name << ", "<<exp << ", " << w << ")"<< endl;
//cout << "addDerived(" << name << ", "<<exp << ", " << w << ")"<< endl;
unitParser->addDerived(name,name,name,exp,Rational(0),Rational(1),Rational(0),true,w);
RML_TAILCALLK(rmlSC);
}
Expand Down

0 comments on commit 1be2b65

Please sign in to comment.