Exemplo n.º 1
0
 // We have to ensure that there are enough batteries to
 // support the shift schedule. There must be at least enough batteries to
 // supply the two largest adjacent shifts, and there must also be enough
 // to power the two largest adjacent shifts, in case a single battery
 // cannot power an entire shift.
 void validateBatteries() {
   int minBatteries = 0;
   Shift s1 = null;
   Shift s2 = null;
   for (int i = 0; i < shiftSchedule.length; i++) {
     Shift s = shiftSchedule[i];
     if (null == s) {
       s1 = s2;
     } else if (s2 != s) {
       s1 = s2;
       s2 = s;
       if (null != s1) {
         int n1 = s1.getTrucks();
         int d1 = s1.getDuration();
         int n2 = s2.getTrucks();
         int d2 = s2.getDuration();
         double neededBatteries = (n1 * d1 + n2 * d2) * truckKW / getBatteryCapacity();
         minBatteries = (int) Math.max(minBatteries, (n1 + n2));
         minBatteries = (int) Math.max(minBatteries, Math.ceil(neededBatteries));
       }
     }
   }
   int neededBatteries = minBatteries - nBatteries;
   if (neededBatteries > 0) {
     log.error("Not enough batteries (" + nBatteries + ") for " + getName());
     // Add discharged batteries to fill out battery complement
     log.warn("Adding " + neededBatteries + " batteries for " + getName());
     setNBatteries(getNBatteries() + neededBatteries);
   }
 }
Exemplo n.º 2
0
 ShiftEnergy(Instant start, int end, int duration) {
   super();
   this.start = start;
   this.endIndex = end;
   Shift next = shiftSchedule[end];
   if (null != next) {
     energyNeeded = next.getTrucks() * next.getDuration() * getTruckKW();
   }
   this.duration = duration;
 }
Exemplo n.º 3
0
  // Validates and creates a shift instance and populates the schedule
  // with references to the new shift
  void addShift(List<Integer> shiftData, List<Integer> blockData) {
    if (shiftData.size() < 3) {
      // nothing to do here
      log.error("Bad shift spec for " + getName() + ": " + shiftData.toString());
      return;
    }
    if (!validBlock(blockData)) {
      log.error("Bad block data for " + getName() + ": " + blockData.toString());
      return;
    }
    int start = shiftData.get(0);
    if (start < 0 || start > 23) {
      log.error("Bad shift start time " + start + " for " + getName());
      return;
    }
    int duration = shiftData.get(1);
    if (duration < 1 || duration > 24) {
      log.error("Bad shift duration " + duration + " for " + getName());
      return;
    }
    int trucks = shiftData.get(2);
    if (trucks < 0) {
      log.error("Negative shift truck count " + trucks + " for " + getName());
      return;
    }
    Shift shift = new Shift(start, duration, trucks);

    // populate the schedule, ignoring overlaps. Later shifts may overlap
    // earlier ones. TODO; warn about overlaps
    for (int day : blockData) {
      for (int hour = shift.getStart(); hour < shift.getStart() + shift.getDuration(); hour++) {
        // Remember that Sunday is 1, not 0
        int index = (hour + (day - 1) * HOURS_DAY) % shiftSchedule.length;
        shiftSchedule[index] = shift;
      }
    }
  }
Exemplo n.º 4
0
 // Computes constraints on future energy needs
 // Amounts are energy needed to run the chargers. Energy input to trucks
 // will be smaller due to charge efficiency.
 ShiftEnergy[] getFutureEnergyNeeds(Instant start, int horizon, double initialCharging) {
   Instant seStart = start;
   int index = indexOfShift(start);
   // current time is likely to be partway into first shift
   Shift currentShift = shiftSchedule[index]; // might be null
   int duration = 0;
   while (shiftSchedule[index] == currentShift) {
     duration += 1;
     index = nextShiftIndex(index);
   }
   Shift nextShift = shiftSchedule[index];
   // this gives us the info we need to start the sequence
   ArrayList<ShiftEnergy> data = new ArrayList<ShiftEnergy>();
   data.add(new ShiftEnergy(seStart, index, duration));
   seStart = seStart.plus(duration * TimeService.HOUR);
   int elapsed = duration;
   // add shifts until we run off the end of the horizon
   // keep in mind that a shift can be null
   while (elapsed < horizon) {
     duration = 0;
     while (nextShift == shiftSchedule[index]) {
       index = nextShiftIndex(index);
       duration += 1;
     }
     nextShift = shiftSchedule[index];
     data.add(new ShiftEnergy(seStart, index, duration));
     elapsed += duration;
     seStart = seStart.plus(duration * TimeService.HOUR);
   }
   // now we convert to array, then walk backward and fill in energy needs
   ShiftEnergy[] result = data.toArray(new ShiftEnergy[data.size()]);
   double shortage = 0.0;
   for (int i = result.length - 1; i >= 0; i--) {
     int endx = result[i].endIndex;
     int prev = previousShiftIndex(endx);
     currentShift = shiftSchedule[prev];
     Shift end = shiftSchedule[endx];
     double needed = 0.0;
     if (null != end) {
       // Assume we need, at the end of each shift, enough energy to
       // run the next shift
       needed = (end.getTrucks() * end.getDuration() * getTruckKW()) / getChargeEfficiency();
     }
     // chargers is min of charger capacity and battery availability
     int chargers = getNChargers();
     int availableBatteries = nBatteries;
     if (null != currentShift) {
       availableBatteries -= currentShift.getTrucks();
     }
     chargers = (int) Math.min(chargers, availableBatteries);
     double available =
         getMaxChargeKW() * result[i].getDuration() * chargers / getChargeEfficiency();
     double surplus = available - needed - shortage;
     shortage = Math.max(0.0, -(available - needed - shortage));
     result[i].setEnergyNeeded(needed);
     result[i].setMaxSurplus(surplus);
   }
   // finally, we need to update the first element with
   // the current battery charge.
   double finalSurplus = result[0].getMaxSurplus();
   if (finalSurplus > 0.0) {
     result[0].setMaxSurplus(finalSurplus + initialCharging);
   } else if (shortage > 0.0) {
     result[0].setMaxSurplus(initialCharging - shortage);
   }
   return result;
 }
Exemplo n.º 5
0
  // make sure we have enough charging capacity to support
  // the shift schedule
  void validateChargers() {
    // ToDo -- A single charging should be able to charge a truck worth
    // of batteries in a single shift

    // The total output of the availableChargers should be at least enough
    // to power the trucks over a 24-hour period. Note that the shift schedule
    // starts at midnight, which may not be the start of the current shift.
    double maxNeeded = 0.0;
    int offset = 0;
    while (null == shiftSchedule[offset]) {
      offset += 1;
    }
    Shift currentShift = shiftSchedule[offset];
    int remainingDuration = 0;
    int hoursInShift = (HOURS_DAY - currentShift.getStart()) % HOURS_DAY;
    remainingDuration = currentShift.getDuration() - hoursInShift;

    for (int i = offset; i < (shiftSchedule.length - HOURS_DAY); i++) {
      double totalEnergy = 0.0;
      Shift thisShift = shiftSchedule[i];
      if (thisShift != currentShift) {
        currentShift = thisShift;
        if (null != currentShift) {
          // first block of energy in 24h window starting at i
          remainingDuration = currentShift.getDuration();
        }
      }
      if (null != currentShift) {
        totalEnergy += currentShift.getTrucks() * remainingDuration * truckKW;
      }
      // now run fwd 24h and add energy from future shifts
      Shift current = currentShift;
      // int shiftStart = i;
      for (int j = i + 1; j < (i + HOURS_DAY); j++) {
        Shift newShift = shiftSchedule[j];
        if (null != newShift && current != newShift) {
          int durationInWindow = (int) Math.min((i + HOURS_DAY - j), newShift.getDuration());
          totalEnergy += newShift.getTrucks() * durationInWindow * truckKW;
          current = newShift;
        }
      }
      maxNeeded = Math.max(maxNeeded, totalEnergy);
      remainingDuration -= 1;
    }

    double chargeEnergy = nChargers * maxChargeKW * HOURS_DAY;
    if (maxNeeded > chargeEnergy) {
      double need = (maxNeeded - chargeEnergy) / (maxChargeKW * HOURS_DAY);
      int add = (int) Math.ceil(need);
      log.error(
          "Insufficient charging capacity for "
              + getName()
              + ": have "
              + chargeEnergy
              + ", need "
              + maxNeeded
              + ". Adding "
              + add
              + " availableChargers.");
      setNChargers(getNChargers() + add);
    }
  }