28 worksheets, each rendered by the engine itself. Every page is self-contained: the charts are SVG the engine drew, the figures are embedded, and nothing here runs a script or fetches anything.
Demonstrates unit tracking across a mixed-unit calculation. Maximum moment and shear Required section modulus, A992 steel
examples/beam.nomo
A bearing's rated life is not how long it lasts. It is the life that nine bearings in ten exceed — the tenth fails earlier, by design, and the spread is wide. A calculated 20 000 hours means half of them are still running at about 100 000 and one in ten has failed before 20 000.
examples/bearing.nomo
A frequency response is read on a logarithmic frequency axis, because what matters about it happens per decade rather than per hertz. Drawn linearly, the first decade of a four-decade sweep is the leftmost thousandth of the chart and everything below the corner is a vertical line at the origin.
examples/bode.nomo
A bolted joint is not a bolt carrying a load. It is a spring in tension clamping springs in compression, and almost all of the external load is taken by the members relaxing rather than by the bolt stretching further. That is why a joint is designed around its **preload** and only then checked against the load it carries — and why a torque figure without a preload behind it says nothing.
examples/bolt.nomo
A worksheet is not finished when it has computed a number. It is finished when it says whether the number is acceptable, and against what. That last step is usually the point of the document: a section is adequate, a bolt is not, a temperature rise is within what the datasheet allows.
examples/checks.nomo
A short column crushes and a long one buckles, and the two have entirely different formulas. Which applies is not a judgement call — it is decided by the slenderness ratio against a transition value that follows from the material, and getting it wrong overestimates a long column's capacity by a factor that grows without limit.
examples/column.nomo
The imaginary unit is `i`, an ordinary constant. Juxtaposition is already multiplication, so `4i` is `4*i` and needs no special number syntax — the same reading that makes `2e` mean `2*e`. Arithmetic. Any operation with a complex operand on either side answers complex, promoting the real one. `i` squared is where the whole thing comes from. Taking a value apart. `Re` and `Im` give real numbers; `Im` is the coefficient of `i`, so `Re(z) + Im(z)*i` rebuilds `z`. Whole powers only, by repeated multiplication. A fractional power of a complex number needs a branch cut, which this language does not choose. A complex value stays complex. Nothing demotes when the imaginary part happens to be zero, so a result's type never depends on its value. Units. Both parts share one dimension, because they are components of one measurement rather than two measurements. The argument is an angle, so it is dimensionless whatever Z is measured in. The impedance of a series RLC branch at one frequency, which is what the corpus uses complex arithmetic for. ## A branch of impedances, as one value
examples/complex.nomo
Comparisons, logic, and the conditional expression. A comparison answers 1 or 0. There is no separate boolean type: SMath worksheets compute with comparisons as numbers, and this language has to be able to receive them. Both sides are held in base SI, so a comparison converts before it compares. Neither of these needs a conversion written into it. `and`, `or` and `not` are words. `!` is factorial to anyone who has met SMath and `&` is bitwise to anyone who has met C, so neither is borrowed here. The conditional is an expression, so it composes with arithmetic and needs no statement form of its own. Only the arm that is taken is evaluated, which is what lets a conditional guard something that would otherwise fail. `bay[0]` would be out of bounds. Chained without brackets: the `else` arm reaches as far as it can, so `else if` is just another conditional inside it. A function body can be piecewise. Substitution shows which way the worksheet went. The arm that did not run is shown as it was written, because it has no values to show. A verdict in words. A string is a value like any other — it binds to a name, an `if` chooses between two, and `==` compares them — and it has no arithmetic at all, which is the whole of what a worksheet does with one.
examples/conditions.nomo
The worked example from the design note.
examples/cylinder.nomo
A worksheet carries its figures inside itself: the body refers to one by name, and the data sits in the trailer at the end of the file. That keeps the mathematics readable and the file a single self-contained document. Nominal bore and working pressure of the gauge shown below. The reference may say how large the figure is drawn: the gauge below is 72 px of pixels placed at 216. That is the size it asks for and not a promise, so a page narrower than the figure shrinks it whole rather than showing part of it. image gauge 216x216 Force on the diaphragm. A reference with no data behind it is reported rather than passed over. image missing_figure --- resources --- Images the worksheet carries, base64, one block each. A block is `' image
examples/figures.nomo
Every transcendental the language offers, in one place.
examples/functions.nomo
examples/globals.nomo
A safety interlock is a loop of wire threaded through every connector that has to be mated before a high-voltage bus may energise. Unplug one and the loop opens. The monitor has to tell four conditions apart — loop closed, loop open, loop shorted to ground, loop shorted to the supply — and one measurement cannot do it: a difference amplifier across the loop reads nearly zero for closed, for a short to ground and for a short to the supply alike, because in all three the two ends sit at the same potential.
examples/interlock.nomo
A worked design for a half-bridge LLC stage, carried out the way the textbooks do it: replace the square wave by its first harmonic, replace the rectifier and its load by the equivalent resistance they present at that frequency, and what is left is a linear network that can be written down. Steigerwald's 1988 comparison of resonant topologies is where the method comes from, and every converter application note since repeats it.
examples/llc.nomo
Element-wise against matrix arithmetic, indexing, and the aggregates. Between two vectors of equal length, `*` is element-wise: what a tabulated calculation wants, column against column. An inner product is asked for by name, so it is never confused with the above. Scalars broadcast. Aggregates. Indexing is one-based. A vector is the column of n that `rows` and `cols` say it is, so it takes the column index as well: these are the same element. Any other column is out of bounds, which is what a column of one means. Vectors carry units element by element, so a tabulated calculation keeps them. A matrix is a vector of rows, and is indexed row first. Between two matrices `*` is the matrix product, not element-wise. `identity(n)` writes the n×n one, which is dimensionless so that `S - λ*identity(2)` — the characteristic equation of a stress tensor — takes its dimension from λ. `diag` writes a matrix with a vector down its diagonal — a mass matrix, here. The zeros carry the diagonal's dimension so the result is usable in arithmetic. Linear algebra. The check that inv is really an inverse. The cross product is three-dimensional, and units come out of the products it is made of: metres crossed with newtons give newton-metres. `-> N*m` asks for the moment to be shown that way rather than in joules, which share the dimension but not the meaning. Parallel vectors cross to zero, which is the check worth writing down. Shape and slicing. A vector answers as the column it is. Joining: side by side, and one above the other.
examples/matrix.nomo
NaN, the infinities, and signed zero.
examples/nonfinite.nomo
Two things a worksheet reaches for that have no closed form: where a function crosses zero, and the area under it. Both take the **name** of a function, the way `map` and `iterate` do, and both do a fixed amount of work rather than testing a tolerance — so both give the same bits on every machine. A root, by bisection. It needs a bracket and says so if it does not have one. Dimensions travel through: a root of a length equation is a length. `root` needs a bracket. `roots` needs only a window: it samples a fixed 200 intervals across it and bisects every sign change it finds. That is the question a worksheet usually has — where does this cross zero between here and here — when the answer may be one place, two, or none. A wider window holds both zeros of the same parabola, and they come back in increasing order. The slope of a function at a point, exactly: no step size, because every value carries how fast it is changing and every operation carries the chain rule. The second derivative is where a curve turns, and it divides the dimension twice: a distance by a time twice over is an acceleration. Which is what makes a peak findable: it is where the slope crosses zero, so the two numerical methods compose. A definite integral, by Simpson's rule over a fixed number of panels. Exact up to a cubic, which covers the load shapes a beam calculation actually uses. The resultant of a triangular distributed load, which is where this earns its place: the dimension falls out of f(x)·dx with no rule about integration. Its line of action, from the first moment of the same load. A system of equations linear in its unknowns, which is what statics is: the reactions of a body under load. `f` is a residual — what is left over when the unknowns are substituted — and the second argument names them by dimension. The Euclidean norm, and the unit vector that comes of dividing by it.
examples/numerics.nomo
A design office does not want the elastic modulus of steel typed into forty worksheets, each free to be wrong on its own. `use` brings in a **pack**: a curated set of definitions that lives in one place and arrives by name. The definitions a pack brings are not shown — a worksheet that shows its work should show the work its author did, not fourteen constants nobody typed. `nomo packs` lists what each one holds. ## A bracket in A992, checked against its grade ## The self-weight of the same section
examples/packs.nomo
`plot(f, a, b)` samples a function across a span and draws it. Like `map`, `iterate`, `root` and `integral`, it takes the **name** of a function — there are no lambdas, and a call's callee is always a name. A fixed number of samples, whatever the span. That is `integral`'s rule — a fixed amount of work rather than a tolerance test — and it is what makes a drawing terminate and come out the same on every machine. The span carries units, and so does what the function returns. Both axes are labelled from the dimensions rather than from anything the author writes twice. A curve that leaves the plane is drawn with a gap rather than a line through values the function never took. The summary line counts them. The gain of an LLC resonant tank against switching frequency — the curve `examples/llc.nomo` designs against, and the reason a worksheet language needs plots at all. Its peak is the thing an engineer is looking for. A plot is a value, so it can be bound to a name. It is not a number, though: there is no arithmetic on one. A flat function still has a chart: the axis is given an extent rather than dividing by one of zero width. Several curves on one plot: every argument but the last two names one. They share the span and the vertical axis, so a gain drawn beside a length is refused rather than given two meanings on one axis. A family of curves is written by naming each member. That is what a language with no lambdas has instead of one, and it is what an engineer wants anyway: the load the tank is designed at has a name on the page. A table of measured points is the other kind of plot: an n-by-2 matrix, x in the first column and y in the second. No span is written and none is needed — the points brought their own x — so the horizontal axis is fitted to the data the way the vertical one always was. The shape `augment` builds, which is how a worksheet plots something it just computed: two columns joined into a table of points. Several tables on one plot, and each carries the name it was written under.
examples/plots.nomo
A comment is Markdown. This worksheet is what pins that: every construct below is in the golden snapshot beside it, so a change to how prose renders shows up here in the diff. ## Paragraphs Consecutive comment lines are one paragraph. Prose wraps at whatever width the file is written to, and comes out as a paragraph rather than as a stack of one-line ones.
examples/prose.nomo
Loops, in the shape a worksheet can have them. A worksheet is a set of definitions with dependencies, not a script. SMath's loops mutate variables inside a statement block, which fights that directly — so what this language provides instead is the three things those loops are actually doing in the corpus, none of which mutates anything. A range is a vector. This is the loop counter, and on its own it already replaces the commonest `for` in the corpus. The end is included when the step lands on it, because `range(1, 5)` has to index a five-element vector. Ranges carry a dimension, so tabulating a physical quantity needs no trick. `map` applies a function to every element. `for(k, range(1, n), y[k] <- f(x[k]))` is what the corpus writes; this is what it means. Accumulating a total is `map` and then `sum`, not a running variable. `iterate` applies a function a fixed number of times, which is what a convergence loop is. Newton-Raphson for the square root of two: A fixed count rather than a tolerance test, deliberately: it terminates, it takes the same number of steps on every machine, and it cannot spin.
examples/repetition.nomo
A transmission shaft is almost never in pure torsion. It carries the torque it was put there for, and it carries bending from the gear or pulley loads that deliver that torque — and the two combine into a stress state neither one predicts on its own.
examples/shaft.nomo
Adapted from the SMath corpus (ling.sm) to exercise units and vectors.
examples/shaker.nomo
A spring is three constraints at once: it has to give the right force at the right deflection, it has to survive the shear stress that produces, and it has to fit — solid length, free length and buckling all decide whether the rate that came out of the first constraint can be built.
examples/spring.nomo
Engineering data arrives as a table: a property against a temperature, a section against a depth, a measured curve against a load. `linterp` reads a value out of one, interpolating linearly between the rows either side.
examples/tables.nomo
°C and °F are offset scales, so not every operation on them is meaningful.
examples/temperature.nomo
A part comes out of a furnace and cools in still air. If it is small enough and conductive enough that its inside and its surface stay at the same temperature, the whole thing is one lumped heat capacity losing heat to the room, and its temperature obeys a first-order differential equation with a known solution. That makes it the right problem to check a numerical integrator against: the answer is already known, so the question is whether the method reproduces it. ## The part, and whether the method applies The lumped assumption holds when conduction inside the part is fast compared with convection off its surface — the Biot number, on the characteristic length that is volume over area. Below about a tenth, the inside and the surface differ by less than the other approximations here. ## The equation
examples/transient.nomo
The thin-wall hoop stress is one of the most useful approximations in engineering and one of the most quietly misused. It is exact in the limit of a membrane and good to a few per cent while the wall is thin; it understates the stress at the bore of a thick one, and the error grows with the wall.
examples/vessel.nomo