1 | initial version |
Hello, @ortollj! After studying your code, I believe the problem comes from the fact that intY0
is a function of two variables---x
and z
, in this case, as you can see from the output your code generates. The thing is that definite_integral
can integrate only one-variable functions. That is why you get the message
ValueError: The function to be integrated depends on 2 variables (x, z), and so cannot be integrated in one dimension. Please fix additional variables with the 'params' argument
What does this mean? That Sage has noticed that there are more than one variable, and you should give the remaining variables some numerical value in order to perform the numerical integral. Basically, Sage is asking you to do something like this:
intYX00 = numerical_integral(intY0,eqLimitL[2].rhs(),eqLimitL[3].rhs(), params=[0])
That specifies that this integral is to be performed on the first variable ($x$), after replacing $z=0$. In short, if you have a $n$-variable function, you need to specify $n-1$ numerical values for the $n-1$ last variables, so that numerical_integral
can perform the integral using the first variable of the function. To better understand this, consider the following example:
f(x,y,z) = x^2 * y * z
numerical_integral(f, 0, 1, params=[2,3])
This is effectively equivalent to the integral $$\int_0^16x^2\;dx$$ since the variables $y$ and $z$ have been given the values $2$ and $3$, respectively.
This brings me to the following matter: why did I use params=[0]
and no other value? In this particular case, the value I choose is irrelevant, since your intY0
is defined to be a function on $(x,z)$, but in reality its value only depends on $x$. This example will clarify this words:
f(x,y) = x^2
numerical_integral(f, 0, 1, params=[0])
Since I defined $f$ to be a function of $(x,y)$, I need to use the params
argument to fix the value of $y$. However, since the value of $f$ does NOT depend on $y$, I can use anything that I please, even params=[y]
itself. It won't make any difference. Of course, if this function were $f(x,y)=x^2y^3$, then there would be a different result for every (numerical) value I choose for $y$ (e.g., params=[2]
to integrate $8x^2$). Notice that in this particular case, I can NOT use params=[y]
, because that would keep $f$ as a two variable function.
Now, when you make
fsgn(x) = -1
intY00 = intY0.substitute_function(sgn,fsgn)
apparently substitute_function
converts intY0
into a simple expression (not a function that maps $(x,z)$, just a formula.) You can check this if you add print(intY00)
. You will notice the part (x,z) |-->
is now missing. In particular, now intY00
is a formula whose value depends only on $x$, but not on $z$. So, when you pass it to numerical_integral
, Sage assumes it is a one-variable function, and that way it is able to integrate.
I believe that answers your question. However, there are a few additional observations that could help you:
I can see that you used assume(0<x<1)
; I also did that. I was quite surprised to see that this had no effect on the sgn
function. Indeed, here is an example that should return 1, but does not:
var('x', domain='real')
assume(0<x<1)
sgn(x)
However, that should not be a problem, since the integration algorithm will anyway evaluate the sgn
function and return an adequate value.
I recommend in this case to remove the variable $z$ from the definition of your functions, since their values do not depend on that variable. That should eliminate the necessity of using the params
argument to eliminate $z$, when it is not needed in the first place.
Unfortunately, in this particular case, you will still need to manually replace the value for sgn
, since intY0
has this expression in it:
sgn(4*x^2*e^(2/9*I*pi) + e^(4/9*I*pi) - 2*e^(2/9*I*pi) + 1)
Sage seems unable to deal with this expression. Indeed, I get the message
TypeError: unable to coerce to a real number
However, replacing only that part with fsgn(x)
or '(-1)' (leaving the other sgn
) in intY0
, returns the correct result without any problem. BUT BE CAREFULL: For complex numbers $z$, the signum function is defined by
$$\operatorname{sgn}(z) = \frac{z}{|z|}.$$
Unfortunately, the last bad news is that numerical_integral
cannot deal with complex functions. Hopefully, there is a solution to this problem, but I can think of it right now...
I hope this answers your questions!