2

I'm trying to integrate a function into a given range that shows the flow of particles in a zero-angle (theta) direction as a function of the energy E of the particles. I've tried several ways and got different errors but there are two that persist at the end. My knowledge of Python is limited, I try to learn new ways of doing stuff as I need them but I've been around this function for days with no success.

My function at the moment looks like this:

from numpy import radians, cos, arange
from scipy.integrate import quad

def integral(self):
    theta=0
    E = arange(1, 5000, 1)
    costh = cos(radians(theta))
    a = 18 / (E * costh + 145)
    b = (E + 2.7 / costh)**-2.7
    c = (E + 5) / (E + 5 / costh)
    return a*b*c*1**4


A = quad(integral, 500, 1000)

Applying "quad" to the function like this returns:

TypeError: only length-1 arrays can be converted to Python scalars

If I don't put "self" as argument in the funtion, it returns:

TypeError: integral() takes 0 positional arguments but 1 was given

Has someone an idea on how to bypass this?

  • 1
    `quad` takes a function that accepts one value, and returns one value. It looks like your `intergral` doesn't do anything with the argument, and returns an array, values over 5000 points. You may need to reread the `quad` docs and experiment with some of its examples. – hpaulj May 20 '18 at 20:02

1 Answers1

1

integral must have one of the signatures described in the scipy documentation. In your case, a function taking a double as argument and returning a double seems appropriate.

self is only used for member functions of a class. It does not make sense outside a class definition. Replace that with a simple name, say x that will be the input argument of the function to integrate.

The function must return a double. Since E is an array and you seem to make calculations with it, then the computed return value is likely to be an array too. It must be a scalar. Fix that and it will work. When you replace your function with something like:

def integral(x):
    return x * x

then it works. This is not what you need, of course, but this is the kind of arguments and return values that are required for quad() to work.

You may want to look here for an example on how quad() is being used.

Some recommendations:

  • use four spaces for indentation (not 5 as in the example)
  • parentheses around the result are not required. Remove for more clarity.
Adrian W
  • 4,563
  • 11
  • 38
  • 52
  • Thank you for the feedback, it helped me a lot. I thought how could I get a scalar and came with a solution. E can be a function of theta, so I got around it by rearranging the funtion to only be dependent of theta. So I created a lambda funtion of theta with only that equation and with that the "quad" integration worked. It's not the same as the function above because in the case above I want to integrate between an energy range not an angular range, but once I got one I could get the other just by modifying the equation. Much appreciated! – Pedro Paxton May 22 '18 at 18:05