8

I would like to plot the contour lines for this function, however I cannot find any useful way to do it.

The potential function is : V(x,y,z) = cos(10x) + cos(10y) + cos(10z) + 2*(x^2 + y^2 + z^2)

I unsuccessfully attempted something like:

import numpy
import matplotlib.pyplot.contour

def V(x,y,z):
    return numpy.cos(10*x) + numpy.cos(10*y) + numpy.cos(10*z) + 2*(x**2 + y**2 + z**2)

X, Y, Z = numpy.mgrid[-1:1:100j, -1:1:100j, -1:1:100j]

But then, I don't know how to do the next step to plot it?

matplotlib.pyplot.contour(X,Y,Z,V)
1
  • I think that plotting four-dimensional data (three arguments and the potential) in 3D space isn't going to work. Fundamentally. Is there no way to reduce the dimensionality of the problem, e.g. using the Buckingham-Pi theorem, i.e. non-dimensionalising some variables? If not and the X,Y,Z are just mock arguments not Cartesian components, you'll probably have to resort to multiple series (mentioned by dermen), video, scatter plots with varying sizes, colour-coding, or projecting onto X,Y,Z, so plotting V(X,Y), V(Y,Z) and V(X,Z) separately. Commented May 27, 2015 at 21:35

2 Answers 2

9

An error will arise when you try to pass contour three-dimensional arrays, as it expects two-dimensional arrays.

With this in mind, try:

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np

def V(x,y,z):
     return np.cos(10*x) + np.cos(10*y) + np.cos(10*z) + 2*(x**2 + y**2 + z**2)

X,Y = np.mgrid[-1:1:100j, -1:1:100j]
Z_vals = [ -0.5, 0, 0.9 ]
num_subplots = len( Z_vals)

fig = plt.figure(figsize=(10, 4))
for i,z in enumerate( Z_vals):
    ax = fig.add_subplot(1 , num_subplots , i+1, projection='3d')
    ax.contour(X, Y, V(X,Y,z), cmap=cm.gnuplot)
    ax.set_title('z = %.2f'%z, fontsize=30)
fig.savefig('contours.png', facecolor='grey', edgecolor='none')

enter image description here

Instead, use ax.contourf(...) to show the surfaces, which looks nicer in my opinion.

enter image description here

There is no direct way to visualize a function of 3 variables, as it is an object (surface) which lives in 4 dimensions. One must play with slices of the function to see what's going on. By a slice, I mean a projection of the function onto a lower dimensional space. A slice is achieved by setting one or more of the function variables as a constant.

Sign up to request clarification or add additional context in comments.

Comments

0

I'm not sure this is what the OP needed, but I think a possible solution might be this one:

import numpy as np

import matplotlib
import matplotlib.pyplot as plt

def compute_torus(precision, c, a):
    U = np.linspace(0, 2*np.pi, precision)
    V = np.linspace(0, 2*np.pi, precision)
    U, V = np.meshgrid(U, V)
    X = (c+a*np.cos(V))*np.cos(U)
    Y = (c+a*np.cos(V))*np.sin(U)
    Z = a*np.sin(V)
    return X, Y, Z

x, y, z = compute_torus(100, 2, 1)

fig = plt.figure()

color_dimension = z  # Here goes the potential
minn, maxx = color_dimension.min(), color_dimension.max()
norm = matplotlib.colors.Normalize(minn, maxx)
m = plt.cm.ScalarMappable(norm=norm, cmap='jet')
m.set_array([])
fcolors = m.to_rgba(color_dimension)

# plot
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(x,y,z, rstride=1, cstride=1, facecolors=fcolors, vmin=minn, vmax=maxx, shade=False)

Setting color_dimension to the values of the potential function, using this code can be plotted over a torus. In general, it can be plotted over any 3D shape of (x,y,z), but of course if the 3D space is fully filled with points everywhere, it's unlikely the image will be clear.

1 Comment

ax = fig.gca(projection='3d') is deprecated. use ax = fig.add_subplot(projection='3d')

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.