// Ambient declarations for @meshioplusplus/wasm's hand-written wrapper // (src/index.mjs). Mirrors the JS-facing mesh object shape produced/consumed // by bindings/wasm/js_bindings.cpp's meshToVal/valToMesh (see doc/wasm.md for // the full format-support table and known v1 limitations). /** * A rectangular (uniform node count) group of cells, all the same meshio++ * cell type. */ /** * What is wrong with a surface, in numbers rather than a bare flag -- the four * counts `surfaceWatertightCheck`, `computeCurvature`, `repair` and * `shrinkwrap` all report. */ export interface SurfaceQualityInfo { boundaryEdges: number; nonManifoldEdges: number; inconsistentPairs: number; degenerateTriangles: number; watertight: boolean; } /** * A `point_data`/`cell_data`/`field_data` array's JS type: it carries its * source dtype crossing the WASM boundary instead of always widening to * `Float64Array` (roadmap §1 "WASM parity": dtype carry). `BigInt64Array`/ * `BigUint64Array` elements are JS `bigint`, not `number` -- see * {@link XdmfTimeSeriesWriter.writeDataArrays} if you need to feed one to an * API that still expects `number`s. */ export type DataArray = | Float32Array | Float64Array | Int8Array | Int16Array | Int32Array | BigInt64Array | Uint8Array | Uint16Array | Uint32Array | BigUint64Array; /** * The index maps an op that prunes/renumbers points and cells returns when * called with `returnMaps: true`, alongside its `mesh`: `pointMap` is input * point index -> output point index (-1 if pruned), `cellMaps` is one array * per **input** cell block, input cell -> output index within the * corresponding output block (-1 if dropped). See doc/wasm.md's "Index maps" * section for the per-op semantics (e.g. what a collapsed/welded point's * -1-or-survivor value means). */ export interface PointCellMaps { pointMap: Int32Array; cellMaps: Int32Array[]; } export interface RectangularCellBlock { /** meshio++ cell type name, e.g. "triangle", "tetra10", "hexahedron". */ type: string; /** Flat, row-major connectivity: length === numCells * nodesPerCell. */ data: Int32Array; nodesPerCell: number; } /** * A 1-level ragged (jagged polygon) group of cells: rows of varying node * count, so there is no single `nodesPerCell`. Two flat CSR arrays instead * of a nested array of arrays, which embind has no efficient representation * for: `data` is every row's node ids concatenated, and `rowOffsets` is each * cell's start index into `data` (length numCells + 1, so cell `c`'s row is * `data.slice(rowOffsets[c], rowOffsets[c + 1])`). */ export interface PolygonCellBlock { type: 'polygon' | 'polygon2'; data: Int32Array; rowOffsets: Int32Array; } /** * A 2-level ragged (polyhedron) group of cells: each cell is a list of * faces, each face a list of node ids. Three flat CSR arrays: `data` is * every face's node ids concatenated; `faceOffsets` is each face's start * index into `data` (length totalFaces + 1); `cellOffsets` is each cell's * start index into the face list (length numCells + 1, so cell `c`'s faces * are `faceOffsets[cellOffsets[c]] .. faceOffsets[cellOffsets[c + 1]]`). * * `writeMesh` accepts a polyhedron block for the formats that can hold one * (`vtu`, `ensight` nfaced, `cgns` NFACE_n, `med` POE, `openfoam`); a format * that cannot (legacy `vtk`, `vtp`, ...) throws naming the format. The shape * also crosses the JS boundary unchanged through operations such as * {@link MeshioPlusPlusModule.clean}. */ export interface PolyhedronCellBlock { type: string; data: Int32Array; faceOffsets: Int32Array; cellOffsets: Int32Array; } /** A single homogeneous group of cells, all the same meshio++ cell type. */ export type CellBlock = RectangularCellBlock | PolygonCellBlock | PolyhedronCellBlock; /** * A mesh as exchanged with the WASM boundary: every array is copied (there * is no zero-copy path across the JS/WASM memory boundary, unlike the * Python bindings' numpy views) and cell connectivity is always Int32Array * (down-cast from the C++ core's Int64, which is safe for any mesh size a * browser can reasonably hold). */ export interface Mesh { /** Flat, row-major point coordinates: length === numPoints * dim. */ points: Float64Array; /** 2 or 3. */ dim: number; cells: CellBlock[]; /** * name -> flat, row-major per-point data. A multi-component (vector/tensor) * array is stored interleaved, `numPoints * components` long, with its width * declared in {@link Mesh.point_data_components}. Each array's JS type is * its source dtype (see {@link DataArray}), not always `Float64Array`. */ point_data?: Record; /** * Per-entity width of any `point_data` array that is not a scalar, since a * flat typed array carries no shape. A name absent here has one component. * Read back from `readMesh` for multi-component arrays only, so a * scalar-only mesh gets an empty object. */ point_data_components?: Record; /** * name -> one flat array per cell block, same order as `cells`. Every * block of one named array shares the same {@link DataArray} class -- * `writeMesh`/`convert`-side callers that mix classes across blocks of the * same name get a thrown Error naming the array. */ cell_data?: Record; /** * Per-entity width of any `cell_data` array that is not a scalar. One value * per *array*, not per block: every block of a named cell_data array must * agree on its component count. */ cell_data_components?: Record; /** name -> scalar/small metadata arrays (e.g. material ids). */ field_data?: Record; /** Per-entity width of any `field_data` array that is not a scalar. */ field_data_components?: Record; /** Named groups of points / cells / cell facets (see {@link Region}). */ regions?: Region[]; /** `Begin Properties` blocks -- Kratos material data (currently MDPA only). See {@link PropertySet}. */ propertySets?: PropertySet[]; /** * Format-specific side-channel metadata a generic `Mesh` cannot represent, * attached by `readMeshSelective(path, {info: true})`. Present only for * formats with one (openfoam/med/mdpa/ansysinp/unv/gmsh/exodus); absent * otherwise, even when `info: true` was requested. Its own `format` field * is what `writeMesh` checks before reusing it on a write with no explicit * `options.info`. See doc/wasm.md's "Side channel (info)" section. */ info?: MeshInfo; } /** The union of every format's side-channel `info` shape. Discriminate on `format`. */ export type MeshInfo = | OpenFoamInfo | MedInfo | MdpaInfo | AnsysInfo | UnvInfo | GmshInfo | ExodusInfo; /** OpenFOAM's side channel: `readMeshSelective`'s cell_tags/patch-type map, reshaped per patch. */ export interface OpenFoamInfo { format: 'openfoam'; patches: Array<{ /** The negative, MED-style family id `cell_tags` uses for this patch. */ familyId: number; /** Names this family id is known by (usually one; more than one on a collision). */ names: string[]; /** The patch `type` (`patch`/`wall`/`symmetry`/...), when known. */ type?: string; }>; } /** MED's side channel: family/group names, units, and per-field step/time metadata. */ export interface MedInfo { format: 'med'; /** Point family id -> subset name(s), as `point_tags`/`cell_tags` key them. */ pointTags: Record; cellTags: Record; meshName: string; description: string; unitTime: string; unitCoords: string; /** Family id -> its `FAM_...` group link name. */ pointTagGroups: Record; cellTagGroups: Record; /** Lenient-mode only: constructs this read could not represent, verbatim. */ skippedConstructs: string[]; /** Lenient-mode only: field name -> `[UNI, UNT]` unit strings. */ fieldUnits: Record; /** Lenient-mode only: field name -> `{ndt, nor, pdt}` (MED's own step/order/time triple). */ stepMeta: Record; /** Field name -> every step's time value (always filled, not lenient-only). */ fieldTimeValues: Record; } /** MDPA's side channel: per-block entity names. Properties ride on `mesh.propertySets` instead (see {@link PropertySet}), not here. */ export interface MdpaInfo { format: 'mdpa'; /** One entry per cell block, mesh block order. */ entityNames: Array<{ name: string; isCondition: boolean }>; /** Lenient-mode only: constructs this read could not represent, verbatim. */ skippedConstructs: string[]; } /** * The shared shape of Ansys (`.cdb`/`.inp`, MAPDL) and UNV's side channel: * named point/cell sets the generic {@link Region} shape does not carry. */ export interface AnsysUnvInfoShape { /** Set name -> 0-based point/node indices. */ pointSets: Record; /** Set name -> one array of 0-based local indices per cell block. */ cellSets: Record; } export interface AnsysInfo extends AnsysUnvInfoShape { format: 'ansysinp'; } export interface UnvInfo extends AnsysUnvInfoShape { format: 'unv'; } /** Gmsh's side channel: `$Entities` bounding-entity tags, one array per cell block. */ export interface GmshInfo { format: 'gmsh'; boundingEntities: number[][]; } /** Exodus's side channel: info/QA records. Read-only -- there is no Info-bearing Exodus writer. */ export interface ExodusInfo { format: 'exodus'; infoRecords: string[]; } /** * One `Begin Properties ` block: an id plus its entries, in file order. * Carried on the {@link Mesh} object itself (like {@link Region}), keyed by * id rather than entity index, so operations that renumber cells/points * cannot invalidate them. Shape-preserving operations (`clean`, `smooth`, * `transform`, `attachQuality`, the `data*` ops) carry them through; * restructuring and multi-input ones (`merge`, `cropBbox`/`cropPlane`/ * `cropPredicate`, `split`, `partition`, `diff`) do not. */ export interface PropertySet { id: number; values: PropertyValue[]; } /** * One `KEY value` entry of a properties block. Exactly one of `values` and * `text` carries the value: a plain number is a one-element `values`; an * inline `Begin Table` is an `(n, k)` `values` (flat, row-major -- `k` given * by `components` when `k > 1`) with `isTable` set and `key` holding the * table header's arguments verbatim; anything else (a constitutive-law name, * a bracketed vector/matrix) is kept verbatim in `text`, which is what makes * an unrecognized value lossless. */ export interface PropertyValue { key: string; values: Float64Array; /** Per-entity width of `values` when `isTable` and `k > 1`. Absent means 1. */ components?: number; /** The value verbatim, when it is not numeric (`values` is then empty). */ text: string; isTable: boolean; } /** * A named group of mesh entities: a gmsh physical group, an Abaqus * `*NSET`/`*ELSET`/`*SURFACE`, an Exodus block or set, a MED family, a Kratos * SubModelPart. Regions travel on the {@link Mesh} object itself rather than * through a function of their own, so `readMesh` / `writeMesh` / `convert` * carry them with no extra call. See doc/regions.md. */ export interface Region { name: string; /** * What `entries` indexes: * - `"point"` — point indices, one value per entry. * - `"cell"` — **global** cell indices, block-major (block 0's cells first, * then block 1's, ...), one value per entry. * - `"side"` — `(global cell index, local facet index)` pairs, so `entries` * holds two values per entry. Facets are numbered as meshio++ numbers the * faces of a 3-D cell and the edges of a 2-D one. */ kind: 'point' | 'cell' | 'side'; /** Topological dimension the group was declared for, or -1 if unspecified. */ dim: number; /** Format-native integer id (gmsh physical tag, MED family id), or -1. */ tag: number; /** Flat entries, ascending and de-duplicated. */ entries: Int32Array; } /** * One region's shape, without its entries -- the `readMetadata` counterpart of * {@link Region}. Cheap to enumerate (build a SubModelPart tree, say) without * the cost of loading every entry. */ export interface RegionSummary { name: string; kind: 'point' | 'cell' | 'side'; /** Topological dimension the group was declared for, or -1 if unspecified. */ dim: number; /** Format-native integer id (gmsh physical tag, MED family id), or -1. */ tag: number; /** Number of grouped entities (not the entries themselves). */ numEntries: number; } /** * Parameterized-write options for `writeMesh`/`convert`, all optional -- * unset/empty reproduces the exact write from before v11.2.0. There is * deliberately no gzip level or VTK 4.2/5.1 selector: neither exists as a * `WriteOptions` field on the C++ side (gzip level 4 is a fixed registry * default; `vtk42`/`vtk51` are separate format keys, not a `vtk` option). */ export interface MeshWriteOptions { /** ASCII vs binary. Errors for a format with only one variant. */ encoding?: "ascii" | "binary"; /** Block-compression codec, for the VTK-XML formats (vtu/vtp) only. */ codec?: "none" | "zlib" | "lz4" | "zstd"; /** `printf`-style float format for ASCII writers that take one (e.g. `".16e"`, the default). */ floatFormat?: string; } /** * `writeMesh`'s own options: `MeshWriteOptions` plus `info`, a format's * side-channel metadata to write (see {@link MeshInfo}) -- wins over a * `mesh.info` whose own `format` matches this write's. Given for a format * with no side-channel writer (openfoam/mdpa/ansysinp/unv/gmsh/med are the * writable ones; exodus is read-only) throws naming it. */ export interface MeshWriteOptionsWithInfo extends MeshWriteOptions { info?: MeshInfo; } export interface ConvertOptions extends MeshWriteOptions { /** Explicit input format key, or omit to infer from inPath's extension. */ inFormat?: string; /** Explicit output format key, or omit to infer from outPath's extension. */ outFormat?: string; } /** One cell block's shape, as reported by {@link MeshioPlusPlusModule.readMetadata}. */ export interface MeshMetadataCellBlock { /** meshio++ cell type name, e.g. `"triangle"`, `"tetra10"`. */ type: string; numCells: number; /** 0 for a ragged block, whose rows have no single node count. */ nodesPerCell: number; ragged: boolean; } /** * A file's shape without its heavy arrays -- the result of `readMetadata`. * * `bboxMin`/`bboxMax` are **omitted** rather than null when no bounding box was * computed, so "not computed" cannot be misread as a box at the origin. */ export interface MeshMetadata { numPoints: number; pointDim: number; /** Total across every block. */ numCells: number; cellBlocks: MeshMetadataCellBlock[]; pointDataNames: string[]; cellDataNames: string[]; fieldDataNames: string[]; /** The format that was actually used, whether given or inferred/sniffed. */ format: string; /** * True when the format has no header-only path and the file had to be read * whole. The summary is still correct, just not cheap. */ fellBackToFullRead: boolean; /** * The file's recorded time-series values, empty for a format with no time * concept. This is the count `readMeshSelective`'s `timeStep` may name, so it * is what makes a step request checkable before issuing it. */ timeValues: number[]; /** * The file's named regions, without their entries. Always present -- empty * on a native metadata path (VTU/VTP/XDMF/Gmsh 4.1 today), since none of * those formats currently map regions at all, so this is never a wrong * answer, only cheap where a full read already happened anyway (every * fallback path, and Exodus, which always falls back). */ regions: RegionSummary[]; bboxMin?: number[]; bboxMax?: number[]; } /** * One operation in a {@link MeshioPlusPlusModule.convertSurfaceOps} pipeline. * * Parameters are optional and fall back to the same defaults the Python API * uses; only `op` is required. */ export type OpSpec = | { op: 'quality' } | { op: 'clean'; weld?: boolean; atol?: number; removeOrphans?: boolean; dropDegenerate?: boolean; dropDuplicateCells?: boolean; } | { op: 'smooth'; method?: SmoothMethod; iterations?: number; /** Negative means "this method's own default" (0.5 Laplacian, 0.33 Taubin). */ lambda?: number; mu?: number; fixBoundary?: boolean; } | { op: 'refine'; levels?: number; /** Global (block-major) indices of the cells to refine. */ cells?: number[]; /** Name of a cell or point region to refine. */ region?: string; /** * Scalar `cell_data` array to threshold, with `compare` and `value`. The * comparison is spelled `compare` rather than `op` because `op` is this * union's own discriminant. */ array?: string; compare?: RefineCompare; value?: number; closure?: RefineClosure; recordLevels?: boolean; /** * Attach `refine:cell_id`/`refine:parent_id` -- the persistent * parent/child hierarchy a multigrid caller resolves across the * sequence of meshes it keeps. Also forces `refine:entity` to be * attached even when the closure leaves no hanging node. */ recordHierarchy?: boolean; } | { /** * QEM surface decimation. With no criterion given the pipeline chip * defaults to `ratio: 0.5`. */ op: 'decimate'; /** Fraction of the (triangulated) faces to KEEP, in (0, 1]. */ ratio?: number; targetFaces?: number; maxError?: number; placement?: DecimatePlacement; preserveBoundary?: boolean; preserveFeatures?: boolean; featureAngle?: number; } | { /** Attaches the assignment as `partition:part` cell data. */ op: 'partition'; nparts?: number; method?: PartitionMethod; } | { /** * The planar cross-section through the mesh (slice), in **world** * coordinates: the volume is replaced by the surface where the plane * intersects it, one dimension lower — a genuine, flat, correctly-coloured * section. `mode` is accepted for backward compatibility but ignored (a * cross-section has no "keep side"). */ op: 'section'; point: number[]; normal: number[]; mode?: CropMode; } | { /** * The level set of a scalar `point_data` field (isosurface) — section's * data-driven sibling, and like it a surface one dimension lower. * `component` is negative for the row magnitude. */ op: 'isosurface'; array: string; isovalue: number; component?: number; } | { /** * The gradient, divergence or curl of a `point_data` field. A pure data * step: geometry is untouched and one new array is attached. */ op: 'gradient'; array: string; operator?: GradientOperator; method?: GradientMethod; location?: 'point' | 'cell'; output?: string; component?: number; } | { /** * The Hessian (second derivative) of a scalar `point_data` field -- * `gradient`'s companion one order further, for curvature-based * adaptive refinement. A pure data step: geometry is untouched and * one new (n,9) array is attached. */ op: 'hessian'; array: string; method?: GradientMethod; location?: 'point' | 'cell'; output?: string; } | { /** * The ZZ recovery-based error indicator of a `point_data` field, plus * optional marking. A pure data step: geometry is untouched and the * indicator (and, when `marking` is not `"none"`, the marking) array * is attached. */ op: 'estimateError'; array: string; method?: ErrorMethod; marking?: ErrorMarking; markingValue?: number; output?: string; marked?: string; } | { /** * A regular grid around the mesh. One of the two steps that replace their * input's geometry rather than transforming it: what comes out is a * lattice, not the mesh that went in. Give exactly one of `resolution` and * `cellSize`. */ op: 'voxelize'; resolution?: number[]; cellSize?: number; bounds?: number[]; padding?: number; paddingRelative?: number; fill?: VoxelFill; attachOccupancy?: boolean; maxCells?: number; sign?: SdfSign; } | { /** * A signed distance field: a grid over the mesh's surface, filled. Like * `voxelize` it replaces the geometry — what comes out is the grid, * carrying `sdf:distance`. `structure: 'octree'` refines only near the * surface and sizes itself from `rootResolution`/`maxDepth`, so passing * `resolution` or `cellSize` with it is an error; its output is * 1-irregular (it has hanging nodes). */ op: 'computeSdf'; structure?: SdfStructure; resolution?: number[]; cellSize?: number; bounds?: number[]; padding?: number; paddingRelative?: number; rootResolution?: number; maxDepth?: number; bandCells?: number; recordLevels?: boolean; maxCells?: number; sign?: SdfSign; location?: SdfLocation; band?: number; }; /** Per-operation counters and caveats from a pipeline run. */ export interface OpReport { steps: ({ op: OpSpec['op'] } & Record)[]; warnings: string[]; } /** `gradient`'s differential operator. See doc/gradient.md. */ export type GradientOperator = 'gradient' | 'divergence' | 'curl'; /** Which cells `voxelize` keeps. See doc/voxelize.md. */ export type VoxelFill = 'all' | 'surface' | 'inside'; /** How a signed distance decides which side of the surface a point is on. */ export type SdfSign = 'unsigned' | 'pseudonormal' | 'winding-number'; /** Where a distance is evaluated on a mesh. */ export type SdfLocation = 'corner' | 'center'; /** What to do about a surface that is not watertight. */ export type SdfWatertightCheck = 'off' | 'warn' | 'error'; /** `gradient`'s reconstruction method. See doc/gradient.md. */ export type GradientMethod = 'green-gauss' | 'least-squares'; /** `estimateError`'s estimator family. Only `"zz"` exists today. */ export type ErrorMethod = 'zz'; /** `estimateError`'s marking policy. See doc/error.md. */ export type ErrorMarking = 'none' | 'absolute' | 'fraction' | 'dorfler'; /** `remesh`'s clustering objective. See doc/remesh.md. */ export type RemeshMetric = 'isotropic' | 'quadric' | 'anisotropic'; /** One data array's location: `point_data`, `cell_data`, or `field_data`. */ export type DataLocation = 'point' | 'cell' | 'field'; /** `data_condition`'s transform. See doc/data_condition.md. */ export type ConditionMode = 'clamp' | 'normalize' | 'standardize'; /** `data_condition`'s scope: independent components, or by row magnitude. */ export type ConditionScope = 'component' | 'magnitude'; /** Weighting for `dataCellToPoint`. See doc/data_average.md. */ export type CellPointWeight = 'uniform' | 'measure'; /** What reaches the output for non-finite (NaN/inf) values. They are always * excluded from reductions regardless of this setting. */ export type NanPolicy = 'ignore' | 'replace' | 'fail'; /** `tensorInvariants`' selectable outputs. See doc/tensor_invariants.md. */ export type TensorInvariantOutput = 'mises' | 'principal' | 'hydrostatic' | 'deviatoric'; /** Cell-keeping rule for the crop operations: every node inside, or any. */ export type CropMode = 'all' | 'any'; /** Comparison for `cropPredicate` — the same vocabulary `refine`'s selector uses. */ export type CropCompare = '<' | '<=' | '>' | '>=' | '==' | '!='; /** What `computeSdf` generates to carry the field. */ export type SdfStructure = 'voxel' | 'octree'; /** Partitioning criterion for `split`. */ export type SplitBy = 'type' | 'component' | 'region' | 'tag'; /** Node-renumbering method for `reorder`. */ export type ReorderMethod = 'rcm' | 'morton' | 'hilbert'; /** How `merge` reconciles data arrays that are not present in every input. */ export type MergeDataPolicy = 'intersection' | 'fill'; /** Element-representation conversion performed by `convertCells`. */ export type ConvertCellsMode = 'linearize' | 'simplexify' | 'elevate'; /** Smoothing operator applied by `smooth`. `'taubin'` is shrink-free. * `'odt'` (optimal-Delaunay-triangulation smoothing) is tet-only and * moves each free interior vertex toward the volume-weighted average of * its incident tets' circumcenters. See doc/smooth.md. */ export type SmoothMethod = 'laplacian' | 'taubin' | 'odt'; /** * How `refine` resolves the hanging nodes a partial refinement leaves behind. * `'redgreen'` promotes an affected cell's split-edge mask to the smallest * admissible superset, keeping the extra refinement local. `'propagate'` * promotes it straight to a full split: always conforming and defined for every * cell type, but it converges to uniform refinement of the whole edge-connected * component. */ export type RefineClosure = 'redgreen' | 'green' | 'propagate' | 'red' | 'balanced' | '2:1'; /** The comparison a `refine` predicate selector applies. */ export type RefineCompare = '<' | '<=' | '>' | '>=' | '==' | '!='; /** * Which cells `refine` should split. At most ONE of `cells`, `region` and * `array` may be given; with none, every cell is refined. */ export interface RefineOptions { /** Global (block-major) indices of the cells to refine. */ cells?: number[]; /** * Name of a region to refine. A cell region selects its own cells, a point * region every cell with any node in it; a side region is an error. */ region?: string; /** Name of a scalar `cell_data` array to threshold. */ array?: string; /** The predicate's comparison (default `'<'`). */ compare?: RefineCompare; /** The predicate's right-hand side. A non-finite cell value never matches. */ value?: number; /** How to resolve hanging nodes (default `'redgreen'`). */ closure?: RefineClosure; /** Attach the `refine:level` `cell_data` array. */ recordLevels?: boolean; /** * Attach the `refine:cell_id`/`refine:parent_id` `cell_data` arrays -- the * persistent parent/child hierarchy a multigrid caller resolves across the * sequence of meshes it keeps ("a link between two meshes, not a tree * inside one"): an unsplit cell keeps its id and is its own parent; a * split cell's children each get a fresh id and carry the parent's id. An * input already carrying `refine:cell_id` is updated whatever this says. * Also forces `refine:entity` to be attached even when the closure leaves * no hanging node, since it already records the coarse corners each new * fine node is the mean of -- the multigrid prolongation weights, which * `'redgreen'`/`'propagate'` would otherwise never expose. */ recordHierarchy?: boolean; } /** Where `decimate` places the surviving vertex of a collapsed edge. */ export type DecimatePlacement = 'optimal' | 'midpoint' | 'endpoint'; /** How `interpolate` draws a target sample's value from the source. * `'barycentric'` simplexifies the source first (simplex-linear on quad/hex * sources; triangles evaluated in the xy-plane) and is exact on a linear * field; `'nearest'` copies the nearest source point's value bit-for-bit. */ export type InterpolateMethod = 'nearest' | 'barycentric'; /** What `interpolate` does when a transferred name already exists on the * target: throw, replace, or write to `name + '_interp'`. */ export type InterpolateOnConflict = 'error' | 'overwrite' | 'suffix'; /** What `conservativeInterpolate` does when a transferred name already * exists on the target: throw, replace, or write to `name + '_interp'`. */ export type ConservativeInterpolateOnConflict = 'error' | 'overwrite' | 'suffix'; /** Partitioning backend: SFC is always available; KaHIP is never compiled * into the WASM build, so `'kahip'` always throws and `'auto'` = `'sfc'`. */ export type PartitionMethod = 'sfc' | 'kahip' | 'auto'; /** KaHIP preconfiguration (ignored by the SFC method). */ export type PartitionMode = 'fast' | 'eco' | 'strong'; /** Read-only per-array summary returned by `dataInfo`. See doc/data_info.md. */ export interface DataArrayInfo { location: 'point_data' | 'cell_data' | 'field_data'; name: string; /** numpy-style dtype string, e.g. "f8", "i4". */ dtype: string; shape: number[]; /** cell_data: number of cell blocks; 1 otherwise. */ numBlocks: number; numEntries: number; numComponents: number; numValues: number; /** Over finite values only; NaN when there are none. */ min: number; max: number; mean: number; minPerComponent: number[]; maxPerComponent: number[]; meanPerComponent: number[]; numNan: number; numInf: number; numFinite: number; /** cell_data whose blocks disagree in component count. */ inconsistentBlocks: boolean; } /** Cell-measure-weighted reduction of one array over one set of cells (the * whole mesh, or one named Cell region) -- see `dataIntegrate`. */ export interface FieldIntegralRegion { /** The region's name; absent on the whole-mesh `domain` entry. */ name?: string; /** Cells with a computable measure. */ numCells: number; /** Cells excluded: unmeasurable geometry (ragged, unsupported type, or * degenerate). */ numSkipped: number; /** `sum(value * |measure|)` over cells finite in component k. */ totalPerComponent: number[]; /** `totalPerComponent[k] / domainMeasurePerComponent[k]`, or NaN when that * denominator is zero. */ meanPerComponent: number[]; /** `sum(|measure|)` over cells finite in component k. */ domainMeasurePerComponent: number[]; /** Measurable cells excluded from component k because its value was * non-finite there. */ numNanPerComponent: number[]; } /** One array's field integral, returned by `dataIntegrate` -- * `gradient`'s integration counterpart. See doc/field_integration.md. */ export interface FieldIntegralArray { name: string; numComponents: number; /** The whole-mesh reduction. */ domain: FieldIntegralRegion; /** One independent entry per named Cell region present on the mesh -- a * cell in two regions contributes fully to both, one in none contributes * to neither. */ regions: FieldIntegralRegion[]; } /** Heavy-data layout of a transient XDMF series. */ export type XdmfDataFormat = 'HDF' | 'XML' | 'Binary'; /** * A transient (time-series) XDMF writer: one static grid, then one `` * per time step inside a temporal collection. Created by * {@link MeshioPlusPlusModule.createXdmfTimeSeriesWriter}. * * ## Why this one is a handle and not a function * * Every other binding in this package is a **stateless function** over a plain * mesh object: hand it values, get values back. A series cannot be that, * because its whole point is that the mesh is written **once** and each solve * appends a cheap step -- and because the `.xdmf` light data can only be * written when the collection is complete, since the collection element has to * enclose every step. So the object has to survive between calls. * * The raw embind surface for it is an **opaque integer handle plus free * functions** (`xdmfSeriesCreate`/`...WritePointsCells`/`...WriteData`/ * `...Finalize`/`...NumSteps`/`...Finalized`/`...Free`), deliberately **not** * an embind `class_`, and this object is the wrapper's ergonomic face of it. * The reasons, in order of weight: * * 1. `@meshioplusplus/wasm` never hands JS a live C++ object -- `NDArray`, * `CellBlock` and `Mesh` are all internal, and JS only ever sees plain * objects of typed arrays. An embind `class_` instance would be the one * exception, and would come with an Emscripten-specific `.delete()` that * has no counterpart anywhere else in this API. * 2. Free functions all go through the same C++ error wrapper, so a * `WriteError` arrives as a readable JS `Error`; a bound *member* function * surfaces as a bare, message-less `WebAssembly.Exception`. * 3. It matches the C API (`mio_xdmf_series*`), so the two flat bindings * describe the same object the same way. * * The handle is an index into a module-local table, not a raw pointer: a * stale or forged handle throws an `Error` instead of corrupting linear * memory. * * ## Getting the files out of MEMFS * * Nothing is on the virtual filesystem until `finalize()`/`close()` runs, and * **`'HDF'` produces TWO files**: the `.xdmf` at the path you gave, plus its * sibling heavy-data file `.h5`. Copy both out, and read * them back together -- an `.xdmf` without its `.h5` is unreadable. * * ```js * const w = m.createXdmfTimeSeriesWriter('/series.xdmf'); // 'HDF' by default * w.writePointsCells(mesh); * for (let k = 0; k < 3; ++k) w.writeData(k * 0.5, stepMesh(k)); * w.close(); // the .xdmf appears here * const xdmf = m.FS.readFile('/series.xdmf'); // Uint8Array * const h5 = m.FS.readFile('/series.h5'); // the companion -- do not skip * ``` * * `'XML'` writes one self-contained file and needs no companion; `'Binary'` * writes the `.xdmf` plus one `.bin` per array. */ export interface XdmfTimeSeriesWriter { /** * Write the static grid -- the points and cell blocks every step shares. * Only geometry and connectivity are used; any data on `mesh` is ignored, * because in a series data belongs to a step. Call exactly once, before the * first `writeData`. * @throws {Error} if called twice, on points of dimension > 3, or on a cell * type with no XDMF spelling. */ writePointsCells(mesh: Mesh): void; /** * Append one time step's `point_data` and `cell_data`. The mesh's geometry * is ignored, so a solver can pass the same object it updates in place -- * but its cell-block structure must match the one given to * `writePointsCells`, since cell data is concatenated across blocks. * @param time emitted as the step's `