Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: correct declarations when subscripted variable is initialized from data and constants #116

Merged
merged 14 commits into from
Sep 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
260 changes: 260 additions & 0 deletions models/directdata/directdata.dat
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,254 @@ j[A1,B2]
2048 180.5
2049 180.25
2050 180
l[A1,B1]
1990 610
1991 609.333
1992 608.667
1993 608
1994 607.333
1995 606.667
1996 606
1997 605.333
1998 604.667
1999 604
2000 603.333
2001 602.667
2002 602
2003 601.333
2004 600.667
2005 600
2006 599
2007 598
2008 597
2009 596
2010 595
2011 594
2012 593
2013 592
2014 591
2015 590
2016 590.2
2017 590.4
2018 590.6
2019 590.8
2020 591
2021 591.2
2022 591.4
2023 591.6
2024 591.8
2025 592
2026 592.2
2027 592.4
2028 592.6
2029 592.8
2030 593
2031 592.5
2032 592
2033 591.5
2034 591
2035 590.5
2036 590
2037 589.5
2038 589
2039 588.5
2040 588
2041 587.5
2042 587
2043 586.5
2044 586
2045 585.5
2046 585
2047 584.5
2048 584
2049 583.5
2050 583
l[A1,B2]
1990 210
1991 209.333
1992 208.667
1993 208
1994 207.333
1995 206.667
1996 206
1997 205.333
1998 204.667
1999 204
2000 203.333
2001 202.667
2002 202
2003 201.333
2004 200.667
2005 200
2006 199
2007 198
2008 197
2009 196
2010 195
2011 194
2012 193
2013 192
2014 191
2015 190
2016 189.667
2017 189.333
2018 189
2019 188.667
2020 188.333
2021 188
2022 187.667
2023 187.333
2024 187
2025 186.667
2026 186.333
2027 186
2028 185.667
2029 185.333
2030 185
2031 184.75
2032 184.5
2033 184.25
2034 184
2035 183.75
2036 183.5
2037 183.25
2038 183
2039 182.75
2040 182.5
2041 182.25
2042 182
2043 181.75
2044 181.5
2045 181.25
2046 181
2047 180.75
2048 180.5
2049 180.25
2050 180
l[A2,B1]
1990 0
1991 0
1992 0
1993 0
1994 0
1995 0
1996 0
1997 0
1998 0
1999 0
2000 0
2001 0
2002 0
2003 0
2004 0
2005 0
2006 0
2007 0
2008 0
2009 0
2010 0
2011 0
2012 0
2013 0
2014 0
2015 0
2016 0
2017 0
2018 0
2019 0
2020 0
2021 0
2022 0
2023 0
2024 0
2025 0
2026 0
2027 0
2028 0
2029 0
2030 0
2031 0
2032 0
2033 0
2034 0
2035 0
2036 0
2037 0
2038 0
2039 0
2040 0
2041 0
2042 0
2043 0
2044 0
2045 0
2046 0
2047 0
2048 0
2049 0
2050 0
l[A2,B2]
1990 0
1991 0
1992 0
1993 0
1994 0
1995 0
1996 0
1997 0
1998 0
1999 0
2000 0
2001 0
2002 0
2003 0
2004 0
2005 0
2006 0
2007 0
2008 0
2009 0
2010 0
2011 0
2012 0
2013 0
2014 0
2015 0
2016 0
2017 0
2018 0
2019 0
2020 0
2021 0
2022 0
2023 0
2024 0
2025 0
2026 0
2027 0
2028 0
2029 0
2030 0
2031 0
2032 0
2033 0
2034 0
2035 0
2036 0
2037 0
2038 0
2039 0
2040 0
2041 0
2042 0
2043 0
2044 0
2045 0
2046 0
2047 0
2048 0
2049 0
2050 0
SAVEPER
1990 1
1991 1
Expand Down Expand Up @@ -626,3 +874,15 @@ i[A1,B2]
2015 190
2030 185
2050 180
k[A1,B1]
1990 610
2005 600
2015 590
2030 593
2050 583
k[A1,B2]
1990 210
2005 200
2015 190
2030 185
2050 180
8 changes: 6 additions & 2 deletions models/directdata/directdata.mdl
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,20 @@ i[A1, DimB] = GET DIRECT DATA('e_data.csv', ',', 'A', 'B2')
|
j[A1, DimB] = i[A1, DimB] ~~~:SUPPLEMENTARY|

k[A1, DimB] = GET DIRECT DATA('e_data.csv', ',', 'A', 'B2') ~~|
k[A2, DimB] = 0 ~~|
l[DimA, DimB] = k[DimA, DimB] ~~|

********************************************************
.Control
********************************************************~
Simulation Control Parameters
|

FINAL TIME = 2050 ~~|
INITIAL TIME = 1990 ~~|
SAVEPER = TIME STEP ~~|
FINAL TIME = 2050 ~~|
TIME STEP = 1 ~~|
SAVEPER = TIME STEP ~~|

\\\---/// Sketch information - do not modify anything except names
V300 Do not put anything below this section - it will be ignored
Expand Down
28 changes: 21 additions & 7 deletions src/EquationGen.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,16 @@ export default class EquationGen extends ModelReader {
generate() {
// Generate code for the variable in either init or eval mode.
if (this.var.isData()) {
if (this.var.directDataArgs) {
return this.generateDirectDataInit()
} else {
return this.generateExternalDataInit()
// If the data var was converted from a const, it will have lookup points.
// Otherwise, read a data file to get lookup data.
if (R.isEmpty(this.var.points)) {
if (this.var.directDataArgs) {
return this.generateDirectDataInit()
} else {
return this.generateExternalDataInit()
}
} else if (this.mode === 'decl') {
return
}
}
if (this.var.isLookup()) {
Expand Down Expand Up @@ -196,7 +202,6 @@ export default class EquationGen extends ModelReader {
}
return value
}

lookupDataNameGen(subscripts) {
// Construct a name for the static data array associated with a lookup variable.
return R.map(subscript => {
Expand Down Expand Up @@ -354,7 +359,6 @@ export default class EquationGen extends ModelReader {
return []
}
}

generateDirectDataInit() {
// If direct data exists for this variable, copy it from the workbook into one or more lookups.
let result = []
Expand Down Expand Up @@ -588,10 +592,20 @@ export default class EquationGen extends ModelReader {
}
return result
}

//
// Visitor callbacks
//
visitEquation(ctx) {
if (this.var.isData() && !R.isEmpty(this.var.points)) {
if (this.mode === 'init-lookups') {
// If the var already has lookup data points, use those instead of reading them from a file.
let lookupData = R.reduce((a, p) => listConcat(a, `${cdbl(p[0])}, ${cdbl(p[1])}`, true), '', this.var.points)
this.emit(`__new_lookup(${this.var.points.length}, /*copy=*/true, (double[]){ ${lookupData} });`)
}
} else {
super.visitEquation(ctx)
}
}
visitCall(ctx) {
// Convert the function name from Vensim to C format and push it onto the function name stack.
// This maintains the name of the current function as its arguments are visited.
Expand Down
26 changes: 25 additions & 1 deletion src/Model.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ function read(parseTree, spec, extData, directData, modelDirname) {
checkSpecVars(spec, extData)
// Remove variables that are not referenced by an input or output variable.
removeUnusedVariables(spec)
// Resolve duplicate declarations by converting to one variable type.
resolveDuplicateDeclarations()
}
function readSubscriptRanges(tree, dimensionFamilies, indexFamilies, modelDirname) {
// Read subscript ranges from the model.
Expand Down Expand Up @@ -372,7 +374,29 @@ function removeUnusedVariables(spec) {
varsForName.push(v)
}
}

function resolveDuplicateDeclarations() {
// Find subscripted const vars where some subscripts are data vars.
// TODO consider doing the same for lookup vars
// Least and greatest safe double values in C rounded to convenient consts
const MIN_SAFE_DBL = -1e308
const MAX_SAFE_DBL = 1e308
let data = dataVars()
for (let constVar of constVars()) {
if (data.find(d => d.varName === constVar.varName)) {
// Change the var type from const to data and add lookup data points.
// For a constant, the equivalent lookup has the same value over the entire x axis.
let value = parseFloat(constVar.modelFormula)
if (isNaN(value)) {
console.error(`The value for const var ${constVar.refId} converted to a lookup is NaN.`)
}
constVar.varType = 'data'
constVar.points = [
[MIN_SAFE_DBL, value],
[MAX_SAFE_DBL, value]
]
}
}
}
//
// Analysis helpers
//
Expand Down