def feasible(h, num): feasible2 = True for i in range(nt): if i != num: if distance(h[num][0], h[num][1], h[i][0], h[i][1]) < 2.0 * diam: feasible2 = False break return feasible2
def find_distance(nt, a, diam, min_x, max_x, min_y, max_y): n = 0 while n == 0: n = 1 for i in range(nt): for j in range(nt): if i != j and distance(a[i][0], a[i][1], a[j][0], a[j][1]) < 2.0 * diam: # print 'counting' a[j] = gen_turbine(min_x, max_x, min_y, max_y) n = 0 return a
def pso_horns(): windrose = open('horns_rev_windrose2.dat', 'r') windrose_angle = [] windrose_speed = [] windrose_frequency = [] for line in windrose: columns = line.split() windrose_angle.append(float(columns[0])) windrose_speed.append(float(columns[1])) windrose_frequency.append(float(columns[2])) windrose.close() data = open('try_best_layout_jensen.dat', 'w') data2 = open('try_random_layout_jensen.dat', 'w') data3 = open('try_best_global_fitness_jensen.dat', 'w', 1) np = 20 ## Number of particles in swarm nt = 80 diam = 80.0 particles = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) if random() < 0.5: sign1 = 1.0 else: sign1 = - 1.0 if random() < 0.5: sign2 = 1.0 else: sign2 = - 1.0 vel = array([[[sign1 * random(), sign2 * random()] for x in range(nt)] for x in range(np)]) best_local = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) best_own_fitness = [0.0 for x in range(np)] best_global_fitness = 0.0 def create(): k = random() l = random() xt = 5457.0 * l if xt <= 412.0: yt = k * 3907.0 + (1.0 - k) * (- 3907.0 / 412.0 * xt + 3907.0) elif xt <= 5040.0: yt = random() * 3907.0 else: yt = k * (3907.0 / 417.0 * (- xt + 5457.0)) return xt, yt ## Produce starting positions. Includes boundaries of Horns Rev for n in range(np): for tur in range(nt): particles[n][tur] = create() best_layout = particles[0] for i in range(nt): data.write('{2:d} {0:f} {1:f}\n'.format(best_layout[i][0], best_layout[i][1], i)) data.write('\n') # Velocity limiting to 10% to start with, for convergence, and then increase speed.s k = 0.1 for iter in range(2000): start_time2 = time.time() # fitness = Parallel(n_jobs=8)(delayed(fit)(particles[i], windrose_angle, windrose_speed, windrose_frequency) for i in range(np)) fitness = [0.0 for x in range(np)] # Fitness evaluation skipped if a turbine is out of boundaries. following: BrattonKennedy07 PSO. for p in range(np): # Can be parallelised in the future. check = True for tur in range(nt): if particles[p][tur][1] > 3907.0: check = False break elif particles[p][tur][1] < 0.0: check = False break elif particles[p][tur][1] > 3907.0 / 417.0 * (- particles[p][tur][0] + 5457.0): check = False break elif particles[p][tur][1] < - 3907.0 / 412.0 * particles[p][tur][0] + 3907.0: check = False break if check: fitness[p] = fit(particles[p], windrose_angle, windrose_speed, windrose_frequency) if fitness[p] > best_own_fitness[p]: best_own_fitness[p] = fitness[p] best_local[p] = particles[p] if fitness[p] > best_global_fitness: best_global_fitness = fitness[p] best_layout = particles[p] for i in range(nt): data.write('{2:d} {0:f} {1:f}\n'.format(best_layout[i][0], best_layout[i][1], i)) data2.write('{2:d} {0:f} {1:f}\n'.format(particles[10][i][0], particles[10][i][1], i)) data2.write('\n') data.write('\n') data3.write('{0:f}\n'.format(best_global_fitness)) for p in range(np): # Can be parallelised in the future. ## Solving Constrained Nonlinear Optimization Problems with Particle Swarm Optimization by Xiaohui Hu and Russell Eberhart. For 1.49445 learning coefficients. vel[p] = (0.5 + random() / 2.0) * vel[p] + 2.0 * random() * (best_local[p] - particles[p]) + 2.0 * random() * (best_layout - particles[p]) for t in range(nt): # Velocity half the maximum distance between boundaries. following: Particle Swarm Optimization: A Tutorial by James Blondin PSO if vel[p][t][0] > k * 2728.5: vel[p][t][0] = k * 2728.5 if vel[p][t][0] < - k * 2728.5: vel[p][t][0] = - k * 2728.5 if vel[p][t][1] > k * 1953.5: vel[p][t][1] = k * 1953.5 if vel[p][t][1] < - k * 1953.5: vel[p][t][1] = - k * 1953.5 particles[p] = particles[p] + vel[p] # Find minimum distance between turbines, and if two are closer than 1D, then randomise one of them. for b in range(np): pp = 0 while pp == 0: pp = 1 for i in range(nt): for j in range(nt): if i != j and distance(particles[b][i][0], particles[b][i][1], particles[b][j][0], particles[b][j][1]) < diam: particles[b][j] = create() pp = 0 print("Iteration --- %s seconds ---" % (time.time() - start_time2)) data.close() data2.close() data3.close()
def pso_horns(): data = open('3horns_pso.dat', 'w') data2 = open('3swarm_horns.dat', 'w') data3 = open('3globalfit.dat', 'w') np = 20 nt = 45 diam = 80.0 particles = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) if random() < 0.5: sign1 = 1.0 else: sign1 = -1.0 if random() < 0.5: sign2 = 1.0 else: sign2 = -1.0 vel = array([[[sign1 * random(), sign2 * random()] for x in range(nt)] for x in range(np)]) best_local = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) best_own_fitness = [0.0 for x in range(np)] best_global_fitness = 0.0 def create(): k = random() l = random() xt = 400.0 * l yt = 3600 * k return xt, yt ## Produce starting positions. Includes boundaries of Horns Rev for n in range(np): for tur in range(nt): particles[n][tur] = create() best_layout = particles[0] for i in range(nt): data.write('{2:d} {0:f} {1:f}\n'.format(best_layout[i][0], best_layout[i][1], i)) data.write('\n') for iter in range(2000): start_time2 = time.time() fitness = Parallel(n_jobs=8)(delayed(fit)(particles[i], nt, diam / 2.0) for i in range(np)) # for p in range(np): # fitness[p] = fit(particles[p], nt, diam / 2.0) for p in range(np): if fitness[p] > best_own_fitness[p]: best_own_fitness[p] = fitness[p] best_local[p] = particles[p] if fitness[p] > best_global_fitness: best_global_fitness = fitness[p] best_layout = particles[p] for i in range(nt): data.write('{2:d} {0:f} {1:f}\n'.format(best_layout[i][0], best_layout[i][1], i)) data2.write('{2:d} {0:f} {1:f}\n'.format(particles[10][i][0], particles[10][i][1], i)) data2.write('\n') data.write('\n') data3.write('{0:f}\n'.format(best_global_fitness)) for p in range(np): ## Solving Constrained Nonlinear Optimization Problems with Particle Swarm Optimization by Xiaohui Hu and Russell Eberhart. For 1.49445 learning coefficients. vel[p] = (0.5 + random() / 2.0) * vel[p] + 2.0 * random() * ( best_local[p] - particles[p]) + 2.0 * random() * (best_layout - particles[p]) for t in range(nt): if vel[p][t][0] > 400.0: vel[p][t][0] = 400.0 if vel[p][t][0] < -400.0: vel[p][t][0] = -400.0 if vel[p][t][1] > 3600.0: vel[p][t][1] = 3600.0 if vel[p][t][1] < -3600.0: vel[p][t][1] = -3600.0 particles[p] = particles[p] + vel[p] for tur in range(nt): if particles[p][tur][1] > 3600.0: particles[p][tur][1] = random() * 3600.0 elif particles[p][tur][1] < 0.0: particles[p][tur][1] = random() * 3600.0 if particles[p][tur][0] > 400.0: particles[p][tur][0] = random() * 400.0 elif particles[p][tur][0] < 0.0: particles[p][tur][0] = random() * 400.0 # Find minimum distance between turbines, and if two are closer than 1D, then randomise one of them. for b in range(np): pp = 0 while pp == 0: pp = 1 for i in range(nt): for j in range(nt): if i != j and distance( particles[b][i][0], particles[b][i][1], particles[b][j][0], particles[b][j][1]) < diam: particles[b][j] = create() pp = 0 print best_global_fitness if iter % 50 == 0: sys.stdout.flush() print("Iteration --- %s seconds ---" % (time.time() - start_time2)) data.close() data2.close() data3.close()
def jensen(a, windrose_angle, windrose_speed, windrose_frequency): import wake from math import sqrt, log, tan, cos from numpy import deg2rad nt = len(a) layout_x = [0.0 for x in range(nt)] layout_y = [0.0 for x in range(nt)] for x in range(nt): layout_x[x] = float(a[x][0]) layout_y[x] = float(a[x][1]) def Ct(U0): if U0 < 4.0: return 0.1 elif U0 <= 25.0: return 0.00000073139922126945 * U0**6.0 - 0.0000668905596915255 * U0**5.0 + 0.0023937885 * U0**4.0 + -0.0420283143 * U0**3.0 + 0.3716111285 * U0**2.0 - 1.5686969749 * U0 + 3.2991094727 else: return 0.0 def power(U0): if U0 < 4.0: return 0.0 elif U0 <= 25.0: return 0.0003234808 * U0**7.0 - 0.0331940121 * U0**6.0 + 1.3883148012 * U0**5.0 - 30.3162345004 * U0**4.0 + 367.6835557011 * U0**3.0 - 2441.6860655008 * U0**2.0 + 8345.6777042343 * U0 - 11352.9366182805 else: return 0.0 # for U0 in range(4, 20): nt = 80 # Number of turbines summation = 0.0 def distance_to_front(x, y, theta, r): theta = deg2rad(theta) return abs(x + tan(theta) * y - r / cos(theta)) / sqrt(1.0 + tan(theta)**2.0) for wind in range(0, len(windrose_angle)): U1 = windrose_speed[wind] # Free stream wind speed U0 = U1 * (70.0 / 10.0)**0.11 # Power or log law for wind shear profile k = 0.04 # Decay constant r0 = 40.0 # Turbine rotor radius angle = windrose_angle[wind] angle3 = angle + 180.0 deficit_matrix = [[0.0 for x in range(nt)] for x in range(nt)] proportion = [[0.0 for x in range(nt)] for x in range(nt)] distance = [[0.0 for x in range(2)] for x in range(nt)] U = [U0 for x in range(nt)] total_deficit = [0.0 for x in range(nt)] for tur in range(nt): distance[tur] = [ distance_to_front(layout_x[tur], layout_y[tur], angle, 100000000.0), tur ] distance.sort() for turbine in range(nt): for num in range(turbine): total_deficit[distance[turbine][1]] += deficit_matrix[ distance[turbine][1]][distance[num][1]]**2.0 total_deficit[distance[turbine][1]] = sqrt( total_deficit[distance[turbine][1]]) U[distance[turbine] [1]] = U0 * (1.0 - total_deficit[distance[turbine][1]]) for i in range(turbine + 1, nt): proportion[distance[turbine][1]][ distance[i][1]] = wake.determine_if_in_wake( layout_x[distance[turbine][1]], layout_y[distance[turbine][1]], layout_x[distance[i][1]], layout_y[distance[i][1]], k, r0, angle3) deficit_matrix[distance[i][1]][ distance[turbine][1]] = proportion[distance[turbine][1]][ distance[i][1]] * wake.wake_deficit( Ct(U[distance[turbine][1]]), k, wake.distance(layout_x[distance[turbine][1]], layout_y[distance[turbine][1]], layout_x[distance[i][1]], layout_y[distance[i][1]]), r0) # Farm efficiency profit = 0.0 efficiency_proportion = [ 0.0 for x in range(0, len(windrose_frequency)) ] for l in range(nt): profit += power(U[l]) efficiency = profit * 100.0 / (float(nt) * power(U[distance[0][1]])) efficiency_proportion[ wind] = efficiency * windrose_frequency[wind] / 100.0 # print 'Farm efficiency with wind direction = {0:d} deg: {1:2.2f}%'.format(int(angle), efficiency) summation += efficiency_proportion[wind] return summation
def pso_horns(): time4 = time.time() windrose = open('horns_rev_windrose2.dat', 'r') windrose_angle = [] windrose_speed = [] windrose_frequency = [] for line in windrose: columns = line.split() windrose_angle.append(float(columns[0])) windrose_speed.append(float(columns[1])) windrose_frequency.append(float(columns[2])) windrose.close() data = open('try6_layout_jensen.dat', 'w') data2 = open('try6_random_layout_jensen.dat', 'w') data3 = open('try6_best_global_fitness_jensen.dat', 'w', 1) allfit = open('try6_all_fitnesses.dat', 'w', 1) np = 10 ## Number of particles in swarm nt = 80 diam = 80.0 particles = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) vel = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) best_own_fitness = [100.0 for x in range(np)] def create(): kk = random() l = random() xt = 5457.0 * l if xt <= 412.0: yt = kk * 3907.0 + (1.0 - kk) * (- 3907.0 / 412.0 * (xt + 10.0) + 3907.0) elif xt <= 5040.0: yt = kk * 3907.0 else: yt = kk * (3907.0 / 417.0 * (- xt + 5457.0 + 10.0)) return xt, yt ## Produce starting positions. Includes boundaries of Horns Rev for n in range(np): for tur in range(nt): particles[n][tur] = create() # layout = open('horns_rev.dat', 'r') # ll = 0 # horns = array([[0, 0] for gf in range(nt)]) # for line in layout: # columns = line.split() # horns[ll] = [float(columns[0]) - 423974.0, float(columns[1]) - 6147543.0] # ll += 1 # layout.close() # particles[np - 1] = deepcopy(horns) best_local = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) # Fitness evaluation skipped if a turbine is out of boundaries. following: BrattonKennedy07 PSO. # More 'repair' methods for particles out of boundaries shown in PhD thesis Helwig2010. # Chu2011 proves that the reflecting boundary method is better than random or absorbing boundary. TODO implement fitness = Parallel(n_jobs=-1)(delayed(efficiency)(particles[i], windrose_angle, windrose_speed, windrose_frequency, nt) for i in range(np)) print fitness for fg in range(np): allfit.write('{0:f}\n'.format(fitness[fg])) allfit.write('\n') for p in range(np): best_own_fitness[p] = deepcopy(fitness[p]) best_local[p] = deepcopy(particles[p]) best_global_fitness = min(fitness) print best_global_fitness print best_own_fitness best_layout = deepcopy(particles[fitness.index(min(fitness))]) print best_local[5][54][1] - particles[5][54][1] # for i in range(nt): # data.write('{2:d} {0:f} {1:f}\n'.format(best_layout[i][0], best_layout[i][1], i)) # data.write('\n') # Velocity limiting to 10% to start with, for convergence, and then increase speed. k = 1.0 for ite in range(200): start_time2 = time.time() particles = Parallel(n_jobs=-1)(delayed(movement)(vel[i], best_local[i], particles[i], best_layout, k, nt) for i in range(np)) # Find minimum distance between turbines, and if two are closer than 1D, then randomise one of them. for b in range(np): pp = 0 while pp == 0: pp = 1 for i in range(nt): for j in range(nt): if i != j and distance(particles[b][i][0], particles[b][i][1], particles[b][j][0], particles[b][j][1]) < 2.0 * diam: particles[b][j] = create() pp = 0 # Fitness evaluation skipped if a turbine is out of boundaries. following: BrattonKennedy07 PSO. # More 'repair' methods for particles out of boundaries shown in PhD thesis Helwig2010. # Chu2011 proves that the reflecting boundary method is better than random or absorbing boundary. TODO implement fitness = Parallel(n_jobs=-1)(delayed(efficiency)(particles[i], windrose_angle, windrose_speed, windrose_frequency, nt) for i in range(np)) for fg in range(np): allfit.write('{0:f}\n'.format(fitness[fg])) allfit.write('\n') for p in range(np): if fitness[p] < best_own_fitness[p]: best_own_fitness[p] = deepcopy(fitness[p]) best_local[p] = deepcopy(particles[p]) if fitness[p] < best_global_fitness: best_global_fitness = deepcopy(fitness[p]) best_layout = deepcopy(particles[p]) for i in range(nt): data.write('{2:d} {0:f} {1:f}\n'.format(best_layout[i][0], best_layout[i][1], i)) data2.write('{2:d} {0:f} {1:f}\n'.format(particles[1][i][0], particles[1][i][1], i)) data2.write('\n') data.write('\n') data3.write('{0:f}\n'.format(best_global_fitness)) print("Iteration --- %s seconds ---" % (time.time() - start_time2)) data.close() data2.close() data3.close() allfit.close()
def pso_horns(): windrose = open('horns_rev_windrose2.dat', 'r') windrose_angle = [] windrose_speed = [] windrose_frequency = [] for line in windrose: columns = line.split() windrose_angle.append(float(columns[0])) windrose_speed.append(float(columns[1])) windrose_frequency.append(float(columns[2])) windrose.close() data = open('pso7_layout_ainslie.dat', 'w', 1) data2 = open('pso7_random_layout_ainslie.dat', 'w', 1) data3 = open('pso7_best_global_fitness_ainslie.dat', 'w', 1) # pso1 first run. Np 40 (max recommended). Ainslie model combination 30 from MCDA. 20 000 iterations to see what happens. 12.91 = 87.09% eff. # pso2 Less particles down to 25. Ive changed the inertia and acceleration coefficients multiplied by 0.1. added e-1. For smaller movements and less chaos. Didnt work because of e-1 i think, it moves too slow so nothing changes. 13.46 = 86.54% eff. # pso3 chagned e-1 to decimal notation of the accel. coefficients. 5 particles only to test. # pso4 n_iter = 80 np = 25 ## Number of particles in swarm. 2000 function calls. 8 hrs # pso5 same as pso4, with np = 15, n_iter = 134 # pso 7 same as pso 5 more iter to 268. n_iter = 268 np = 15 ## Number of particles in swarm nt = 80 diam = 80.0 particles = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) if random() < 0.5: sign1 = 1.0 else: sign1 = - 1.0 if random() < 0.5: sign2 = 1.0 else: sign2 = - 1.0 vel = array([[[sign1 * random(), sign2 * random()] for x in range(nt)] for x in range(np)]) best_own_fitness = [100.0 for x in range(np)] best_global_fitness = 100.0 def create(): k = random() l = random() xt = 5457.0 * l if xt <= 412.0: yt = k * 3907.0 + (1.0 - k) * (- 3907.0 / 412.0 * xt + 3907.0) elif xt <= 5040.0: yt = k * 3907.0 else: yt = k * (3907.0 / 417.0 * (- xt + 5457.0)) return xt, yt ## Produce starting positions. Includes boundaries of Horns Rev for n in range(np): for tur in range(nt): particles[n][tur] = create() best_layout = particles[0] best_local = array(particles) for ite in range(n_iter): # while best_global_fitness > 0.001: start_time2 = time.time() for p in range(np): # Can be parallelised in the future. # Solving Constrained Nonlinear Optimization Problems with Particle Swarm Optimization by Xiaohui Hu and Russell Eberhart. For 1.49445 learning coefficients. vel[p] = 0.72984 * vel[p] + 1.49617 * random() * (best_local[p] - particles[p]) + 1.49617 * random() * (best_layout - particles[p]) particles[p] += vel[p] for t in range(nt): # Reflect on boundary j = 1.0 w = 1.0 while particles[p][t][1] > 3907.0 or particles[p][t][1] < 0.0: if particles[p][t][1] > 3907.0: particles[p][t][1] = 3907.0 * 2.0 - particles[p][t][1] j = random() elif particles[p][t][1] < 0.0: particles[p][t][1] = - particles[p][t][1] j = random() while particles[p][t][1] < - 3907.0 / 412.0 * particles[p][t][0] + 3907.0 or particles[p][t][1] > 3907.0 / 417.0 * (- particles[p][t][0] + 5457.0): if particles[p][t][0] < 412.0 / 3907.0 * (3907.0 - particles[p][t][1]): particles[p][t][0] = 2.0 * (412.0 / 3907.0) * (3907.0 - particles[p][t][1]) - particles[p][t][0] w = random() elif particles[p][t][0] > 5457.0 - particles[p][t][0] * 417.0 / 3907.0: particles[p][t][0] = 2.0 * (5457.0 - particles[p][t][0] * 417.0 / 3907.0) - particles[p][t][0] w = random() vel[p][t] *= [- w, - j] # Find minimum distance between turbines, and if two are closer than 1D, then randomise one of them. TODO Must be 2D if used with Ainslie model, since it does not guarantee any data before 2D. for b in range(np): pp = 0 while pp == 0: pp = 1 for i in range(nt): for j in range(nt): if i != j and distance(particles[b][i][0], particles[b][i][1], particles[b][j][0], particles[b][j][1]) < 2.0 * diam: particles[b][j] = create() pp = 0 # Fitness evaluation skipped if counter turbine is out of boundaries. following: BrattonKennedy07 PSO. Not used. # More 'repair' methods for particles out of boundaries shown in PhD thesis Helwig2010. # Chu2011 proves that the reflecting boundary method is better than random or absorbing boundary. fitness = Parallel(n_jobs=8)(delayed(fit)(particles[i], windrose_angle, windrose_speed, windrose_frequency) for i in range(np)) for p in range(np): if fitness[p] < best_own_fitness[p]: best_own_fitness[p] = fitness[p] best_local[p] = copy.deepcopy(particles[p]) if fitness[p] < best_global_fitness: best_global_fitness = fitness[p] best_layout = copy.deepcopy(particles[p]) for i in range(nt): data.write('{2:d} {0:f} {1:f}\n'.format(best_layout[i][0], best_layout[i][1], i)) data.write('\n') data3.write('{1:d} {0:f}\n'.format(best_global_fitness, ite)) for i in range(nt): data2.write('{2:d} {0:f} {1:f}\n'.format(particles[4][i][0], particles[4][i][1], i)) data2.write('\n') print(" --- %s seconds ---" % (time.time() - start_time2)) data.close() data2.close() data3.close()
def pso_horns(): windrose = open('horns_rev_windrose2.dat', 'r') windrose_angle = [] windrose_speed = [] windrose_frequency = [] for line in windrose: columns = line.split() windrose_angle.append(float(columns[0])) windrose_speed.append(float(columns[1])) windrose_frequency.append(float(columns[2])) windrose.close() data = open('pso7_layout_ainslie.dat', 'w', 1) data2 = open('pso7_random_layout_ainslie.dat', 'w', 1) data3 = open('pso7_best_global_fitness_ainslie.dat', 'w', 1) # pso1 first run. Np 40 (max recommended). Ainslie model combination 30 from MCDA. 20 000 iterations to see what happens. 12.91 = 87.09% eff. # pso2 Less particles down to 25. Ive changed the inertia and acceleration coefficients multiplied by 0.1. added e-1. For smaller movements and less chaos. Didnt work because of e-1 i think, it moves too slow so nothing changes. 13.46 = 86.54% eff. # pso3 chagned e-1 to decimal notation of the accel. coefficients. 5 particles only to test. # pso4 n_iter = 80 np = 25 ## Number of particles in swarm. 2000 function calls. 8 hrs # pso5 same as pso4, with np = 15, n_iter = 134 # pso 7 same as pso 5 more iter to 268. n_iter = 268 np = 15 ## Number of particles in swarm nt = 80 diam = 80.0 particles = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) if random() < 0.5: sign1 = 1.0 else: sign1 = -1.0 if random() < 0.5: sign2 = 1.0 else: sign2 = -1.0 vel = array([[[sign1 * random(), sign2 * random()] for x in range(nt)] for x in range(np)]) best_own_fitness = [100.0 for x in range(np)] best_global_fitness = 100.0 def create(): k = random() l = random() xt = 5457.0 * l if xt <= 412.0: yt = k * 3907.0 + (1.0 - k) * (-3907.0 / 412.0 * xt + 3907.0) elif xt <= 5040.0: yt = k * 3907.0 else: yt = k * (3907.0 / 417.0 * (-xt + 5457.0)) return xt, yt ## Produce starting positions. Includes boundaries of Horns Rev for n in range(np): for tur in range(nt): particles[n][tur] = create() best_layout = particles[0] best_local = array(particles) for ite in range(n_iter): # while best_global_fitness > 0.001: start_time2 = time.time() for p in range(np): # Can be parallelised in the future. # Solving Constrained Nonlinear Optimization Problems with Particle Swarm Optimization by Xiaohui Hu and Russell Eberhart. For 1.49445 learning coefficients. vel[p] = 0.72984 * vel[p] + 1.49617 * random() * ( best_local[p] - particles[p]) + 1.49617 * random() * ( best_layout - particles[p]) particles[p] += vel[p] for t in range(nt): # Reflect on boundary j = 1.0 w = 1.0 while particles[p][t][1] > 3907.0 or particles[p][t][1] < 0.0: if particles[p][t][1] > 3907.0: particles[p][t][1] = 3907.0 * 2.0 - particles[p][t][1] j = random() elif particles[p][t][1] < 0.0: particles[p][t][1] = -particles[p][t][1] j = random() while particles[p][t][1] < -3907.0 / 412.0 * particles[p][t][ 0] + 3907.0 or particles[p][t][1] > 3907.0 / 417.0 * ( -particles[p][t][0] + 5457.0): if particles[p][t][0] < 412.0 / 3907.0 * ( 3907.0 - particles[p][t][1]): particles[p][t][0] = 2.0 * (412.0 / 3907.0) * ( 3907.0 - particles[p][t][1]) - particles[p][t][0] w = random() elif particles[p][t][ 0] > 5457.0 - particles[p][t][0] * 417.0 / 3907.0: particles[p][t][0] = 2.0 * ( 5457.0 - particles[p][t][0] * 417.0 / 3907.0) - particles[p][t][0] w = random() vel[p][t] *= [-w, -j] # Find minimum distance between turbines, and if two are closer than 1D, then randomise one of them. TODO Must be 2D if used with Ainslie model, since it does not guarantee any data before 2D. for b in range(np): pp = 0 while pp == 0: pp = 1 for i in range(nt): for j in range(nt): if i != j and distance( particles[b][i][0], particles[b][i][1], particles[b][j][0], particles[b][j][1]) < 2.0 * diam: particles[b][j] = create() pp = 0 # Fitness evaluation skipped if counter turbine is out of boundaries. following: BrattonKennedy07 PSO. Not used. # More 'repair' methods for particles out of boundaries shown in PhD thesis Helwig2010. # Chu2011 proves that the reflecting boundary method is better than random or absorbing boundary. fitness = Parallel(n_jobs=8)(delayed(fit)( particles[i], windrose_angle, windrose_speed, windrose_frequency) for i in range(np)) for p in range(np): if fitness[p] < best_own_fitness[p]: best_own_fitness[p] = fitness[p] best_local[p] = copy.deepcopy(particles[p]) if fitness[p] < best_global_fitness: best_global_fitness = fitness[p] best_layout = copy.deepcopy(particles[p]) for i in range(nt): data.write('{2:d} {0:f} {1:f}\n'.format( best_layout[i][0], best_layout[i][1], i)) data.write('\n') data3.write('{1:d} {0:f}\n'.format(best_global_fitness, ite)) for i in range(nt): data2.write('{2:d} {0:f} {1:f}\n'.format(particles[4][i][0], particles[4][i][1], i)) data2.write('\n') print(" --- %s seconds ---" % (time.time() - start_time2)) data.close() data2.close() data3.close()
def pso_horns(): windrose = open('horns_rev_windrose2.dat', 'r') windrose_angle = [] windrose_speed = [] windrose_frequency = [] for line in windrose: columns = line.split() windrose_angle.append(float(columns[0])) windrose_speed.append(float(columns[1])) windrose_frequency.append(float(columns[2])) windrose.close() data = open('try_best_layout_jensen.dat', 'w') data2 = open('try_random_layout_jensen.dat', 'w') data3 = open('try_best_global_fitness_jensen.dat', 'w', 1) np = 20 ## Number of particles in swarm nt = 80 diam = 80.0 particles = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) if random() < 0.5: sign1 = 1.0 else: sign1 = - 1.0 if random() < 0.5: sign2 = 1.0 else: sign2 = - 1.0 vel = array([[[sign1 * random(), sign2 * random()] for x in range(nt)] for x in range(np)]) best_local = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) best_own_fitness = [0.0 for x in range(np)] best_global_fitness = 0.0 def create(): k = random() l = random() xt = 5457.0 * l if xt <= 412.0: yt = k * 3907.0 + (1.0 - k) * (- 3907.0 / 412.0 * xt + 3907.0) elif xt <= 5040.0: yt = random() * 3907.0 else: yt = k * (3907.0 / 417.0 * (- xt + 5457.0)) return xt, yt # Produce starting positions. Includes boundaries of Horns Rev for n in range(np): for tur in range(nt): particles[n][tur] = create() best_layout = particles[0] for i in range(nt): data.write('{2:d} {0:f} {1:f}\n'.format(best_layout[i][0], best_layout[i][1], i)) data.write('\n') # Velocity limiting to 10% to start with, for convergence, and then increase speed.s k = 0.1 for iter in range(2000): start_time2 = time.time() # fitness = Parallel(n_jobs=8)(delayed(fit)(particles[i], windrose_angle, windrose_speed, windrose_frequency) for i in range(np)) fitness = [0.0 for x in range(np)] # Fitness evaluation skipped if a turbine is out of boundaries. following: BrattonKennedy07 PSO. for p in range(np): # Can be parallelised in the future. check = True for tur in range(nt): if particles[p][tur][1] > 3907.0: check = False break elif particles[p][tur][1] < 0.0: check = False break elif particles[p][tur][1] > 3907.0 / 417.0 * (- particles[p][tur][0] + 5457.0): check = False break elif particles[p][tur][1] < - 3907.0 / 412.0 * particles[p][tur][0] + 3907.0: check = False break if check: fitness[p] = fit(particles[p], windrose_angle, windrose_speed, windrose_frequency) if fitness[p] > best_own_fitness[p]: best_own_fitness[p] = fitness[p] best_local[p] = particles[p] if fitness[p] > best_global_fitness: best_global_fitness = fitness[p] best_layout = particles[p] for i in range(nt): data.write('{2:d} {0:f} {1:f}\n'.format(best_layout[i][0], best_layout[i][1], i)) data2.write('{2:d} {0:f} {1:f}\n'.format(particles[10][i][0], particles[10][i][1], i)) data2.write('\n') data.write('\n') data3.write('{0:f}\n'.format(best_global_fitness)) for p in range(np): # Can be parallelised in the future. ## Solving Constrained Nonlinear Optimization Problems with Particle Swarm Optimization by Xiaohui Hu and Russell Eberhart. For 1.49445 learning coefficients. vel[p] = (0.5 + random() / 2.0) * vel[p] + 2.0 * random() * (best_local[p] - particles[p]) + 2.0 * random() * (best_layout - particles[p]) for t in range(nt): # Velocity half the maximum distance between boundaries. following: Particle Swarm Optimization: A Tutorial by James Blondin PSO if vel[p][t][0] > k * 2728.5: vel[p][t][0] = k * 2728.5 if vel[p][t][0] < - k * 2728.5: vel[p][t][0] = - k * 2728.5 if vel[p][t][1] > k * 1953.5: vel[p][t][1] = k * 1953.5 if vel[p][t][1] < - k * 1953.5: vel[p][t][1] = - k * 1953.5 particles[p] = particles[p] + vel[p] # Find minimum distance between turbines, and if two are closer than 1D, then randomise one of them. for b in range(np): pp = 0 while pp == 0: pp = 1 for i in range(nt): for j in range(nt): if i != j and distance(particles[b][i][0], particles[b][i][1], particles[b][j][0], particles[b][j][1]) < diam: particles[b][j] = create() pp = 0 print("Iteration --- %s seconds ---" % (time.time() - start_time2)) data.close() data2.close() data3.close()
def jensen(a, windrose_angle, windrose_speed, windrose_frequency): import wake from math import sqrt, log, tan, cos from numpy import deg2rad nt = len(a) layout_x = [0.0 for x in range(nt)] layout_y = [0.0 for x in range(nt)] for x in range(nt): layout_x[x] = float(a[x][0]) layout_y[x] = float(a[x][1]) def Ct(U0): if U0 < 4.0: return 0.1 elif U0 <= 25.0: return 0.00000073139922126945 * U0 ** 6.0 - 0.0000668905596915255 * U0 ** 5.0 + 0.0023937885 * U0 ** 4.0 + - 0.0420283143 * U0 ** 3.0 + 0.3716111285 * U0 ** 2.0 - 1.5686969749 * U0 + 3.2991094727 else: return 0.0 def power(U0): if U0 < 4.0: return 0.0 elif U0 <= 25.0: return 0.0003234808 * U0 ** 7.0 - 0.0331940121 * U0 ** 6.0 + 1.3883148012 * U0 ** 5.0 - 30.3162345004 * U0 ** 4.0 + 367.6835557011 * U0 ** 3.0 - 2441.6860655008 * U0 ** 2.0 + 8345.6777042343 * U0 - 11352.9366182805 else: return 0.0 # for U0 in range(4, 20): nt = 80 # Number of turbines summation = 0.0 def distance_to_front(x, y, theta, r): theta = deg2rad(theta) return abs(x + tan(theta) * y - r / cos(theta)) / sqrt(1.0 + tan(theta) ** 2.0) for wind in range(0, len(windrose_angle)): U1 = windrose_speed[wind] # Free stream wind speed U0 = U1 * (70.0 / 10.0) ** 0.11 # Power or log law for wind shear profile k = 0.04 # Decay constant r0 = 40.0 # Turbine rotor radius angle = windrose_angle[wind] angle3 = angle + 180.0 deficit_matrix = [[0.0 for x in range(nt)] for x in range(nt)] proportion = [[0.0 for x in range(nt)] for x in range(nt)] distance = [[0.0 for x in range(2)] for x in range(nt)] U = [U0 for x in range(nt)] total_deficit = [0.0 for x in range(nt)] for tur in range(nt): distance[tur] = [distance_to_front(layout_x[tur], layout_y[tur], angle, 100000000.0), tur] distance.sort() for turbine in range(nt): for num in range(turbine): total_deficit[distance[turbine][1]] += deficit_matrix[distance[turbine][1]][distance[num][1]] ** 2.0 total_deficit[distance[turbine][1]] = sqrt(total_deficit[distance[turbine][1]]) U[distance[turbine][1]] = U0 * (1.0 - total_deficit[distance[turbine][1]]) for i in range(turbine + 1, nt): proportion[distance[turbine][1]][distance[i][1]] = wake.determine_if_in_wake(layout_x[distance[turbine][1]], layout_y[distance[turbine][1]], layout_x[distance[i][1]], layout_y[distance[i][1]], k, r0, angle3) deficit_matrix[distance[i][1]][distance[turbine][1]] = proportion[distance[turbine][1]][distance[i][1]] * wake.wake_deficit(Ct(U[distance[turbine][1]]), k, wake.distance(layout_x[distance[turbine][1]], layout_y[distance[turbine][1]], layout_x[distance[i][1]], layout_y[distance[i][1]]), r0) # Farm efficiency profit = 0.0 efficiency_proportion = [0.0 for x in range(0, len(windrose_frequency))] for l in range(nt): profit += power(U[l]) efficiency = profit * 100.0 / (float(nt) * power(U[distance[0][1]])) efficiency_proportion[wind] = efficiency * windrose_frequency[wind] / 100.0 # print 'Farm efficiency with wind direction = {0:d} deg: {1:2.2f}%'.format(int(angle), efficiency) summation += efficiency_proportion[wind] return summation
def pso_horns(): windrose = open('horns_rev_windrose.dat', 'r') windrose_angle = [] windrose_speed = [] windrose_frequency = [] for line in windrose: columns = line.split() windrose_angle.append(float(columns[0])) windrose_speed.append(float(columns[1])) windrose_frequency.append(float(columns[2])) windrose.close() data = open('ref3_layout.dat', 'w', 1) data2 = open('ref3_random_layout.dat', 'w', 1) data3 = open('ref3_best_global_fitness.dat', 'w', 1) allfit = open('ref3_all_fitnesses.dat', 'w', 1) # pso1 first run. Np 40 (max recommended). Ainslie model combination 30 from MCDA. 20 000 iterations to see what happens. 12.91 = 87.09% eff. # pso2 Less particles down to 25. Ive changed the inertia and acceleration coefficients multiplied by 0.1. added e-1. For smaller movements and less chaos. Didnt work because of e-1 i think, it moves too slow so nothing changes. 13.46 = 86.54% eff. # pso3 chagned e-1 to decimal notation of the accel. coefficients. 5 particles only to test. # pso4 n_iter = 80 np = 25 ## Number of particles in swarm. 2000 function calls. 8 hrs # pso6 same as pso 4 more iterations to 160. # pso8 includes one particle as the original horns rev. 10 particles to test. # ref1 reflecting, 10 particles. Changed vel and particles update with one operation per dimension. 138 seconds per iteration. # ref2 10 particles, changed windrose to 30 degrees for speed. 3.5 seconds per iteration. 200 iterations. # ref3 same as ref2, 2000 iterations. n_iter = 2000 np = 10 ## Number of particles in swarm nt = 80 diam = 80.0 particles = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) # if random() < 0.5: # sign1 = 1.0 # else: # sign1 = - 1.0 # if random() < 0.5: # sign2 = 1.0 # else: # sign2 = - 1.0 vel = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) best_own_fitness = [100.0 for x in range(np)] best_global_fitness = 100.0 def create(): k = random() l = random() xt = 5457.0 * l if xt <= 412.0: yt = k * 3907.0 + (1.0 - k) * (- 3907.0 / 412.0 * xt + 3907.0) elif xt <= 5040.0: yt = k * 3907.0 else: yt = k * (3907.0 / 417.0 * (- xt + 5457.0)) return xt, yt ## Produce starting positions. Includes boundaries of Horns Rev for n in range(np): for tur in range(nt): particles[n][tur] = create() # layout = open('horns_rev.dat', 'r') # ll = 0 # horns = array([[0, 0] for gf in range(nt)]) # for line in layout: # columns = line.split() # horns[ll] = [float(columns[0]) - 423974.0, float(columns[1]) - 6147543.0] # ll += 1 # layout.close() # particles[np - 1] = horns fitness = Parallel(n_jobs=-1)(delayed(fit)(particles[i], windrose_angle, windrose_speed, windrose_frequency) for i in range(np)) # fitness = Parallel(n_jobs=-1)(delayed(fit)(particles[i], nt) for i in range(np)) best_layout = copy.deepcopy(particles[fitness.index(min(fitness))]) best_local = copy.deepcopy(particles) for ite in range(n_iter): start_time2 = time.time() for p in range(np): # Can be parallelised in the future. # Solving Constrained Nonlinear Optimization Problems with Particle Swarm Optimization by Xiaohui Hu and Russell Eberhart. For 1.49445 learning coefficients. for t in range(nt): for coord in range(2): vel[p][t][coord] = 0.72984 * vel[p][t][coord] + 1.49617 * random() * (best_local[p][t][coord] - particles[p][t][coord]) + 1.49617 * random() * (best_layout[t][coord] - particles[p][t][coord]) particles[p][t][coord] += vel[p][t][coord] j = 1.0 w = 1.0 while particles[p][t][1] > 3907.0 or particles[p][t][1] < 0.0: if particles[p][t][1] > 3907.0: particles[p][t][1] = 3907.0 * 2.0 - particles[p][t][1] j = random() elif particles[p][t][1] < 0.0: particles[p][t][1] = - particles[p][t][1] j = random() while particles[p][t][1] < - 3907.0 / 412.0 * (particles[p][t][0]+10.) + 3907.0 or particles[p][t][1] > 3907.0 / 417.0 * (- particles[p][t][0] + 5457.0+10.): if particles[p][t][1] < - 3907.0 / 412.0 * (particles[p][t][0]+10.) + 3907.0: particles[p][t][0] = 2.0 * (412.0 / 3907.0) * (3907.0 - particles[p][t][1]) - particles[p][t][0] w = random() elif particles[p][t][1] > 3907.0 / 417.0 * (- particles[p][t][0] + 5457.0+10.): particles[p][t][0] = 2.0 * (5457.0 - particles[p][t][0] * 417.0 / 3907.0) - particles[p][t][0] w = random() vel[p][t] *= [- w, - j] # Find minimum distance between turbines, and if two are closer than 1D, then randomise one of them. TODO Must be 2D if used with Ainslie model, since it does not guarantee any data before 2D. for b in range(np): pp = 0 while pp == 0: pp = 1 for i in range(nt): for j in range(nt): if i != j and distance(particles[b][i][0], particles[b][i][1], particles[b][j][0], particles[b][j][1]) < 2.0 * diam: particles[b][j] = create() pp = 0 # More 'repair' methods for particles out of boundaries shown in PhD thesis Helwig2010. # Chu2011 proves that the reflecting boundary method is better than random or absorbing boundary. for fg in range(np): allfit.write('{0:f}\n'.format(fitness[fg])) allfit.write('\n') fitness = Parallel(n_jobs=-1)(delayed(fit)(particles[i], windrose_angle, windrose_speed, windrose_frequency) for i in range(np)) # fitness = Parallel(n_jobs=-1)(delayed(fit)(particles[i], nt) for i in range(np)) for p in range(np): if fitness[p] < best_own_fitness[p]: best_own_fitness[p] = fitness[p] best_local[p] = copy.deepcopy(particles[p]) if fitness[p] < best_global_fitness: best_global_fitness = fitness[p] best_layout = copy.deepcopy(particles[p]) for i in range(nt): data.write('{2:d} {0:f} {1:f}\n'.format(best_layout[i][0], best_layout[i][1], i)) data.write('\n') data3.write('{1:d} {0:f}\n'.format(best_global_fitness, ite)) for i in range(nt): data2.write('{2:d} {0:f} {1:f}\n'.format(particles[2][i][0], particles[2][i][1], i)) data2.write('\n') print(" --- %s seconds ---" % (time.time() - start_time2)) data.close() data2.close() data3.close() allfit.close()
def pso_horns(): windrose = open('horns_rev_windrose2.dat', 'r') windrose_angle = [] windrose_speed = [] windrose_frequency = [] for line in windrose: columns = line.split() windrose_angle.append(float(columns[0])) windrose_speed.append(float(columns[1])) windrose_frequency.append(float(columns[2])) windrose.close() data = open('refpar_layout_jensen.dat', 'w') data2 = open('refpar_random_layout_jensen.dat', 'w') data3 = open('refpar_best_global_fitness_jensen.dat', 'w', 1) np = 5 ## Number of particles in swarm nt = 21 diam = 80.0 particles = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) if random() < 0.5: sign1 = 1.0 else: sign1 = - 1.0 if random() < 0.5: sign2 = 1.0 else: sign2 = - 1.0 vel = array([[[sign1 * random(), sign2 * random()] for x in range(nt)] for x in range(np)]) best_local = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) best_own_fitness = [0.0 for x in range(np)] best_global_fitness = 0.0 def create(): k = random() l = random() xt = 5457.0 * l if xt <= 412.0: yt = k * 3907.0 + (1.0 - k) * (- 3907.0 / 412.0 * xt + 3907.0) elif xt <= 5040.0: yt = random() * 3907.0 else: yt = k * (3907.0 / 417.0 * (- xt + 5457.0)) return xt, yt ## Produce starting positions. Includes boundaries of Horns Rev for n in range(np): for tur in range(nt): particles[n][tur] = create() # best_layout = particles[0] # for i in range(nt): # data.write('{2:d} {0:f} {1:f}\n'.format(best_layout[i][0], best_layout[i][1], i)) # data.write('\n') # Velocity limiting to 10% to start with, for convergence, and then increase speed. k = 1.0 for ite in range(100): start_time2 = time.time() # Fitness evaluation skipped if counter turbine is out of boundaries. following: BrattonKennedy07 PSO. # More 'repair' methods for particles out of boundaries shown in PhD thesis Helwig2010. # Chu2011 proves that the reflecting boundary method is better than random or absorbing boundary. TODO implement fitness = Parallel(n_jobs=8)(delayed(fit)(particles[i], windrose_angle, windrose_speed, windrose_frequency) for i in range(np)) for p in range(np): if fitness[p] >= best_own_fitness[p]: best_own_fitness[p] = fitness[p] best_local[p] = particles[p] if fitness[p] >= best_global_fitness: best_global_fitness = fitness[p] best_layout = particles[p] for i in range(nt): data.write('{2:d} {0:f} {1:f}\n'.format(best_layout[i][0], best_layout[i][1], i)) data.write('\n') for i in range(nt): data2.write('{2:d} {0:f} {1:f}\n'.format(particles[4][i][0], particles[4][i][1], i)) data2.write('\n') data3.write('{0:f}\n'.format(best_global_fitness)) move = Parallel(n_jobs=8)(delayed(repair)(particles[i], vel[i], best_local[i], best_layout, nt) for i in range(np)) particles = move[:][0] vel = move[:][1] # Find minimum distance between turbines, and if two are closer than 1D, then randomise one of them. for b in range(np): pp = 0 while pp == 0: pp = 1 for i in range(nt): for j in range(nt): if i != j and distance(particles[b][i][0], particles[b][i][1], particles[b][j][0], particles[b][j][1]) < diam: particles[b][j] = create() pp = 0 print("Iteration --- %s seconds ---" % (time.time() - start_time2)) data.close() data2.close() data3.close()
def Jensen(a, Nt, rad): from math import sqrt, log import wake # from power_curve5MW import power5MW_kW as power # Power curve 5 MW NREL windrose = open('horns_rev_windrose2.dat', 'r') nt = Nt layout_x = [0.0 for x in range(nt)] layout_y = [0.0 for x in range(nt)] for x in range(nt): layout_x[x] = float(a[x][0]) layout_y[x] = float(a[x][1]) windrose_angle = [] windrose_speed = [] windrose_frequency = [] for line in windrose: columns = line.split() windrose_angle.append(float(columns[0])) windrose_speed.append(float(columns[1])) windrose_frequency.append(float(columns[2])) windrose.close() summation = 0.0 # Power curve 2 MW Siemens. def power(U0): if U0 < 4.0: return 0.0 elif U0 <= 25.0: return 0.0003234808 * U0 ** 7.0 - 0.0331940121 * U0 ** 6.0 + 1.3883148012 * U0 **5.0 - 30.3162345004 * U0 **4.0 + 367.6835557011 * U0 ** 3.0 - 2441.6860655008 * U0 ** 2.0 + 8345.6777042343 * U0 - 11352.9366182805 else: return 0.0 # for wind in range(0, len(windrose_speed)): for wind in range(0, 1): # U1 = windrose_speed[wind] # Free stream wind speed # U0 = U1 * (90.0 / 10.0) ** 0.11 # Power or log law for wind shear profile # U0 = U1 * log(70.0 / 0.005) / log(10.0 / 0.005) U0 = 8.5 k = 0.04 # Decay constant r0 = rad # Turbine rotor radius angle = windrose_angle[wind] angle3 = angle + 180.0 wake_deficit_matrix = [[0.0 for x in range(nt)] for x in range(nt)] for turbine in range(nt): flag = [False for x in range(nt)] proportion = [0.0 for x in range(nt)] for i in range(nt): try: proportion[i], flag[i] = wake.determine_if_in_wake(layout_x[turbine], layout_y[turbine], layout_x[i], layout_y[i], k, r0, angle3) except TypeError: print layout_x[turbine], layout_y[turbine], layout_x[i], layout_y[i], k, r0, angle3 # Matrix with effect of each turbine <i = turbine> on every other turbine <j> of the farm for j in range(nt): if turbine != j and flag[j] is True: wake_deficit_matrix[turbine][j] = proportion[j] * wake.wake_deficit(0.81, k, wake.distance(layout_x[turbine], layout_y[turbine], layout_x[j], layout_y[j]), r0) elif turbine == j: wake_deficit_matrix[turbine][j] = 0.0 total_deficit = [0.0 for x in range(nt)] total_speed = [0.0 for x in range(nt)] for j in range(nt): for i in range(nt): total_deficit[j] += wake_deficit_matrix[i][j] ** 2.0 total_deficit[j] = sqrt(total_deficit[j]) total_speed[j] = U0 * (1.0 - total_deficit[j]) # Farm efficiency profit = 0.0 efficiency_proportion = [0.0 for x in range(0, len(windrose_frequency))] efficiency = 0.0 for l in range(nt): profit += power(total_speed[l]) efficiency = profit * 100.0 / (float(nt) * power(U0)) efficiency_proportion[wind] = efficiency * windrose_frequency[wind] / 100.0 summation += efficiency_proportion[wind] return efficiency # Farm efficiency # if __name__ == '__main__': # start_time = time.time() # Jensen() # print("--- %s seconds ---" % (time.time() - start_time))
def solve_nonlinear(self, params, unknowns, resids): a = params['a'] from math import sqrt, log import wake windrose = open('horns_rev_windrose2.dat', 'r') nt = 80 layout_x = [0.0 for x in range(nt)] layout_y = [0.0 for x in range(nt)] for x in range(nt): layout_x[x] = float(a[x][0]) layout_y[x] = float(a[x][1]) windrose_angle = [] windrose_speed = [] windrose_frequency = [] for line in windrose: columns = line.split() windrose_angle.append(float(columns[0])) windrose_speed.append(float(columns[1])) windrose_frequency.append(float(columns[2])) windrose.close() summation = 0.0 def Ct(U0): return 0.0001923077 * U0 ** 4.0 + -0.0075407925 * U0 ** 3.0 + 0.096462704 * U0 ** 2.0 - 0.5012354312 * U0 + 1.7184749184 def power(U0): if U0 < 4.0: return 0.0 elif U0 >= 4.0: return 19.7907842158 * U0 ** 2.0 - 74.9080669331 * U0 + 37.257967033 # From 4 to 11 m/s for wind in range(0, len(windrose_speed)): # for wind in range(0, 1): U1 = windrose_speed[wind] # Free stream wind speed U0 = U1 * (70.0 / 10.0) ** 0.11 # Power or log law for wind shear profile # U0 = U1 * log(70.0 / 0.005) / log(10.0 / 0.005) k = 0.04 # Decay constant r0 = 40.0 # Turbine rotor radius angle = windrose_angle[wind] angle3 = angle + 180.0 wake_deficit_matrix = [[0.0 for x in range(nt)] for x in range(nt)] for turbine in range(nt): flag = [False for x in range(nt)] proportion = [0.0 for x in range(nt)] for i in range(nt): try: proportion[i], flag[i] = wake.determine_if_in_wake(layout_x[turbine], layout_y[turbine], layout_x[i], layout_y[i], k, r0, angle3) except TypeError: print(layout_x[turbine], layout_y[turbine], layout_x[i], layout_y[i], k, r0, angle3) # Matrix with effect of each turbine <i = turbine> on every other turbine <j> of the farm for j in range(nt): if turbine != j and flag[j] is True: wake_deficit_matrix[turbine][j] = proportion[j] * wake.wake_deficit(0.81, k, wake.distance(layout_x[turbine], layout_y[turbine], layout_x[j], layout_y[j]), r0) elif turbine == j: wake_deficit_matrix[turbine][j] = 0.0 total_deficit = [0.0 for x in range(nt)] total_speed = [0.0 for x in range(nt)] for j in range(nt): for i in range(nt): total_deficit[j] += wake_deficit_matrix[i][j] ** 2.0 total_deficit[j] = sqrt(total_deficit[j]) total_speed[j] = U0 * (1.0 - total_deficit[j]) # Farm efficiency profit = 0.0 efficiency_proportion = [0.0 for x in range(0, len(windrose_frequency))] for l in range(nt): profit += power(total_speed[l]) efficiency = profit * 100.0 / (float(nt) * power(U0)) efficiency_proportion[wind] = efficiency * windrose_frequency[wind] / 100.0 summation += efficiency_proportion[wind] unknowns['eff'] = summation # Farm efficiency
def jensen(a, windrose_angle, windrose_speed, windrose_frequency): import wake from math import sqrt, log, tan, cos from numpy import deg2rad nt = len(a) layout_x = [0.0 for x in range(nt)] layout_y = [0.0 for x in range(nt)] for x in range(nt): layout_x[x] = float(a[x][0]) layout_y[x] = float(a[x][1]) # Ct curves. # Polynomials 6th, 4th 3rd # - 3.10224672352816e-5 * U0 ** 4.0 + 0.0021367624 * U0 ** 3.0 - 0.0495873986 * U0 ** 2.0 + 0.3976324804 * U0 - 0.1608576035 # 3.374593e-4 * U0 ** 3.0 - 0.0136412226 * U0 ** 2.0 + 0.1118003309 * U0 + 0.5782039288 # Ct look-up table for linear interpolation # def thrust_table(v): # if v == 4: return 0.82 # if v == 5: return 0.81 # if v == 6: return 0.8 # if v == 7: return 0.81 # if v == 8: return 0.81 # if v == 9: return 0.78 # if v == 10: return 0.74 # if v == 11: return 0.65 # if v == 12: return 0.57 # if v == 13: return 0.41 # if v == 14: return 0.31 # if v == 15: return 0.25 # if v == 16: return 0.2 # if v == 17: return 0.17 # if v == 18: return 0.14 # if v == 19: return 0.12 # if v == 20: return 0.1 # if v == 21: return 0.09 # if v == 22: return 0.08 # if v == 23: return 0.07 # if v == 24: return 0.06 # if v == 25: return 0.05 # 2 step thrust curve: # 0.80 if U0 in 4 - 9 m/s # 0.250625 if U0 in 10 - 25 m/s def Ct(U0): if U0 < 4.0: return 0.1 elif U0 <= 25.0: return 7.3139922126945e-7 * U0**6.0 - 6.68905596915255e-5 * U0**5.0 + 2.3937885e-3 * U0**4.0 + -0.0420283143 * U0**3.0 + 0.3716111285 * U0**2.0 - 1.5686969749 * U0 + 3.2991094727 else: return 0.0 def power(U0): if U0 < 4.0: return 0.0 elif U0 <= 25.0: return 3.234808e-4 * U0**7.0 - 0.0331940121 * U0**6.0 + 1.3883148012 * U0**5.0 - 30.3162345004 * U0**4.0 + 367.6835557011 * U0**3.0 - 2441.6860655008 * U0**2.0 + 8345.6777042343 * U0 - 11352.9366182805 else: return 0.0 # Power curve polynomials. # elif U0 <= 25.0 # - 0.0110778061 * U0 ** 5.0 + 0.8986075613 * U0 ** 4.0 - 27.2165513154 * U0 ** 3.0 + 368.8877606215 * U0 ** 2.0 - 1994.1905079276 * U0 + 3712.3986113386 # 5th degree # - 0.5308414162 * U0 ** 3.0 - 15.4948143381 * U0 ** 2.0 + 13.1508234816 * U0 # 3rd degree # Interpolation #table: # def power_table(v): # if v == 4: return 66.3 # if v == 5: return 152 # if v == 6: return 280 # if v == 7: return 457 # if v == 8: return 690 # if v == 9: return 978 # if v == 10: return 1296 # if v == 11: return 1598 # if v == 12: return 1818 # if v == 13: return 1935 # if v == 14: return 1980 # if v == 15: return 1995 # if v == 16: return 1999 # if v == 17: return 2000 # if v == 18: return 2000 # if v == 19: return 2000 # if v == 20: return 2000 # if v == 21: return 2000 # if v == 22: return 2000 # if v == 23: return 2000 # if v == 24: return 2000 # if v == 25: return 2000 # interpolation function # def interpolate(minx, miny, maxx, maxy, valx): # return miny + (maxy - miny) * ((valx - minx) / (maxx - minx)) # 2 step Power curve # 815.0333333 kw from 4 to 13 m/s, 2000 from 13-25 m/s # for U0 in range(4, 20): summation = 0.0 def distance_to_front(x, y, theta, r): theta = deg2rad(theta) return abs(x + tan(theta) * y - r / cos(theta)) / sqrt(1.0 + tan(theta)**2.0) # for wind in range(0, 1): for wind in range(0, len(windrose_angle)): U1 = windrose_speed[wind] # Free stream wind speed U0 = U1 * (70.0 / 10.0)**0.11 # Power or log law for wind shear profile # U0 = 8.5 k = 0.04 # Decay constant r0 = 40.0 # Turbine rotor radius angle = windrose_angle[wind] angle3 = angle + 180.0 deficit_matrix = [[0.0 for x in range(nt)] for x in range(nt)] proportion = [[0.0 for x in range(nt)] for x in range(nt)] distance = [[0.0 for x in range(2)] for x in range(nt)] U = [U0 for x in range(nt)] total_deficit = [0.0 for x in range(nt)] for tur in range(nt): distance[tur] = [ distance_to_front(layout_x[tur], layout_y[tur], angle, 100000000.0), tur ] distance.sort() for turbine in range(nt): for num in range(turbine): total_deficit[distance[turbine][1]] += deficit_matrix[ distance[turbine][1]][distance[num][1]]**2.0 total_deficit[distance[turbine][1]] = sqrt( total_deficit[distance[turbine][1]]) U[distance[turbine] [1]] = U0 * (1.0 - total_deficit[distance[turbine][1]]) for i in range(turbine + 1, nt): proportion[distance[turbine][1]][ distance[i][1]] = wake.determine_if_in_wake( layout_x[distance[turbine][1]], layout_y[distance[turbine][1]], layout_x[distance[i][1]], layout_y[distance[i][1]], k, r0, angle3) deficit_matrix[distance[i][1]][ distance[turbine][1]] = proportion[distance[turbine][1]][ distance[i][1]] * wake.wake_deficit( Ct(U[distance[turbine][1]]), k, wake.distance(layout_x[distance[turbine][1]], layout_y[distance[turbine][1]], layout_x[distance[i][1]], layout_y[distance[i][1]]), r0) # Farm efficiency profit = 0.0 efficiency_proportion = [ 0.0 for x in range(0, len(windrose_frequency)) ] for l in range(nt): profit += power(U[l]) efficiency = profit * 100.0 / (float(nt) * power(U[distance[0][1]])) efficiency_proportion[ wind] = efficiency * windrose_frequency[wind] / 100.0 # print 'Farm efficiency with wind direction = {0:d} deg: {1:2.2f}%'.format(int(angle), efficiency) summation += efficiency_proportion[wind] return 100.0 - summation
def pso_horns(): windrose = open('horns_rev_windrose.dat', 'r') windrose_angle = [] windrose_speed = [] windrose_frequency = [] for line in windrose: columns = line.split() windrose_angle.append(float(columns[0])) windrose_speed.append(float(columns[1])) windrose_frequency.append(float(columns[2])) windrose.close() data = open('ref3_layout.dat', 'w', 1) data2 = open('ref3_random_layout.dat', 'w', 1) data3 = open('ref3_best_global_fitness.dat', 'w', 1) allfit = open('ref3_all_fitnesses.dat', 'w', 1) # pso1 first run. Np 40 (max recommended). Ainslie model combination 30 from MCDA. 20 000 iterations to see what happens. 12.91 = 87.09% eff. # pso2 Less particles down to 25. Ive changed the inertia and acceleration coefficients multiplied by 0.1. added e-1. For smaller movements and less chaos. Didnt work because of e-1 i think, it moves too slow so nothing changes. 13.46 = 86.54% eff. # pso3 chagned e-1 to decimal notation of the accel. coefficients. 5 particles only to test. # pso4 n_iter = 80 np = 25 ## Number of particles in swarm. 2000 function calls. 8 hrs # pso6 same as pso 4 more iterations to 160. # pso8 includes one particle as the original horns rev. 10 particles to test. # ref1 reflecting, 10 particles. Changed vel and particles update with one operation per dimension. 138 seconds per iteration. # ref2 10 particles, changed windrose to 30 degrees for speed. 3.5 seconds per iteration. 200 iterations. # ref3 same as ref2, 2000 iterations. n_iter = 2000 np = 10 ## Number of particles in swarm nt = 80 diam = 80.0 particles = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) # if random() < 0.5: # sign1 = 1.0 # else: # sign1 = - 1.0 # if random() < 0.5: # sign2 = 1.0 # else: # sign2 = - 1.0 vel = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) best_own_fitness = [100.0 for x in range(np)] best_global_fitness = 100.0 def create(): k = random() l = random() xt = 5457.0 * l if xt <= 412.0: yt = k * 3907.0 + (1.0 - k) * (-3907.0 / 412.0 * xt + 3907.0) elif xt <= 5040.0: yt = k * 3907.0 else: yt = k * (3907.0 / 417.0 * (-xt + 5457.0)) return xt, yt ## Produce starting positions. Includes boundaries of Horns Rev for n in range(np): for tur in range(nt): particles[n][tur] = create() # layout = open('horns_rev.dat', 'r') # ll = 0 # horns = array([[0, 0] for gf in range(nt)]) # for line in layout: # columns = line.split() # horns[ll] = [float(columns[0]) - 423974.0, float(columns[1]) - 6147543.0] # ll += 1 # layout.close() # particles[np - 1] = horns fitness = Parallel(n_jobs=-1)(delayed(fit)( particles[i], windrose_angle, windrose_speed, windrose_frequency) for i in range(np)) # fitness = Parallel(n_jobs=-1)(delayed(fit)(particles[i], nt) for i in range(np)) best_layout = copy.deepcopy(particles[fitness.index(min(fitness))]) best_local = copy.deepcopy(particles) for ite in range(n_iter): start_time2 = time.time() for p in range(np): # Can be parallelised in the future. # Solving Constrained Nonlinear Optimization Problems with Particle Swarm Optimization by Xiaohui Hu and Russell Eberhart. For 1.49445 learning coefficients. for t in range(nt): for coord in range(2): vel[p][t][ coord] = 0.72984 * vel[p][t][coord] + 1.49617 * random( ) * (best_local[p][t][coord] - particles[p][t][coord] ) + 1.49617 * random() * (best_layout[t][coord] - particles[p][t][coord]) particles[p][t][coord] += vel[p][t][coord] j = 1.0 w = 1.0 while particles[p][t][1] > 3907.0 or particles[p][t][1] < 0.0: if particles[p][t][1] > 3907.0: particles[p][t][1] = 3907.0 * 2.0 - particles[p][t][1] j = random() elif particles[p][t][1] < 0.0: particles[p][t][1] = -particles[p][t][1] j = random() while particles[p][t][1] < -3907.0 / 412.0 * ( particles[p][t][0] + 10.) + 3907.0 or particles[p][t][ 1] > 3907.0 / 417.0 * (-particles[p][t][0] + 5457.0 + 10.): if particles[p][t][1] < -3907.0 / 412.0 * ( particles[p][t][0] + 10.) + 3907.0: particles[p][t][0] = 2.0 * (412.0 / 3907.0) * ( 3907.0 - particles[p][t][1]) - particles[p][t][0] w = random() elif particles[p][t][1] > 3907.0 / 417.0 * ( -particles[p][t][0] + 5457.0 + 10.): particles[p][t][0] = 2.0 * ( 5457.0 - particles[p][t][0] * 417.0 / 3907.0) - particles[p][t][0] w = random() vel[p][t] *= [-w, -j] # Find minimum distance between turbines, and if two are closer than 1D, then randomise one of them. TODO Must be 2D if used with Ainslie model, since it does not guarantee any data before 2D. for b in range(np): pp = 0 while pp == 0: pp = 1 for i in range(nt): for j in range(nt): if i != j and distance( particles[b][i][0], particles[b][i][1], particles[b][j][0], particles[b][j][1]) < 2.0 * diam: particles[b][j] = create() pp = 0 # More 'repair' methods for particles out of boundaries shown in PhD thesis Helwig2010. # Chu2011 proves that the reflecting boundary method is better than random or absorbing boundary. for fg in range(np): allfit.write('{0:f}\n'.format(fitness[fg])) allfit.write('\n') fitness = Parallel(n_jobs=-1)(delayed(fit)( particles[i], windrose_angle, windrose_speed, windrose_frequency) for i in range(np)) # fitness = Parallel(n_jobs=-1)(delayed(fit)(particles[i], nt) for i in range(np)) for p in range(np): if fitness[p] < best_own_fitness[p]: best_own_fitness[p] = fitness[p] best_local[p] = copy.deepcopy(particles[p]) if fitness[p] < best_global_fitness: best_global_fitness = fitness[p] best_layout = copy.deepcopy(particles[p]) for i in range(nt): data.write('{2:d} {0:f} {1:f}\n'.format( best_layout[i][0], best_layout[i][1], i)) data.write('\n') data3.write('{1:d} {0:f}\n'.format(best_global_fitness, ite)) for i in range(nt): data2.write('{2:d} {0:f} {1:f}\n'.format(particles[2][i][0], particles[2][i][1], i)) data2.write('\n') print(" --- %s seconds ---" % (time.time() - start_time2)) data.close() data2.close() data3.close() allfit.close()
def analysis(): # Random layout to test, since optimiser will always be dealing with random layouts. layout_x = [] layout_y = [] nt = 80 for xx in range(nt): l = random() k = random() layout_x.append(5457.0 * l) if layout_x[-1] <= 412.0: layout_y.append(k * 3907.0 + (1.0 - k) * (- 3907.0 / 412.0 * layout_x[-1] + 3907.0)) elif layout_x[-1] <= 5040.0: layout_y.append(k * 3907.0) else: layout_y.append(k * (3907.0 / 417.0 * (- layout_x[-1] + 5457.0))) nt = len(layout_y) # Number of turbines ## Length of layout list summation = 0.0 def distance_to_front(x, y, theta, r): ## TODO: Calculate distance to any front and use negative distances to order. theta = deg2rad(theta) return abs(x + tan(theta) * y - r / cos(theta)) / sqrt(1.0 + tan(theta) ** 2.0) for wind in range(0, len(windrose_angle)): # for wind in range(90, 91): # if wind in [100, 133, 271, 280, 313]: # continue U1 = windrose_speed[wind] # Free stream wind speed U0 = U1 * (70.0 / 10.0) ** 0.11 # Power or log law for wind shear profile # U0 = U1 * log(70.0 / 0.005) / log(10.0 / 0.005) # U0 = 8.5 k = 0.04 # Decay constant r0 = 40.0 # Turbine rotor radius angle = windrose_angle[wind] angle3 = angle + 180.0 deficit_matrix = [[0.0 for x in range(nt)] for x in range(nt)] proportion = [[0.0 for x in range(nt)] for x in range(nt)] distance = [[0.0 for x in range(2)] for x in range(nt)] U = [U0 for x in range(nt)] total_deficit = [0.0 for x in range(nt)] for tur in range(nt): distance[tur] = [distance_to_front(layout_x[tur], layout_y[tur], angle, 100000000.0), tur] distance.sort() for turbine in range(nt): for num in range(turbine): total_deficit[distance[turbine][1]] += deficit_matrix[distance[turbine][1]][distance[num][1]] ** 2.0 total_deficit[distance[turbine][1]] = sqrt(total_deficit[distance[turbine][1]]) U[distance[turbine][1]] = U0 * (1.0 - total_deficit[distance[turbine][1]]) for i in range(turbine + 1, nt): proportion[distance[turbine][1]][distance[i][1]] = wake.determine_if_in_wake(layout_x[distance[turbine][1]], layout_y[distance[turbine][1]], layout_x[distance[i][1]], layout_y[distance[i][1]], k, r0, angle3) # If statement for proportion = 0 deficit_matrix[distance[i][1]][distance[turbine][1]] = proportion[distance[turbine][1]][distance[i][1]] * wake.wake_deficit(Ct(U[distance[turbine][1]]), k, wake.distance(layout_x[distance[turbine][1]], layout_y[distance[turbine][1]], layout_x[distance[i][1]], layout_y[distance[i][1]]), r0) # for turb in range(nt): # for i in range(nt): # output.write('{0:f}\t'.format(deficit_matrix[turb][i])) # output.write('\n') # output2.write('{0:d}\t{1:.1f}\t{2:.1f}\t{3:f}\t{4:f}\t{5:d}\t{6:f}\n'.format(turb, layout_x[turb], layout_y[turb], total_deficit[turb], U[turb], int(angle), power(U[turb]))) # output2.write('\n') # for n in range(nt): # aver[n] += power(U[n]) / 360.0 # ---------------------------------------TODO UNCOMMENT ----------------------------------------- if withdata: turb_data.write('{0:f} {1:f}\n'.format(angle, power(U[14]))) # Farm efficiency profit = 0.0 efficiency_proportion = [0.0 for x in range(0, len(windrose_frequency))] for l in range(nt): profit += power(U[l]) efficiency = profit * 100.0 / (float(nt) * power(U[distance[0][1]])) # same as using U0 efficiency_proportion[wind] = efficiency * windrose_frequency[wind] / 100.0 # print 'Farm efficiency with wind direction = {0:d} deg: {1:2.2f}%'.format(int(angle), efficiency) # ---------------------------------------TODO UNCOMMENT ------------------------------------------ if withdata: direction.write('{0:f} {1:f}\n'.format(angle, profit)) summation += efficiency_proportion[wind] return summation
def pso_horns(): data = open('3horns_pso.dat', 'w') data2 = open('3swarm_horns.dat', 'w') data3 = open('3globalfit.dat', 'w') np = 20 nt = 45 diam = 80.0 particles = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) if random() < 0.5: sign1 = 1.0 else: sign1 = - 1.0 if random() < 0.5: sign2 = 1.0 else: sign2 = - 1.0 vel = array([[[sign1 * random(), sign2 * random()] for x in range(nt)] for x in range(np)]) best_local = array([[[0.0, 0.0] for x in range(nt)] for x in range(np)]) best_own_fitness = [0.0 for x in range(np)] best_global_fitness = 0.0 def create(): k = random() l = random() xt = 400.0 * l yt = 3600 * k return xt, yt ## Produce starting positions. Includes boundaries of Horns Rev for n in range(np): for tur in range(nt): particles[n][tur] = create() best_layout = particles[0] for i in range(nt): data.write('{2:d} {0:f} {1:f}\n'.format(best_layout[i][0], best_layout[i][1], i)) data.write('\n') for iter in range(2000): start_time2 = time.time() fitness = Parallel(n_jobs=8)(delayed(fit)(particles[i], nt, diam / 2.0) for i in range(np)) # for p in range(np): # fitness[p] = fit(particles[p], nt, diam / 2.0) for p in range(np): if fitness[p] > best_own_fitness[p]: best_own_fitness[p] = fitness[p] best_local[p] = particles[p] if fitness[p] > best_global_fitness: best_global_fitness = fitness[p] best_layout = particles[p] for i in range(nt): data.write('{2:d} {0:f} {1:f}\n'.format(best_layout[i][0], best_layout[i][1], i)) data2.write('{2:d} {0:f} {1:f}\n'.format(particles[10][i][0], particles[10][i][1], i)) data2.write('\n') data.write('\n') data3.write('{0:f}\n'.format(best_global_fitness)) for p in range(np): ## Solving Constrained Nonlinear Optimization Problems with Particle Swarm Optimization by Xiaohui Hu and Russell Eberhart. For 1.49445 learning coefficients. vel[p] = (0.5 + random() / 2.0) * vel[p] + 2.0 * random() * (best_local[p] - particles[p]) + 2.0 * random() * (best_layout - particles[p]) for t in range(nt): if vel[p][t][0] > 400.0: vel[p][t][0] = 400.0 if vel[p][t][0] < - 400.0: vel[p][t][0] = - 400.0 if vel[p][t][1] > 3600.0: vel[p][t][1] = 3600.0 if vel[p][t][1] < - 3600.0: vel[p][t][1] = - 3600.0 particles[p] = particles[p] + vel[p] for tur in range(nt): if particles[p][tur][1] > 3600.0: particles[p][tur][1] = random() * 3600.0 elif particles[p][tur][1] < 0.0: particles[p][tur][1] = random() * 3600.0 if particles[p][tur][0] > 400.0: particles[p][tur][0] = random() * 400.0 elif particles[p][tur][0] < 0.0: particles[p][tur][0] = random() * 400.0 # Find minimum distance between turbines, and if two are closer than 1D, then randomise one of them. for b in range(np): pp = 0 while pp == 0: pp = 1 for i in range(nt): for j in range(nt): if i != j and distance(particles[b][i][0], particles[b][i][1], particles[b][j][0], particles[b][j][1]) < diam: particles[b][j] = create() pp = 0 print best_global_fitness if iter % 50 == 0: sys.stdout.flush() print("Iteration --- %s seconds ---" % (time.time() - start_time2)) data.close() data2.close() data3.close()
def Jensen(a, Nt, rad): from math import sqrt, log import wake from power_curve5MW import power5MW_kW as power # Power curve 5 MW NREL windrose = open('horns_rev_windrose.dat', 'r') nt = Nt layout_x = [0.0 for x in range(nt)] layout_y = [0.0 for x in range(nt)] for x in range(nt): layout_x[x] = float(a[x][0]) layout_y[x] = float(a[x][1]) windrose_angle = [] windrose_speed = [] windrose_frequency = [] for line in windrose: columns = line.split() windrose_angle.append(float(columns[0])) windrose_speed.append(float(columns[1])) windrose_frequency.append(float(columns[2])) windrose.close() summation = 0.0 ## Power curve 2 MW Siemens. # def power(U0): # if U0 < 4.0: # return 0.0 # elif U0 >= 4.0: # return 19.7907842158 * U0 ** 2.0 - 74.9080669331 * U0 + 37.257967033 # From 4 to 11 m/s # for wind in range(0, len(windrose_speed)): for wind in range(0, 1): U1 = windrose_speed[wind] # Free stream wind speed U0 = U1 * (90.0 / 10.0) ** 0.11 # Power or log law for wind shear profile # U0 = U1 * log(70.0 / 0.005) / log(10.0 / 0.005) k = 0.04 # Decay constant r0 = rad # Turbine rotor radius angle = windrose_angle[wind] angle3 = angle + 180.0 wake_deficit_matrix = [[0.0 for x in range(nt)] for x in range(nt)] for turbine in range(nt): flag = [False for x in range(nt)] proportion = [0.0 for x in range(nt)] for i in range(nt): try: proportion[i], flag[i] = wake.determine_if_in_wake(layout_x[turbine], layout_y[turbine], layout_x[i], layout_y[i], k, r0, angle3) except TypeError: print layout_x[turbine], layout_y[turbine], layout_x[i], layout_y[i], k, r0, angle3 # Matrix with effect of each turbine <i = turbine> on every other turbine <j> of the farm for j in range(nt): if turbine != j and flag[j] is True: wake_deficit_matrix[turbine][j] = proportion[j] * wake.wake_deficit(0.46, k, wake.distance(layout_x[turbine], layout_y[turbine], layout_x[j], layout_y[j]), r0) elif turbine == j: wake_deficit_matrix[turbine][j] = 0.0 total_deficit = [0.0 for x in range(nt)] total_speed = [0.0 for x in range(nt)] for j in range(nt): for i in range(nt): total_deficit[j] += wake_deficit_matrix[i][j] ** 2.0 total_deficit[j] = sqrt(total_deficit[j]) total_speed[j] = U0 * (1.0 - total_deficit[j]) # Farm efficiency profit = 0.0 efficiency_proportion = [0.0 for x in range(0, len(windrose_frequency))] efficiency = 0.0 for l in range(nt): profit += power(total_speed[l]) efficiency = profit * 100.0 / (float(nt) * power(U0)) efficiency_proportion[wind] = efficiency * windrose_frequency[wind] / 100.0 summation += efficiency_proportion[wind] return summation # Farm efficiency # if __name__ == '__main__': # start_time = time.time() # Jensen() # print("--- %s seconds ---" % (time.time() - start_time))
def Jensen(a, Nt, rad): from math import sqrt, log import wake # from power_curve5MW import power5MW_kW as power # Power curve 5 MW NREL windrose = open('horns_rev_windrose2.dat', 'r') nt = Nt layout_x = [0.0 for x in range(nt)] layout_y = [0.0 for x in range(nt)] for x in range(nt): layout_x[x] = float(a[x][0]) layout_y[x] = float(a[x][1]) windrose_angle = [] windrose_speed = [] windrose_frequency = [] for line in windrose: columns = line.split() windrose_angle.append(float(columns[0])) windrose_speed.append(float(columns[1])) windrose_frequency.append(float(columns[2])) windrose.close() summation = 0.0 # Power curve 2 MW Siemens. def power(U0): if U0 < 4.0: return 0.0 elif U0 <= 25.0: return 0.0003234808 * U0**7.0 - 0.0331940121 * U0**6.0 + 1.3883148012 * U0**5.0 - 30.3162345004 * U0**4.0 + 367.6835557011 * U0**3.0 - 2441.6860655008 * U0**2.0 + 8345.6777042343 * U0 - 11352.9366182805 else: return 0.0 # for wind in range(0, len(windrose_speed)): for wind in range(0, 1): # U1 = windrose_speed[wind] # Free stream wind speed # U0 = U1 * (90.0 / 10.0) ** 0.11 # Power or log law for wind shear profile # U0 = U1 * log(70.0 / 0.005) / log(10.0 / 0.005) U0 = 8.5 k = 0.04 # Decay constant r0 = rad # Turbine rotor radius angle = windrose_angle[wind] angle3 = angle + 180.0 wake_deficit_matrix = [[0.0 for x in range(nt)] for x in range(nt)] for turbine in range(nt): flag = [False for x in range(nt)] proportion = [0.0 for x in range(nt)] for i in range(nt): try: proportion[i], flag[i] = wake.determine_if_in_wake( layout_x[turbine], layout_y[turbine], layout_x[i], layout_y[i], k, r0, angle3) except TypeError: print layout_x[turbine], layout_y[turbine], layout_x[ i], layout_y[i], k, r0, angle3 # Matrix with effect of each turbine <i = turbine> on every other turbine <j> of the farm for j in range(nt): if turbine != j and flag[j] is True: wake_deficit_matrix[turbine][ j] = proportion[j] * wake.wake_deficit( 0.81, k, wake.distance(layout_x[turbine], layout_y[turbine], layout_x[j], layout_y[j]), r0) elif turbine == j: wake_deficit_matrix[turbine][j] = 0.0 total_deficit = [0.0 for x in range(nt)] total_speed = [0.0 for x in range(nt)] for j in range(nt): for i in range(nt): total_deficit[j] += wake_deficit_matrix[i][j]**2.0 total_deficit[j] = sqrt(total_deficit[j]) total_speed[j] = U0 * (1.0 - total_deficit[j]) # Farm efficiency profit = 0.0 efficiency_proportion = [ 0.0 for x in range(0, len(windrose_frequency)) ] efficiency = 0.0 for l in range(nt): profit += power(total_speed[l]) efficiency = profit * 100.0 / (float(nt) * power(U0)) efficiency_proportion[ wind] = efficiency * windrose_frequency[wind] / 100.0 summation += efficiency_proportion[wind] return efficiency # Farm efficiency # if __name__ == '__main__': # start_time = time.time() # Jensen() # print("--- %s seconds ---" % (time.time() - start_time))
def jensen(a, windrose_angle, windrose_speed, windrose_frequency): import wake from math import sqrt, log, tan, cos from numpy import deg2rad nt = len(a) layout_x = [0.0 for x in range(nt)] layout_y = [0.0 for x in range(nt)] for x in range(nt): layout_x[x] = float(a[x][0]) layout_y[x] = float(a[x][1]) # Ct curves. # Polynomials 6th, 4th 3rd # - 3.10224672352816e-5 * U0 ** 4.0 + 0.0021367624 * U0 ** 3.0 - 0.0495873986 * U0 ** 2.0 + 0.3976324804 * U0 - 0.1608576035 # 3.374593e-4 * U0 ** 3.0 - 0.0136412226 * U0 ** 2.0 + 0.1118003309 * U0 + 0.5782039288 # Ct look-up table for linear interpolation # def thrust_table(v): # if v == 4: return 0.82 # if v == 5: return 0.81 # if v == 6: return 0.8 # if v == 7: return 0.81 # if v == 8: return 0.81 # if v == 9: return 0.78 # if v == 10: return 0.74 # if v == 11: return 0.65 # if v == 12: return 0.57 # if v == 13: return 0.41 # if v == 14: return 0.31 # if v == 15: return 0.25 # if v == 16: return 0.2 # if v == 17: return 0.17 # if v == 18: return 0.14 # if v == 19: return 0.12 # if v == 20: return 0.1 # if v == 21: return 0.09 # if v == 22: return 0.08 # if v == 23: return 0.07 # if v == 24: return 0.06 # if v == 25: return 0.05 # 2 step thrust curve: # 0.80 if U0 in 4 - 9 m/s # 0.250625 if U0 in 10 - 25 m/s def Ct(U0): if U0 < 4.0: return 0.1 elif U0 <= 25.0: return 7.3139922126945e-7 * U0 ** 6.0 - 6.68905596915255e-5 * U0 ** 5.0 + 2.3937885e-3 * U0 ** 4.0 + - 0.0420283143 * U0 ** 3.0 + 0.3716111285 * U0 ** 2.0 - 1.5686969749 * U0 + 3.2991094727 else: return 0.0 def power(U0): if U0 < 4.0: return 0.0 elif U0 <= 25.0: return 3.234808e-4 * U0 ** 7.0 - 0.0331940121 * U0 ** 6.0 + 1.3883148012 * U0 ** 5.0 - 30.3162345004 * U0 ** 4.0 + 367.6835557011 * U0 ** 3.0 - 2441.6860655008 * U0 ** 2.0 + 8345.6777042343 * U0 - 11352.9366182805 else: return 0.0 # Power curve polynomials. # elif U0 <= 25.0 # - 0.0110778061 * U0 ** 5.0 + 0.8986075613 * U0 ** 4.0 - 27.2165513154 * U0 ** 3.0 + 368.8877606215 * U0 ** 2.0 - 1994.1905079276 * U0 + 3712.3986113386 # 5th degree # - 0.5308414162 * U0 ** 3.0 - 15.4948143381 * U0 ** 2.0 + 13.1508234816 * U0 # 3rd degree # Interpolation #table: # def power_table(v): # if v == 4: return 66.3 # if v == 5: return 152 # if v == 6: return 280 # if v == 7: return 457 # if v == 8: return 690 # if v == 9: return 978 # if v == 10: return 1296 # if v == 11: return 1598 # if v == 12: return 1818 # if v == 13: return 1935 # if v == 14: return 1980 # if v == 15: return 1995 # if v == 16: return 1999 # if v == 17: return 2000 # if v == 18: return 2000 # if v == 19: return 2000 # if v == 20: return 2000 # if v == 21: return 2000 # if v == 22: return 2000 # if v == 23: return 2000 # if v == 24: return 2000 # if v == 25: return 2000 # interpolation function # def interpolate(minx, miny, maxx, maxy, valx): # return miny + (maxy - miny) * ((valx - minx) / (maxx - minx)) # 2 step Power curve # 815.0333333 kw from 4 to 13 m/s, 2000 from 13-25 m/s # for U0 in range(4, 20): summation = 0.0 def distance_to_front(x, y, theta, r): theta = deg2rad(theta) return abs(x + tan(theta) * y - r / cos(theta)) / sqrt(1.0 + tan(theta) ** 2.0) # for wind in range(0, 1): for wind in range(0, len(windrose_angle)): U1 = windrose_speed[wind] # Free stream wind speed U0 = U1 * (70.0 / 10.0) ** 0.11 # Power or log law for wind shear profile # U0 = 8.5 k = 0.04 # Decay constant r0 = 40.0 # Turbine rotor radius angle = windrose_angle[wind] angle3 = angle + 180.0 deficit_matrix = [[0.0 for x in range(nt)] for x in range(nt)] proportion = [[0.0 for x in range(nt)] for x in range(nt)] distance = [[0.0 for x in range(2)] for x in range(nt)] U = [U0 for x in range(nt)] total_deficit = [0.0 for x in range(nt)] for tur in range(nt): distance[tur] = [distance_to_front(layout_x[tur], layout_y[tur], angle, 100000000.0), tur] distance.sort() for turbine in range(nt): for num in range(turbine): total_deficit[distance[turbine][1]] += deficit_matrix[distance[turbine][1]][distance[num][1]] ** 2.0 total_deficit[distance[turbine][1]] = sqrt(total_deficit[distance[turbine][1]]) U[distance[turbine][1]] = U0 * (1.0 - total_deficit[distance[turbine][1]]) for i in range(turbine + 1, nt): proportion[distance[turbine][1]][distance[i][1]] = wake.determine_if_in_wake(layout_x[distance[turbine][1]], layout_y[distance[turbine][1]], layout_x[distance[i][1]], layout_y[distance[i][1]], k, r0, angle3) deficit_matrix[distance[i][1]][distance[turbine][1]] = proportion[distance[turbine][1]][distance[i][1]] * wake.wake_deficit(Ct(U[distance[turbine][1]]), k, wake.distance(layout_x[distance[turbine][1]], layout_y[distance[turbine][1]], layout_x[distance[i][1]], layout_y[distance[i][1]]), r0) # Farm efficiency profit = 0.0 efficiency_proportion = [0.0 for x in range(0, len(windrose_frequency))] for l in range(nt): profit += power(U[l]) efficiency = profit * 100.0 / (float(nt) * power(U[distance[0][1]])) efficiency_proportion[wind] = efficiency * windrose_frequency[wind] / 100.0 # print 'Farm efficiency with wind direction = {0:d} deg: {1:2.2f}%'.format(int(angle), efficiency) summation += efficiency_proportion[wind] return 100.0 - summation
def analysis(): # Random layout to test, since optimiser will always be dealing with random layouts. layout_x = [] layout_y = [] nt = 80 for xx in range(nt): l = random() k = random() layout_x.append(5457.0 * l) if layout_x[-1] <= 412.0: layout_y.append( k * 3907.0 + (1.0 - k) * (-3907.0 / 412.0 * layout_x[-1] + 3907.0)) elif layout_x[-1] <= 5040.0: layout_y.append(k * 3907.0) else: layout_y.append(k * (3907.0 / 417.0 * (-layout_x[-1] + 5457.0))) nt = len( layout_y ) # Number of turbines ## Length of layout list summation = 0.0 def distance_to_front( x, y, theta, r ): ## TODO: Calculate distance to any front and use negative distances to order. theta = deg2rad(theta) return abs(x + tan(theta) * y - r / cos(theta)) / sqrt(1.0 + tan(theta)**2.0) for wind in range(0, len(windrose_angle)): # for wind in range(90, 91): # if wind in [100, 133, 271, 280, 313]: # continue U1 = windrose_speed[wind] # Free stream wind speed U0 = U1 * ( 70.0 / 10.0 )**0.11 # Power or log law for wind shear profile # U0 = U1 * log(70.0 / 0.005) / log(10.0 / 0.005) # U0 = 8.5 k = 0.04 # Decay constant r0 = 40.0 # Turbine rotor radius angle = windrose_angle[wind] angle3 = angle + 180.0 deficit_matrix = [[0.0 for x in range(nt)] for x in range(nt)] proportion = [[0.0 for x in range(nt)] for x in range(nt)] distance = [[0.0 for x in range(2)] for x in range(nt)] U = [U0 for x in range(nt)] total_deficit = [0.0 for x in range(nt)] for tur in range(nt): distance[tur] = [ distance_to_front(layout_x[tur], layout_y[tur], angle, 100000000.0), tur ] distance.sort() for turbine in range(nt): for num in range(turbine): total_deficit[ distance[turbine][1]] += deficit_matrix[ distance[turbine][1]][distance[num] [1]]**2.0 total_deficit[distance[turbine][1]] = sqrt( total_deficit[distance[turbine][1]]) U[distance[turbine][1]] = U0 * ( 1.0 - total_deficit[distance[turbine][1]]) for i in range(turbine + 1, nt): proportion[distance[turbine][1]][distance[i][ 1]] = wake.determine_if_in_wake( layout_x[distance[turbine][1]], layout_y[distance[turbine][1]], layout_x[distance[i][1]], layout_y[distance[i][1]], k, r0, angle3) # If statement for proportion = 0 deficit_matrix[distance[i][1]][ distance[turbine] [1]] = proportion[distance[turbine][1]][ distance[i][1]] * wake.wake_deficit( Ct(U[distance[turbine][1]]), k, wake.distance( layout_x[distance[turbine][1]], layout_y[distance[turbine][1]], layout_x[distance[i][1]], layout_y[distance[i][1]]), r0) # for turb in range(nt): # for i in range(nt): # output.write('{0:f}\t'.format(deficit_matrix[turb][i])) # output.write('\n') # output2.write('{0:d}\t{1:.1f}\t{2:.1f}\t{3:f}\t{4:f}\t{5:d}\t{6:f}\n'.format(turb, layout_x[turb], layout_y[turb], total_deficit[turb], U[turb], int(angle), power(U[turb]))) # output2.write('\n') # for n in range(nt): # aver[n] += power(U[n]) / 360.0 # ---------------------------------------TODO UNCOMMENT ----------------------------------------- if withdata: turb_data.write('{0:f} {1:f}\n'.format( angle, power(U[14]))) # Farm efficiency profit = 0.0 efficiency_proportion = [ 0.0 for x in range(0, len(windrose_frequency)) ] for l in range(nt): profit += power(U[l]) efficiency = profit * 100.0 / (float(nt) * power( U[distance[0][1]])) # same as using U0 efficiency_proportion[ wind] = efficiency * windrose_frequency[ wind] / 100.0 # print 'Farm efficiency with wind direction = {0:d} deg: {1:2.2f}%'.format(int(angle), efficiency) # ---------------------------------------TODO UNCOMMENT ------------------------------------------ if withdata: direction.write('{0:f} {1:f}\n'.format( angle, profit)) summation += efficiency_proportion[wind] return summation
def Jensen(a, Nt, rad): from math import sqrt, log import wake from power_curve5MW import power5MW_kW as power # Power curve 5 MW NREL windrose = open('horns_rev_windrose.dat', 'r') nt = Nt layout_x = [0.0 for x in range(nt)] layout_y = [0.0 for x in range(nt)] for x in range(nt): layout_x[x] = float(a[x][0]) layout_y[x] = float(a[x][1]) windrose_angle = [] windrose_speed = [] windrose_frequency = [] for line in windrose: columns = line.split() windrose_angle.append(float(columns[0])) windrose_speed.append(float(columns[1])) windrose_frequency.append(float(columns[2])) windrose.close() summation = 0.0 ## Power curve 2 MW Siemens. # def power(U0): # if U0 < 4.0: # return 0.0 # elif U0 >= 4.0: # return 19.7907842158 * U0 ** 2.0 - 74.9080669331 * U0 + 37.257967033 # From 4 to 11 m/s # for wind in range(0, len(windrose_speed)): for wind in range(0, 1): U1 = windrose_speed[wind] # Free stream wind speed U0 = U1 * (90.0 / 10.0)**0.11 # Power or log law for wind shear profile # U0 = U1 * log(70.0 / 0.005) / log(10.0 / 0.005) k = 0.04 # Decay constant r0 = rad # Turbine rotor radius angle = windrose_angle[wind] angle3 = angle + 180.0 wake_deficit_matrix = [[0.0 for x in range(nt)] for x in range(nt)] for turbine in range(nt): flag = [False for x in range(nt)] proportion = [0.0 for x in range(nt)] for i in range(nt): try: proportion[i], flag[i] = wake.determine_if_in_wake( layout_x[turbine], layout_y[turbine], layout_x[i], layout_y[i], k, r0, angle3) except TypeError: print layout_x[turbine], layout_y[turbine], layout_x[ i], layout_y[i], k, r0, angle3 # Matrix with effect of each turbine <i = turbine> on every other turbine <j> of the farm for j in range(nt): if turbine != j and flag[j] is True: wake_deficit_matrix[turbine][ j] = proportion[j] * wake.wake_deficit( 0.46, k, wake.distance(layout_x[turbine], layout_y[turbine], layout_x[j], layout_y[j]), r0) elif turbine == j: wake_deficit_matrix[turbine][j] = 0.0 total_deficit = [0.0 for x in range(nt)] total_speed = [0.0 for x in range(nt)] for j in range(nt): for i in range(nt): total_deficit[j] += wake_deficit_matrix[i][j]**2.0 total_deficit[j] = sqrt(total_deficit[j]) total_speed[j] = U0 * (1.0 - total_deficit[j]) # Farm efficiency profit = 0.0 efficiency_proportion = [ 0.0 for x in range(0, len(windrose_frequency)) ] efficiency = 0.0 for l in range(nt): profit += power(total_speed[l]) efficiency = profit * 100.0 / (float(nt) * power(U0)) efficiency_proportion[ wind] = efficiency * windrose_frequency[wind] / 100.0 summation += efficiency_proportion[wind] return summation # Farm efficiency # if __name__ == '__main__': # start_time = time.time() # Jensen() # print("--- %s seconds ---" % (time.time() - start_time))