0

I would like to improve the run time of my code. It's currently very slow because I open a text file in append mode and write values to the end of the file and then I close the file each time I loop. Could someone help me store all my data in a python data structure and then output the results in the same format (i.e. all of the results in a text file with each value seperated by a space)? I am new to python and don't really understand how to implement this. Here's my code:

######import required packages########
import numpy 
import math

#######Set working directory##########
import os 
os.chdir('/Users/DevEnv/')

######Remove files generated from previous simulations##### 
try:
    os.remove('excitations.txt')
except OSError:
    pass

##############Set Model Parameters#####################
n=2 #number of iterations -Change for desired number of loops

tlength=1501 #Length of time interval - DO NOT CHANGE

wu=100 #DO NOT CHANGE

N=250 #wu*T/4Pi approximately - DO NOT CHANGE

Pi=math.radians(180)
t=numpy.linspace(0,10,tlength)
Dw=wu/float(N)


for k in range(0,n):

    A=[]

    wi=[]
    for i in range (0,N):
        wi.append(Dw/2+i*Dw) #Middle of distribution
    for j in range (0,tlength):
        Aj=[]
        phi=numpy.random.rand(N,1)*2*Pi #Generate random phase angle on 0,2pi
        for i in range (0,N):
            w=wi[i]
            Sv=(((1+4*0.6**2*(w/15)**2)/((1-(w/15)**2)**2+4*0.6**2*(w/15)**2))*(0.0000753*(w/1.5)**4/((1-(w/1.5)**2)**2+4*0.6**2*(w/1.5)**2)))
            Aj.append(math.sqrt(Sv*Dw)*2*math.cos(wi[i]*t[j]+phi[i]))
        A.append(sum(Aj))
    outFile = open('excitations.txt','a') #open/create the output file
    for item in A:
        outFile.write('%s ' %item)
    outFile.write('\n')
    outFile.close() #close the output file
user7269405
  • 59
  • 2
  • 8
  • 1
    First of all you can store the calculation results that are constant. E.g- 4*0.6**2. Second you have three nested loops, which is usually bad. Check if you really need three? – Gurwinder Singh Dec 18 '16 at 06:24
  • Thanks for the suggestion. I will store the constant values as variables. However, I do need three nested loops – user7269405 Dec 18 '16 at 06:33

1 Answers1

1

Most of the time in your code is taken up by the cosine calculation (not due to writing to file). Use time to measure the time taken by different parts of your code as described here.

You can get significant improvement (~10 times faster) by converting to numpy array operations like below (untested please check before using)

for k in range(0,n):

    A=[]

    wi=[]
    for i in range (0,N):
        wi.append(Dw/2+i*Dw) #Middle of distribution

    # convert wi to numpy array as that allows array operations
    wi_np = numpy.array(wi) 

    # Sv calculation does not change with j so moving it outside the loop
    # also instead of looping over i to calculate each element
    # use numpy's array operations over wi_np
    p1 = (wi_np / 15)**2
    p2 = p1 * 100 # => (wi_np / 1.5) ** 2
    arg1 = (1 + 4 * 0.6**2 * p1) / ((1 - p1)**2 + 4 * 0.6**2 * p1)
    arg2 = 0.0000753 * p2**2 / ((1 - p2)**2 + 4 * 0.6**2 * p2) 
    Sv_np = arg1 * arg2

    # amp is an array of size N
    amp =  numpy.sqrt(Sv_np * Dw) 

    for j in range (0,tlength):
        # changing the dimensions from (N, 1) to N
        # so that phi is an array of scalars
        # otherwise it messes up the array operations
        phi = numpy.random.rand(N) * 2 * Pi 

        # angle is an array of size N
        angle = wi_np * t[j] + phi 

        # numpy cos is faster than math.cos
        # the multiplication operator between numpy arrays is element wise 
        # hence Aj_np is also array of size N
        Aj_np = 2 * amp * numpy.cos(angle)
        A.append(sum(Aj_np))

    outFile = open('excitations.txt','a') #open/create the output file
    for item in A:
       outFile.write('%s ' %item)
    outFile.write('\n')
    outFile.close() #close the output file
Community
  • 1
  • 1
tihom
  • 7,923
  • 1
  • 25
  • 29