Show IDs Values
Nodes Elements Forces Constraints Elem Coord Sys

Show IDs
Points Lines Planes Curves Surfaces

Click or drag (box-select) to add entities to the selection — only entity types currently shown above are pickable. Nothing is ever cleared by clicking; Ctrl+click or Ctrl+drag removes an already-selected entity instead. Shift+drag still rotates the camera; right-drag pans, middle-drag zooms, both unchanged. Esc clears the whole selection. Info for each pick prints to the console.



Ortho-mode panning is scaled down automatically; lower this further if it still feels too fast.


Realistic: shells become true-thickness plates (PSHELL), rods become true-radius cylinders (PROD). Bars/beams are unaffected for now.





Legend

    Click a row to make it active. Check a group's box to show it — once any group exists, only checked groups are shown (everything else, including ungrouped entities, is hidden), so checking just the group(s) you need isolates them for focused analysis. Check "Show full model" above to see everything regardless.

    Also restricts what Direct Pick (click / box-select) is allowed to grab below.
    Uses the same Selection Tool as the Display tab (click / box-select, Ctrl to remove). The Entity Type above restricts what this tool can pick — e.g. set to "Node" so a box-select grabs only nodes, not elements or constraints underneath them. Picked entities are added to the active group live, and the current selection can be pushed into the group at any time.
    Snaps a new point onto an existing finite element node. Turn on, then click a node in the model space — stays on so you can drop several points in a row. Esc or the button turns it back off.
    Creates a new point along the line between two existing points, at the given ratio from A to B. Needs at least two points in the list below.
    Creates a point at every location where two lines, a line and a curve, or two curves cross (within Tolerance) — a curve can cross the other entity more than once, and each crossing gets its own point. Needs at least two lines/curves total.
    Duplicates an existing point by translating or rotating it. Repetitions repeat the same transform cumulatively, so multiple copies form a straight (translate) or circular (rotate) pattern rather than landing on top of each other.
    Click ✏️ next to a point in the list below, or Pick Point above, to edit its coordinates here — either way it highlights and the camera focuses on it.

    Connects two existing points with a straight line. Needs at least two points in the Points list above.
    Start
    End
    Click ✏️ next to a line in the list below, or Pick Line above, to edit its endpoints here — either way it highlights and the camera focuses on it.

    Point 1 is the plane's origin, Point 2 sets its X-axis direction, and Point 3 establishes its orientation. Needs at least three points in the Points list above.
    Click ✏️ next to a plane in the list below, or Pick Plane above, to edit it here — either way it highlights and the camera focuses on it.

    Chains points together in order into a series of connected straight segments. Pick a point, click "Add to Chain", repeat, then create the curve.
    Chain
    (empty — add points above)
    Fits a smooth natural cubic spline (G2 curvature-continuous) through the chained points, in order. Pick a point, click "Add to Chain", repeat, then create the curve.
    Chain
    (empty — add points above)
    Click ✏️ next to a curve in the list below, or Pick Curve above, to edit it here — either way it highlights and the camera focuses on it.

    Fan-triangulates a flat surface across an ordered list of 3–50 existing Points. Pick each vertex in order around the polygon's boundary, click "Add to Chain", repeat, then create the surface.
    Chain
    (empty — add points above)
    Revolves an exact profile (a line or a circular arc) 360° around an axis — Cylinder, Cone, or Sphere.
    Sweeps a straight line between two existing lines (its rails), connecting corresponding ends — flat if the rails are coplanar, a twisted (hyperbolic paraboloid) surface if they're skew.
    Axis-aligned to the Global X/Y/Z axes — e.g. a pressure-vessel tank end cap.
    Click ✏️ next to a surface in the list below, or Pick Surface above, to edit it here — either way it highlights and the camera focuses on it.

    Defines an isotropic material (MAT1). E is mandatory. NU is mandatory unless G is given. Leave G blank to auto-compute it as E / (2·(1+ν)). RHO is only needed for gravity/mass loads (GRAV, RFORCE). Load a model first.


    Adds a new GRID node to the loaded model at the given coordinates. Load a model first — there's no coordinate-system list (and nothing to add a node to) without one.
    Generates GRID nodes at the location of existing construction Points (Geometry tab ▸ Points) — node IDs are assigned automatically, starting one past the model's current highest node ID.
    A node still referenced by a CTRIA3/CQUAD4/CROD/CBAR/CBEAM element, an RBE2 rigid element, or a concentrated mass (CONM1/CONM2) can't be deleted directly — remove that connection (or delete the referencing element) first.

    Or delete several at once: turn on Multi-Select, then box-drag or Ctrl+click nodes in the model space to build a selection (Ctrl+click/drag again removes one, Esc clears it), then Delete Selected. A node still in use is reported and skipped, same as above.
    Selected: 0
    Places nodes evenly (by arc length) along an existing construction Line or Curve (Geometry tab) and connects them into a chain of rod/bar/beam elements.
    Draws one rod/bar/beam element directly between two existing nodes.
    Breaks an existing rod/bar/beam element into multiple smaller segments — new nodes are placed evenly between its two endpoints, and the original element is replaced by a chain of new ones with the same Property and Orientation.
    Loads an existing rod/bar/beam element's nodes, property, and orientation for editing.
    CROD/CBAR/CBEAM is determined entirely by which property (PROD/PBAR·PBARL/PBEAM) an element references — converting means reassigning that property. Pick a target property below (add one under Properties first if the list you need is empty), then convert one element or several at once. Orientation Vector carries over unchanged between CBAR and CBEAM; converting to/from CROD clears it since a rod has no cross-section to rotate.

    Or convert several at once: turn on Multi-Select, then box-drag or Ctrl+click elements in the model space to build a selection (Ctrl+click/drag again removes one, Esc clears it), then Convert Selected. Anything picked that isn't a rod/bar/beam, or that already uses the target property, is skipped.
    Selected: 0
    Removes a rod/bar/beam element from the model. Its nodes are left in place.

    Or delete several at once: turn on Multi-Select, then box-drag or Ctrl+click elements in the model space to build a selection (Ctrl+click/drag again removes one, Esc clears it), then Delete Selected. Anything picked that isn't a rod/bar/beam is skipped.
    Selected: 0
    Draws one shell element from existing nodes — pick a Shell Property, choose Tria or Quad, then click (or type) each corner node in order, clockwise or counter-clockwise, as long as it's consistent.
    Auto-meshes a flat Geometry ▸ Surfaces ▸ Polygon into shell elements using the Scheme below. All nodes/elements are freshly created, independent of any Nodes/Elements already in the model.
    Holes (optional) (0)
    Pick a closed Curve inside the boundary above — its interior is left unmeshed. A full-sweep Arc (Center-Radius) makes a round hole.
    Ruppert's algorithm is only proven to terminate for a Min Angle up to ~20.7° — kept clamped to 28° here so a too-ambitious value can't loop forever instead of quietly capping at the Steiner-point safety limit.
    Quad Quality Limits
    Suggested defaults, adjustable — a paved quad that fails any one of these splits into 2 triangles along its shorter diagonal instead of being kept.
    Max Angle — a corner flatter than this (too obtuse) fails; doesn't see concavity, that's what Jacobian is for. Max Aspect Ratio — longest edge ÷ shortest edge; catches an elongated sliver even if every angle looks fine. Min Jacobian Ratio — smallest ÷ largest corner area contribution; 1 = perfectly uniform, ≤0 = a concave or inverted corner. Max Taper — how much one pair of opposite edges differs in length from the other pair (0 = a parallelogram); doesn't see angle skew, Max Angle covers that.
    Loads an existing Tria/Quad element's corner nodes and property for editing. The element's corner count (3 or 4) can't be changed here — delete and recreate it to switch between Tria and Quad.
    Removes a Tria/Quad element from the model. Its nodes are left in place.

    Or delete several at once: turn on Multi-Select, then box-drag or Ctrl+click elements in the model space to build a selection (Ctrl+click/drag again removes one, Esc clears it), then Delete Selected. Anything picked that isn't a Tria/Quad is skipped.
    Selected: 0
    Click a node (or type its ID), check which DOF to constrain, and save — adds or updates that node's row in the given SPC Set (SID). Rendered as a pin/triangle marker instead of a plain sphere; only the SID the active subcase actually uses is ever shown in the 3D view.
    DOF Constraints

    Click a node (or type its ID), set a magnitude and direction vector, and save — adds or updates that node's row in the given Load Set (LID). Only the LID the active subcase actually uses is ever shown in the 3D view.
    Direction

    Click a node (or type its ID), set a magnitude and direction vector, and save — adds or updates that node's row in the given Load Set (LID). Only the LID the active subcase actually uses is ever shown in the 3D view.
    Direction

    Click a 2D element (tria/quad), or type its element ID, then set a pressure and save — adds or updates a PLOAD entry for that face's nodes in the given Load Set (LID). Positive pressure pushes along the face's outward normal.


    Create, edit, or delete a subcase and assign which SPC Set (SID) and Load Set (LID) it uses — the File tab's Subcase dropdown drives which one is currently shown in the 3D view. Leave SID/LID blank for none.

    Defines the Executive Control (ID/SOL/TIME) and Case Control (TITLE, SPC/LOAD selection, output requests) sections of a Nastran-compatible input deck. Bulk Data — Geometry & Nodes, Elements, Properties, Materials, Boundary Conditions, Loads — comes from the model already defined in FEM Entities and BCs and Loads.
    1. Executive Control Section
    2. Case Control Section
    Output Requests
    Target Format MYSTRAN also adds PARAM,OP2,1 and PARAM,PRTOP2,YES automatically — together with PARAM,POST,-1 above, this is what makes MYSTRAN actually write a .op2 with real results in it (Run Solver below, then Results tab ▸ Open Results reads it straight back in), not just a .f06. This pair does log a harmless "PARAMETER NAMED PRTOP2 MUST BE Y OR N BUT INPUT VALUE IS: 1" warning every run (confirmed on working runs too) — cosmetic, not a sign of trouble.
    PARAM Cards (Bulk Data)
    MSC/NX Nastran only:
    3. Bulk Data Section
    Geometry & Nodes, Elements, Element Properties, Material Properties, Boundary Conditions & Constraints, and Loads all come from the currently loaded model — see FEM Entities and BCs and Loads. Ends with ENDDATA.
    Live preview of the Executive Control and Case Control text — also sent to the Console (Hide Console panel, bottom-left) every time you click Generate.

    Generate Nastran Deck
    Serializes the currently loaded model (nodes, elements, properties, materials, constraints, loads) into real Bulk Data cards and saves the complete, solver-ready deck as a file. Chrome/Edge get a native Save dialog — pick any folder, including the same one as your loaded model; other browsers download to your default Downloads folder instead (browsers can't silently write to an arbitrary folder either way).
    Runs MYSTRAN via the local Flask backend. 📂 Browse only works when that backend runs on this machine — it walks that machine's own filesystem.
    Leave blank to use the server's own MYSTRAN_EXE_OVERRIDE/MYSTRAN_EXE/PATH.
    Auto-fills from the deck's own folder; remembered per-browser. Leave blank to only preview in the Console.
    No results loaded.
    Application 3D Nastran Viewer
    Version —
    Last Updated —
    Author Mircea-Vlad Radulescu
    Author Ada

    Three.js r153
    Renderer WebGL / Vite

    🖱️ Left drag — Rotate
    🖱️ Right drag — Pan
    🖱️ Scroll — Zoom
    ⊟ Collapse All — on the Geometry, FEM Entities, BCs and Loads, and Solve tabs, stays pinned to the top of that tab's tool list as you scroll, so it's always one click away without scrolling back up first
    ↔️ Panel resize — drag the thin strip along the tool panel's right edge to widen it (300–900px, remembered across reloads) — mainly useful on the Solve tab, where Card Preview's box also grows to fit however many lines the deck currently has, so a wide panel shows full 80-column Nastran card lines without wrapping or side-scrolling, closer to reading the saved file in a text editor

    The vertical tab docked to the right edge (collapsed by default; click it, or the tall grab strip along the open panel's own left edge, to toggle — state remembered across reloads) is independent of every other tab, so it can stay open no matter which one is active. Its dot shows green/yellow/red at a glance without opening it.

    Solve Readiness runs the same checklist as File tab ▸ Model Info's own Sanity Check (they always agree — one shared check underneath both): the original checks (nodes/elements/materials/properties present, every element has a property and valid node refs, every SPC/FORCE/MOMENT/PLOAD/RBE2 references a real node, no empty sets, every Subcase has both an SPC and a LOAD — MOMENT-only counts as a LOAD too now, previously only FORCE/PLOAD did) plus several that only live here: duplicate element IDs; an element referencing the same node twice (zero-area/zero-length); a material or PSHELL/PROD with a missing or non-positive E/thickness/area; every SPC set actually used constraining all 6 DOF components somewhere (not necessarily the same node) — a component never constrained anywhere is a likely rigid-body mode; the model splitting into more than one disconnected piece with no shared elements/RBE2 tying them together; coincident/near-coincident nodes (within a small fraction of the model's own bounding-box diagonal); shell elements with a longest-to-shortest edge ratio over 10:1; and CBAR/CBEAM elements with no Orientation Vector/Reference Node set (Generate Nastran Deck already writes a valid fallback for these, so it's a heads-up, not a blocker).

    Deck Overview shows the Solve tab's current Target Format, SOL, and how many Subcases the generated deck will actually write (an implicit top-level SPC/LOAD with no named Subcase reads "1 (implicit)", not a bare 0).

    Estimated Solve Time is a rough order-of-magnitude bucket from node count alone (DOF ≈ nodes × 6) — there's no run-history yet to calibrate against, so treat it as "might take a while", not a forecast. Updates live as the model or Solve tab settings change, same as Model Info does.

    New Model starts a genuinely blank one — every blank model shares the same filename ("Untitled.dat"), so it also wipes that filename's saved construction geometry (Points/Lines/Planes/Curves/Surfaces) and Groups, which otherwise persist per-filename and would resurface leftover geometry from an earlier New Model session (build it up from FEM Entities and BCs and Loads) — a from-scratch blank model shows a small red placeholder cube at the origin until it has something real to show instead, gone the moment the first Node, Element, or construction Geometry entity (Point/Line/Plane/Curve/Surface) is added.

    Open Model loads a .dat/.bdf/.nas/.fem (Nastran-format Bulk Data, including OptiStruct/HyperMesh-flavored decks — same fixed-column parser handles all of them); Save Model writes back to the file this model was opened from or last saved to (Chrome/Edge — prompts for a location the first time, or whenever that's not possible, e.g. a plain upload with no file-system access); Save Model As always prompts.

    Either one updates the Open Model button's label and the Name/Size/Modified rows below to the just-saved filename — previously only Open Model did that, so saving under a new name (Save Model As, or Save Model's own first-time prompt) left those showing the old/original filename until the next Open.

    Open Model and Results tab's Open Results both retry automatically (then fall back to the browser's plain upload dialog) if the native file picker fails for any reason other than an actual Cancel — most commonly a remembered folder handle from an earlier session that's since moved or been deleted — so a real click succeeds on its own instead of silently needing a second one.

    Below that: model info & sanity checks.

    Camera presets (Top/Right/Front/Bottom/Left/Back/ISO/DIM/TRI) & rotation center; every preset frames whatever's actually in the scene — FEM model, construction Geometry, or both together — so a geometry-only model (no FEM nodes/elements yet) still works with every preset instead of silently doing nothing.

    View Size to Fit frames everything currently in the scene the same way — FEM model (Nodes/Elements), FORCE/MOMENT/Pressure load arrows, and construction Geometry (Points/Lines/Planes/Curves/Surfaces) alike, regardless of their own Show toggles on the Display tab — a load arrow at the model's edge is included by its own full extent (tip and all), not just the node it's anchored to, so it never pokes past an otherwise-clean fit.

    In Orthographic mode (the default), the fit is centered on whatever's actually visible between the top tab bar, the left tool panel, and the Console — not the full window behind them — so opening/closing the Console, or resizing either it or the tool panel, before clicking Fit changes how much of the model shows.

    Colors, labels, edges, color scheme & legend.

    FEM Entities and Geometry each have a Hide All toggle next to their section title for a quick "show nothing in this group" — flip it back off and every checkbox in that group returns to shown, not whatever mix was on before.

    The Forces row also has a Values checkbox (its own column, separate from IDs) — magnitude-only labels for Forces, Moments, and Pressure Loads (Pressure Loads have no ID label of their own, only this). Between Font Size and Markers, Values ▸ Number Format (Decimal / Scientific) sets how every value label reads — this one, and Results ▸ Reaction Vector Display — together, not independently.

    Colors includes a Solid Element Color swatch (CHEXA/CPENTA/CTETRA), alongside the existing Tri/Quad/Rod ones.

    Create/manage named groups in a tree; toggle per-group visibility; add entities by ID, property/material, or direct pick.

    🗑️ Delete only forgets the grouping — its members stay in the model; 💥 Delete Group + Model Data instead removes the group's member nodes/elements from the model itself (a node still referenced by something outside the group is kept and reported), so a whole mesh region can be discarded as one unit instead of only via serial Ctrl+Z.

    Surface Mesh (FEM Entities ▸ 2D Elements) auto-creates a "Surface Mesh Sf<id>" group for each mesh it generates, and Generate Nastran Deck writes any group's member elements as their own `$ --- Group: name --- ... $ --- End Group: name ---` block in the Bulk Data, instead of interleaved with everything else.

    Build construction Points, Lines, Planes, Curves & Surfaces (parametric — edits cascade to anything built from them); Save/Open as JSON or IGES.

    Each entity's own List (bottom of its folder) can be shown/hidden via the header next to its count — collapsed by default since these can get long — and the state is remembered per list across reloads.

    Every Edit panel now has a "Pick [Entity] (click)" button alongside the list's own ✏️ — either way, loading an entity for editing also highlights it with a bright wireframe box and pans the camera to center on it, keeping whatever zoom level was already set rather than zooming in tight, so it's easy to find and edit even amid a busy scene without losing surrounding context. Edit Line's Start/End Point fields (when the line follows two Points rather than raw coordinates) also each get their own 🖱️ pick button now, same as Add Line ▸ Points above it, to re-target either end by clicking a point marker instead of hunting for its ID in the dropdown.

    Esc now also closes whichever of these five Edit panels is currently open (and clears its highlight box) the same way it already cancels an in-progress pick — previously Esc only cancelled a pick attempt itself, so backing out of an in-progress "Pick [Entity]" that was offering to replace an entity already open for editing left that other entity's own edit form and box sitting there untouched.

    Surfaces' first option, Polygon, fan-triangulates a flat surface across an ordered chain of 3–50 existing Points — pick a point, "Add to Chain", repeat (same one-at-a-time builder as Curves ▸ Continuous, with a live yellow preview of the boundary and fill as you go), then Add Surface; like an Imported mesh surface, a Polygon has no editable recipe once created (delete and recreate instead) — but since it stores which Points it's built from, editing any of those Points' coordinates (Edit Point) automatically re-triangulates the Polygon to follow, same as moving a Point that a Line/Plane/Curve was built from already cascades to those.

    Materials (MAT1: E/G/NU/RHO, MIL-HDBK-5J presets) and Properties (PROD/PBAR/PBARL/PBEAM/PSHELL/PBUSH).

    Nodes — add by coordinates or at a construction Point — both show a live preview of exactly where the new node will land, and the suggested Node ID always follows one past the model's current highest node ID, whichever tool last created one; edit/delete with connectivity protection, Esc to cancel a pick.

    1D Elements — mesh a construction Line/Curve, draw a rod/bar/beam node-to-node, split an existing one into segments, edit any of them, convert one or many between CROD/CBAR/CBEAM, or Delete Element to remove one by pick or ID — its nodes are left in place. CBAR/CBEAM take an optional Orientation Vector/Reference-Node; leave it on "none" and a Generate Nastran Deck / Save Model still writes a valid fallback V vector automatically, since MYSTRAN rejects a CBAR/CBEAM with none at all.

    Convert Element Type: CROD/CBAR/CBEAM isn't its own field — it's derived entirely from which property (PROD vs PBAR/PBARL vs PBEAM) an element references — so converting is just picking a target Line Property (add the PBAR/PBARL or PBEAM property first under Properties if the one you need doesn't exist yet) and applying it, either to a single pick/ID-looked-up element or, via the same Multi-Select flow as Delete Element below, to a whole box-drag/Ctrl+click selection at once (handy for flipping every CBEAM in an imported model — e.g. a truck frame modeled entirely in CBEAM — over to CBAR in one go, or back). Orientation carries over unchanged between CBAR and CBEAM; converting to/from CROD clears it since a rod has no cross-section to rotate. Each converted element is a normal Ctrl+Z-undoable edit — a bulk conversion (Multi-Select) undoes/redoes all of it together in one press.

    Mesh on Curve, Node-to-Node, and Splitting Elements all show a live yellow preview — highlighted endpoints and a dashed line through where the new node(s)/element(s) will land — as you fill in or pick each field, same scheme as 2D Elements below.

    2D Elements — Manual Corner Selection: pick a Shell Property, then click 3 or 4 existing nodes in order to draw a Tria/Quad, edit an existing one, or Delete Element the same way as 1D Elements above.

    Surface Mesh auto-meshes a flat Geometry ▸ Surfaces ▸ Polygon into shell elements — pick which Polygon, Shell Property, and Scheme, optionally add one or more closed Curves as Holes (a full-sweep Arc/Circle works for a round one — think a plate with a hole; not supported by Polyhedron, see below), and set a Target Edge Length (and, for Tri/Quad, Min Angle) — 💡 Suggest fills in a sensible starting value: about a tenth of the shorter side of the Polygon's own bounding box, or of the smallest Hole's, whichever is smaller (so a small hole in a big plate still gets enough elements around it).

    Tri (Delaunay): with no holes it ear-clips the boundary directly; with holes it instead builds an unconstrained Delaunay triangulation of every boundary/hole point and recovers each boundary edge by flipping (a boundary-only ear-clip-plus-bridge was tried first but turned out to be unreliable for anything but a tiny, distant hole — the flip-recovery approach handles any size/position). Either way it's Lawson-flipped into a full Constrained Delaunay Triangulation, then runs Delaunay refinement/Ruppert's algorithm: any encroached boundary segment is split at its midpoint, and any triangle that's still too big or too skinny gets a new node at its circumcenter, repeating until every element meets both targets or a 3000-Steiner-point safety cap is hit (a spinner shows while this runs — a fine mesh against the cap can take a few seconds) — writes CTRIA3 only.

    Quad (Paving) [WIP — a real per-element advancing-front paver is in progress; today's version still stops after only a row or two around a hole, so expect mostly triangles rather than mostly quads on hole geometry]: rings quad rows inward from the boundary and outward from each hole (row height ≈ Target Edge Length, mitered at corners like a stroke renderer's line join) until two fronts would collide or a front gets too small to keep going — a row whose full Target Edge Length would collide instead shrinks to whatever distance still fits (down to about a third of Target Edge Length; below that it's not worth another row), so a boundary/hole gap only a little tighter than Target Edge Length still gets a paved row instead of skipping straight to all-triangle infill — then hands whatever's left to the same Tri (Delaunay) engine above as its new boundary/holes — most models end up mostly CQUAD4 with a small CTRIA3 patch wherever the rows would otherwise have met (a real plate-with-a-hole ends up with quad rings around both the outer edge and the hole, and a triangulated band between them, same as this method's classic textbook demonstration).

    Quad Quality Limits (Max Angle, Max Aspect Ratio, Min Jacobian Ratio, Max Taper — suggested defaults shown, all adjustable, FEMAP-style) then check every paved quad against those thresholds and split any that fails one into 2 CTRIA3 along its shorter diagonal instead of keeping a badly-shaped element.

    Polyhedron (Quad Fan) [WIP]: Cubit/Coreform's single-loop "Polyhedron" primitive — one quad per boundary edge (boundary point, edge midpoint, the boundary's own center, previous edge's midpoint), all meeting at the center; exact for a convex boundary, still valid but uneven on a mildly non-convex one (a warning notes this), CQUAD4 only, no refinement pass, Holes ignored.

    Generate Mesh also logs every parameter it's about to use — Polygon, Scheme, Shell Property, Holes (if any), Target Edge Length, Min Angle, and, for Quad, the four Quality Limits — to the Console before meshing starts. Whichever Scheme, nodes/elements are all freshly created, independent of whatever Nodes/Elements already exist; undoable as one step like Mesh on Curve above; every generated mesh is also saved into its own auto-created Group tab entry — "Surface Mesh Sf<id>", or "... (N holes)" — so it can be isolated, deck-labeled, or deleted as a unit later via the Group tab's 💥 Delete Group + Model Data, without touching Ctrl+Z.

    Every Delete panel (Node, 1D Element, 2D Element) also has a Multi-Select toggle below its single pick/ID flow: turns on the same box-drag/Ctrl+click Selection Tool used elsewhere (Ctrl+click or Ctrl+drag again removes one, Esc clears it), and Delete Selected then removes everything currently selected that belongs to that panel in one confirm — a node still referenced by an element/RBE2/mass, or an element that isn't actually the right kind for that panel (e.g. a shell picked while in the 1D panel), is reported and skipped rather than blocking the rest. A Multi-Select bulk deletion undoes/redoes all of it together in one Ctrl+Z, same as a single delete undoes in one.

    Deleting a node (single or Multi-Select) also removes any SPC constraint, FORCE, MOMENT, or PLOAD entry still pointing at it, with a warning before and after — left behind, those become dangling references a solver rejects outright (MYSTRAN/Nastran's "GRID n ON SPC OR SPC1 n IS UNDEFINED"), which is exactly what used to happen after trimming a mesh down without also touching its BCs/loads. Ctrl+Z brings those same BC/load entries back along with the node (Ctrl+Shift+Z/Ctrl+Y removes them again), so a delete-then-undo round-trip leaves the model exactly as it was.

    3D solid elements — CHEXA (8/20-node), CPENTA (6/15-node), and CTETRA (4/10-node), linear or quadratic — and quadratic CQUAD8 (8-node) shells are read from a loaded file and rendered (solids as outer skin/boundary faces only, shaded by their PSOLID's material, same as other shells; CQUAD8 as a flat quad using its 4 corners, same as CQUAD4) but have no Add/Edit/Delete tooling here yet.

    SPC Editor: pick or type a node, check DOF 1-6 (Tx/Ty/Tz/Rx/Ry/Rz) and save to add/update its constraint in an SPC Set (SID), rendered as pin/triangle markers instead of spheres.

    Force Editor and Moment Editor: pick or type a node, set a magnitude and direction vector, and save to add/update its row in a Load Set (LID) — arrow length auto-scales from the model's own size and the largest magnitude in view (Display tab's Force Scale Fine slider then adjusts from there, never a fixed/zero ratio), and Moments render as curved arc arrows, not straight shafts.

    Pressure Loads: pick or type a 2D element (tria/quad), set a pressure, and save to add/update a pressure entry for that face — a loaded file's own legacy PLOAD or PLOAD4 entries (shell face pressures, and solid-element face pressures identified by corner grids) are all read and rendered as the same arrows either way.

    Generate Nastran Deck / Save Model always write these back out as PLOAD4 with all four pressure fields filled in explicitly (SID, element ID, P1=P2=P3=P4), never the legacy 5-grid PLOAD — MYSTRAN's own Bulk Data QRG doesn't document plain PLOAD at all, and it logs "card name not found" for every one, which on a model with several of them can cascade into losing the whole load set; leaving P2-P4 blank (documented as defaulting to P1) was also tried and produced a run with the load silently not applied at all, hence all four written out instead of relying on that default.

    FORCE, MOMENT, and Pressure arrows always render on top of solid elements' opaque outer-skin shading now, not behind/inside it — previously the only way to see a pressure arrow on a CHEXA/CPENTA/CTETRA face at all was to turn down Solid Element Color's opacity first. Picking any of the three is also far more forgiving now: clicking anywhere within about 20 screen pixels of an arrow's shaft (not just its arrowhead) hits it, the same generous tolerance line/curve picking under Geometry already used.

    Every editor supports editing an existing entry via the list's ✏️ or by picking its symbol/arrow/face in the model space, only the SID/LID the active subcase actually uses is ever shown in the 3D view (falling back to the model's first-defined SID/LID before any Subcase exists yet, so a from-scratch model's constraints/loads are visible the moment they're created), and every field highlights its target node/face and sketches a live preview as you type — Esc cancels any in-progress pick, edit, or preview.

    Below a divider, Subcase Manager: create/edit/delete a subcase and assign the SPC Set (SID) and Load Set (LID) it uses, each a dropdown of sets actually defined in the model (plus "(none)") — the File tab's Subcase dropdown drives which one renders.

    Solution Definition: builds the Executive Control (ID/SOL/TIME) and Case Control (TITLE, SPC/LOAD selection, DISPLACEMENT/OLOAD/SPCFORCES/STRESS output requests) sections of a Nastran-compatible deck for a chosen Target Format — MYSTRAN by default, or FEMAP/Patran (all three MSC/NX Nastran-compatible syntax).

    PARAM,POST,-1 is offered for every target now (MYSTRAN understands it too); Target Format MYSTRAN also offers PARAM,OP2,1 + PARAM,PRTOP2,YES together — without that pair MYSTRAN can produce a perfectly normal-looking successful run whose .op2 is missing or empty, which used to silently break Run Solver → Results tab's round-trip. This pair also logs a harmless "PARAMETER NAMED PRTOP2 MUST BE Y OR N BUT INPUT VALUE IS: 1" warning on every single run, including clean fully-solved ones — cosmetic only, safe to ignore.

    Every PARAM card (POST, the OP2 pair, PRGPST, OGEOM, AUTOSPC, GRDPNT, K6ROT) has its own control under PARAM Cards. PRGPST and OGEOM are real MSC/NX Nastran PARAMs that current MYSTRAN doesn't recognize at all (it just logs a harmless "NOT RECOGNIZED" warning for each) — their YES/NO/(omit) dropdowns only show for FEMAP/Patran, where they're real.

    AUTOSPC has no include/omit checkbox on purpose: per MYSTRAN's own User Manual, AUTOSPC runs automatically unless it sees an explicit N, so omitting the line would silently do nothing — the Y/N dropdown is always written, alongside its four real sub-fields (Ratio/AUTOSPC_RAT, NSET, INFO, SPCF) once Y is selected. Switching to N is worth trying whenever a run "succeeds" with suspiciously small or zero displacement: AUTOSPC's singularity check is a *relative* stiffness threshold that can occasionally catch a marginally-supported node too (e.g. a point load applied at a node with only one attached element), silently absorbing the entire applied load into a reaction right there; N instead makes MYSTRAN fail loudly on a real singularity, and turning on INFO/SPCF first prints exactly the messages/reaction-forces (also visible in the .f06's own AUTOSPC Summary and "SPC Force Summary on AUTOSPC'd DOF's" table) needed to catch it without switching AUTOSPC off first.

    GRDPNT takes a real grid ID now instead of a fixed 0 — -1 disables the Grid Point Weight Generator report entirely (MYSTRAN's own default if the line is omitted), 0 is the basic coordinate system origin, or point it at any specific grid.

    K6ROT is unchecked/0 by default (matching MYSTRAN's own default) and adds a small fictitious drilling-DOF spring at every shell node — worth trying when a lone element at a curved-shell corner leaves that node's normal-rotation DOF with a nonzero-but-tiny coupling stiffness that AUTOSPC's ratio test doesn't catch, producing wildly oversized stress right at that corner; MYSTRAN's own .ERR calls K6ROT "AN EXPERIMENTAL FEATURE" and it has been observed to crash MYSTRAN 17.0.0 outright on a plain shell PSHELL with no transverse-shear material (MID3) defined, so it's opt-in, not a fix to leave on by default.

    Output Requests now also offers ELFORCE — worth checking even though the Results tab can't read element forces back from F06 yet (only STRESS is), so the .f06 already has it ready for when that support lands.

    Seamless by default: TITLE auto-fills from the filename and SOL choice. If the model has no real Subcase yet (BCs and Loads ▸ Subcase Manager), SPC/LOAD are dropdowns defaulting to the first set actually defined in the model — nothing to type for a quick run, and "Load from Subcase" quick-fills Title/SPC/LOAD from an existing Subcase.

    The moment any real Subcase exists, those flat fields are replaced by a "Subcases to Include" checklist instead (every Subcase starts checked) — Subcases are only ever defined once, in Subcase Manager, not redefined here; this panel just picks which of them go into this particular deck, each written as its own SUBCASE block with a `$ ─── Subcase N: Title ───` comment ahead of it so a deck with several is easy to scan. The note under the checklist (or the flat fields) says which of the two modes is in effect.

    Card Preview's live-updating text (Click Generate to print it to the Console too; Copy to Clipboard grabs it) shows the real Subcase blocks as you check/uncheck them and stays a lightweight placeholder for Bulk Data as you type; its box auto-sizes to however many lines that currently is (10–60 rows, its own scrollbar takes over past that), and after Generate Nastran Deck below it re-shows that exact real, complete deck too — see Panel resize above for widening the tool panel itself alongside it.

    Below it, Generate Nastran Deck actually serializes the whole loaded model (nodes, elements, properties, materials, constraints, loads) into real Bulk Data cards and saves the complete, solver-ready file as .dat or .bdf — an element belonging to a Group tab entry (e.g. a Surface Mesh result) is written inside its own `$ --- Group: name ---` / `$ --- End Group: name ---` block rather than interleaved with everything else; a model with no grouped elements writes the plain flat layout unchanged — a native Save dialog on Chrome/Edge (pick any folder), a plain download elsewhere — and pre-fills Run Solver's Input Deck below with that same just-generated file so there's nothing to re-browse for.

    Run Solver: three path fields, each with its own 📂 Browse — MYSTRAN Executable (blank = server's own MYSTRAN_EXE_OVERRIDE/MYSTRAN_EXE/PATH), Input Deck (blank = the deck Generate Nastran Deck/Save Model most recently produced, or the last model loaded), and Destination Folder (blank = preview only, nothing saved). If no solver is actually available to run it — the Flask backend is unreachable, or it's reachable but reports no MYSTRAN installed (some deployments deliberately run Flask for OP2 parsing without bundling a MYSTRAN binary — see Backend status below) — this panel shows a note instead: download your deck with Generate Nastran Deck above, run it yourself with MYSTRAN, NX Nastran, or MSC Nastran installed on your own machine, then bring the result back in with Results ▸ Open Results — F06 import needs no backend at all; only OP2 does.

    Browse opens a small popup that walks the Flask backend's own filesystem and picks a real full path — only works when that backend runs on this machine, since a normal browser file picker can never read one back; Destination Folder's Browse lists folders only, and picking one selects wherever you're currently browsing, no need to open a specific item. Typing (or browsing to) an Input Deck path auto-fills Destination Folder with that file's own folder; both MYSTRAN Executable and Destination Folder remember whatever you last set — instantly in this browser, and synced to your account so a new browser/machine picks up the same values once logged in.

    Click Run Solver to execute MYSTRAN via the local Flask backend. Clicking it also clears the Results tab immediately (same as opening a new model does) — whatever's currently loaded there is about to be superseded by this run's .f06/.op2, win or lose, so leaving the old one showing would just risk reading stale node IDs or subcases as if they were current; Results tab ▸ Open Results is the explicit step back in once the new run finishes.

    Basic run messages (return code, stdout, and the .f06 tail on failure) print to the Console; the full .f06, .op2, and a run log are saved into the Destination Folder whenever one is set (directly or via the Deck Path default) — leaving both blank still runs, but nothing is kept afterward.

    Node Location and Measure Distance (pick or type node IDs).

    Entity Info looks up the raw card for a Node/Element/Force (by LID)/Pressure (by LID, PLOAD/PLOAD4 — Pick clicks a pressure arrow directly rather than an element, since a shell's pressure face is the element itself but a solid's is only one of several)/Constraint (by SID)/Material/Property by ID or pick — Esc clears whatever's currently highlighted (here or from any other tool's pick/lookup, since they all share the same on-screen highlight), same as clicking ✖ Clear Highlight.

    Coincident Nodes checks every node pair against a threshold (default 1×10⁻⁴ length units, the standard "these are really the same point" tolerance), prints a table of every pair found — the two node IDs, their ΔX/ΔY/ΔZ, and distance — to the Console, and can merge them: each cluster of coincident nodes (chains of 3+ included) collapses onto its lowest-numbered node, with every element, SPC, FORCE/MOMENT, PLOAD/PLOAD4 face, RBE2, mass, and group reference to a removed node redirected first so nothing is left dangling.

    Free Floating Nodes finds every node not attached to any element/RBE2/mass (same definition as Model Info's own "not used by any element" warning), lists each one's position and whether it still carries a constraint/load in a Console table, and deletes the ones that don't — one still carrying a constraint/load is reported but skipped rather than silently stranding that SPC/FORCE/MOMENT/PLOAD.

    Neither tool's changes are undoable with Ctrl+Z — reload the file to start over if a run wasn't wanted.

    Load OP2 or F06 result sets and view displacement/stress/force fringe plots. F06 supports both MSC/NX Nastran and MYSTRAN dialects: displacements, SPC reactions, OLOAD/SPCFORCE resultants, 2D shell (QUAD4/TRIA3) stress, and CROD axial/torsional stress all parse from either; shell forces and CBAR/CBEAM forces still need an OP2. Bar/beam stress and rod/bar element forces aren't read from F06 yet — the Results Tree shows where each still-missing category stands.

    Model Concordance (right under the loaded results filename) checks the results file against the loaded model on five fronts — filename (a soft/advisory check: related-looking names pass, since a solver-renamed output like "model-013.op2" is normal and shouldn't be flagged just for not sharing the model's name), Subcases (the model's own SUBCASE definitions, or its implicit single subcase, against whichever subcase IDs the results file actually reports), grid point count, element counts by type, and displacement-node coverage. Any single ⚠️ among these — most usefully "opened the wrong sibling results file for this model" — pops a red warning banner right under the filename at the top of the tab, impossible to miss without needing to scroll down and read the detailed list yourself first.

    Deformation Display has an Opacity slider (below Scale) — lower it to see markers like SPC reaction arrows through the shaded deformed shell instead of them being hidden behind it. Animate (next to Scale) breathes the shape from undeformed out to full Scale and back, both directions (0 → +Scale → 0 → −Scale → 0) so the deformation direction reads clearly at a glance — just two settings, Frames (steps per cycle) and Interval in ms (pause between steps), not Patran's tangle of start/end/output-frame fields; Scale/Auto lock while it's running and hand back exactly what they were set to once you uncheck it.

    Between Deformation Display and Fringe Display, Reaction Vector Display controls the SPC/MPC reaction arrows from Forces & Reactions (Nodal) in the tree above: Vector picks Magnitude (Total SPC/MPC Reaction Force draws one combined arrow, the default) or 3 Components, which instead draws separate X/Y/Z arrows (red/green/blue) resolved into the chosen Coordinate System — the individual FX/FY/FZ/MX/MY/MZ tree items always stay single global-axis arrows either way. The magnitude-labels checkbox still applies to both modes (one combined "x, y, z" label per node in Components mode).

    Fringe Display has a Style choice for shell stress/force fringes: Filled Contour (the default) averages each element's value across its corner nodes and lets the corners blend smoothly, giving the classic soft-gradient contour look; Element (single value) instead paints each element one flat color from its own value, with no blending — pick it when you want to see exactly which element owns which value. The Style choice only applies to shell (QUAD4/TRIA3) fringes; rod/beam fringe (colored line segments) always uses the single-value coloring.

    The shell stress fringe list also includes Radial, Tangential (Hoop), and Radial-Tangential Shear — these rotate each element's local σx/σy/τxy into a polar frame about a Polar Center point (X, Y in global coordinates, editable once one of the three is selected, default the origin) so curved-boundary stresses like NAFEMS-style "tangential edge stress" read directly off the fringe instead of needing a manual per-element rotation. Show Contour Lines overlays iso-value lines at the same 9 levels the viewport colorbar labels, traced through the nodally-averaged field (marching triangles) so the bands read at a glance regardless of which Style is active.

    Pick Entity Results' dropdown always offers a live "📍 Active Fringe" entry whenever a shell fringe is showing — its label tracks whatever's currently selected (including the derived Radial/Tangential components), and picking a node reads off the exact nodally-averaged value that node is colored by, both in the panel and as a console table for multi-node box-selects.

    Esc is staged: the first press clears the current pick (even after "Pick Entities" has been toggled back Off — it stays visible in the panel until dismissed), and a second press (once there's nothing left to clear) turns "Pick Entities" off — so leaving it on in the background while working in another tab is always one or two Escapes away from fully off, not a dead end. Picking elements only boosts element markers to pick-size, leaving node markers at their normal size since they aren't clickable in that mode.

    When Deformation Display's Animate is running and a shell/beam fringe is also active, the fringe breathes in sync with the shape — values scale from 0 up to their true magnitude and back as the animation phase ramps 0→1→0, while the colorbar legend stays fixed at the true converged range throughout, so the fringe visibly "loads" alongside the deforming shape instead of jumping straight to its final colors.

    Profile: your username (fixed, not editable) and an optional Contact Email, saved as you tab away from the field; Change Password needs the current password plus a new one (8+ characters) typed twice, and signs you out of every other logged-in browser/tab — this one stays logged in.

    Settings: Solver Executable and Scratch Location are the exact same account preferences as the Solve tab ▸ Run Solver panel's MYSTRAN Executable and Destination Folder fields — editing either copy updates the other immediately, in this tab or that one. Solver is a dropdown with only MYSTRAN in it today (the only one this app actually runs) — saved for whenever a second solver is supported, not functional yet.

    The two small arrows next to Hide Console (bottom-left) undo/redo Node, 1D/2D Element, SPC/Force/Moment/Pressure Load, Subcase, Material, Property, Group, and Geometry ▸ Edit Point changes as one shared history; Ctrl+Z / Ctrl+Y (or Ctrl+Shift+Z) work the same way from anywhere except a text field.

    Undoing/redoing an Edit Point also re-runs the parametric cascade, so any Line/Plane/Curve/Polygon Surface built from that Point snaps back to (or re-applies) its own shape right along with it.

    A bulk action that changes many things at once (Multi-Select delete/convert, deleting a group with its members, generating a Surface Mesh and its auto-created group) undoes/redoes as one combined step, not one press per item.

    Undo/redo isn't yet tracked for every entity kind — Point/Line/Plane/Curve/Surface create and delete (only Edit Point is) and a couple of narrower gaps noted where they're most likely to matter are the known exceptions.

    Two small dots next to Undo/Redo, one per backend process, visible from any tab. The first shows the Flask backend (python server.py) — Results (OP2 parsing) and Solve ▸ Run Solver (MYSTRAN) depend on it; hover it for the pyNastran version and MYSTRAN availability.

    The second shows the Node backend (node server-node/index.js) — this one is required now for most of the app's actual work, not optional: opening a model, Generate Nastran Deck, every Geometry ▸ Point/Line/Plane/Curve/Surface creation recipe that computes something (not a literal passthrough like From Coordinates or Continuous), FEM Entities/BCs and Loads ▸ Node coordinate transforms, Material/Property save and connectivity checks, 1D Element resample/split, Force/Moment vector math, and 2D Elements ▸ Surface Mesh's Delaunay/Ruppert-refinement/paving engine all route through it with no client-side fallback — an unreachable Node backend fails that specific action with a clear Console message instead of silently computing locally, everything else in the app keeps working.

    Card Preview is one deliberate exception — always client-only, never routed through this backend, so it keeps working live either way; the parametric cascade that re-runs on every edit (keeping dependent Lines/Planes/Curves/Surfaces in sync) is another, for the same reason, and so is the Surface Mesh panel's own "💡 Suggest" button, which only needs a quick bounding-box estimate. Both re-check themselves every ~10s, so starting either backend after the page is already open lights its own dot up on its own — no reload needed.

    Invite-only: an account needs a one-time invite token (an admin generates one per person) alongside a chosen username and password; there's no self-service signup without one.

    Logged-in state is a cookie against the Node backend, good for 30 days — closing the tab doesn't log you out, only "Log Out" (next to the backend status dots) or the cookie expiring does. If your login expires while the app is open, the next action that needs the Node backend brings the login screen back with a note explaining why, rather than failing silently or asking for an unrelated "unavailable backend" fix.

    Forgotten passwords aren't self-service yet — ask whoever set up your invite to reset it. See the User tab below for changing your password once logged in, and for the account-wide preferences every login carries with it.


    Change Password
    Changing your password signs you out of every other logged-in browser/tab — this one stays logged in.
    These are the same preferences as the Solve tab's Run Solver panel — editing either one updates the other, and they follow your account to any machine you log in from.
    MYSTRAN is the only solver this app runs today — saved for when a second one is supported.
    Where solver runs read/write their working files — same field as the Solve tab's "Destination Folder."
    Backend… Backend2…
    Console
    Loading…
    Nastran Viewer
    Have an invite? Create an account
    🩺 Deck Sanity Check