Source code for topopt.guis

"""Graphics user interfaces for topology optimization."""
from __future__ import division

from matplotlib import colors
import matplotlib.cm as colormaps
import matplotlib.pyplot as plt
import numpy

from topopt.utils import id_to_xy


[docs]class GUI(object): """ Graphics user interface of the topology optimization. Draws the outputs a topology optimization problem. """
[docs] def __init__(self, problem, title=""): """ Create a plot and draw the initial design. Args: problem (topopt.Problem): problem to visualize title (str): title of the plot """ self.problem = problem self.title = title plt.ion() # Ensure that redrawing is possible self.init_subplots() plt.xlabel(title) # self.fig.tight_layout() self.plot_force_arrows() self.fig.show()
def __str__(self): """Create a string representation of the solver.""" return self.__class__.__name__ def __format__(self, format_spec): """Create a formated representation of the solver.""" return str(self) def __repr__(self): """Create a representation of the solver.""" return '{}(problem={!r}, title="{}")'.format( self.__class__.__name__, self.problem, self.title)
[docs] def init_subplots(self): """Create the subplots.""" self.fig, self.ax = plt.subplots() self.im = self.ax.imshow( -numpy.zeros((self.problem.nely, self.problem.nelx)), cmap='gray', interpolation='none', norm=colors.Normalize(vmin=-1, vmax=0))
[docs] def plot_force_arrows(self): """Add arrows to the plot for each force.""" arrowprops = {"arrowstyle": "->", "connectionstyle": "arc3", "lw": "2", "color": 0} nelx, nely, f = (self.problem.nelx, self.problem.nely, self.problem.f) cmap = plt.cm.get_cmap("hsv", f.shape[1] + 1) for load_i in range(f.shape[1]): nz = numpy.nonzero(f[:, load_i]) arrowprops["color"] = cmap(load_i) for i in range(nz[0].shape[0]): x, y = id_to_xy(nz[0][i] // 2, nelx, nely) x = max(min(x, nelx - 1), 0) y = max(min(y, nely - 1), 0) z = int(nz[0][i] % 2) mag = -50 * f[nz[0][i], load_i] self.ax.annotate( "", xy=(x, y), xycoords="data", xytext=(0 if z else mag, mag if z else 0), textcoords="offset points", arrowprops=arrowprops)
[docs] def update(self, xPhys, title=None): """Plot the results.""" self.im.set_array( -xPhys.reshape((self.problem.nelx, self.problem.nely)).T) self.fig.canvas.draw() self.fig.canvas.flush_events() if title is not None: plt.title(title) plt.pause(0.01)
[docs]class StressGUI(GUI): """ Graphics user interface of the topology optimization. Draws the output, stress, and derivative of stress of the topology optimization problem. """
[docs] def __init__(self, problem, title=""): """Create a plot and draw the initial design.""" self.mcmap = colormaps.viridis self.myColorMap2 = colormaps.ScalarMappable( norm=colors.Normalize(vmin=-1, vmax=1), cmap=self.mcmap) GUI.__init__(self, problem) plt.suptitle(title) title_sty = {"boxstyle": "square,pad=0.0", "fc": "white", "ec": "none"} self.ax.set_title("Von Mises Stress", bbox=title_sty) self.ax2.set_title("Derivative of Stress", bbox=title_sty)
[docs] def init_subplots(self): """Create the subplots (one for the stress and one for diff stress).""" self.myColorMap = colormaps.ScalarMappable( norm=colors.Normalize(vmin=0, vmax=1), cmap=colormaps.plasma) self.fig, (self.ax, self.ax2) = plt.subplots(figsize=(8, 4), ncols=2) # Generate image for the plots self.stress_im = self.ax.imshow( numpy.zeros((self.problem.nely, self.problem.nelx, 4)), norm=colors.Normalize(vmin=0, vmax=1), cmap='plasma') self.stress_d_im = self.ax2.imshow( numpy.zeros((self.problem.nely, self.problem.nelx, 4)), norm=colors.Normalize(vmin=-1, vmax=1), cmap=self.mcmap) self.cbar = self.fig.colorbar(self.stress_im, ax=self.ax) self.cbar2 = self.fig.colorbar(self.stress_d_im, ax=self.ax2)
[docs] def update(self, xPhys, title=None): """Plot the results.""" nelx, nely = self.problem.nelx, self.problem.nely def values_to_rgba(values, alpha_values, cmap): values_rgba = cmap.to_rgba(values) values_rgba[:, 3] = alpha_values # Set alpha by x return values_rgba # Updated von Mises subplot stress = self.problem.stress self.myColorMap.set_norm(colors.Normalize(vmin=0, vmax=max(stress))) stress_rgba = values_to_rgba(stress, xPhys, self.myColorMap) self.stress_im.set_array( numpy.swapaxes(stress_rgba.reshape(nelx, nely, 4), 0, 1)) self.ax.set_xlabel(r"$\sigma_v \in$ [{:.2f}, {:.2f}]".format( min(stress), max(stress))) # self.cbar.set_clim(vmin=0, vmax=max(stress)) # cbar_ticks = numpy.linspace(0., max(stress), num=11, endpoint=True) # self.cbar.set_ticks(cbar_ticks) # Updated derivative of von Mises subplot dstress = self.problem.dstress max_val = max(abs(dstress)) self.myColorMap2.set_norm( colors.Normalize(vmin=-max_val, vmax=max_val)) values_rgba = values_to_rgba(dstress, xPhys, self.myColorMap2) self.stress_d_im.set_array( numpy.swapaxes(values_rgba.reshape(nelx, nely, 4), 0, 1)) self.ax2.set_xlabel( r"$\partial_{{x_e}} \|\sigma_v\|^2 \in $[{:.2f}, {:.2f}]".format( min(dstress), max(dstress))) # self.cbar2.set_clim(vmin=-max_val, vmax=max_val) # cbar_ticks = numpy.linspace(-max_val, max_val, num=11, endpoint=True) # self.cbar2.set_ticks(cbar_ticks) if title is not None: plt.suptitle(title) self.fig.canvas.draw() self.fig.canvas.flush_events() plt.pause(0.01)