matto.postprocess#

Postprocessors: objects the OptimizationDriver calls while it runs.

A problem lists them under problem["postprocessors"]. The driver calls

on_start(driver) before the first iteration on_iteration(driver, iteration, info) after every iteration on_failure(driver, iteration, error) when the state solve fails on_finish(driver, result) after the final report

on every rank. info holds the objective, the constraint values, the maximum displacements, the design change and the iteration time. A postprocessor that raises is reported once and not called again; the optimization continues.

A postprocessor that gathers fields must do all its gathers before any work that only rank 0 does. An error on rank 0 then cannot leave the other ranks waiting inside a collective call.

Provided here: HistoryWriter (a CSV row per iteration), DesignSnapshots (the design fields and the displacement as arrays, every few iterations and at a failure) and SnapshotPlotter (the same, with a picture drawn by matplotlib). To draw something else, subclass SnapshotPlotter and override draw().

class matto.postprocess.PostProcessor(every=1)[source]#

Bases: object

Base class; override the hooks that are needed.

due(iteration)[source]#

True at iteration 1 and at every multiple of every.

on_start(driver)[source]#
on_iteration(driver, iteration, info)[source]#
on_failure(driver, iteration, error)[source]#
on_finish(driver, result)[source]#
class matto.postprocess.HistoryWriter(filename='history.csv')[source]#

Bases: PostProcessor

One CSV row per iteration: objective, constraints, change, time.

on_start(driver)[source]#
on_iteration(driver, iteration, info)[source]#
class matto.postprocess.DesignSnapshots(every=10, displacement=True, directory='snapshots')[source]#

Bases: PostProcessor

Saves the design every every iterations and when the state solve fails.

Each snapshot is <output_dir>/<directory>/iter_NNNN.npz with the raw and physical values of every design variable, in the dof order of the plotting mesh, and the displacement when displacement is true. The dof coordinates are saved once as coordinates.npz. A snapshot taken at a failure is named failure_iter_NNNN.npz and has no displacement.

on_start(driver)[source]#
gather(driver, with_displacement)[source]#

All arrays of one snapshot on rank 0, None elsewhere. Collective.

on_iteration(driver, iteration, info)[source]#
on_failure(driver, iteration, error)[source]#
save(driver, tag, iteration, objective, arrays)[source]#

Write one snapshot. Rank 0 only.

matto.postprocess.boundary_faces(cells, cell_type)[source]#

The faces that belong to exactly one of the given cells.

cells is an (n, vertices per cell) array of vertex indices. Returns the faces as an (m, vertices per face) array and, for each face, the row of the cell it belongs to.

matto.postprocess.default_views(extent)[source]#

Camera angles for a 3D body with the given extents along x, y, z.

One view from above. A plate-like body, smallest extent under a quarter of the largest, gets a second view from below, since a design under a solid top layer shows only from there.

class matto.postprocess.SnapshotPlotter(every=10, fields=None, direction=None, weight=None, threshold=None, color=None, views=None, arrow_cutoff=0.1, displacement=True, directory='snapshots')[source]#

Bases: DesignSnapshots

DesignSnapshots with a picture beside each array file.

2D: one panel per field, coloured cell by cell. 3D: the cells where the threshold field exceeds its level, drawn as a body coloured by color, one panel per camera view.

fields

Names of the design variables to draw; default all.

direction

Name of an angle field. In 2D its direction (cos, sin) is drawn as arrows where weight exceeds arrow_cutoff times its maximum. Arrows inside a 3D body would not be visible and are not drawn.

weight

Name of the field that decides where arrows are drawn.

threshold

(field name, level) selecting the 3D body; default (“rho”, 0.5) when the problem has a field rho.

color

Field that colours the 3D body; default weight, else the threshold field.

views

List of {“elev”: degrees, “azim”: degrees}; default from default_views().

Needs matplotlib, imported here and not by the package. Pictures are for following a run: matplotlib sorts 3D faces by depth only approximately, and a mesh of more than about 200 000 cells makes each picture slow.

on_start(driver)[source]#
save(driver, tag, iteration, objective, arrays)[source]#

Write one snapshot. Rank 0 only.

draw(figure, data)[source]#

Draw one snapshot.

Override for a different picture; draw_field() and draw_body() draw one panel each into an axis of your own.

data: points (n, 3), cells (m, vertices per cell), cell_type, dim, iteration, objective, fields {name: value per cell}, bounds {name: (lower, upper)}, u (n, dim) or None with the coordinates of its rows in u_points.

body_color()[source]#

Name of the field that colours the 3D body.

draw_field(axis, data, name)[source]#

One 2D field, coloured cell by cell, into a 2D axis. Returns the image.

draw_body(axis, data, camera)[source]#

The 3D body seen from one camera, into a 3D axis.

camera is {“elev”: degrees, “azim”: degrees}. Returns the mappable of the body’s colours, for a colorbar.