The Schedule object is currently a wrapper around an array of ScheduleState objects and has been for a long time. At present, the constructor function populates this array–see iterateScheduleSection() for details–and client code queries the per report step information either through member functions that take a report step parameter or by direct ScheduleState inspection through Schedule::operator[](reportStep). This representation has served us well for a long time, but it fundamentally assumes that the simulation objects such as wells, groups, connections, controls, &c, are unchanging other than at discrete time points (new report steps). In turn, this means we have to perform extra work for those cases that are genuinely dynamic, notably those that involve ACTIONX. Right now we handle actions by "replaying" future report step definitions on top of the current state whenever an action triggers. There are other problems as well, for instance in the way we handle the WELPI operation which is, in a word, convoluted.
I'm now in the process of scoping out the work for some features that will introduce even more dynamism into the SCHEDULE section processing and adhering to the current model of "all report steps are unchanging from the input" is becoming a little too constraining in my opinion. I therefore propose to switch to a more piecemeal construction process. In particular, I suggest not constructing the full array of ScheduleState objects all at once, but instead constructing the ScheduleState object for the "current" report step–as determined by the client code, typically the simulator–only when it's actually needed. This will also have the added benefit of making our ACTIONX implementation simpler, since we won't have to "replay" the future whenever an action triggers. This also potentially opens up an opportunity to save a bit of memory since we won't have to have the full set of dynamic objects for the entire simulation history in memory at all times. Further along that road, we could even consider having just the "current/active" ScheduleState in memory and not preserve earlier history, though adjoint simulations may require that all objects be available somehow.
The biggest barrier to changing this fundamental data model is, of course, that our parallel load balancing procedure uses the full set of wells and well/reservoir connections at the end of the simulation as an input. In my proposed change, that would not exist at load balancing time. Instead, I propose we add a special-purpose operation that infers this set of wells and connection cells once, without actually constructing the complete well and connection objects, and use that for load balancing. Would that be a workable alternative? This set would also be useful when configuring the set of summary vectors.
From a technical point of view, the piecemeal construction will leverage the ScheduleDeck data member of class Schedule. This is essentially a container of unprocessed SCHEDULE section input keywords, with a little bit of logic on top to keep track of dates and which input keywords are part of which report step. This is also the same data source that we currently use for the report step replay operation whenever an action triggers. Since this information, in a parallel run, is already distributed to each MPI rank, we won't need any additional MPI communication to enable each rank to build its own consistent notion of the current ScheduleState.
Most of the work, at least as far as I can see right now, will be internal to the Schedule object. We will need to add a hook to allow client code to request that the current report step be advanced to the "next" level, and I expect we will need to remove all/most (public) Schedule object member functions that take a report step argument. The latter, in turn, means that client code will have to be rephrased in terms of a current ScheduleState object instead of the existing practice of calling member functions that take a report step argument. Most of those member functions could become free helper functions that operate on a ScheduleState object, however.
Since this is nevertheless a rather substantial behavioural change, I welcome any and all comments and reservations about the proposal.
The
Scheduleobject is currently a wrapper around an array ofScheduleStateobjects and has been for a long time. At present, the constructor function populates this array–seeiterateScheduleSection()for details–and client code queries the per report step information either through member functions that take a report step parameter or by directScheduleStateinspection throughSchedule::operator[](reportStep). This representation has served us well for a long time, but it fundamentally assumes that the simulation objects such as wells, groups, connections, controls, &c, are unchanging other than at discrete time points (new report steps). In turn, this means we have to perform extra work for those cases that are genuinely dynamic, notably those that involveACTIONX. Right now we handle actions by "replaying" future report step definitions on top of the current state whenever an action triggers. There are other problems as well, for instance in the way we handle theWELPIoperation which is, in a word, convoluted.I'm now in the process of scoping out the work for some features that will introduce even more dynamism into the SCHEDULE section processing and adhering to the current model of "all report steps are unchanging from the input" is becoming a little too constraining in my opinion. I therefore propose to switch to a more piecemeal construction process. In particular, I suggest not constructing the full array of
ScheduleStateobjects all at once, but instead constructing theScheduleStateobject for the "current" report step–as determined by the client code, typically the simulator–only when it's actually needed. This will also have the added benefit of making ourACTIONXimplementation simpler, since we won't have to "replay" the future whenever an action triggers. This also potentially opens up an opportunity to save a bit of memory since we won't have to have the full set of dynamic objects for the entire simulation history in memory at all times. Further along that road, we could even consider having just the "current/active"ScheduleStatein memory and not preserve earlier history, though adjoint simulations may require that all objects be available somehow.The biggest barrier to changing this fundamental data model is, of course, that our parallel load balancing procedure uses the full set of wells and well/reservoir connections at the end of the simulation as an input. In my proposed change, that would not exist at load balancing time. Instead, I propose we add a special-purpose operation that infers this set of wells and connection cells once, without actually constructing the complete well and connection objects, and use that for load balancing. Would that be a workable alternative? This set would also be useful when configuring the set of summary vectors.
From a technical point of view, the piecemeal construction will leverage the
ScheduleDeckdata member of classSchedule. This is essentially a container of unprocessed SCHEDULE section input keywords, with a little bit of logic on top to keep track of dates and which input keywords are part of which report step. This is also the same data source that we currently use for the report step replay operation whenever an action triggers. Since this information, in a parallel run, is already distributed to each MPI rank, we won't need any additional MPI communication to enable each rank to build its own consistent notion of the currentScheduleState.Most of the work, at least as far as I can see right now, will be internal to the
Scheduleobject. We will need to add a hook to allow client code to request that the current report step be advanced to the "next" level, and I expect we will need to remove all/most (public)Scheduleobject member functions that take a report step argument. The latter, in turn, means that client code will have to be rephrased in terms of a currentScheduleStateobject instead of the existing practice of calling member functions that take a report step argument. Most of those member functions could become free helper functions that operate on aScheduleStateobject, however.Since this is nevertheless a rather substantial behavioural change, I welcome any and all comments and reservations about the proposal.