Integraph

One sign convention, across every tool

Sign errors do not crash anything. They produce a plausible number with the wrong sense, and they survive review. So we fixed the convention once, platform-wide.

Ask three structural engineers which way is positive and you will get three answers, all defensible. Compression positive, because concrete. Tension positive, because that is how the steel texts write it. Sagging positive, unless the analysis package you grew up on said otherwise.

Inside one person’s head this is fine. Inside a platform with several tools, a report generator, an API, and a drawing canvas, it is a defect factory. A sign error does not throw. It returns a number with the right magnitude, the right units, and the wrong sense — and it passes every test that only checks magnitude.

So Coriolis has exactly one convention, written down once, and every tool obeys it.

The convention

The coordinate system is right-handed: X positive right, Y positive up, Z positive out of the screen. Persisted geometry is engineer-Y-up throughout — data, solvers, persistence, and reports all agree — and the fact that the drawing canvas is Y-down is handled by a single flip at the renderer boundary, in one file, and nowhere else.

Actions follow from that. Axial force NN^* is positive in compression. Positive bending MxM^*_x is sagging: compression at the top face, tension at the bottom. Positive MyM^*_y puts compression at the left face. Apply both and the peak compression lands in the top-left quadrant, which you can check on a sketch in about five seconds — a property we value more than elegance.

Strain and stress are positive in compression, matching the concrete convention, and adopted platform-wide rather than per-tool. For cold-formed steel this is a deliberate departure from the AISI and AISC textbook convention, which takes tension as positive. We document that departure rather than quietly having two conventions in one product, because “it depends which module you are in” is not a convention at all.

Curvature is defined to be consistent with all of it:

ε(x,y)=ε0+κx(yyref)κy(xxref)\varepsilon(x, y) = \varepsilon_0 + \kappa_x (y - y_{ref}) - \kappa_y (x - x_{ref})

so that κx>0\kappa_x > 0 accompanies positive MxM^*_x, with compression at increasing yy.

Names that stay true

The part of this that pays off most is the least interesting to write down. A variable naming a face uses its physical name — top, bottom, left, right. A variable naming a coordinate extreme uses the coordinate name — yMin, yMax. We never alias one to the other.

The temptation is real: in one tool’s frame top and yMax refer to the same edge, so the names look interchangeable, and someone writes top because it reads better. Then the renderer flips Y, and top is now the bottom, and the name is a lie that no test can see. Serialised API fields carry the honest form for the same reason — a field called strainAtYMax is checkable; one called strainAtTop is a claim about a frame the caller cannot see.

That naming rule holds at all five boundaries where the value crosses into something else: persistence, API serialisation, the renderer, user input, and the report PDF.

Why it is a single file

The convention lives in one document that every tool defers to. When code, tests, documentation, or the interface disagree with it, the document wins and the code gets fixed — not the other way around, and not with a local exception. Alongside it sits a single canonical fixture, a worked biaxial case consumed by the backend unit tests, the frontend tests, and the browser end-to-end tests alike. Change the convention and that fixture changes, and every dependent test with it.

It is an unglamorous piece of infrastructure. It is also the reason a moment you enter in the concrete tool means the same thing it means in the section tool, in the API, and on the page you hand to a checker.