gearbox.fem.post#

Post-processing of the FEM analyses: line of action, contact patches, sweeps and plots.

The plots draw on a matplotlib Axes that the caller creates, so they can be combined freely; matplotlib comes with pip install python-gearbox[fem] and is imported only by the functions that draw. Coordinates follow mesh_pair(): the pinion is centred at the origin, the wheel at (0, a_w) above it, and the pinion turns counter-clockwise, so the contact runs up the line of action from A (start of contact, at the wheel tip) to E (end of contact, at the pinion tip). Positions on the line are measured from the pitch point C, positive towards E.

class ContactPatch[source]#

Bases: object

The contact of one pinion tooth.

tooth#

Name of the pinion flank group ("PINION_TOOTH2_FLANK_CCW").

Type:

str

point#

Centre of the patch, the coordinates of its nodes weighted by their pressure [mm].

Type:

tuple[float, float]

position#

Its position along the line of action [mm].

Type:

float

offset#

Its distance from the line of action [mm].

Type:

float

pressure#

Largest contact pressure of the patch [MPa].

Type:

float

on_path#

Whether the patch lies on the path of contact A-E. False for the sharp tip edge of a tooth that the deflection brings into contact just before A or after E; the pressure there is singular and depends on the mesh.

Type:

bool

__init__(tooth, point, position, offset, pressure, on_path)#
class LineOfAction[source]#

Bases: object

Line of action of an external spur (or, in the transverse section, helical) pair.

pressure_angle#

Transverse working pressure angle alpha_wt [rad].

Type:

float

base_radii#

(r_b1, r_b2) [mm].

Type:

tuple[float, float]

pitch_radii#

Working pitch radii (r_w1, r_w2) [mm].

Type:

tuple[float, float]

approach#

Length A C of the path of contact [mm].

Type:

float

recess#

Length C E [mm].

Type:

float

base_pitch#

Transverse base pitch p_bt [mm].

Type:

float

reduced_modulus#

1 / ((1 - nu1^2)/E1 + (1 - nu2^2)/E2) [MPa], the modulus of the Hertzian contact of two cylinders in plane strain.

Type:

float

pinion_half_angle#

Half the angular tooth thickness of the pinion at its working pitch circle [rad].

Type:

float

classmethod of(transmission)[source]#

Build the line of action of a transmission.

Raises:

ValueError – For an internal gear.

Return type:

LineOfAction

property direction: ndarray#

Unit vector along the line, from A to E.

property normal: ndarray#

Unit vector normal to the line, towards the pinion tooth ahead of the contact.

property pitch_curvature: tuple[float, float]#

Radii of curvature of the flanks at the pitch point, r_b tan(alpha_wt) [mm].

points()[source]#

Positions of T1, A, B, C, D, E, T2 on the line [mm].

Return type:

dict[str, float]

point(position)[source]#

Coordinates (x, y) of a position on the line [mm].

Return type:

ndarray

coordinates(point)[source]#

Position of point along the line and its distance from it (along normal).

Return type:

tuple[float, float]

double_contact_zones()[source]#

The stretches A-B and D-E where two pairs of teeth are in contact.

Return type:

list[tuple[float, float]]

is_single_contact(position)[source]#

Whether only one pair of teeth is in contact at position.

Return type:

bool

hertz_pressure(position, load)[source]#

Hertzian pressure of two cylinders with the radii of curvature of the flanks.

Parameters:
  • position (float | ndarray) – Position, or array of positions, on the line of action [mm].

  • load (float) – Normal load per unit face width carried by the pair [N/mm].

Returns:

The maximum contact pressure sqrt(w E* / (pi rho)) [MPa].

Return type:

float | ndarray

mesh_position(position)[source]#

Mesh position that puts the contact at position on the line of action.

Returns:

The pinion_rotation of mesh_pair() [deg], for the pinion tooth that is on the line of centres in the symmetric position.

Return type:

float

__init__(pressure_angle, base_radii, pitch_radii, approach, recess, base_pitch, reduced_modulus, pinion_half_angle)#
class SweepPoint[source]#

Bases: object

One mesh position of contact_sweep().

position#

Position on the line of action of the followed pinion tooth [mm].

Type:

float

root_stress_pinion#

Largest root stress of the pinion [MPa].

Type:

float

root_stress_wheel#

Largest root stress of the wheel [MPa].

Type:

float

patches#

Contact of each pinion tooth, see ContactPatch.

Type:

list[ContactPatch]

followed#

The patch of the followed tooth (the one closest to position).

Type:

ContactPatch

requested_torque#

Pinion torque [N*mm] (per unit width).

Type:

float

bore_rotation#

Rotation of the pinion bore that gave it [rad].

Type:

float

nodes#

Node coordinates in the displaced position, (n, 2).

Type:

ndarray

triangles#

Triangles of the mesh as node indices, (m, 3).

Type:

ndarray

principal#

First principal stress per node [MPa].

Type:

ndarray

von_mises#

Von Mises stress per node [MPa].

Type:

ndarray

stress(kind='principal')[source]#

Nodal "principal" or "von_mises" stress, for plot_field().

Return type:

tuple[Any, ndarray]

__init__(position, root_stress_pinion, root_stress_wheel, patches, followed, requested_torque, bore_rotation, nodes, triangles, principal, von_mises)#
contact_patches(result, line, tolerance=0.05)[source]#

Split the contact pressure of a solve_contact() result by pinion tooth.

The pressures are scaled to the requested torque like max_contact_pressure, and the points are in the displaced position, where the flanks actually touch on the line of action.

Parameters:
  • result (ContactResult) – A 2D contact result.

  • line (LineOfAction) – The line of action of the same pair.

  • tolerance (float) – Distance from the line and from A/E within which a patch counts as on the path of contact [mm].

Returns:

One ContactPatch per pinion tooth in contact, sorted by position.

Return type:

list[ContactPatch]

contact_sweep(transmission, output_dir, positions, tangential_force=None, cache=True, progress=None, **solve_options)[source]#

Solve the 2D contact of a pair at several positions along the line of action.

Each position is solved with solve_contact() at the mesh position LineOfAction.mesh_position(), starting from the bore rotation of the previous one. Only the summary and the nodal stresses are kept: with cache they are stored in output_dir and reused when the same transmission, force and options are asked again; the solver files are removed.

Parameters:
  • transmission (Transmission) – The gear pair (external gears).

  • output_dir (str | Path) – Folder for the cache and the temporary solver files.

  • positions (Iterable[float]) – Positions of the followed tooth on the line of action [mm].

  • tangential_force (float | None) – Nominal Ft [N], the transmission’s by default.

  • cache (bool) – Reuse and store solved positions.

  • progress (Any) – Optional callable progress(index, count, point) called after each position.

  • **solve_options (Any) – Passed to solve_contact() (settings, teeth, contact_stiffness, ccx, …); dimension is always 2D.

Returns:

One SweepPoint per position.

Return type:

list[SweepPoint]

nodal_field(mesh, values, positions=None)[source]#

Triangulate the quadrilaterals of a 2D mesh and attach nodal values.

Parameters:
  • mesh (MeshData) – A 2D mesh (gearbox.fem._mesh_io.read_mesh()).

  • values (Mapping[int, float]) – Value per node tag; missing nodes get nan.

  • positions (Mapping[int, Sequence[float]] | None) – Node coordinates to draw at, e.g. the displaced ones; the mesh nodes if omitted.

Returns:

A matplotlib.tri.Triangulation and the values in its node order.

Raises:

ValueError – For a 3D mesh.

Return type:

tuple[Any, ndarray]

plot_field(ax, field_data, vmax=None, levels=64, cmap='turbo', edges=True, edge_width=0.1)[source]#

Draw a nodal field as filled contours; returns the contour set (for colorbar).

Parameters:
  • ax (Any) – Matplotlib axes.

  • field_data (tuple[Any, ndarray]) – (triangulation, values) from nodal_field() or stress_field().

  • vmax (float | None) – Upper end of the colour scale; the largest value by default. Values outside [0, vmax] are clipped.

  • levels (int) – Number of colour levels.

  • cmap (str) – Colour map.

  • edges (bool) – Draw the element edges faintly.

  • edge_width (float) – Line width of the element edges.

Return type:

Any

plot_line_of_action(ax, line, contact=None, labels=True, others=(), label_size=14, label_offset=1.0)[source]#

Overlay the classic scheme of the mesh on a plot of the pair.

Base circles (dashed), working pitch circles (dotted), the line of centres, the radii to the tangent points T1 and T2, the line of action and, in magenta, the path of contact A-E with the single contact points B and D.

Parameters:
  • ax (Any) – Matplotlib axes with the pair in the coordinates of mesh_pair().

  • line (LineOfAction) – The line of action of the pair.

  • contact (Sequence[float] | None) – A contact point to mark, e.g. the followed one.

  • labels (bool) – Write the names of the points that fall inside the current view, so set the axes limits first. The scheme never changes the view.

  • others (Iterable[Sequence[float]]) – Further contact points, marked with hollow circles.

  • label_size (float) – Font size of the names.

  • label_offset (float) – Distance of the names from the line [mm].

plot_mesh(ax, mesh, linewidth=0.25, **style)[source]#

Draw the elements of a 2D mesh.

Parameters:
  • ax (Any) – Matplotlib axes.

  • mesh (MeshData) – A 2D mesh (gearbox.fem._mesh_io.read_mesh()).

  • linewidth (float) – Line width of the element edges.

  • **style (Any) – Further PolyCollection options (facecolor, edgecolor, …).

Returns:

The PolyCollection added to the axes.

Return type:

Any

stress_field(result, kind='principal', mesh=None)[source]#

First principal ("principal") or von Mises ("von_mises") stress of a 2D result.

Contact results are scaled from the torque reached to the requested torque, as their summaries are, and drawn in the displaced position, where the contact lies on the line of action; bending results in the undisplaced one.

Parameters:
  • result (Any) – A BendingResult or ContactResult.

  • kind (str) – "principal" or "von_mises".

  • mesh (MeshData | None) – The mesh of the result, read from its files if omitted.

Returns:

See nodal_field().

Return type:

tuple[Any, ndarray]