The function voltage_table_t::calculate_max_discharge_w takes q as an input, but this q is the full amount of charge left in the battery down to 0 SOC, rather than a target SOC specified by dispatch and the capacity model. Create functions in the voltage classes (or at least for the voltage table) that calculate the charge and discharge power required to reach a specific SOC, instead of just to 0 or 100%. Then use these in the dispatch classes to better enforce the SOC constraints.
The function voltage_table_t::calculate_max_discharge_w takes q as an input, but this q is the full amount of charge left in the battery down to 0 SOC, rather than a target SOC specified by dispatch and the capacity model. Create functions in the voltage classes (or at least for the voltage table) that calculate the charge and discharge power required to reach a specific SOC, instead of just to 0 or 100%. Then use these in the dispatch classes to better enforce the SOC constraints.