InterpND for one dimension - openmdao

I'm trying to use the function InterpND from openmdao.components.interp_util.interp.
No problem using it for multidimensional data - I can interpolate a 3-D tensor without problems. However I'd also like to use for 1-D data. Not sure what I am doing wrong, but when I try to do something really simple like
import numpy as np
from openmdao.components.interp_util.interp import InterpND
x = np.array([0.,1.,2.,3.,4.])
y = x**2
f = InterpND(points=x, values=y)
I get the following error message:
ValueError: There are 5 point arrays, but values has 1 dimensions
Looking at the InterpND source code it seems like I SHOULD be able to just have x and y as simple 1-D arrays.
Parameters
----------
points : ndarray or tuple of ndarray of float, with shapes (m1, ), ..., (mn, )
The points defining the regular grid in n dimensions. For 1D interpolation, this
can be an ndarray.
values : array_like, shape (m1, ..., mn, ...)
x is a 1D ndarray, y is also a 1D nd array.

This looks like a bug in OpenMDAO V3.7.0 related to the input error checking. Here is a workaround. If you put the 1-D table points into a list, it works without error:
f = InterpND(points=[x], values=y)

Related

Problem to clearly differentiate contour levels in contourf

I try to get a useful plot with contourf using (107,107) arrays multiplying with a proportional factor. I use the following code:
con_sun_mass = 1.98892e+30
C=3.04
a=np.logspace(np.log10(0.02*1e-06),np.log10(10*1e-06),107)
b=np.linspace(con_sun_mass*1e-17,con_sun_mass*1e-13,107)
A, B= np.meshgrid(a,b )
fig,ax=plt.subplots(1,1)
test=B*np.abs(f1[:,7])/((B*np.abs(f2[:,7])+(B*f3[:,7]+C)))
cp = ax.contourf(A, B,test,levels=100,cmap="seismic",extend='both')
plt.colorbar(cp).set_label("P")
ax.set_xlabel("a")
ax.set_ylabel('b')
plt.ticklabel_format(style='sci', axis='y', scilimits=(0,0), useMathText=True)
plt.ticklabel_format(style='sci', axis='x', scilimits=(0,0), useMathText=True)
plt.savefig("relation.png")
plt.show()
The exact forms of the (107,107) arrays f1, f2 and f3 are not important, but they all should increase with increasing B so that according to the equation for test, test should increase with increasing values of b.
The result is:
But as you can see, it seems like constant contourlevels with increasing B which is strange. I also tried to use pcolormesh and imshow instead of contourf but they seem not to work with my numpy arrays. Does anyone know what could I possibly do to observe differences on the axis for "b"?

Plot of function, DomainError. Exponentiation yielding a complex result requires a complex argument

Background
I read here that newton method fails on function x^(1/3) when it's inital step is 1. I am tring to test it in julia jupyter notebook.
I want to print a plot of function x^(1/3)
then I want to run code
f = x->x^(1/3)
D(f) = x->ForwardDiff.derivative(f, float(x))
x = find_zero((f, D(f)),1, Roots.Newton(),verbose=true)
Problem:
How to print chart of function x^(1/3) in range eg.(-1,1)
I tried
f = x->x^(1/3)
plot(f,-1,1)
I got
I changed code to
f = x->(x+0im)^(1/3)
plot(f,-1,1)
I got
I want my plot to look like a plot of x^(1/3) in google
However I can not print more than a half of it
That's because x^(1/3) does not always return a real (as in numbers) result or the real cube root of x. For negative numbers, the exponentiation function with some powers like (1/3 or 1.254 and I suppose all non-integers) will return a Complex. For type-stability requirements in Julia, this operation applied to a negative Real gives a DomainError. This behavior is also noted in Frequently Asked Questions section of Julia manual.
julia> (-1)^(1/3)
ERROR: DomainError with -1.0:
Exponentiation yielding a complex result requires a complex argument.
Replace x^y with (x+0im)^y, Complex(x)^y, or similar.
julia> Complex(-1)^(1/3)
0.5 + 0.8660254037844386im
Note that The behavior of returning a complex number for exponentiation of negative values is not really different than, say, MATLAB's behavior
>>> (-1)^(1/3)
ans =
0.5000 + 0.8660i
What you want, however, is to plot the real cube root.
You can go with
plot(x -> x < 0 ? -(-x)^(1//3) : x^(1//3), -1, 1)
to enforce real cube root or use the built-in cbrt function for that instead.
plot(cbrt, -1, 1)
It also has an alias ∛.
plot(∛, -1, 1)
F(x) is an odd function, you just use [0 1] as input variable.
The plot on [-1 0] is deducted as follow
The code is below
import numpy as np
import matplotlib.pyplot as plt
# Function f
f = lambda x: x**(1/3)
fig, ax = plt.subplots()
x1 = np.linspace(0, 1, num = 100)
x2 = np.linspace(-1, 0, num = 100)
ax.plot(x1, f(x1))
ax.plot(x2, -f(x1[::-1]))
ax.axhline(y=0, color='k')
ax.axvline(x=0, color='k')
plt.show()
Plot
That Google plot makes no sense to me. For x > 0 it's ok, but for negative values of x the correct result is complex, and the Google plot appears to be showing the negative of the absolute value, which is strange.
Below you can see the output from Matlab, which is less fussy about types than Julia. As you can see it does not agree with your plot.
From the plot you can see that positive x values give a real-valued answer, while negative x give a complex-valued answer. The reason Julia errors for negative inputs, is that they are very concerned with type stability. Having the output type of a function depend on the input value would cause a type instability, which harms performance. This is less of a concern for Matlab or Python, etc.
If you want a plot similar the above in Julia, you can define your function like this:
f = x -> sign(x) * abs(complex(x)^(1/3))
Edit: Actually, a better and faster version is
f = x -> sign(x) * abs(x)^(1/3)
Yeah, it looks awkward, but that's because you want a really strange plot, which imho makes no sense for the function x^(1/3).

Julia - plot with 2 arrays of same size

I have two arrays:
sigma = logspace(-4,4,5)
which looks like = [10^-4,10^-2,10,10^2,10^4]
and some other array that contains 5 values which were generated from norm-2 of some 5 different vectors.
assume this is the second array:
Xnorm = [1,2,3,4,5]
I'm trying to plot those two arrays:
figure()
plot(Xnorm,sigma)
I would like that sigma will represent the X-axis and Xnorm the y-axis.
The result right now is an empty graph. (I've tried to swap between both of them also).
Unfortunately, I did not found any good documentation for plotting with array.
You need to import the plotting library
sigma = logspace(-4,4,5)
Xnorm = [1,2,3,4,5]
# Pkg.add("Plots") # Do this only the first time to install.
using Plots
plot(Xnorm,sigma)

IPython, Plotting a Polynomial

I've been working with Sympy for an Interpolation, in which I obtain as a result a 7th degree Polynomial (ax^7 + bx^6 + cx^5 + ...+ h) which I want to Plot, but wen I try to plot it I get errors, for example, if I try:
plt.plot(r,U.subs(x,r))
where r = np.linspace(0,20,num=100) and U = Polynomial(x);
the result is an error message: ValueError: sequence too large; must be smaller than 32, I obtain MemoryError: if I try `r = np.arange(20)'. The only way I could plot it is with a for cycle, substituting one by one and saving it in another variable as a list. So my question is, what is wrong with the first's inputs? is there an easy way to plot a polynomial?
Welcome to SO!
The subs() method is not meant to be used with numpy arrays. lambdify() does what you want. Try:
import numpy as np
import matplotlib.pyplot as plt
import sympy as sy
sy.init_printing() # nice formula rendering in IPython
x = sy.symbols("x", real=True)
# the sample polynomial:
pp = x**3 + 3*x**2 - 6*x - 8
# Convert expression function usable with numpy array:
f_pp = sy.lambdify(x, pp, modules=np)
# Do the plotting:
x_n = np.linspace(-5, 2, 500)
y_n = f_pp(x_n) # evaluate all x_n
fg, ax = plt.subplots(1, 1)
ax.plot(x_n, y_n)
fg.canvas.draw()
plt.show()
The parameter modules=np ensures, that numpy is used for functions in the expression (e.g., sin() => np.sin()). In this example, it is not explicitly needed.
PS: If you include a runnable example in your question, it makes live much easier for potential answerers.

Can't generate a surface plot in scilab

I'm having trouble generating a three-dimensional surface plot in Scilab. I keep getting the error:
!--error 999
Objplot3d: x vector is not monotonous.
I'm using the command:
plot3d(x,y,z)
where x and y are 200X1 matrices (aka column vectors) and z is a 200X200 matrix. I thought maybe I had to transpose y, but that led to the same error as well.
help plot3d requires, indeed, that the first two arguments be monotonous (ie sorted). I wish someone could tell me why!
Since your x (and possibly y) is not ordered, which causes the error, you just need to sort them, and then pay some attention to keep the z values where they belong. Something like:
[newx,ix]=gsort(x);
[newy,iy]=gsort(y);
newz = z(ix,iy);
plot3d(newx,newy,newz)
(ix is the permutation such that x(ix)==newx)

Resources