Connecting ordered sets

Hello,
I am currently learning GAMS and I came up on this issue:
I am using these sets:

Sets
y “Set of years in the planning horizon” /y2023y2045/
d “Set of all days in a year” /d1
d366/
t “Set of all hours in a day” /h1*h24/;

Then I am importing data for some parameters from excel. e.g. E(y,d,t)
Therefore I would prefer not to change the way my sets are defined, because I will need to change everything in my excel as well.

And further down the code, in certain equations I need to use variables like this one: “E_b_res(y,d,t-1)”
So is should work like this:
if ( ord(t)=1 AND ord(d)=1 AND E(y-1,‘d366’,‘h24’) <> 0 )
x=E_b_res(y-1,‘d366’,‘h24’)
else if ( ord(t=1) AND ord(d)=1 )
x=E_b_res(y-1,‘d365’,‘h24’)
else if( ord(t=1) )
x=E_b_res(y,d-1,‘h24’)
else
x=E_b_res(y,d,t-1)

Where x is the value I need E_b_res(y,d,t-1) to have.

*note: in the E(y-1,‘d366’,‘h24’) <> 0 part, I am checking whether or not its a leap year. My excel doesn’t input values for d366 of non leap years so this is an easy way of checking

This felt very complex to do using the $ operator. I am also considering using Multi-Dimensional Sets, but I couldn’t really figure out how they work just using the documentation. For example: why can’t I define a variable over a multi-dimensional set?
I am pretty sure there are some easy solutions for this that I am missing.

If you need the previous “period” in your model, you should think in terms single dimension time periods rather than (y,d,t) tuples and model with this. If you need occasionally access to data of a particular year, date, hour of a period you can do this by mapping from the period to the y,d,t tuple and access the data (or variable). I hope the GAMS code below will help you understand what I mean.

-Michael

Sets
  y "Set of years in the planning horizon" /y2023*y2045/
  d "Set of all days in a year" /d1*d366/
  t "Set of all hours in a day" /h1*h24/;
  
$eval P card(y)*card(d)*card(t)
Set p period / p1*p%P% /;

Parameter E(y,d,t), cnt /0/;
loop((y,d,t), cnt=cnt+1; E(y,d,t) = cnt);

* Remove data for non leap years
set leap(y) / y2024, y2028, y2032, y2036, y2040, y2044 /;
E(y,'d366',t)$(not leap(y)) = 0;

* Now match non-zero E to p:
set ydt(y,d,t), pydtmap(p,y,d,t);
option ydt<E, pydtmap(p:ydt);

* Have parameters in p space
alias (y,yy), (d,dd), (t,tt);
Parameter Ep(p); Ep(p) = sum(pydtmap(p,y,d,t), E(y,d,t));

Variable Ep_b_res(p), oo(d);
Equation balance(p), daystart(p);
balance(p).. Ep_b_res(p) =e= sum(pydtmap(p,y,d,t), oo(d))*(Ep_b_res(p-1) + Ep(p));
daystart(p)$sum(pydtmap(p,y,d,'h1'),1).. Ep_b_res(p) =l= 2*Ep_b_res(p-1);

I actually managed to do it using the $ operator pretty easily, thank you thought either way!