-
Notifications
You must be signed in to change notification settings - Fork 0
/
fbp.py
151 lines (119 loc) · 4.94 KB
/
fbp.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
"""
Contains routines for unifying the components of the fire behavior
prediction model coded in this package.
"""
import math
import nffl
from model import RothermelFuel
from rothweights import WeightedRothermelModel, RothermelFuelComplex, \
LIVE, DEAD
from albini import WeightedAlbiniModel, AlbiniFuelComplex, AlbiniFuel
from common.fbp import FireBehaviorPrediction
class RothermelFBP(FireBehaviorPrediction) :
"""
Configures a "fire behavior prediction" element using the
Rothermel weighting scheme.
"""
fuelModelMethods = { '1' : nffl.nffl1, '2' : nffl.nffl2,
'3' : nffl.nffl3, '4' : nffl.nffl4,
'5' : nffl.nffl5, '6' : nffl.nffl6,
'7' : nffl.nffl7, '8' : nffl.nffl8,
'9' : nffl.nffl9, '10' : nffl.nffl10,
'11' : nffl.nffl11, '12' : nffl.nffl12,
'13' : nffl.nffl13 }
fuelModelNames = fuelModelMethods.keys()
# Produce Rothermel-weighted fuel classes
_fbpFireModelClass = WeightedRothermelModel
_fbpFuelModelClass = RothermelFuelComplex
_fbpFuelComponentClass = RothermelFuel
# represents the fuel complex and the fire model
fuelComplex = None
fireModel = None
def _setFuelModel(self) :
if self.fireModel == None :
self.fireModel = self._fbpFireModelClass(self.fuelComplex)
else :
self.fireModel.fuel = self.fuelComplex
def setNamedFuelModel(self, modelName) :
# let the parent do it's thing
FireBehaviorPrediction.setNamedFuelModel(self, modelName)
# create a named NFFL fuel model
nffl.FuelComponent = self._fbpFuelComponentClass
nffl.FuelComplex = self._fbpFuelModelClass
self.fuelComplex = (self.fuelModelMethods[modelName])()
self._setFuelModel()
def setCustomFuelModel(self, model) :
# let the parent do it's thing
FireBehaviorPrediction.setCustomFuelModel(self, model)
# retain the reference
self.fuelComplex = model
self._setFuelModel()
def setDeadFuelMoistures(self, moistures) :
# let the parent do it's thing
FireBehaviorPrediction.setDeadFuelMoistures(self, moistures)
# user MUST have selected a fuel model first!
if self.fireModel == None :
raise AttributeError("Set the fuel model before setting fuel moistures!")
for i in moistures.items() :
sizeClass = i[0]
moisture = i[1]
if not (sizeClass in self.fuelComplex.fuelParameters[DEAD]) :
raise ValueError("Size class: " + sizeClass + " not in fuel model.")
self.fuelComplex.setFuelMoisture(DEAD, sizeClass, moisture)
def setLiveFuelMoistures(self, moistures) :
# let the parent do it's thing
FireBehaviorPrediction.setLiveFuelMoistures(self, moistures)
# user MUST have selected a fuel model first!
if self.fireModel == None :
raise AttributeError("Set the fuel model before setting fuel moistures!")
# user MUST have selected a fuel model with LIVE fuels!
if not LIVE in self.fuelComplex.fuelParameters :
raise ValueError("This fuel model does not have live fuels!!")
for i in moistures.items() :
sizeClass = i[0]
moisture = i[1]
if not sizeClass in self.fuelComplex.fuelParameters[LIVE] :
raise ValueError("Size class: " + sizeClass + " not in fuel model.")
self.fuelComplex.setFuelMoisture(LIVE, sizeClass, moisture)
def getRateOfSpread(self) :
# check to see if the value is cached.
if self.rateOfSpread != None :
return self.rateOfSpread
self.evaluate()
if self.rateOfSpread < 0. :
self.rateOfSpread = 0.
return self.rateOfSpread
def getHeatPerArea(self) :
# check to see if the value is cached.
if self.rateOfSpread != None :
return self.heatPerArea
self.evaluate()
if self.heatPerArea < 0. :
self.heatPerArea = 0.
return self.heatPerArea
def evaluate(self) :
# only recompute if BOTH rateOfSpread and heatPerArea are null
if (self.rateOfSpread == None) and (self.heatPerArea == None) :
# aggregate the components into category and complex values
self.fuelComplex.compute()
# if there are live fuels, compute the live fuel moisture of
# extinction
if LIVE in self.fuelComplex.fuelParameters :
self.fuelComplex.calcLivingExtMoisture()
# set the slope and the wind now
self.fireModel.setSlope(math.radians(self.slope))
self.fireModel.setWind(self.midflameWindSpeed * (5280. / 60.))
# compute the fire behavior
self.fireModel.evaluate()
# store the results
self.heatPerArea = self.fireModel.reactionIntensity
self.rateOfSpread = self.fireModel.ros
class AlbiniFBP(RothermelFBP) :
"""
Configures a fire behavior prediction element utilizing the Albini
weighting scheme.
"""
# Produce Albini-weighted fuel classes
_fbpFireModelClass = WeightedAlbiniModel
_fbpFuelModelClass = AlbiniFuelComplex
_fbpFuelComponentClass = AlbiniFuel