/// <summary> /// Applies a bounding function to the current capacity of the battery, to prohibit discharging below 0 joules, /// and the prevent charging above the maximum specified capabilities. If the battery exceeds the specification, /// a warning (for overcharge) or critical error (for discharged) will be logged to the solution. /// </summary> /// <param name="battery">The battery parameters to enforce.</param> /// <param name="pass">The last pass that was executed.</param> /// <returns>A value indicating whether the requested capacity could be accomplished successfully.</returns> private bool EnforceBatteryLimits(Battery battery, PassOrbit pass, IPassPhase phase) { var success = true; if (this.currentCapacityJoules < 0) { // Orbit parameters are impossible - we've run out of power. // Error is fatal - denote the problem and abort scheduling. this.solution.IsSolvable = false; this.solution.Problems.Add(new ScheduleSolution.SchedulerProblem( ScheduleSolution.SchedulerProblem.SeverityLevel.Fatal, $"Orbit parameters for {pass.Name} are impossible. No power remains while scheduling the {phase.PhaseName} for {pass.Name}.")); this.currentCapacityJoules = 0; // Discharging completely is a fatal error that will prevent the pass from completing success = false; } else if (this.currentCapacityJoules > battery.EffectiveCapacityJ) { this.solution.Problems.Add(new ScheduleSolution.SchedulerProblem( ScheduleSolution.SchedulerProblem.SeverityLevel.Warning, $"The battery was a contraint during {pass.Name}. {this.currentCapacityJoules:n} J were available, but max charge capacity is {battery.EffectiveCapacityJ:n} J")); // Apply the cap. this.currentCapacityJoules = battery.EffectiveCapacityJ; // Overcharging doesn't prevent the mission from continuing, but indicates inefficiency success = true; } return(success); }
/// <summary> /// Initializes a new instance of the <see cref="EditControlViewModel"/> class. /// </summary> /// <param name="pass">The pass to edit.</param> /// <param name="editComplete">The action to execute when the edit is completed.</param> public EditControlViewModel(PassOrbit pass, Action <PassOrbit> editComplete) { this.originalPass = pass; this.InitPhases(); this.SaveCallback = editComplete; this.SaveCommand = new RelayCommand(this.SaveCommandHandler); this.CancelCommand = new RelayCommand(this.CancelCommandHandler); }
private void ReportProfileNotAvailable(PassOrbit pass, string operation) { // No profile could be found that fits the available power and time // All previous schedules have already been done with the lowest-power option that fits // so if we're out of power, there is no solution possible. // If we're out of time, faster devices are needed, or the phase needs lengthened. this.solution.IsSolvable = false; this.solution.Problems.Add(new ScheduleSolution.SchedulerProblem( ScheduleSolution.SchedulerProblem.SeverityLevel.Fatal, $"Orbit parameters for {pass.Name} are impossible. No devices are capable of performing the {operation} in the required power and time window.")); }
private bool FindProfileForPhase(SortedDictionary <double, IByteStreamProcessor> optimizationMap, PassOrbit pass, IPassPhase phase, long bytes) { var allowedTime = phase.EndTime.Subtract(phase.StartTime); // For the encryption phase, we have an abs max of currentCapacityJoules // and the time allocated to encryptionPhase. // Start with the most ideal profile and keep testing until we find one that fits var foundViableProfile = false; foreach (var profile in optimizationMap.Values) { var timeRequired = bytes / profile.BytesPerSecond; var energyRequired = bytes * profile.JoulesPerByte; if (timeRequired > allowedTime.TotalSeconds) { // Out of time foundViableProfile = false; } else if (energyRequired > this.currentCapacityJoules) { // Out of power foundViableProfile = false; } else { // This solution works for this part this.solution.ViableProfiles[pass][phase.PhaseName] = profile; phase.TotalEnergyUsed = energyRequired; foundViableProfile = true; this.currentCapacityJoules -= energyRequired; break; } } return(foundViableProfile); }