Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I'm currently working on a wind farm design software and basically I have to analyze the incidence of certain wind turbines on other downwind, in order to calculate the velocity drop in the wind once the downstream turbine "sees" the flow.

I have sorted out most of the code and it works, yet this particular piece of it is extremely slow to compute.

for wd in wind_direction_index:
        self.list_for_speed.append([])
        for ws in wind_speed_index:
            self.list_for_speed[wd].append([])
            wind_speed = self._wind_speeds[ws]
            #For every wind turbine, remember this list is still ordered from up to dow
            dummylist=copy.deepcopy(self.list_for_direction[wd])            
            for WT in dummylist:
                #Replace No deficit with 0
                if WT[6]=='NO_deficit':
                    WT[6]=[0.0]
                else:
                    pass
                #For every WT that causes a wake effect on current one
                for upWT in WT[3]:
                    #Define current turbine and rotating upwind turbine
                    for ready in dummylist:
                        if upWT[0]==ready[0]:
                            upWT[6]=ready[6]
                        else:
                            pass
                    current_turbine=WT
                    upwind_turbine=upWT
                    #Calculate wind speeds deficits in every current WT due to every upwind WT to it only if here are upwind WTS
                    if len(current_turbine[3])!=0:
                        self.calculate_deficits(current_turbine,upwind_turbine,wind_speed)
                    else:
                        pass
                #Now we have appended all deficits in current_turbine(6) Time to add them up, find the speed and replace
                #First, I square the list of deficits
                WT[6]=[i**2 for i in WT[6]]
                #Now, i add the squares of the deficits
                deficit_squared=sum(WT[6])
                #Take the square root
                deficit_current=sqrt(deficit_squared)
                #Finally calculate wind speed at the rotor
                U=wind_speed*(1-deficit_current)
                #And I replace the list of wind speed deficits with the wind speed at the rotor
                WT[6]=U
                _Ct=self.team.rna_analysts.get_Ct(U)
                #Save results to local wind speeds array
                self.local_wind_speeds[WT[0]][wd][ws]=[U,_Ct]
            self.list_for_speed[wd][ws].append(dummylist)

I know it's a bit messy, but you can see more or less how my data structures are arranged. I have to calculate a wind speed "deficit" for every turbine, based on the wind direction and the wind speed (evidenced by local_wind_speeds). Can anyone spot how to make this piece of code much much faster?

share|improve this question

migrated from stackoverflow.com May 9 at 14:32

This question came from our site for professional and enthusiast programmers.

2  
Well, what have you tried so far to make it faster? In general, I'd ask myself if Python is the right language for such a computationally intensive problem.. –  lethal-guitar May 5 at 15:31
1  
Check out NumPy and see if you can eliminate loops by operating on whole arrays instead. –  Janne Karila May 10 at 7:11
    
Can you provide some example data, so that we can run the code easier? –  Simon André Forsberg May 10 at 12:39
add comment

1 Answer 1

up vote 2 down vote accepted

I suspect copy.deepcopy is costing you much time; try to avoid it if possible.

Also you are only copying self.list_for_direction[wd], is it necessary to do it multiple time for ws in wind_speed_index?

I try at my best to guess what you are trying to achieve and do not guarantee my code would do exactly what you want. Here the dummylist is no longer needed except for self.list_for_speed[wd][ws].append(dummylist). Unless you really need self.list_for_speed later and it is important that those sharing the same wd are distinct object, I am afraid you can't save much time doing so many copy.deepcopy.

One thing that confuses me is that you have nested for WT in dummylist and for ready in dummylist. And you change WT[6] when it is "NO_deficit" in the first for-loop. Say you are at the i-th iteration in the first for loop and the j-th iteration in the second for-loop. If j>i, it is possible that you have ready[6] being "NO_deficit". I assume this is not what you want.

def U_Ct(OBJ,WT6,wind_speed):
    if WT6 == 'NO_deficit':
        deficit_current = 0.0
    else:
        deficit_squared = sum([i**2 for i in WT6])
        deficit_current = sqrt(deficit_squared)
    U = wind_speed*(1-deficit_current)
    _Ct = OBJ.team.rna_analysts.get_Ct(U)
    return U,_Ct

def get_turbine(WT,upWT):
    '''  WT is a value in the dummylist
    upWT is the WT[3] where WT is from the dummylist
    '''
    if WT[6] == 'NO_deficit':
        WT[6] = [0.0]
    for ready in WT:
        if upWT[0] == ready[0]:
            upWT[6] = ready[6]
    current_turbine = WT
    upwind_turbine = upWT
    return current_turbine,upwind_turbine


for wd in wind_direction_index:
    for ws in wind_speed_index:
        dummylist = copy.deepcopy(self.list_for_direction[wd])
        self.list_for_speed[wd][ws].append(dummylist)
        wind_speed = self._wind_speeds[ws]
        for WT in self.list_for_direction[wd]:
            for upWT in WT[3]:
                current_turbine,upwind_turbine = get_turbine(WT,upWT)
                if len(current_turbine[3])!=0:
                    # What does this function do? It doesn't return anything
                    self.calculate_deficits(current_turbine,upwind_turbine,wind_speed)
            U,_Ct = U_Ct(self,WT[6],wind_speed)
            self.local_wind_speeds[WT[0]][wd][ws] = [U,_Ct]
share|improve this answer
    
Yes, indeed the use of deepcopy was slowing down my code quite a bit. Your code does pretty much what I want it to, although the list_for_speed structure is something I do need, thus I am still using it with a single deepcopy at the end as in the original code. Thank you very very much KYC! –  user3181463 May 14 at 19:16
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.