Prelude
Prelude

Reputation: 151

Summation in python using recursive function

I am trying to calculate below summation

enter image description here

where f_j,f_j are functions of q calculated before and q=sin(theta) where theta varies[0,90], and r_ij is the respective distance bewteen each two elements I am doing this calculation for.

I used the sum() function at first but it didn't work proberly as it returns a float number, but as q is changing and there's no summation for it I'm expecting an array!Ergo I gave it up.

My second approach was recursive function for calculating this summation,but I get so many errors and have no idea what is wrong with my code as I thing all the syntaxes are correct and I have no idea why I get errors or wrong values one after another!

    theta=arange(radians(0.5), radians(40.010), radians(0.03))
    q=sin(theta) 

    f_q_1= 2*exp(-3*pow(q,2))+4*exp(-5*pow(q,2))+1.95
    f_q_2=...
    .
    f_q_i(or j).

    atom_positions= open('coordinates.txt','r')

    lines = atom_positions.readlines()
    for i in range(0, len(lines)):
        line = lines[i]
        values = line.split(" ")
        for j in range(0,len(lines)):
         if j<>i: 
          nextLine = lines[j]
          nextLineValues = nextLine.split(" ")

           r =sqrt((float(values[5])-float(nextLineValues[5]))**2 + (float(values[6])
          -float(nextLineValues[6]))**2+(float(values[7])-float(nextLineValues[7]))**2)

            line_len = len(lines)
            def I_tot(line_len,i,f_i,f_j,r):
             I=0
             if i<line_len:
                I=I+(f_i*f_j*sin(q*r)/(q*r))
                return I + I_tot(line_len,i,f_i,f_j,r)
             else:
                return I
else:

     plot(2*theta,I_tot)
     show()
    atom_positions.close()

error:

RuntimeError: maximum recursion depth exceeded while calling a Python object

+This question is not a duplicate of recursive summation questions asked here before, As I checked them and couldn't find a solution to my problem.


I have also tried the function

def I_tot():
       I=0
       for i in range(0,len(lines)):
          I=I+(f_i*f_j*sin(q*r)/(q*r))

       return I

But I have no idea whether it gives me the correct summation or not, because the graph I get in the end is far from my expectation and indicates that this summation should not be correct.

Upvotes: 0

Views: 2921

Answers (2)

Ronen
Ronen

Reputation: 486

Recursion in Python is limited. I would try summation anyway.

Note that in Numpy's sum function, you have two parameters:

def sum(a, axis=None, dtype=None, out=None, keepdims=False):
    """
    Sum of array elements over a given axis.

    Parameters
    ----------
    a : array_like
        Elements to sum.
    axis : None or int or tuple of ints, optional
        Axis or axes along which a sum is performed.
        The default (`axis` = `None`) is perform a sum over all
        the dimensions of the input array. `axis` may be negative, in
        which case it counts from the last to the first axis.
...

The axis parameters tell it to sum in only sum of the dimensions. Meaning, if you sum along the q and j axis, you can still have a vector result in the q axis .

You should have something similar to that.

import numpy as np
qs = np.array([1,2,3]) #Generate sum qs.
r = np.array([[11,21, 41,51]]) #the r_ij compnent. as a 1D vector 
                               #(you can get it using reshape() )

np.kron(qs,r.T).sum(axis=0) #a vector containing sum(q*r) for each q.

Here, np.krons gives you

array([[ 11,  22,  33],
       [ 21,  42,  63],
       [ 41,  82, 123],
       [ 51, 102, 153]])

and the summation gives

array([124, 248, 372])

A single element for each line.

You can easily generalize it to include f_i(q) (a 2D array of the same structure), add sin, etc.

Upvotes: 1

M4rtini
M4rtini

Reputation: 13539

still not sure what your end result is gonna be. But here are some starting points.

Use this to load inn the positions, calculate the distances and put it in a array.

import numpy as np
from scipy.spatial import distance
values = np.genfromtxt('coordinates.txt', dtype=float, usecols=[5,6,7])
r_ij = distance.squareform(distance.pdist(xyz))
nPositions = r_ij.shape()[0]

If you can make arrays of f_j and f_i, you can probably vectorize the summation, by utilizing array multiplication and the numpy version of sum. which allows you to define what axis to sum over.

Upvotes: 1

Related Questions