Method: OSut#availabilitySchedule

Defined in:
lib/osut/utils.rb

#availabilitySchedule(model = nil, avl = "") ⇒ OpenStudio::Model::Schedule?

Generates an HVAC availability schedule.

Parameters:

  • model (OpenStudio::Model::Model) (defaults to: nil)

    a model

  • avl (String) (defaults to: "")

    seasonal availability choice (optional, default “ON”)

Returns:

  • (OpenStudio::Model::Schedule)

    HVAC availability sched

  • (nil)

    if invalid input (see logs)



2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
# File 'lib/osut/utils.rb', line 2419

def availabilitySchedule(model = nil, avl = "")
  mth    = "OSut::#{__callee__}"
  cl     = OpenStudio::Model::Model
  limits = nil
  return mismatch("model",     model, cl, mth) unless model.is_a?(cl)
  return invalid("availability", avl,  2, mth) unless avl.respond_to?(:to_sym)

  # Either fetch availability ScheduleTypeLimits object, or create one.
  model.getScheduleTypeLimitss.each do |l|
    break    if limits
    next     if l.lowerLimitValue.empty?
    next     if l.upperLimitValue.empty?
    next     if l.numericType.empty?
    next unless l.lowerLimitValue.get.to_i == 0
    next unless l.upperLimitValue.get.to_i == 1
    next unless l.numericType.get.downcase == "discrete"
    next unless l.unitType.downcase == "availability"
    next unless l.nameString.downcase == "hvac operation scheduletypelimits"

    limits = l
  end

  unless limits
    limits = OpenStudio::Model::ScheduleTypeLimits.new(model)
    limits.setName("HVAC Operation ScheduleTypeLimits")
    limits.setLowerLimitValue(0)
    limits.setUpperLimitValue(1)
    limits.setNumericType("Discrete")
    limits.setUnitType("Availability")
  end

  time = OpenStudio::Time.new(0,24)
  secs = time.totalSeconds
  on   = OpenStudio::Model::ScheduleDay.new(model, 1)
  off  = OpenStudio::Model::ScheduleDay.new(model, 0)

  # Seasonal availability start/end dates.
  year  = model.yearDescription
  return empty("yearDescription", mth, ERR) if year.empty?

  year  = year.get
  may01 = year.makeDate(OpenStudio::MonthOfYear.new("May"),  1)
  oct31 = year.makeDate(OpenStudio::MonthOfYear.new("Oct"), 31)

  case trim(avl).downcase
  when "winter" # available from November 1 to April 30 (6 months)
    val = 1
    sch = off
    nom = "WINTER Availability SchedRuleset"
    dft = "WINTER Availability dftDaySched"
    tag = "May-Oct WINTER Availability SchedRule"
    day = "May-Oct WINTER SchedRule Day"
  when "summer" # available from May 1 to October 31 (6 months)
    val = 0
    sch = on
    nom = "SUMMER Availability SchedRuleset"
    dft = "SUMMER Availability dftDaySched"
    tag = "May-Oct SUMMER Availability SchedRule"
    day = "May-Oct SUMMER SchedRule Day"
  when "off" # never available
    val = 0
    sch = on
    nom = "OFF Availability SchedRuleset"
    dft = "OFF Availability dftDaySched"
    tag = ""
    day = ""
  else # always available
    val = 1
    sch = on
    nom = "ON Availability SchedRuleset"
    dft = "ON Availability dftDaySched"
    tag = ""
    day = ""
  end

  # Fetch existing schedule.
  ok = true
  schedule = model.getScheduleByName(nom)

  unless schedule.empty?
    schedule = schedule.get.to_ScheduleRuleset

    unless schedule.empty?
      schedule = schedule.get
      default  = schedule.defaultDaySchedule
      ok = ok && default.nameString           == dft
      ok = ok && default.times.size           == 1
      ok = ok && default.values.size          == 1
      ok = ok && default.times.first          == time
      ok = ok && default.values.first         == val
      rules = schedule.scheduleRules
      ok = ok && rules.size < 2

      if rules.size == 1
        rule = rules.first
        ok = ok && rule.nameString            == tag
        ok = ok && !rule.startDate.empty?
        ok = ok && !rule.endDate.empty?
        ok = ok && rule.startDate.get         == may01
        ok = ok && rule.endDate.get           == oct31
        ok = ok && rule.applyAllDays

        d = rule.daySchedule
        ok = ok && d.nameString               == day
        ok = ok && d.times.size               == 1
        ok = ok && d.values.size              == 1
        ok = ok && d.times.first.totalSeconds == secs
        ok = ok && d.values.first.to_i        != val
      end

      return schedule if ok
    end
  end

  schedule = OpenStudio::Model::ScheduleRuleset.new(model)
  schedule.setName(nom)

  unless schedule.setScheduleTypeLimits(limits)
    log(ERR, "'#{nom}': Can't set schedule type limits (#{mth})")
    return nil
  end

  unless schedule.defaultDaySchedule.addValue(time, val)
    log(ERR, "'#{nom}': Can't set default day schedule (#{mth})")
    return nil
  end

  schedule.defaultDaySchedule.setName(dft)

  unless tag.empty?
    rule = OpenStudio::Model::ScheduleRule.new(schedule, sch)
    rule.setName(tag)

    unless rule.setStartDate(may01)
      log(ERR, "'#{tag}': Can't set start date (#{mth})")
      return nil
    end

    unless rule.setEndDate(oct31)
      log(ERR, "'#{tag}': Can't set end date (#{mth})")
      return nil
    end

    unless rule.setApplyAllDays(true)
      log(ERR, "'#{tag}': Can't apply to all days (#{mth})")
      return nil
    end

    rule.daySchedule.setName(day)
  end

  schedule
end