-
Notifications
You must be signed in to change notification settings - Fork 9
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
Resize index variable dynamically #163
Comments
Hi @jvail, Thanks! There's no way built in xarray-simlab to resize data along given dimensions. I'm not sure how xarray-simlab would take care of this as the Automatically resizing variables in all processes is a complex problem that may have many sub-problems (e.g., process dependencies vs. when to resize the variables), so I'm afraid you'd still need to handle this "manually". Maybe you could use runtime hooks to retrieve all variables with Maybe #141 would help if we add an option like |
Hey @benbovy , thank you sharing your ideas. I definitely need to dig deeper into your sources to have a better idea how this could be done. I will give it a try with your suggestion (runtime hook) first and see how far I can get.
Not sure if understand that correctly. If If you don't mind I'll leave this issue open for a while. |
What I suggest in #141 is something like With
Yeah, I wouldn't recommend it. |
Thank you for clarifying.
Having access to the xarray itself within a process is certainly useful and having the dimension labeled (as far as I understand the xarray vocabulary - sorry, just starting to learn to work with xarray) as in the index variable even more so.
Hm, I don't think this would help me a lot in my use case. Then I would need to replace all Instead calling a function inside each process, iterating over each variable and resizing it if necessary seems to be a better - not ideal I admit - way. Just another idea: Maybe a I'll keep on digging... |
For more convenience, I also suggest in #141 to have an option at the process level, e.g.,
Note that most numpy functions should now work with xarray objects, which are nep-18 compliant.
I think that you would still need to manually resize each variable in each process. If I understand correctly, what you'd like to do is to perform some operation (resize) on a set of variables (model-wise) that meet some condition (sharing the same dimension), at a given "time" in the workflow (after the index variable has been updated). Runtime hooks currently allows doing such thing, but I wouldn't rely on that much, those hooks are more for simulation monitoring and are not meant to update the state variables in the model (it might not be consistent with the |
Variable groups would have been helpful for, e.g., resizing all the variables of the same group (you can assign a group name to all variables with dimension This restriction is needed so that xarray-simlab can automatically sort the processes in a model. If we allow We could allow in xarray-simlab user-defined process order and relax this restriction, but that would require some work. |
To save some code duplication, you could use process class inheritance, e.g., @xs.process
class Foo:
idx = xs.index(dims='X')
def run_step(self):
# update idx (which gets resized)
@xs.process
class ResizeX:
idx = xs.foreign(Foo, 'idx')
def _resize(self, vars):
for v in vars:
# resize v
@xs.process
class Bar(ResizeX):
var = xs.variable(dims='X', intent='out')
def run_step(self):
self._resize([self.var])
# do other things That is still not ideal, though. |
Yes, that is what I had in mind to to try as a first solution. Maybe I'd name that base class function P.S.: Of course for performance it would be nicer to only exercise this if I knew the index has changed (in our model it will only change once in a while).
Ah! Thanks for this hint. That certainly helps. |
You could do something like: @xs.process
class Foo:
idx = xs.index(dims='X')
idx_resized = xs.any_object()
def run_step(self):
# maybe update idx...
if is_resized(self.idx): # anything that checks if the index has changed
self.idx_resized = True
else:
self.idx_resized = False
@xs.process
class ResizeX:
idx = xs.foreign(Foo, 'idx')
idx_resized = xs.foreign(Foo, 'idx_resized')
def _resize(self, vars):
if not self.idx_resized:
return
for v in vars:
# resize v |
After some experiments we ended up with an awful hack. But all solutions seem to involve some sort of semi ideal work-around. I did replace the set_state function of the ModelBuilder in order to "inject" our own State class. This is just a dictionary with a new setter. When an index variable changes it will go through all other variables and align their shape to match the index's shape/length. We just need something more powerful than a process class and I did not like the idea of importing the index everywhere. I did a few experiments with introducing some sort of "meta-process" that is not involved in the actual model logic. The idea was to have something that is powerful enough and could do some work in administering the model: e.g. watch variables, maybe more complex validation, read input files and pass them on to the initialization function of processes, manipulate the state - these sort of things. But I did not really get far and soon hacked too much around in the simlab core. However, would be nice if (in some distant future) simlab could provide extension points, "slots" to drill your own hole into the implementation to add custom stuff. This is not a feature request - just an idea. Will be a lot of work, I suppose. Thank you for your support and ideas! |
You're welcome. Feel free to open issues if you have suggestions on how we can refactor xarray-simlab to make it more flexible. I'm sure there are ways to make it so without introducing much new concepts. |
Hi,
first of all: Great library! I was supposed to create something similar and I am happy I found xarray-simlab. Saves a lot of time and I doubt I could have come up with something as good and solid.
I have two dimensions (time and X - X being an xs.index) and I do not know upfront how large X will be i.e. the length of the 1d array. It is necessary to resize, add entries to X while the simulation runs (the process where X is defined takes care of it). If X is resized I need to resize all variables in all processes that have the dims property set to ('X').
I was wondering if you have an idea how to do that most efficiently. Is there a way to avoid resizing all variables inside each process run_step function?
The text was updated successfully, but these errors were encountered: