Skip to content

Commit e93101e

Browse files
feat: implement DEPRECIATE STRAIGHTLINE (#264)
Fixes #258
1 parent 260a872 commit e93101e

9 files changed

Lines changed: 387 additions & 3 deletions

File tree

models/depreciate/depreciate.dat

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
Capacity Cost
2+
2020 1e+06
3+
Depreciated Amount
4+
2020 0
5+
2021 0
6+
2022 5e+07
7+
2023 5e+07
8+
2024 5e+07
9+
2025 5e+07
10+
2026 1.75e+08
11+
2027 1.75e+08
12+
2028 1.75e+08
13+
2029 1.75e+08
14+
2030 1.75e+08
15+
2031 1.75e+08
16+
2032 1.75e+08
17+
2033 1.75e+08
18+
2034 1.75e+08
19+
2035 1.75e+08
20+
2036 1.75e+08
21+
2037 1.75e+08
22+
2038 1.75e+08
23+
2039 1.75e+08
24+
2040 1.75e+08
25+
2041 1.75e+08
26+
2042 1.25e+08
27+
2043 1.25e+08
28+
2044 1.25e+08
29+
2045 1.25e+08
30+
2046 0
31+
2047 0
32+
2048 0
33+
2049 0
34+
2050 0
35+
dtime
36+
2020 20
37+
FINAL TIME
38+
2020 2050
39+
INITIAL TIME
40+
2020 2020
41+
New Capacity
42+
2020 0
43+
2021 0
44+
2022 1000
45+
2023 0
46+
2024 0
47+
2025 0
48+
2026 2500
49+
2027 0
50+
2028 0
51+
2029 0
52+
2030 0
53+
2031 0
54+
2032 0
55+
2033 0
56+
2034 0
57+
2035 0
58+
2036 0
59+
2037 0
60+
2038 0
61+
2039 0
62+
2040 0
63+
2041 0
64+
2042 0
65+
2043 0
66+
2044 0
67+
2045 0
68+
2046 0
69+
2047 0
70+
2048 0
71+
2049 0
72+
2050 0
73+
SAVEPER
74+
2020 1
75+
2021 1
76+
2022 1
77+
2023 1
78+
2024 1
79+
2025 1
80+
2026 1
81+
2027 1
82+
2028 1
83+
2029 1
84+
2030 1
85+
2031 1
86+
2032 1
87+
2033 1
88+
2034 1
89+
2035 1
90+
2036 1
91+
2037 1
92+
2038 1
93+
2039 1
94+
2040 1
95+
2041 1
96+
2042 1
97+
2043 1
98+
2044 1
99+
2045 1
100+
2046 1
101+
2047 1
102+
2048 1
103+
2049 1
104+
2050 1
105+
str
106+
2020 0
107+
2021 0
108+
2022 1e+09
109+
2023 0
110+
2024 0
111+
2025 0
112+
2026 2.5e+09
113+
2027 0
114+
2028 0
115+
2029 0
116+
2030 0
117+
2031 0
118+
2032 0
119+
2033 0
120+
2034 0
121+
2035 0
122+
2036 0
123+
2037 0
124+
2038 0
125+
2039 0
126+
2040 0
127+
2041 0
128+
2042 0
129+
2043 0
130+
2044 0
131+
2045 0
132+
2046 0
133+
2047 0
134+
2048 0
135+
2049 0
136+
2050 0
137+
TIME STEP
138+
2020 1

models/depreciate/depreciate.mdl

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
{UTF-8}
2+
dtime=
3+
20
4+
~
5+
~ |
6+
7+
Capacity Cost=
8+
1e+06
9+
~ $/MW
10+
~ |
11+
12+
New Capacity=
13+
IF THEN ELSE (Time = 2022, 1000, IF THEN ELSE(Time = 2026,2500,0))
14+
~ MW
15+
~ |
16+
17+
str=
18+
Capacity Cost*New Capacity
19+
~ $
20+
~ |
21+
22+
Depreciated Amount=
23+
DEPRECIATE STRAIGHTLINE(str, dtime, 1, 0)
24+
~
25+
~ |
26+
27+
********************************************************
28+
.Control
29+
********************************************************~
30+
Simulation Control Parameters
31+
|
32+
33+
FINAL TIME = 2050
34+
~ Year
35+
~ The final time for the simulation.
36+
|
37+
38+
INITIAL TIME = 2020
39+
~ Year
40+
~ The initial time for the simulation.
41+
|
42+
43+
SAVEPER =
44+
TIME STEP
45+
~ Year [0,?]
46+
~ The frequency with which output is stored.
47+
|
48+
49+
TIME STEP = 1
50+
~ Year [0,?]
51+
~ The time step for the simulation.
52+
|
53+
54+
\\\---/// Sketch information - do not modify anything except names
55+
V300 Do not put anything below this section - it will be ignored
56+
*View 1
57+
$192-192-192,0,Courier|12||0-0-0|0-0-0|0-0-255|-1--1--1|255-255-255|96,96,100,0
58+
10,1,New Capacity,344,277,56,9,8,3,0,0,0,0,0,0,0,0,0,0,0,0
59+
10,2,Time,310,223,29,9,8,2,0,3,-1,0,0,0,128-128-128,0-0-0,|||128-128-128,0,0,0,0,0,0
60+
1,3,2,1,0,0,0,0,0,64,0,-1--1--1,,1|(0,0)|
61+
10,4,Capacity Cost,423,168,39,16,8,3,0,0,0,0,0,0,0,0,0,0,0,0
62+
10,5,str,537,238,53,16,8,3,0,0,0,0,0,0,0,0,0,0,0,0
63+
1,6,1,5,0,0,0,0,0,128,0,-1--1--1,,1|(0,0)|
64+
1,7,4,5,0,0,0,0,0,128,0,-1--1--1,,1|(0,0)|
65+
10,8,Depreciated Amount,713,243,53,16,8,3,0,0,0,0,0,0,0,0,0,0,0,0
66+
1,9,5,8,0,0,0,0,0,128,0,-1--1--1,,1|(0,0)|
67+
10,10,dtime,587,313,46,23,8,3,0,0,-1,0,0,0,0,0,0,0,0,0
68+
1,11,10,8,0,0,0,0,0,64,1,-1--1--1,,1|(0,0)|
69+
///---\\\
70+
:L<%^E!@
71+
1:depreciate.vdfx
72+
4:Time
73+
5:Capacity Cost
74+
9:depreciate
75+
19:100,0
76+
24:2020
77+
25:2050
78+
26:2050
79+
57:1
80+
54:0
81+
55:0
82+
82:1
83+
86:0
84+
59:0
85+
56:0
86+
58:0
87+
71:0
88+
110:0
89+
111:0
90+
44:0
91+
46:0
92+
45:0
93+
49:0
94+
50:0
95+
51:
96+
52:
97+
53:
98+
43:/Users/todd/Projects/SDEverywhere/models/depreciate/depreciate.dat
99+
47:
100+
48:
101+
15:0,0,0,0,0,0
102+
27:0,
103+
34:0,
104+
42:1
105+
72:0
106+
73:0
107+
35:Date
108+
36:YYYY-MM-DD
109+
37:2020
110+
38:1
111+
39:1
112+
40:0
113+
41:0
114+
95:0
115+
96:0
116+
97:0
117+
77:0
118+
78:0
119+
102:1
120+
93:0
121+
94:0
122+
92:0
123+
91:0
124+
90:0
125+
87:0
126+
75:
127+
43:/Users/todd/Projects/SDEverywhere/models/depreciate/depreciate.dat
128+
103:8,8,8,3,8
129+
105:0,0,0,0,0,0,0,0,0,0
130+
104:Courier|12||0-0-0|0-0-0|-1--1--1|0-0-255|192-192-192|-1--1--1

packages/cli/src/c/vensim.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,3 +464,54 @@ double _DELAY_FIXED(double input, FixedDelay* fixed_delay) {
464464
}
465465
return result;
466466
}
467+
468+
//
469+
// DEPRECIATE STRAIGHTLINE
470+
//
471+
Depreciation* __new_depreciation(Depreciation* depreciation, double dtime, double initial_value) {
472+
// Construct a Depreciation struct with a ring buffer for the time steps in the depreciation time.
473+
// We don't know the size until runtime, so it must be dynamically allocated.
474+
// The depreciation time is quantized to an integral number of time steps.
475+
// The Depreciation should be constructed at init time to latch the depreciation time and initial value.
476+
// Allocate memory on the first call only. Pass the same pointer back in on subsequent runs.
477+
size_t n = (size_t)ceil(dtime / _time_step);
478+
size_t bufsize = n * sizeof(double);
479+
if (depreciation == NULL) {
480+
// Create the Depreciation object and allocate its data buffer.
481+
depreciation = malloc(sizeof(Depreciation));
482+
depreciation->data = malloc(bufsize);
483+
} else if (depreciation->n != n) {
484+
// The depreciation time has changed since a previous run. Reallocate the data buffer.
485+
free(depreciation->data);
486+
depreciation->data = malloc(bufsize);
487+
}
488+
// Reset state at the start of each run.
489+
memset(depreciation->data, 0, bufsize);
490+
depreciation->n = n;
491+
depreciation->data_index = 0;
492+
depreciation->dtime = dtime;
493+
depreciation->initial_value = initial_value;
494+
return depreciation;
495+
}
496+
double _DEPRECIATE_STRAIGHTLINE(double input, Depreciation* depreciation) {
497+
// Distribute the input at this time step over the depreciation time in a ring buffer.
498+
// Return the depreciation amout at the current time.
499+
double result;
500+
// Require the buffer size to be positive to protect from buffer overflows.
501+
if (depreciation->n > 0) {
502+
// Distribute input from the stream over the depreciation time.
503+
double distribution = input / depreciation->dtime;
504+
for (size_t i = 0; i < depreciation->n; i++) {
505+
size_t pos = (depreciation->data_index + i) % depreciation->n;
506+
depreciation->data[pos] += distribution;
507+
}
508+
result = depreciation->data[depreciation->data_index];
509+
// Move to the next time step by pushing zero and shifting.
510+
depreciation->data[depreciation->data_index] = 0;
511+
depreciation->data_index = (depreciation->data_index + 1) % depreciation->n;
512+
} else {
513+
// For a zero deprecitation time, take the value directly from the input.
514+
result = input;
515+
}
516+
return result;
517+
}

packages/cli/src/c/vensim.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,20 @@ typedef struct {
8484
double _DELAY_FIXED(double input, FixedDelay* fixed_delay);
8585
FixedDelay* __new_fixed_delay(FixedDelay* fixed_delay, double delay_time, double initial_value);
8686

87+
//
88+
// DEPRECIATE STRAIGHTLINE
89+
//
90+
typedef struct {
91+
double* data;
92+
size_t n;
93+
size_t data_index;
94+
double dtime;
95+
double initial_value;
96+
} Depreciation;
97+
98+
double _DEPRECIATE_STRAIGHTLINE(double input, Depreciation* depreciation);
99+
Depreciation* __new_depreciation(Depreciation* depreciation, double dtime, double initial_value);
100+
87101
#ifdef __cplusplus
88102
}
89103
#endif

packages/compile/src/_shared/helpers.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ let nextTmpVarSeq = 1
1414
let nextLookupVarSeq = 1
1515
// next sequence number for generated fixed delay variable names
1616
let nextFixedDelayVarSeq = 1
17+
// next sequence number for generated depreciation variable names
18+
let nextDepreciationVarSeq = 1
1719
// next sequence number for generated level variable names
1820
let nextLevelVarSeq = 1
1921
// next sequence number for generated aux variable names
@@ -73,6 +75,10 @@ export let newFixedDelayVarName = () => {
7375
// Return a unique fixed delay variable name
7476
return `_fixed_delay${nextFixedDelayVarSeq++}`
7577
}
78+
export let newDepreciationVarName = () => {
79+
// Return a unique depreciation variable name
80+
return `_depreciation${nextDepreciationVarSeq++}`
81+
}
7682
export let newLevelVarName = (basename = null, levelNumber = 0) => {
7783
// Return a unique level variable name.
7884
let levelName = basename || nextLevelVarSeq++

packages/compile/src/generate/code-gen.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ ${postStep}
217217
function declSection() {
218218
// Emit a declaration for each variable in the model.
219219
let fixedDelayDecls = ''
220+
let depreciationDecls = ''
220221
let decl = v => {
221222
// Build a C array declaration for the variable v.
222223
// This uses the subscript family for each dimension, which may overallocate
@@ -229,6 +230,12 @@ ${postStep}
229230
family => `[${sub(family).size}]`,
230231
families
231232
).join('')};`
233+
} else if (v.isDepreciation()) {
234+
// Add the associated Depreciation var decl.
235+
depreciationDecls += `\nDepreciation* ${v.depreciationVarName}${R.map(
236+
family => `[${sub(family).size}]`,
237+
families
238+
).join('')};`
232239
}
233240
return varType + v.varName + R.map(family => `[${sub(family).size}]`, families).join('')
234241
}
@@ -239,7 +246,7 @@ ${postStep}
239246
asort,
240247
lines
241248
)
242-
return decls(Model.allVars()) + fixedDelayDecls
249+
return decls(Model.allVars()) + fixedDelayDecls + depreciationDecls
243250
}
244251
function internalVarsSection() {
245252
// Declare internal variables to run the model.

0 commit comments

Comments
 (0)