MAXIMIZING ENERGY SAVINGS WITH SOLAR PANELS ON BUILDING FACADES (Approach: Genetic Algorithm)
By: Fereshteh Shahmiri - Master of Science in Computational Design Alan Shteyman - Master of Science in Computational Biology Introduction: Current Architecture uses ad hoc methods of designing buildings. As a result most designs are not optimized for energy efficiency. Using Genetic Algorithms to optimize performance can be a way of overcoming this shortcoming of ad hoc design. Genetic Algorithms (GA’s) are a method of taking random solutions to a problem and optimizing them in a way analogous to evolution. Depending on the nature of the problem and solutions, over successive iterations or generations, a set of solutions slowly converge to a better set of solutions. The solutions found depend on the constraints given, or the fitness function used, to find the best possible solution. Eventually, the GA will find at least a locally optimal solution to the problem. Regarding to solar panels in building facades, one issue that has not fully been solved is how to position and control these panels such that the most efficient use of the solar panels’ energy generation capability can be included in an appealing design. This project intends to use a GA to both find a design that is visually appealing and is optimized to intercept the most sunlight possible. Methods: Original plan was to use a design framework called Grasshopper, to design a layout of solar panels on the side of a building. In this model, several solar panels would be integrated on a component. Each component could be inflated to different sizes in order to adjust the position of the solar panels. This can be used to calibrate a component to be oriented to collect the most sunlight possible, given the angle of the sun. The number and position of these solar cells would also be calibrated for the best performance. A two-dimensional array of these components were to be modelled on the side of the building and then optimized to collect the most energy with a set program of inflation for each component. This optimization would be performed with a Grasshopper plug-in called Galapagos. Galapagos would run a GA on the designs, selecting for designs and inflation schedules, such that the amount of energy collected from the sun would be maximized over the whole year. This would be done taking into account the effects that shadowing would have on the energy collected. The data for how the sun would move across the sky would be provided by another plugin called Geco that is connected to Ecotect software. Due to the complexity of the solutions, the model would initially be designed to be very basic. However, we would add more detail into the model, such that each addition would more accurately model what happens in the real world. After enough of these improvements, we would have gotten a good solution for how to layout the components and panels and what inflation schedules should be used, after running the GA for long enough. This did not work out because the programs used could not handle the amount of computation we required of them. So we moved onto modelling our solutions in python. Using the equations and simple models of how the sun interacts with solar panels 1, we recoded our program as follows. We modelled the side of a building as a two-dimensional array of Cells, see Figure 1. Each cell could hold components in a 2X2, 3X3 or 4X4 array, see Figure 2. A component is an object that can inflate and has solar panels on itself. It would hold all its solar panels at well-defined angles relative to the side of the building. The angles it would hold the solar panels depend on the number of the solar panels on that component and how much inflation the component has undergone. A component can have 1, 2 or 3 solar panel and an overhang to prevent too much direct sun from entering a building (see Figure 6 for the types of shadows that were programmed into our model) above the
1
solar panels, the arrangement of solar panels and overhangs in a grid of components is shown in Figure 3. The effect that inflation has on the component is modeled as an angle factor. The orientations of the solar panels when the Angle Factor is, is provided below in Figure 4. When the Angle Factor is not one, all the angles of the solar panels are multiplied by the angle factor. For example if the angle factor is 2/3 for a component with 1 solar panel, that solar panel has an angle of 2/3*(-45°) =-30° relative to the normal from the side of a building. In the python program, the above design is implemented in a list of length n, where n are all the Cells in the building. Each entry is a tuple of the cell setup and an angle factor. The cell setup is an integer from 1 to 9 corresponding to the layout of the cell and the mapping of integer to cell is shown in Figure 5. These solutions are randomly generated as the starting population for the Genetic Algorithm. We used a population size of 60. The fitness function rewards energy gathered, but penalizes cost of design, in that the more panels a design requires the more of a cost is subtracted from the fitness function. The individuals in a generation undergo recombination and a mutation before being included in the next population generation. The best seen solution is kept as the best solution overall, and not just the best solution in a generation is the best overall solution. After running for 100 generations, the best solution is harvested. Model of a building is restricted to only the top floor. This is because at the top floor, there is little inter-Cell shadowing. Also modeling only the top floor sped up the program, considerably. Results: To see if this method resulted in improvements in design, roughly 20 GA’s, as described above, are run and then the fitness, cost and average angle of the best solutions are pooled. Then 1000 random designs are generated and have their fitness, cost and average angle pooled. The angle factor for each cell for each solution was averaged and included as data points. The box plot of both groups are compared for fitness, cost, and average angle, where the 25, 50 and 75 percentile are compared. The results are shown in Figures 6-8.
Clearly for the fitness function the two distributions do not overlap. For the cost of the design the cost for random solution was on average much larger than for the optimized solutions, also the deviation for the optimized group was much lower than for the random group. For the average angle the deviation decreased.
2
Discussion: For the fitness function, clearly, there was a dramatic difference for each of the two groups. Since there was no overlap at all, this means that the GA optimized for the fitness function as it should have. For cost, there was also a clear trend. While there was overlap between the two distributions, the data from the optimized solutions clearly on average had a much lower cost than a random generated solution. Therefore the GA succeeded in making its best solution relatively inexpensive compared to a random solution. For the average angle factor, clearly the results point to the range of seen angles factors for the optimized solutions as getting smaller and converging on an angle factor of 1. This may indicate that out initial guesses for the angles for the solar panels on the components might be a reasonable solution. Implementing the model for multiple components in Grasshopper was straight forward, however there were some issues with the actually running the simulation. One was that when Galapagos, was run with more than a few components it eventually slowed and crashed. Another problem was that implementing shadows, characteristic of real life, was very complicated, in the grasshopper environment. These and other reasons led to abandoning of grasshopper as the framework with which to do this project.
3
Another issue encountered with this project was the fully implemented fitness function was initially designed to sample the efficiency of the solar panel design across several time points over the day for every day of the year. This proofed to take too much computation time, so for the results obtained, the design was examined by the fitness function at one day from 8 AM to 4PM, in order for the GA to run fast enough for results to be obtained. Clearly, to fully model this, requires something like a dedicated supercomputer running for weeks, to get realistic results. Shadows couldn’t be fully implemented, due to lack of time to design and debug the program for inter-Cell shadows. Future work would require accounting for this. Also other tweaks would likely needed in order to fully model designs in the real world. We would continue refining the model, till it very closely reflected reality. This might be difficult because it would require a lot of verification to show that it represents very closely how the model would behave in the real world. A Wrapper and GUI and perhaps be eventually written to make this program published, so other people could use it to design optimal arrangements for collecting solar energy. In Conclusion, a program is designed and implemented for optimizing the cost and energy collected in a solar panel design. It performed as expected and gave results that show, without any a-prior assumptions about the design, a design can be made to converge to a solution that balanced cost and energy collection efficiency, while allowing for diversity of form with which an architect could choose from to design efficient buildings.
References: 1.
2. 3.
American Society of Heating, Refrigerating and Air-Conditioning Engineers (ASHRAE) (2009) 2009 ASHRAE Handbook: Fundamentals SI. Atlanta, GA: American Society of Heating, Refrigerating and AirConditioning Engineers, Inc. “Genetic Algorithms in Architecture: a Necessity or a Trend?” Eleftheria Fasoulaki, Master of Science in Architecture, Computation Group ,Department of Architecture, Massachusetts Institute of Technology “The optimization of architectural shape based on Genetic Algorithm” Computer Aided Architectural Design, Institute for Technology in Architecture(ITA), Department for Architecture, ETH Zurich, Zurich 8092,Switzerland Urban Architectural Lab, Architectural Design Institute of South east University, Nanjing 210096,China Received 6 April 2012; received in revised form 19 July 2012; accepted 23 July 2012
4
Figure 1: Cells on Building Faรงade
Figure 2: Arrangements of components in a Cell
Figure 3: Solar Panels on Components
5
Figure 4: Angles of Solar Panels for different number of solar panels on a component
Figure 5: Mapping of Integers on to Components Layouts
Figure 6: Different Shadowing Situation that were modeled
6
POSTSCRIPT: Calculation Process1: Equation of Time and Solar Time The earth’s orbital velocity also varies throughout the year, so apparent solar time (AST), as determined by a solar time sundial, varies somewhat from the mean time kept by a clock running at a uniform rate. This variation is called the equation of time (ET) and is approximated by the following formula (Iqbal 1983): ET = 2.2918(0.0075 + 0.1868 cos(r) – 3.2077 sin(r) –1.4615 cos(2r) – 4.089 sin(2r) With ET expressed in minutes and: r = 360° * n – 1/365 Where ET is used in project coding, is in function of H(day,hour); def H(day,hour): r=360*(day-1)/365.0 ET=2.2918*(0.0075+0.1868*cos(pi/180.0*r)-3.2077*sin(pi/180.0*r)-1.4615*cos(2*pi/180.0*r)-4.089*sin(2*pi/180.0*r)) return 15*((hour+ET/60+(LONG-15*TZ)/15)-12)
Declination Because the earth’s equatorial plane is tilted at an angle of 23.45 to the orbital plane, the solar declination δ (the angle between the arth-sun line and the equatorial plane) varies throughout the year. This variation causes the changing seasons with their unequal periods of daylight and darkness. Declination can be obtained from astronomical or nautical almanacs; however, for most engineering applications, the following equation provides sufficient accuracy: δ = 23.45 * sin(360° *(n + 284)/365)) Sun Position The sun’s position in the sky is conveniently expressed in terms of the solar altitude above the horizontal and the solar azimuth measured from the south. The solar altitude angle β is defined as the angle between the horizontal plane and a line emanating from the sun. Its value ranges from 0° when the sun is on the horizon, to 90° if the sun is directly overhead. Negative values correspond to night times. The solar azimuth angle φ is defined as angular displacement from south of the projection, on the horizontal plane, of the earth-sun line. By convention, it is counted positive for afternoon hours and negative for morning hours. Solar altitude and azimuth angles, in turn, depend on the local latitude L (°N, negative in the southern hemisphere); the solar declination δ, which is a function of the date; and the hour angle H, defined as the angular displacement of the sun east or west of the local meridian due to the rotation of the earth, and expressed in degrees as H = 15(AST – 12); where AST is the apparent solar time. H is zero at solar noon, positive in the afternoon, and negative in the morning. AST is coded in project like AST = (hour+ET/60+(LONG-15*TZ)/15). This equation is related the solar altitude angle β to L, δ, and H: sin β = cos L cos δ cos H + sin L sin δ Note that at solar noon, H = 0 and the sun reaches its maximumaltitude in the sky, so: 1
Based on: American Society of Heating, Refrigerating and Air-Conditioning Engineers (ASHRAE) (2009) 2009 ASHRAE Handbook: Fundamentals SI. Atlanta, GA: American Society of Heating, Refrigerating and Air-Conditioning Engineers, Inc
7
βmax = 90° – |L – δ| The azimuth angle φ is uniquely determined by its sine and cosine, given in these equations: sin φ = sin Hcos δ/cos β cos φ = (cos Hcos δ sin L – sin δ cos L)/cos β Where β is defined in project coding, is in function of Beta(day,hour,delta); def Beta(day,hour,delta): return asin(cos(pi/180.0*LAT)*cos(pi/180.0*delta)*cos(pi/180.0*H(day,hour))+sin(pi/180.0*LAT)*sin(pi/180.0*delta))*180/pi Where φ is defined in project coding, is in function of Phi(day,hour,delta); def Phi(day,hour,delta): return -asin(sin(pi/180*H(day,hour))*cos(pi/180*delta)/cos(pi/180*Beta(day,hour,delta)))*180/pi
Transportation to Receiving Surfaces of Various Orientations Calculations developed in the previous section are chiefly concerned with estimating clear-sky solar irradiance either normal to the rays of the sun (direct beam) or on a horizontal surface (diffuse). However, in many circumstances, calculation of clear-sky solar irradiance is required on surfaces of arbitrary orientations. Receiving surfaces can be vertical (e.g., walls and windows) or tilted (e.g., skylights or active solar devices). Solar Angles Related to Receiving Surfaces The orientation of a receiving surface is best characterized by its tilt angle and its azimuth. The tilt angle Σ (also called slope) is the angle between the surface and the horizontal plane. Its value lies between 0 and 180°. The surface azimuth Kapa is defined as the displacement from south of the projection, on the horizontal plane, of the normal to the surface. Surfaces that face west have a positive surface azimuth; those that face east have a negative surface azimuth. The surface-solar azimuth angle γ is defined as the angular difference between the solar azimuth φ and the surface azimuth Kapa: γ = φ – Kapa Values of φ – Kapa, greater than 90° or less than –90° indicate that the surface is in the shade. Finally, the angle between the line normal to the irradiated surface and the earth-sun line is called the angle of incidence θ. It is important in fenestration, load calculations, and solar technology because it affects the intensity of the direct component of solar radiation striking the surface and the surface’s ability to absorb, transmit, or reflect the sun’s rays. Its value is given by cos θ = cos β cos γ sin Σ + sin β cos Σ Note that for vertical surfaces (Σ = 90°), we have :
cos θ = cos β cos γ
Whereas for horizontal surfaces (Σ = 0°), we have :
θ = 90 – β
Where θ is defined in project coding, is in function of Theta(day,hour,delta,sigma); def Theta(day,hour,delta,sigma): return acos(cos(pi/180*Beta(day,hour,delta))*cos(pi/180*(Phi(day,hour,delta) kapa))*sin(pi/180*sigma)+sin(pi/180*Beta(day,hour, delta))*cos(pi/180*sigma))*180/pi
8
CODING PART import random from math import * #generates individuals def randomarray(n,k): a=[] for i in xrange(n): a+=[(random.randint(1,k),random.uniform(0,1.5))] return a def crossover(a1,a2,n): c1=random.randint(0,n-1) c2=random.randint(c1,n-1) ax1=[] ax2=[] for i in xrange(n): if (i>c1 and i<c2): ax1+=[a2[i]] ax2+=[a1[i]] else: ax1+=[a1[i]] ax2+=[a2[i]] return (ax1,ax2) def mutation(a,n,k): m=random.randint(0,n/10) for i in xrange(m): index=random.randint(0,n-1) a[index]=(random.randint(1,k),random.uniform(0,1.5)) return a def H(day,hour): r=360*(day-1)/365.0 ET=2.2918*(0.0075+0.1868*cos(pi/180.0*r)-3.2077*sin(pi/180.0*r)-1.4615*cos(2*pi/180.0*r)4.089*sin(2*pi/180.0*r)) return 15*((hour+ET/60+(LONG-15*TZ)/15)-12) def Beta(day,hour,delta): return asin(cos(pi/180.0*LAT)*cos(pi/180.0*delta)*cos(pi/180.0*H(day,hour))+sin(pi/180.0*LAT)*sin(pi/180 .0*delta))*180/pi def Phi(day,hour,delta): #print acos((cos(pi/180*H(day,hour))*cos(pi/180*delta)*sin(pi/180*LAT)sin(pi/180*delta)*cos(pi/180*LAT))/cos(pi/180*Beta(day,hour,delta)))*180/pi return -asin(sin(pi/180*H(day,hour))*cos(pi/180*delta)/cos(pi/180*Beta(day,hour,delta)))*180/pi def Theta(day,hour,delta,sigma): return acos(cos(pi/180*Beta(day,hour,delta))*cos(pi/180*(Phi(day,hour,delta)kapa))*sin(pi/180*sigma)+sin(pi/180*Beta(day,hour,delta))*cos(pi/180*sigma))*180/pi def energy_per_panel(day,hour,d1,d2,dist,l,e): max=0 for i in xrange(11): #11 angles of panels (0 to d1 or d2) s=0 # keeps track of how much shadow delta=23.45*sin(pi*2*(day+284)/365) x=Theta(day,hour,delta,d1*i/10)*(1-e/t/100) y=Theta(day,hour,delta,d2*i/10)*(1-e/t/100) D=tan(pi/180*(x+d1*i/10))*l*cos(pi/180*(d1*i/10))-dist-l*sin(pi/180*d1*i/10) # does this happen repeatedly? if (D>0): s=D*cos(pi/180*(y+d2*i/10))/sin(pi/180*y) if((x+d1*i/10)<90 and s>=0 and s<l and sin(pi/180*y)*(l-s)/l>max): #sin(pi/180*y)*(l-s)/l shows area without shadow, (x+d1*i/10)<90 shows that there is no complete over shadow max=sin(pi/180*y)*(l-s)/l return max #maximum area without shadow that one panel can save energy with it
9
#calculates the energy saving for all panels during the whole year (365*24) def modularity(a): mod=0 panels=0 for day in xrange(124,125): for hour in xrange(8,17): for i in xrange(n): for j in xrange((a[i][0]-1)/3+2): #number of components in each row for k in xrange((a[i][0]-1)/3+2): #number of components in each column anglefactor=a[i][1] af=anglefactor if ((a[i][0]-1)%3+2==2): mod+=energy_per_panel(day,hour,af*45,af*-45,dist/((a[i][0]1)/3+2),l,i)/(((a[i][0]-1)/3+2)*((a[i][0]-1)/3+2)) panels+=1 elif ((a[i][0]-1)%3+2==3): mod+=energy_per_panel(day,hour,af*45,af*0,dist/(2*((a[i][0]1)/3+2)),l,i)/(((a[i][0]-1)/3+2)*((a[i][0]-1)/3+2)) mod+=energy_per_panel(day,hour,af*0,af*-45,dist/(2*((a[i][0]1)/3+2)),l,i)/(((a[i][0]-1)/3+2)*((a[i][0]-1)/3+2)) panels+=2 else: mod+=energy_per_panel(day,hour,af*45,af*15,dist/(3*((a[i][0]1)/3+2)),l,i)/(((a[i][0]-1)/3+2)*((a[i][0]-1)/3+2)) mod+=energy_per_panel(day,hour,af*15,af*-15,dist/(3*((a[i][0]1)/3+2)),l,i)/(((a[i][0]-1)/3+2)*((a[i][0]-1)/3+2)) mod+=energy_per_panel(day,hour,af*-15,af*-45,dist/(3*((a[i][0]1)/3+2)),l,i)/(((a[i][0]-1)/3+2)*((a[i][0]-1)/3+2)) panels+=3 return mod-panels*cost def selection(a,num_tests): mod=[] b=[] #top quarter (1/2) individuals with highest modularity for i in xrange(len(a)): mod+=[modularity(a[i])] modx=sorted(mod) for i in range(len(a)): if mod[i]>modx[num_tests-num_tests/2-1]: b+=[a[i]] return (b,max(mod),a[mod.index(max(mod))]) #top half individuals, maximum modularity, individual corresponding to the maximum modularity n=10 t=5 LONG=-84.43 LAT=33.64 TZ=-5 kapa=0 l=50 b=[] dist=40 num_tests=60 k=9
#number of cells #number of cells in each floor #Longitute #Latitute #Time Zone #South side #panel length #indivuals (possible solutions) #distance between lower and upper panels #number of individuals in each step #number of components and panels in each cell from 1 to 9 #(k-1)/3+2 number of components, (k-1)%3+2 number of panles #cost penalty per solar panel used in design, more panels used more penalty
cost= 10.0/270 for it for i in xrange(num_tests): b+=[randomarray(n,k)] #print modularity([9, 9, 9, 9, 9, 9, 9, 9, 9, 9]) #print modularity([9, 4, 9, 9, 2, 9, 9, 2, 9, 7]) #print modularity([3, 2, 4, 5, 6, 2, 9, 8, 4, 9]) maxm=modularity(b[0]) opt=b[0] j=0 #generating next generations while(j<100):
10
j+=1 print "this is generation:", j, opt, maxm (b,mod,indiv)=selection(b,num_tests) if mod>maxm: maxm=mod opt=indiv for i in xrange(num_tests/2): i1=random.randint(0,num_tests/2-1) i2=random.randint(0,num_tests/2-1) (cr1,cr2)=crossover(b[i1],b[i2],n) b+=[mutation(cr1,n,k)] #adding next generation after crossover and mutation b+=[mutation(cr2,n,k)] print opt, maxm
11