Skip to content

Commit c9872a7

Browse files
committed
Completes MIN/MAX methods for degC scheds
1 parent 48749ef commit c9872a7

File tree

2 files changed

+372
-33
lines changed

2 files changed

+372
-33
lines changed

src/osut/osut.py

Lines changed: 158 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,7 @@ def defaultConstructionSet(s=None):
952952

953953

954954
def are_standardOpaqueLayers(lc=None) -> bool:
955-
"""Validates if every material in a layered construction is standard & opaque.
955+
"""Validates if every material in a layered construction is standard/opaque.
956956
957957
Args:
958958
lc (openstudio.model.LayeredConstruction):
@@ -1002,7 +1002,7 @@ def thickness(lc=None) -> float:
10021002
return d
10031003

10041004

1005-
def glazingAirFilmRSi(usi=5.85):
1005+
def glazingAirFilmRSi(usi=5.85) -> float:
10061006
"""Returns total air film resistance of a fenestrated construction (m2•K/W).
10071007
10081008
Args:
@@ -1180,7 +1180,7 @@ def insulatingLayer(lc=None) -> dict:
11801180
return res
11811181

11821182

1183-
def is_spandrel(s=None):
1183+
def is_spandrel(s=None) -> bool:
11841184
"""Validates whether opaque surface can be considered as a curtain wall
11851185
(or similar technology) spandrel, regardless of construction layers, by
11861186
looking up AdditionalProperties or its identifier.
@@ -1217,7 +1217,7 @@ def is_spandrel(s=None):
12171217
return "spandrel" in s.nameString().lower()
12181218

12191219

1220-
def is_fenestration(s=None):
1220+
def is_fenestration(s=None) -> bool:
12211221
"""Validates whether a sub surface is fenestrated.
12221222
12231223
Args:
@@ -1249,7 +1249,31 @@ def is_fenestration(s=None):
12491249
return True
12501250

12511251

1252-
def scheduleRulesetMinMax(sched=None):
1252+
def has_airLoopsHVAC(model=None) -> bool:
1253+
"""Validates if model has zones with HVAC air loops.
1254+
1255+
Args:
1256+
model (openstudio.model.Model):
1257+
An OpenStudio model.
1258+
1259+
Returns:
1260+
bool: Whether model has HVAC air loops.
1261+
False: If invalid input (see logs).
1262+
"""
1263+
mth = "osut.has_airLoopsHVAC"
1264+
cl = openstudio.model.Model
1265+
1266+
if not isinstance(model, cl):
1267+
return oslg.mismatch("model", model, cl, mth, CN.DBG, False)
1268+
1269+
for zone in model.getThermalZones():
1270+
if zone.canBePlenum(): continue
1271+
if zone.airLoopHVACs() or zone.isPlenum(): return True
1272+
1273+
return False
1274+
1275+
1276+
def scheduleRulesetMinMax(sched=None) -> dict:
12531277
"""Returns MIN/MAX values of a schedule (ruleset).
12541278
12551279
Args:
@@ -1272,7 +1296,7 @@ def scheduleRulesetMinMax(sched=None):
12721296
res = dict(min=None, max=None)
12731297

12741298
if not isinstance(sched, cl):
1275-
return oslg.invalid("sched", mth, 0, CN.DBG, res)
1299+
return oslg.mismatch("sched", sched, cl, mth, CN.DBG, res)
12761300

12771301
values = list(sched.defaultDaySchedule().values())
12781302

@@ -1294,6 +1318,134 @@ def scheduleRulesetMinMax(sched=None):
12941318
return res
12951319

12961320

1321+
def scheduleConstantMinMax(sched=None) -> dict:
1322+
"""Returns MIN/MAX values of a schedule (constant).
1323+
1324+
Args:
1325+
sched (openstudio.model.ScheduleConstant):
1326+
A schedule.
1327+
1328+
Returns:
1329+
dict:
1330+
- "min" (float): min temperature. (None if invalid inputs - see logs).
1331+
- "max" (float): max temperature. (None if invalid inputs - see logs).
1332+
"""
1333+
# Largely inspired from David Goldwasser's
1334+
# "schedule_constant_annual_min_max_value":
1335+
#
1336+
# github.com/NREL/openstudio-standards/blob/
1337+
# 99cf713750661fe7d2082739f251269c2dfd9140/lib/openstudio-standards/
1338+
# standards/Standards.ScheduleConstant.rb#L21
1339+
mth = "osut.scheduleConstantMinMax"
1340+
cl = openstudio.model.ScheduleConstant
1341+
res = dict(min=None, max=None)
1342+
1343+
if not isinstance(sched, cl):
1344+
return oslg.mismatch("sched", sched, cl, mth, CN.DBG, res)
1345+
1346+
try:
1347+
value = float(sched.value())
1348+
except:
1349+
return None
1350+
1351+
res["min"] = value
1352+
res["max"] = value
1353+
1354+
return res
1355+
1356+
1357+
def scheduleCompactMinMax(sched=None) -> dict:
1358+
"""Returns MIN/MAX values of a schedule (compact).
1359+
1360+
Args:
1361+
sched (openstudio.model.ScheduleCompact):
1362+
A schedule.
1363+
1364+
Returns:
1365+
dict:
1366+
- "min" (float): min temperature. (None if invalid inputs - see logs).
1367+
- "max" (float): max temperature. (None if invalid inputs - see logs).
1368+
"""
1369+
# Largely inspired from Andrew Parker's
1370+
# "schedule_compact_annual_min_max_value":
1371+
#
1372+
# github.com/NREL/openstudio-standards/blob/
1373+
# 99cf713750661fe7d2082739f251269c2dfd9140/lib/openstudio-standards/
1374+
# standards/Standards.ScheduleCompact.rb#L8
1375+
mth = "osut.scheduleCompactMinMax"
1376+
cl = openstudio.model.ScheduleCompact
1377+
vals = []
1378+
prev = ""
1379+
res = dict(min=None, max=None)
1380+
1381+
if not isinstance(sched, cl):
1382+
return oslg.mismatch("sched", sched, cl, mth, CN.DBG, res)
1383+
1384+
for eg in sched.extensibleGroups():
1385+
if "until" in prev:
1386+
if eg.getDouble(0): vals.append(eg.getDouble(0).get())
1387+
1388+
str = eg.getString(0)
1389+
1390+
if str: prev = str.get().lower()
1391+
1392+
if not vals:
1393+
return oslg.empty("compact sched values", mth, CN.WRN, res)
1394+
1395+
res["min"] = min(vals)
1396+
res["max"] = max(vals)
1397+
1398+
try:
1399+
res["min"] = float(res["min"])
1400+
except:
1401+
res["min"] = None
1402+
1403+
try:
1404+
res["max"] = float(res["max"])
1405+
except:
1406+
res["max"] = None
1407+
1408+
return res
1409+
1410+
1411+
def scheduleIntervalMinMax(sched=None) -> dict:
1412+
"""Returns MIN/MAX values of a schedule (interval).
1413+
1414+
Args:
1415+
sched (openstudio.model.ScheduleInterval):
1416+
A schedule.
1417+
1418+
Returns:
1419+
dict:
1420+
- "min" (float): min temperature. (None if invalid inputs - see logs).
1421+
- "max" (float): max temperature. (None if invalid inputs - see logs).
1422+
"""
1423+
mth = "osut.scheduleCompactMinMax"
1424+
cl = openstudio.model.ScheduleInterval
1425+
vals = []
1426+
res = dict(min=None, max=None)
1427+
1428+
if not isinstance(sched, cl):
1429+
return oslg.mismatch("sched", sched, cl, mth, CN.DBG, res)
1430+
1431+
vals = sched.timeSeries().values()
1432+
1433+
res["min"] = min(values)
1434+
res["max"] = max(values)
1435+
1436+
try:
1437+
res["min"] = float(res["min"])
1438+
except:
1439+
res["min"] = None
1440+
1441+
try:
1442+
res["max"] = float(res["max"])
1443+
except:
1444+
res["max"] = None
1445+
1446+
return res
1447+
1448+
12971449
def transforms(group=None) -> dict:
12981450
""""Returns OpenStudio site/space transformation & rotation angle.
12991451

0 commit comments

Comments
 (0)