Search code examples
pythonnumpyfor-loopsumnested-loops

A summation using nested loop and zip


I have a file: volume_FREQ.dat:

# Volume (V)  FREQ    mode
18.1          400.9    1      #| 
18.1          401.3    2      #| 1st Volume: 18.1
18.1          404.2    3      #| 
18.1          505.2    4      #|
19.2          202.4    1           #|  
19.2          203.6    2           #| 2nd Volume: 19.2 
19.2          205.4    3           #|
19.2          199.5    4           #|

In the real file there are 11 volumes, and 45 modes at each volume.

Then I have this file: parameters.dat :

# c           d         f        mode
-1.14     -24.70     1297.20     1
-1.24     -22.60     1295.20     2
-1.54     -21.08     1296.20     3
-1.72     -22.4      1298.40     4        

For each of these 11 volumes, there is a value of P. In the following formula, this is represented by P(V): This value of P at each Volume is calculated by summing over the modes, using the values of c, d,f, andFREQ accordingly:

enter image description here

Figure 1.

The variable T is this list:

 T =  [10.0, 30.1, 50.2]

The real list has a length of 100.

For each T and each V there is a value of P.

The final solution would be to end up with a file like data.dat :

# Volume (V)  FREQ    mode   T        P
18.1          400.9    1    10.0     x            #| 
18.1          401.3    2    10.0     x            #| 1st Volume: 18.1
18.1          404.2    3    10.0     x            #| 
18.1          505.2    4    10.0     x            #|
19.2          202.4    1    10.0     x                #|  
19.2          203.6    2    10.0     x                #| 2nd Volume: 19.2 
19.2          205.4    3    10.0     x                #|
19.2          199.5    4    10.0     x                #|
18.1          400.9    1    30.1     x            #| 
18.1          401.3    2    30.1     x            #| 1st Volume: 18.1
18.1          404.2    3    30.1     x            #| 
18.1          505.2    4    30.1     x            #|
19.2          202.4    1    30.1     x                #|  
19.2          203.6    2    30.1     x                #| 2nd Volume: 19.2 
19.2          205.4    3    30.1     x                #|
19.2          199.5    4    30.1     x                #|
18.1          300.1    1    50.2     x            #| 
18.1          305.2    2    50.2     x            #| 1st Volume: 18.1
18.1          303.6    3    50.2     x            #| 
18.1          303.9    4    50.2     x            #|
19.2          304.5    1    50.2     x                #|  
19.2          305.9    2    50.2     x                #| 2nd Volume: 19.2 
19.2          306.5    3    50.2     x                #|
19.2          307.1    4    50.2     x                #|

Each of the input variables can be easily extracted by numpy:

import numpy as np
c, d, f, mode = np.loadtxt('parameters.dat', skiprows = 1).T
V, FREQ, mode = np.loadtxt('Volume_FREQ.dat',  skiprows = 1).T

However, the difficulty comes when applying the formula and looping over the modes:

I can create a VOLUME list:

 VOLUME = [19.2, 18.1]

And then a nested loop + zip:

 sum_for_each_volume = []
 for i_VOLUME in VOLUME:

   P_CORRECT = []

   for j_c1, j_d, j_FREQ, i_T in zip(c1, d, FREQ, T):

        P = j_FREQ * i_T * (i_VOLUME * j_c1 + j_d)

        P_CORRECT.append(P)

   summation = sum(P_CORRECT)

   sum_for_each_volume.append(summation)

However, this solution is not grabbing the FREQS at each volume correctly, and also the all theT elements are not read by each volume.

I would appreciate if you could help me.

Based on @user7138814 's answer :

Running this script:

import numpy as np
n_volume = 2
n_mode = 4
n_T = 3

c, d, f, mode = np.loadtxt('parameters.dat', skiprows = 1).T
V, FREQ, mode = np.loadtxt('Volume_FREQ.dat',  skiprows = 1).T
T =  [10.0, 30.1, 50.2]

V = V.reshape(n_volume, n_mode)
FREQ = FREQ.reshape(n_volume, n_mode)


P_for_each_volume_and_each_T = []

for i in range(n_volume):
  for j in range(n_T):
    P = 0
    for k in range(n_mode)
        P += FREQ[i,k] * T[j] * (V[i,k]*c[k] + d[k])
    P_for_each_volume_and_each_T.append(P)


print 'P = ', P_for_each_volume_and_each_T

the output is the following:

P = [-830821.31000000006, -2500772.1431000005, -4170722.9762000004, -403382.67200000002, -1214181.8427200001, -2024981.0134400004]

However, by using the P_for_each_volume_and_each_T[i] = P_for_each_volume_and_each_T[i] + P_for_each_volume_and_each_T[i-1] strategy, as shown here (run the following script):

import numpy as np

n_volume = 2 
n_mode = 4

n_T = 3

c, d, f, mode = np.loadtxt('parameters.dat', skiprows = 1).T
V, FREQ, mode = np.loadtxt('Volume_FREQ.dat',  skiprows = 1).T
T =  [10.0, 30.1, 50.2]

V = V.reshape(n_volume, n_mode)
FREQ = FREQ.reshape(n_volume, n_mode)


P_for_each_volume_and_each_T = []

for i in range(n_volume):

  for j in range(n_T):
    P = 0
    for k in range(n_mode):
        P = FREQ[i,k] * T[j] * (V[i,k]*c[k] + d[k])
        print 'FREQ[i,k] = ', FREQ[i,k]
        print 'V[i,k] = ', V[i,k]
        print 'c[k] = ', c[k]
        print 'd[k] = ',  d[k]
        print 'P = ', P
    P_for_each_volume_and_each_T.append(P)
print 'P = ', P_for_each_volume_and_each_T


for i in xrange(1,len(P_for_each_volume_and_each_T)):
    P_for_each_volume_and_each_T[i] = P_for_each_volume_and_each_T[i] + P_for_each_volume_and_each_T[i-1]


print 'P after summing= ', P_for_each_volume_and_each_T

you get this output:

P = [-270443.66399999999, -814035.42863999994, -1357627.19328, -110570.88, -332818.34880000004, -555065.81760000007]

this makes total sense when summing:

P after summing= [-270443.66399999999, -1084479.0926399999, -2442106.2859199997, -2552677.1659199996, -2885495.5147199994, -3440561.3323199996]

Therefore, P after summing list does not match @user7138814's P list.

Which strategy is therefore the correct one for solving this problem (see Figure 1) ?

Either += strategy or [i] + [i-1] strategy ?


Solution

  • You need one more for-loop, since you have arrays of 3 different lenghts (i.e. your parameter space is 3 dimensional). The V and FREQ you load from volume_FREQ.dat are in fact two dimensional data. So with reshapes and another loop you would get something like:

    import numpy as np
    
    n_volume = 11
    n_mode = 45
    n_T = 3
    
    c, d, f, mode = np.loadtxt('parameters.dat', skiprows = 1).T
    V, FREQ, mode = np.loadtxt('Volume_FREQ.dat',  skiprows = 1).T
    T =  [10.0, 30.1, 50.2]
    
    V = V.reshape(n_volume, n_mode)
    FREQ = FREQ.reshape(n_volume, n_mode)
    
    P_for_each_volume_and_each_T = []
    for i in range(n_volume):
        for j in range(n_T):
            P = 0
            for k in range(n_mode)
                P += FREQ[i,k] * T[j] * (V[i,k]*c[k] + d[k])
            P_for_each_volume_and_each_T.append(P)
    

    A more numpythonic would be the following array operation:

    V = V.reshape(n_volume, n_mode)
    FREQ = FREQ.reshape(n_volume, n_mode)
    T = np.array(T).reshape(-1, 1, 1)
    P_for_each_volume_and_each_T = (FREQ * T * (V*c + d)).sum(axis=0)
    

    This would give a (n_volume, n_T) 2D array. Use ravel to get the same result as with the for-loops.