Untitled
unknown
plain_text
4 years ago
10 kB
8
Indexable
import random
import numpy as np
import math
import sys
import matplotlib.pyplot as plt
from matplotlib import animation
from matplotlib import colors
from matplotlib.animation import FuncAnimation
EMPTY, FLAMMABLE, BURNING, BURNED = 0,1,2,3
def get_states(my_grid):
state_grid = np.empty((GRID_HEIGHT, GRID_WIDTH), dtype=int)
#state_grid = [map(myfunc, x) for x in my_grid]
for y in range(0, GRID_HEIGHT ):
for x in range(0, GRID_WIDTH ):
state_grid[y][x] = my_grid[y][x].state
return state_grid
def get_time_to_burn(my_grid):
time_to_burn_grid = np.empty((GRID_HEIGHT, GRID_WIDTH), dtype=float)
for y in range(0, GRID_HEIGHT ):
for x in range(0, GRID_WIDTH ):
time_to_burn_grid[y][x] = my_grid[y][x].time_to_burn
return time_to_burn_grid
class Fuel:
def __init__(self, Wo, Rho_p, Stau, Mx, Se, h, sigma, delta):
self.Wo = Wo
self.Rho_p = Rho_p
self.Stau = Stau
self.Mx = Mx
self.Se = Se
self.h = h
self.sigma = sigma
self.delta = delta
# w_o Oven-dry fuel load
# ρ_p Fuel particle density
# S_τ Total mineral content
# M_x Moisture of extinction
# S_e Effective mineral content
# h Heat content of the fuel
# σ Surface-area-to-volume-ratio
# δ Fuel bed depth
grass = Fuel(1.347, 512, 0.0555, 25, 0.01, 18622, 57, 0.76)
shrub = Fuel(2.35, 512, 0.0555, 26, 0.01, 18622, 55, 0.80)
conifer = Fuel(2.4, 512, 0.0555, 30, 0.01, 18622, 53, 0.72)
# M_f Fuel moisture
# U Wind speed
# θ Slope angle at midflame height
class Cell:
def __init__(self, Mf, U, pi, fuel=None):
self.Mf = Mf
self.U = U
self.pi = pi
self.fuel = fuel
self.time_to_burn = sys.maxsize #change to better
self.has_burning_neighbour = False
if self.fuel is None:
self.state = EMPTY # let's write burning, burned...
self.ROS = 0
self.time_to_burn = None
else:
self.state = FLAMMABLE
self.ROS = self.calc_ROS()
def calc_ROS(self):
Gm_max = ((30.48 * self.fuel.sigma) ** 1.5) / ( 495 + .0594 * (30.48 * self.fuel.sigma) ** 1.5) # FROM FIRESTATION =/= Paper
Rho_b = self.fuel.Wo / self.fuel.delta #kg/m
b = Rho_b / self.fuel.Rho_p # m^2
bop = 0.20395 * self.fuel.sigma ** (-0.8189) # CORRIGIDO #cm^-1
A = 8.9033 * self.fuel.sigma ** (-0.7913) # CORRIGIDO #cm^-1
Gm = Gm_max * ((b / bop) ** A) * np.exp(A * (1 - b / bop)) # FROM FIRESTATION =/= Paper
Wn = self.fuel.Wo * (1 - self.fuel.Stau) # CORRIGIDO #kg/m^2
Tau_m = self.Mf / self.fuel.Mx
Eta_m = 1 - 2.59 * Tau_m + 5.11 * (Tau_m ** 2) - 3.52 * (Tau_m ** 3)
Eta_s = 0.174 * self.fuel.Se ** (-0.19)
Ir = Gm * Wn * self.fuel.h * Eta_m * Eta_s / 60 # OUTPUT R in m/s
Xi = (192 + 7.9095 * self.fuel.sigma) ** (-1) * np.exp((0.792 + 3.7597 * self.fuel.sigma ** 0.5) * (b + 0.1)) # (42)CORRIGIDO
C = 7.47 * np.exp(-0.8711 * (self.fuel.sigma ** 0.55)) # CORRIGIDO
B = 0.15988 * (self.fuel.sigma ** 0.54) # CORRIGIDO
E = 0.715 * np.exp(-0.01094 * self.fuel.sigma) # CORRIGIDO
Pi_w = C * (3.281 * self.U ** B) * ((b / bop) ** (-E)) # 47 CORRIGIDO
Pi_s = 5.275 * (b ** (-0.3)) * (np.tan(self.pi) ** (2)) # 51 CORRIGIDO
EE = np.exp(-4.528 / self.fuel.sigma) # 14 CORRIGIDO
Qig = 581 + 2594 * self.Mf
R = Ir * Xi * (1 + Pi_w + Pi_s) / (Rho_b * EE * Qig)
R = round(R, 6)
return R
def Harmonic_ROS(self, neighbor_cell):
return (2 * self.ROS * neighbor_cell.ROS) / (self.ROS + neighbor_cell.ROS)
def Harmonic_ROS_time_adjacent(self, neighbor_cell):
if self.Harmonic_ROS(neighbor_cell) == 0:
return sys.maxsize #make this better
return round((LENGTH_EDGE / self.Harmonic_ROS(neighbor_cell)) / 60, 6) # min
def Harmonic_ROS_time_sub_adjacent(self, neighbor_cell):
if self.Harmonic_ROS(neighbor_cell) == 0:
return sys.maxsize #make this better
return round(((math.sqrt(2) * LENGTH_EDGE) / self.Harmonic_ROS(neighbor_cell)) / 60, 6) # min
GRID_HEIGHT = 8
GRID_WIDTH = 8
TOTAL_TIME = 5
LENGTH_EDGE = 25 # m I should do differently. cells' edge should equal to this number
adjacent_neighbours = ((-1, 0), (0, -1), (0, 1), (1, 0))
sub_adjacent_neighbours = ((-1, -1), (-1, 1), (1, -1), (1, 1))
all_neighbours = ((-1, 0), (0, -1), (0, 1), (1, 0), (-1, -1), (-1, 1), (1, -1), (1, 1))
grid = np.empty((GRID_HEIGHT, GRID_WIDTH), dtype=Cell)
state_grid = np.empty((GRID_HEIGHT, GRID_WIDTH), dtype=int)
fuel_grid = np.empty((GRID_HEIGHT, GRID_WIDTH), dtype=str)
results = []
for y in range(0, GRID_HEIGHT):
for x in range(0, GRID_WIDTH):
new_random_number = random.randint(0, 100)
if new_random_number <= 1:
# water cell
new_cell = Cell(0, 0, 0)
fuel_grid[y][x] = 'EMPTY'
elif new_random_number > 1 and new_random_number <= 15:
# grass cell
new_cell = Cell(12.8, 2.82, 0, grass)
fuel_grid[y][x] = 'GRASS'
elif new_random_number > 15 and new_random_number <= 65:
# shrub cell
new_cell = Cell(12.8, 2.82, 0, shrub)
fuel_grid[y][x] = 'SHRUB'
else:
# conifer cell
new_cell = Cell(12.8, 2.82, 0, conifer)
fuel_grid[y][x] = 'CONIFER'
grid[y][x] = new_cell
state_grid[y][x] = new_cell.state
grid[2][3].state = BURNING
grid[4][3].state = BURNING
print('STATES at beginning ')
print(get_states(grid))
print()
for time in range(0, TOTAL_TIME):
time_to_burn_compare = []
for y in range(1, GRID_HEIGHT-1):
for x in range(1, GRID_WIDTH-1):
# if grid[y][x].time_to_burn <= 0:
#
# grid[y][x].time_to_burn = sys.maxsize
if grid[y][x].state == BURNED:
grid[y][x].time_to_burn = sys.maxsize
grid[y][x].has_burning_neighbour = False # maybe we should not put here?
if grid[y][x].state == FLAMMABLE: #checking flammable cells' neighbors
current_shortest_time_pos = (None, None)
Harmonic_ROS_times_to_compare = []
for (dx, dy) in all_neighbours:
# if grid[y+dy][x+dx].state == BURNED or grid[y+dy][x+dx].state == EMPTY or grid[y+dy][x+dx].state == FLAMMABLE:
# #maybe I need to say like if == 0,1,3 don't calculate H.ROS but how?
# continue
if grid[y+dy][x+dx].state == BURNING:
grid[y][x].has_burning_neighbour = True
if (dx, dy) in adjacent_neighbours:
Harmonic_ROS_time = grid[y][x].Harmonic_ROS_time_adjacent(grid[y+dy][x+dx])
if (dx, dy) in sub_adjacent_neighbours:
Harmonic_ROS_time = grid[y][x].Harmonic_ROS_time_sub_adjacent(grid[y+dy][x+dx])
Harmonic_ROS_times_to_compare.append(Harmonic_ROS_time)
if grid[y][x].has_burning_neighbour:
Harmonic_ROS_times_to_compare.append(grid[y][x].time_to_burn)
print('Harmonic_ROS_times_to_compare:')
print(Harmonic_ROS_times_to_compare)
grid[y][x].time_to_burn = min(Harmonic_ROS_times_to_compare)
time_to_burn_compare.append(grid[y][x].time_to_burn)
else:
grid[y][x].time_to_burn = sys.maxsize
print('cell time_to_burn(min):')
print(grid[y][x].time_to_burn)
print()
print('time_to_burn_compare: ')
print(time_to_burn_compare)
if min(time_to_burn_compare) == sys.maxsize:
current_shortest_time = 0
print('current shortest time is 0, there is a problem?')
else:
current_shortest_time = min(time_to_burn_compare)
print()
print('current_shortest_time(min):')
print(current_shortest_time)
for y in range(1, GRID_HEIGHT - 1):
for x in range(1, GRID_WIDTH - 1):
if grid[y][x].time_to_burn != None:
#if grid[y][x].has_burning_neighbour:
grid[y][x].time_to_burn = grid[y][x].time_to_burn - current_shortest_time
if grid[y][x].state == BURNING:
grid[y][x].state = BURNED
grid[y][x].time_to_burn = sys.maxsize #i should make this better
elif grid[y][x].state == FLAMMABLE and grid[y][x].time_to_burn <= 0 and grid[y][x].time_to_burn != None:
grid[y][x].state = BURNING
#grid[y][x].time_to_burn = sys.maxsize #i should make this better because i can not track which cell has 0 timetoburn
print()
print('time_to_burn_after_reducing_CurrentShortestTime(min):')
print(grid[y][x].time_to_burn)
results.append(get_states(grid))
print()
print('STATES at end of TİME: ' + str(time))
print(get_states(grid))
# print()
# print('TTB at end of TİME: ' + str(time))
# print(get_time_to_burn(grid))
# print()
print(fuel_grid)
fig, ax = plt.subplots(figsize=(5, 8))
cmap = colors.ListedColormap(['mediumblue','limegreen', 'red', 'darkred'])
def update(i):
im_normed = results[i]
ax.imshow(im_normed, cmap=cmap)
ax.set_title("Time step: {}".format(i), fontsize=20)
ax.set_axis_off()
anim = animation.FuncAnimation(fig, update, frames=np.arange(0, 5), interval=10)
anim.save('colour_rotation.gif', dpi=80, writer='imagemagick')
plt.close()
print("finished")
Editor is loading...