Module PDESolver.Visuals
Expand source code
import os
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from mpl_toolkits.axes_grid1 import make_axes_locatable
def _outFolderExists():
if not os.path.isdir('../out/'):
os.mkdir('../out/')
def _plot_loss(solver):
fig = plt.figure(figsize=(9, 6))
ax = fig.add_subplot(111)
n = len(solver.loss_history)
k = min(100, n)
averaged_loss = np.convolve(solver.loss_history, np.ones(k) / k, mode='same')
ax.semilogy(range(n), solver.loss_history, 'k-', lw=0.5)
ax.semilogy(range(n), averaged_loss, 'r--', lw=1)
ax.set_xlabel('$Iteration$')
ax.set_ylabel('$Loss$')
ax.set_xlim(0, n - (1 if n > 1 else 0))
plt.show()
def _plot_3d(X, Y, Z, ax, variables, title, show=True):
ax.view_init(35, 135)
ax.invert_xaxis()
ax.invert_yaxis()
ax.set_xlabel('$%s$' % variables[0])
ax.set_ylabel('$%s$' % variables[1])
ax.set_zlabel('$u(%s, %s)$' % (variables[0], variables[1]))
ax.set_title(title)
plot = ax.plot_surface(X, Y, Z, cmap='jet')
if show:
plt.show()
return plot
def _plot_heatmap(X, Y, Z, ax, variables, title, show=True):
plot = ax.imshow(np.flip(Z, 0), cmap='jet', extent=[X.min(), X.max(), Y.min(), Y.max()], aspect='auto')
ax.set_xlabel('$%s$' % variables[0])
ax.set_ylabel('$%s$' % variables[1])
ax.set_title(title)
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)
plt.colorbar(plot, cax=cax)
if show:
plt.show()
return plot
def plot_1D(solver):
"""
Plots the solution of a BVP defined in one spacial dimension and one output.
Parameters
-----------
solver: Solver
Trained solver to be visualized
"""
def plot_sample_points():
fig = plt.figure(figsize=(9, 6))
for cond in solver.bvp.get_conditions():
t, x = cond.sample_points()[:, 0], cond.sample_points()[:, 1]
if cond.name != 'inner':
plt.scatter(t, x, c='black', marker='X')
else:
plt.scatter(t, x, c='r', marker='.', alpha=0.1)
plt.xlabel('$t$')
plt.ylabel('$x$')
plt.title('Positions of collocation points and boundary data')
plt.show()
def plot_u():
# Set up meshgrid
N = 1000
xspace = np.linspace(bounds[0][0], bounds[1][0], N + 1)
yspace = np.linspace(bounds[0][1], bounds[1][1], N + 1)
X, Y = np.meshgrid(xspace, yspace)
XYgrid = np.vstack([X.flatten(), Y.flatten()]).T
# Determine predictions of u(t, x)
upred = solver.model(tf.cast(XYgrid, 'float32'))[:, 0]
minu, maxu = np.min(upred), np.max(upred)
# Reshape upred
U = upred.numpy().reshape(N + 1, N + 1)
# Surface plot of solution u(t,x)
fig = plt.figure(figsize=(9, 6))
ax = fig.add_subplot(111, projection='3d')
_plot_3d(X, Y, U, ax, ['t', 'x'], 'Solution of equation', False)
plt.savefig('../out/3D_%s_solution.pdf' % solver.bvp.__class__.__name__, bbox_inches='tight', dpi=300)
plt.show()
fig = plt.figure(figsize=(9, 6))
plt.imshow(U, cmap='viridis')
ax.set_xlabel('$t$')
ax.set_ylabel('$x$')
ax.set_title('Solution of equation')
plt.savefig('../out/2D_%s_solution.pdf' % solver.bvp.__class__.__name__, bbox_inches='tight', dpi=300)
plt.show()
return minu, maxu
def animate_solution():
fig, ax = plt.subplots()
xdata, ydata = tf.linspace(bounds[0][1], bounds[1][1], 1000), []
ln, = plt.plot([], [], color='b')
title = ax.text((bounds[0][1] + bounds[1][1]) / 2, maxu - 0.1 * abs(maxu), "", ha='center')
def init():
ax.set_xlim(bounds[0][1], bounds[1][1])
ax.set_ylim(minu, maxu)
return ln,
def update(frame):
ydata = solver.model(tf.transpose(tf.stack([tf.ones_like(xdata) * frame, xdata])))[:, 0]
ln.set_data(xdata, ydata)
title.set_text(u"t = {:.3f}".format(frame))
return ln, title
anim = FuncAnimation(fig, update, frames=np.linspace(bounds[0][0], bounds[1][0], 300),
interval=16, init_func=init, blit=True)
anim.save("../out/2D_%s_solution.gif" % solver.bvp.__class__.__name__, fps=30)
plt.show()
inner = [cond for cond in solver.bvp.conditions if cond.name == "inner"][0]
bounds = inner.get_region_bounds()
_outFolderExists()
plot_sample_points()
_plot_loss(solver)
minu, maxu = plot_u()
animate_solution()
def plot_2D(solver):
"""
Plots the solution of a BVP defined in two spacial dimensions and one output.
Parameters
-----------
solver: Solver
Trained solver to be visualized
"""
def animate_solution():
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
N = 100
xspace = np.linspace(0, 1, N)
yspace = np.linspace(0, 1, N)
X, Y = np.meshgrid(xspace, yspace)
XYgrid = np.vstack([X.flatten(), Y.flatten()]).T
XYgrid = tf.cast(XYgrid, 'float32')
x, y = XYgrid[:, 0], XYgrid[:, 1]
zarray = np.zeros((N, N, 120))
for i in range(120):
z = solver.model(tf.transpose(tf.stack([tf.ones_like(x) * i, x, y])))
zarray[:, :, i] = tf.reshape(z, X.shape)
def update_plot(frame_number, zarray, plot):
plot[0].remove()
plot[0] = ax.plot_surface(X, Y, zarray[:,:,frame_number], cmap="magma")
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
plot = [ax.plot_surface(X, Y, zarray[:, :, 0], color='0.75', rstride=1, cstride=1)]
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_zlim(-0.1, 1)
anim = FuncAnimation(fig, update_plot, 120, fargs=(zarray, plot), interval=16)
anim.save("../out/%s_solution.gif" % solver.bvp.__class__.__name__, fps=30)
plt.show()
_outFolderExists()
_plot_loss(solver)
animate_solution()
def plot_2Dvectorfield(solver):
"""
Plots the solution of a BVP defined in two spacial dimensions and two outputs.
Parameters
-----------
solver: Solver
Trained solver to be visualized
"""
def animate_solution():
fig = plt.figure()
ax = fig.add_subplot()
N = 30
xspace = np.linspace(-2, 2, N)
yspace = np.linspace(-2, 2, N)
X, Y = np.meshgrid(xspace, yspace)
XYgrid = np.vstack([X.flatten(), Y.flatten()]).T
XYgrid = tf.cast(XYgrid, 'float32')
x, y = XYgrid[:, 0], XYgrid[:, 1]
z = solver.model(tf.transpose(tf.stack([tf.zeros_like(x), x, y])))
Zx = tf.reshape(z[:, 0], X.shape)
Zy = tf.reshape(z[:, 1], X.shape)
plot = ax.quiver(X, Y, Zx, Zy, scale=1.0)
def data_gen(frame):
x, y = XYgrid[:, 0], XYgrid[:, 1]
z = solver.model(tf.transpose(tf.stack([tf.ones_like(x) * frame, x, y])))
Zx = tf.reshape(z[:, 0], X.shape)
Zy = tf.reshape(z[:, 1], X.shape)
ax.clear()
plot = ax.quiver(X, Y, Zx, Zy, scale=1.0)
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)
title = ax.set_title("t = %.2f" % frame, ha='center')
return plot, title
anim = FuncAnimation(fig, data_gen, fargs=(plot,), frames=np.linspace(0, 2, 240),
interval=16, blit=False)
anim.save("../out/%s_solution.gif" % solver.bvp.__class__.__name__, fps=30)
plt.show()
_outFolderExists()
_plot_loss()
animate_solution()
def plot_phaseplot(solver, t_start=0, t_end=2, N=500):
"""
(WIP) Plots the solution of a DAE defined in one temporal dimension and two spacial outputs.
Only works for the pendulum example.
Parameters
-----------
solver: Solver
Trained solver to be visualized
"""
def animate_solution():
fig, ax = plt.subplots(figsize=(5, 5))
tspace = tf.linspace([t_start], [t_end], N, axis=0)
xy = solver.model(tspace)
xd, yd = xy[:, 0].numpy(), xy[:, 1].numpy()
pendulum, = plt.plot([], [], 'lightgray')
ln, = plt.plot([], [], 'cornflowerblue')
sc, = plt.plot([], [], 'bo', markersize=10)
title = ax.text(0, 1.15, "", ha='center')
def init():
ax.set_xlim(-1.25, 1.25)
ax.set_ylim(-1.25, 1.25)
return ln, sc, pendulum, title
def update(frame):
trail = 20
start = max(frame - trail, 0)
pendulum.set_data([0, xd[frame]], [0, yd[frame]])
ln.set_data(xd[start:frame+1], yd[start:frame+1])
sc.set_data(xd[frame], yd[frame])
title.set_text(u"t = {:.3f}".format(t_start + (t_end - t_start) * frame / N))
return ln, sc, pendulum, title
anim = FuncAnimation(fig, update, frames=len(tspace),
init_func=init, blit=True, interval=16)
anim.save("../out/%s_solution.gif" % solver.bvp.__class__.__name__, fps=60)
plt.show()
_outFolderExists()
_plot_loss(solver)
animate_solution()
def debug_plot_2D(solver, variables, domain):
"""
Plots the solution of a BVP defined in two spacial dimensions and one output.
Parameters
-----------
solver: Solver
Trained solver to be visualized
variables: list
List of variables to be plotted
domain: list
Domain on which the solution is plotted
"""
N = 1000
xspace = np.linspace(domain[0], domain[1], N + 1)
yspace = np.linspace(domain[2], domain[3], N + 1)
X, Y = np.meshgrid(xspace, yspace)
XYgrid = np.vstack([X.flatten(), Y.flatten()]).T
upred = solver.model(tf.cast(XYgrid, 'float32'))[:, 0]
U = upred.numpy().reshape(N + 1, N + 1)
fig = plt.figure(figsize=(9, 6))
ax = fig.add_subplot(111, projection='3d')
_plot_3d(X, Y, U, ax, variables, 'Solution of equation')
plt.imshow(np.flip(U, 0), cmap='jet', extent=domain)
plt.colorbar()
plt.show()
_plot_loss(solver)
def error_plot_2D(solver, exact_solution, variables, domain, heatmap=True):
"""
Plots the solution of a BVP defined in two spacial dimensions and one output
together with its exact solution and the absolute error.
Parameters
-----------
solver: Solver
Trained solver to be visualized
exact_solution: function
Function representing the exact solution to the given problem
variables: list
List of variables to be plotted
domain: list
Domain on which the solution is plotted
heatmap: bool
If True, the solution is plotted as a heatmap, otherwise as a 3D surface plot
"""
N = 1000
xspace = np.linspace(domain[0], domain[1], N + 1)
yspace = np.linspace(domain[2], domain[3], N + 1)
X, Y = np.meshgrid(xspace, yspace)
XYgrid = np.vstack([X.flatten(), Y.flatten()]).T
upred = solver.model(tf.cast(XYgrid, 'float32'))[:, 0]
U = upred.numpy().reshape(N + 1, N + 1)
fig = plt.figure(figsize=(18, 5))
plt.subplots_adjust(left=0.01, right=0.97)
options, plot_fun = ({'projection': '3d'}, _plot_3d) if not heatmap else ({}, _plot_heatmap)
ax = fig.add_subplot(131, **options)
plot_fun(X, Y, exact_solution(X, Y), ax, variables, 'Exact solution', False)
ax = fig.add_subplot(132, **options)
plot_fun(X, Y, U, ax, variables, 'Predicted solution', False)
ax = fig.add_subplot(133)
_plot_heatmap(X, Y, np.abs(U - exact_solution(X, Y)),
ax, variables, 'Absolute Error', True)
_plot_loss(solver)
Functions
def debug_plot_2D(solver, variables, domain)
-
Plots the solution of a BVP defined in two spacial dimensions and one output.
Parameters
solver
:Solver
- Trained solver to be visualized
variables
:list
- List of variables to be plotted
domain
:list
- Domain on which the solution is plotted
Expand source code
def debug_plot_2D(solver, variables, domain): """ Plots the solution of a BVP defined in two spacial dimensions and one output. Parameters ----------- solver: Solver Trained solver to be visualized variables: list List of variables to be plotted domain: list Domain on which the solution is plotted """ N = 1000 xspace = np.linspace(domain[0], domain[1], N + 1) yspace = np.linspace(domain[2], domain[3], N + 1) X, Y = np.meshgrid(xspace, yspace) XYgrid = np.vstack([X.flatten(), Y.flatten()]).T upred = solver.model(tf.cast(XYgrid, 'float32'))[:, 0] U = upred.numpy().reshape(N + 1, N + 1) fig = plt.figure(figsize=(9, 6)) ax = fig.add_subplot(111, projection='3d') _plot_3d(X, Y, U, ax, variables, 'Solution of equation') plt.imshow(np.flip(U, 0), cmap='jet', extent=domain) plt.colorbar() plt.show() _plot_loss(solver)
def error_plot_2D(solver, exact_solution, variables, domain, heatmap=True)
-
Plots the solution of a BVP defined in two spacial dimensions and one output together with its exact solution and the absolute error.
Parameters
solver
:Solver
- Trained solver to be visualized
exact_solution
:function
- Function representing the exact solution to the given problem
variables
:list
- List of variables to be plotted
domain
:list
- Domain on which the solution is plotted
heatmap
:bool
- If True, the solution is plotted as a heatmap, otherwise as a 3D surface plot
Expand source code
def error_plot_2D(solver, exact_solution, variables, domain, heatmap=True): """ Plots the solution of a BVP defined in two spacial dimensions and one output together with its exact solution and the absolute error. Parameters ----------- solver: Solver Trained solver to be visualized exact_solution: function Function representing the exact solution to the given problem variables: list List of variables to be plotted domain: list Domain on which the solution is plotted heatmap: bool If True, the solution is plotted as a heatmap, otherwise as a 3D surface plot """ N = 1000 xspace = np.linspace(domain[0], domain[1], N + 1) yspace = np.linspace(domain[2], domain[3], N + 1) X, Y = np.meshgrid(xspace, yspace) XYgrid = np.vstack([X.flatten(), Y.flatten()]).T upred = solver.model(tf.cast(XYgrid, 'float32'))[:, 0] U = upred.numpy().reshape(N + 1, N + 1) fig = plt.figure(figsize=(18, 5)) plt.subplots_adjust(left=0.01, right=0.97) options, plot_fun = ({'projection': '3d'}, _plot_3d) if not heatmap else ({}, _plot_heatmap) ax = fig.add_subplot(131, **options) plot_fun(X, Y, exact_solution(X, Y), ax, variables, 'Exact solution', False) ax = fig.add_subplot(132, **options) plot_fun(X, Y, U, ax, variables, 'Predicted solution', False) ax = fig.add_subplot(133) _plot_heatmap(X, Y, np.abs(U - exact_solution(X, Y)), ax, variables, 'Absolute Error', True) _plot_loss(solver)
def plot_1D(solver)
-
Plots the solution of a BVP defined in one spacial dimension and one output.
Parameters
solver
:Solver
- Trained solver to be visualized
Expand source code
def plot_1D(solver): """ Plots the solution of a BVP defined in one spacial dimension and one output. Parameters ----------- solver: Solver Trained solver to be visualized """ def plot_sample_points(): fig = plt.figure(figsize=(9, 6)) for cond in solver.bvp.get_conditions(): t, x = cond.sample_points()[:, 0], cond.sample_points()[:, 1] if cond.name != 'inner': plt.scatter(t, x, c='black', marker='X') else: plt.scatter(t, x, c='r', marker='.', alpha=0.1) plt.xlabel('$t$') plt.ylabel('$x$') plt.title('Positions of collocation points and boundary data') plt.show() def plot_u(): # Set up meshgrid N = 1000 xspace = np.linspace(bounds[0][0], bounds[1][0], N + 1) yspace = np.linspace(bounds[0][1], bounds[1][1], N + 1) X, Y = np.meshgrid(xspace, yspace) XYgrid = np.vstack([X.flatten(), Y.flatten()]).T # Determine predictions of u(t, x) upred = solver.model(tf.cast(XYgrid, 'float32'))[:, 0] minu, maxu = np.min(upred), np.max(upred) # Reshape upred U = upred.numpy().reshape(N + 1, N + 1) # Surface plot of solution u(t,x) fig = plt.figure(figsize=(9, 6)) ax = fig.add_subplot(111, projection='3d') _plot_3d(X, Y, U, ax, ['t', 'x'], 'Solution of equation', False) plt.savefig('../out/3D_%s_solution.pdf' % solver.bvp.__class__.__name__, bbox_inches='tight', dpi=300) plt.show() fig = plt.figure(figsize=(9, 6)) plt.imshow(U, cmap='viridis') ax.set_xlabel('$t$') ax.set_ylabel('$x$') ax.set_title('Solution of equation') plt.savefig('../out/2D_%s_solution.pdf' % solver.bvp.__class__.__name__, bbox_inches='tight', dpi=300) plt.show() return minu, maxu def animate_solution(): fig, ax = plt.subplots() xdata, ydata = tf.linspace(bounds[0][1], bounds[1][1], 1000), [] ln, = plt.plot([], [], color='b') title = ax.text((bounds[0][1] + bounds[1][1]) / 2, maxu - 0.1 * abs(maxu), "", ha='center') def init(): ax.set_xlim(bounds[0][1], bounds[1][1]) ax.set_ylim(minu, maxu) return ln, def update(frame): ydata = solver.model(tf.transpose(tf.stack([tf.ones_like(xdata) * frame, xdata])))[:, 0] ln.set_data(xdata, ydata) title.set_text(u"t = {:.3f}".format(frame)) return ln, title anim = FuncAnimation(fig, update, frames=np.linspace(bounds[0][0], bounds[1][0], 300), interval=16, init_func=init, blit=True) anim.save("../out/2D_%s_solution.gif" % solver.bvp.__class__.__name__, fps=30) plt.show() inner = [cond for cond in solver.bvp.conditions if cond.name == "inner"][0] bounds = inner.get_region_bounds() _outFolderExists() plot_sample_points() _plot_loss(solver) minu, maxu = plot_u() animate_solution()
def plot_2D(solver)
-
Plots the solution of a BVP defined in two spacial dimensions and one output.
Parameters
solver
:Solver
- Trained solver to be visualized
Expand source code
def plot_2D(solver): """ Plots the solution of a BVP defined in two spacial dimensions and one output. Parameters ----------- solver: Solver Trained solver to be visualized """ def animate_solution(): fig = plt.figure() ax = fig.add_subplot(projection='3d') N = 100 xspace = np.linspace(0, 1, N) yspace = np.linspace(0, 1, N) X, Y = np.meshgrid(xspace, yspace) XYgrid = np.vstack([X.flatten(), Y.flatten()]).T XYgrid = tf.cast(XYgrid, 'float32') x, y = XYgrid[:, 0], XYgrid[:, 1] zarray = np.zeros((N, N, 120)) for i in range(120): z = solver.model(tf.transpose(tf.stack([tf.ones_like(x) * i, x, y]))) zarray[:, :, i] = tf.reshape(z, X.shape) def update_plot(frame_number, zarray, plot): plot[0].remove() plot[0] = ax.plot_surface(X, Y, zarray[:,:,frame_number], cmap="magma") fig = plt.figure() ax = fig.add_subplot(111, projection='3d') plot = [ax.plot_surface(X, Y, zarray[:, :, 0], color='0.75', rstride=1, cstride=1)] ax.set_xlim(0, 1) ax.set_ylim(0, 1) ax.set_zlim(-0.1, 1) anim = FuncAnimation(fig, update_plot, 120, fargs=(zarray, plot), interval=16) anim.save("../out/%s_solution.gif" % solver.bvp.__class__.__name__, fps=30) plt.show() _outFolderExists() _plot_loss(solver) animate_solution()
def plot_2Dvectorfield(solver)
-
Plots the solution of a BVP defined in two spacial dimensions and two outputs.
Parameters
solver
:Solver
- Trained solver to be visualized
Expand source code
def plot_2Dvectorfield(solver): """ Plots the solution of a BVP defined in two spacial dimensions and two outputs. Parameters ----------- solver: Solver Trained solver to be visualized """ def animate_solution(): fig = plt.figure() ax = fig.add_subplot() N = 30 xspace = np.linspace(-2, 2, N) yspace = np.linspace(-2, 2, N) X, Y = np.meshgrid(xspace, yspace) XYgrid = np.vstack([X.flatten(), Y.flatten()]).T XYgrid = tf.cast(XYgrid, 'float32') x, y = XYgrid[:, 0], XYgrid[:, 1] z = solver.model(tf.transpose(tf.stack([tf.zeros_like(x), x, y]))) Zx = tf.reshape(z[:, 0], X.shape) Zy = tf.reshape(z[:, 1], X.shape) plot = ax.quiver(X, Y, Zx, Zy, scale=1.0) def data_gen(frame): x, y = XYgrid[:, 0], XYgrid[:, 1] z = solver.model(tf.transpose(tf.stack([tf.ones_like(x) * frame, x, y]))) Zx = tf.reshape(z[:, 0], X.shape) Zy = tf.reshape(z[:, 1], X.shape) ax.clear() plot = ax.quiver(X, Y, Zx, Zy, scale=1.0) ax.set_xlim(-2, 2) ax.set_ylim(-2, 2) title = ax.set_title("t = %.2f" % frame, ha='center') return plot, title anim = FuncAnimation(fig, data_gen, fargs=(plot,), frames=np.linspace(0, 2, 240), interval=16, blit=False) anim.save("../out/%s_solution.gif" % solver.bvp.__class__.__name__, fps=30) plt.show() _outFolderExists() _plot_loss() animate_solution()
def plot_phaseplot(solver, t_start=0, t_end=2, N=500)
-
(WIP) Plots the solution of a DAE defined in one temporal dimension and two spacial outputs. Only works for the pendulum example.
Parameters
solver
:Solver
- Trained solver to be visualized
Expand source code
def plot_phaseplot(solver, t_start=0, t_end=2, N=500): """ (WIP) Plots the solution of a DAE defined in one temporal dimension and two spacial outputs. Only works for the pendulum example. Parameters ----------- solver: Solver Trained solver to be visualized """ def animate_solution(): fig, ax = plt.subplots(figsize=(5, 5)) tspace = tf.linspace([t_start], [t_end], N, axis=0) xy = solver.model(tspace) xd, yd = xy[:, 0].numpy(), xy[:, 1].numpy() pendulum, = plt.plot([], [], 'lightgray') ln, = plt.plot([], [], 'cornflowerblue') sc, = plt.plot([], [], 'bo', markersize=10) title = ax.text(0, 1.15, "", ha='center') def init(): ax.set_xlim(-1.25, 1.25) ax.set_ylim(-1.25, 1.25) return ln, sc, pendulum, title def update(frame): trail = 20 start = max(frame - trail, 0) pendulum.set_data([0, xd[frame]], [0, yd[frame]]) ln.set_data(xd[start:frame+1], yd[start:frame+1]) sc.set_data(xd[frame], yd[frame]) title.set_text(u"t = {:.3f}".format(t_start + (t_end - t_start) * frame / N)) return ln, sc, pendulum, title anim = FuncAnimation(fig, update, frames=len(tspace), init_func=init, blit=True, interval=16) anim.save("../out/%s_solution.gif" % solver.bvp.__class__.__name__, fps=60) plt.show() _outFolderExists() _plot_loss(solver) animate_solution()