@matteria-js/volumetric
v0.1.0
Published
Lattice-aware scalar grids for MATTERIA.
Readme
@matteria-js/volumetric
Lattice-aware scalar and vector grids for MATTERIA.
This package currently provides ScalarFieldGrid / VolumetricGrid for charge-density-like scalar data and VectorFieldGrid for interleaved xyz vector data on a 3D grid. It is meant for parsed VASP/QE/CUBE-style data after an IO package has read the file.
Current scope:
Float32ArrayandFloat64Arraystorage.- Cartesian origin, dimensions, and a full-cell lattice or axis-vector basis.
- x-fastest index/value access with an explicit
valueLayoutfield and standalone flat-index helpers. - scalar value units, length-unit metadata, and JSON-friendly grid summaries.
clone(),asDict(), andfromDict().- grid
add(),subtract(), andscale()operations with geometry checks. - integer-factor mean downsampling.
- threshold masks with
Uint8Arraybinary data and finite filled-grid outputs. - masked scalar-field integrals with voxel volume and selected-volume metadata.
- orthogonal axis slices with typed-array data plus plane metadata.
- planar averages for charge-density, potential, ELF, and work-function-style profiles.
- line profiles with nearest or trilinear sampling in fractional or Cartesian coordinates.
VectorFieldGridwith explicitinterleaved-xyzcomponent layout, JSON-friendly summaries, and scalar component/magnitude projections.
Non-goals:
- no Three.js or rendering APIs.
- no file parsing here; CHGCAR/CUBE/etc. parsers belong in
@matteria-js/io. - no GPU volume rendering, meshing, or isosurface extraction yet.
- no DFT solving or charge-density generation.
Example
import { Lattice } from "@matteria-js/core";
import {
VectorFieldGrid,
VolumetricGrid,
gridPointToLinearIndex,
linearIndexToGridPoint,
summarizeGridValueLayout,
} from "@matteria-js/volumetric";
const grid = new VolumetricGrid({
lattice: Lattice.orthorhombic(5, 5, 8),
origin: [0, 0, 0],
dimensions: [64, 64, 96],
data: new Float32Array(64 * 64 * 96),
units: "electron_per_angstrom3",
metadata: { lengthUnit: "angstrom", integralUnits: "electron" },
});
const summary = grid.summary();
const slice = grid.slice("z", 32);
const coarse = grid.downsample([2, 2, 2]);
const mask = grid.createMask({ min: 0.03 });
const selected = grid.masked(mask, { fillValue: 0 });
const integral = grid.integrate({ mask });
const average = grid.planarAverage("z");
const profile = grid.lineProfile({
start: [0, 0, 0],
end: [0, 0, 1],
pointCount: 128,
});
const vectors = new VectorFieldGrid({
lattice: Lattice.orthorhombic(5, 5, 8),
dimensions: [64, 64, 96],
data: new Float32Array(64 * 64 * 96 * 3),
units: "eV/angstrom",
});
const zComponent = vectors.componentGrid("z");
const magnitude = vectors.magnitudeGrid();
const layout = summarizeGridValueLayout(grid.dimensions);
const offset = gridPointToLinearIndex(grid.dimensions, 1, 2, 3);
const point = linearIndexToGridPoint(grid.dimensions, offset);
console.log(summary.valueLayout); // "x-fastest"
console.log(layout.strides); // [1, nx, nx * ny]
console.log(summary.units); // electron_per_angstrom3
console.log(average.values); // Float32Array or Float64Array
console.log(average.distances); // distance along the selected axis
console.log(mask.data); // Uint8Array with 1 for selected voxels
console.log(selected.data); // finite filled scalar grid
console.log(integral.integral, integral.selectedVolume);
console.log(profile.values); // sampled values along the line
console.log(point.fractionalCoordinate); // [i / nx, j / ny, k / nz]
console.log(vectors.summary().componentLayout); // interleaved-xyz
console.log(zComponent.data); // scalar z-component grid
console.log(magnitude.data); // scalar magnitude gridCUBE Bridge
Current CUBE parsing lives in @matteria-js/io. parseCube returns this grid model directly as cube.grid:
const cube = parseCube(cubeText);
const field = cube.grid;@matteria-js/adapters accepts the same scalar-grid shape for slice image data and worker-transfer payloads, so callers can pass a ScalarFieldGrid directly. Vector fields can be projected to scalar component or magnitude grids first when a scalar adapter is needed.
