blob: 8eacd1c7b3676f46e732d159806e8ae849d8546f [file]
#include "tlbmc/thermal/controller/algorithm/stepwise.h"
#include <cmath>
#include "thermal_config.pb.h"
namespace milotic_tlbmc {
namespace thermal {
double StepwiseThermalLoop::FindStepwiseOutput(double input) const {
int low = 0;
int high = GetCriticalPointsSize() - 1;
// Find the first critical point whose `threshold` is larger than `input`.
while (low <= high) {
int mid = low + (high - low) / 2;
StepwiseCriticalPoint critical_point = GetCriticalPointAt(mid);
if (std::isnan(critical_point.threshold()) ||
critical_point.threshold() > input) {
high = mid - 1;
} else {
low = mid + 1;
}
}
// Return the `stepwise_output` of the last critical point whose `threshold`
// is smaller than or equal to `input`.
// If no such critical point exists, return the `stepwise_output` of the first
// critical point by default.
int output_index = low - 1;
if (output_index < 0 || output_index >= GetCriticalPointsSize()) {
output_index = 0;
}
double output = GetCriticalPointAt(output_index).stepwise_output();
if (std::isnan(output)) {
output = 0;
}
return output;
}
double StepwiseThermalLoop::ExecuteStepwiseLoop(double input) {
double output = GetLastOutput();
double last_input = GetLastInput();
if (!std::isnan(output) && (input - last_input) <= GetPositiveHysteresis() &&
(last_input - input) <= GetNegativeHysteresis()) {
return output;
}
output = FindStepwiseOutput(input);
SetLastInput(input);
SetLastOutput(output);
return output;
}
} // namespace thermal
} // namespace milotic_tlbmc