I’m working on a dymos problem which represents a simplified building energy model. I would like to add some discrete controls – essentially just binary on/offs – and have some questions.
First, some context about the model:
- Walls are represented as RC networks, with thermal transfer from the exterior through the building envelope to the interior of a thermal zone (i.e. a room). Each capacitor in the wall has a state/state-rate associated with it, and the state rate is computed using KCL vis-a-vis the adjacent capacitor nodes. The state is Temperature.
- Thermal zones are represented by a single capacitor, representing the specific heat of the air and any thermal mass in the room, and again, state is temp, state rate computed via KCL.
- There can be multiple zones with walls between them, but that’s beside the point here.
- Each thermal zone has three controls: Cooling power, Heating power, and outdoor air mass flow rate. For now though, we can just simplify it and consider only a single control (let’s say cooling power).
- Outside air temperature conditions are modeled as a differentiable function of time (essentially a voltage source in the context of the RC network) so that e.g. the first cap in a wall assembly can correctly compute
J["T_cap_1_dot","time"]
, sinceoutputs["T_cap_1_dot"]
does depend oninputs["time"]
via the external boundary condition. - The goal is always to keep the interior zone temperature within a certain temperature range, e.g. 20C to 21C.
Currently, I achieve this by setting bounds on each zone’s temp with upper and lower bounds equal to the setpoints. I do this when adding the state vars for the zone temps – I’m not sure if it is “better” to add a path constraint? Or if alternatively, I should add it as a penalty to the objective function which is zero when the temp is within the band and grows when it is out of band? This is trivial if there is a single setpoint, but with a “deadband” the objective becomes a little messier if you want it to be differentiable.
I fix the start and end time of the setpoint, as well as the initial conditions for all states (voltages across the caps) and controls. I then ask it to minimize the total energy usage over the phase (so there is an additional state variable which is just the integral of the cooling+heating power).
This works – very cool! It’s “cheating” to some extent because it knows the future weather conditions, so I guess it’s a form of model predictive control. It can even find strategies like “night-time flushing” for thermal mass, where you bring in outdoor air overnight before a hot day to cool the concrete layers of walls in order to keep the space cool during the daytime and avoid using any heating/cooling energy at all.
Anyways, I would like to use a slightly different form for my cooling/heating controls or outdoor air flow control. I would like to be able to model controls that are discrete in nature – really just “on/off” would be sufficient.
Three ideas:
- Set a path constraint on the control: e.g.
binary_constraint = (control-control_on)*control
withequals=0
for the constraint type. However, when I do this, I get a singular matrix error:
Singular matrix C in LSQ subproblem (Exit mode 6)
Current function value: 5e-07
Iterations: 1
Function evaluations: 1
Gradient evaluations: 1
Optimization FAILED.
Singular matrix C in LSQ subproblem
- Let the control be non-dimensional and apply a sigmoid function to it, and then multiply it by the corresponding “actual” control value. I don’t think this would work, since if the optimizer works well enough, it should still find the solutions in the critical region of the sigmoid.
- Split time up into multiple phases, where in each phase, the control alternates between its on/off value, and then let the optimizer solve for the timing of the phase boundaries. I don’t love this because (a) I have to take a prior as to how many on/off segments there are, and (b) I don’t think this really scales to having multiple on/off controls, since you do not know in advance which should be simultaneously on/off etc.
I couldn’t find anything in the dymos docs mentioning discrete controls, but maybe I missed that!