matterviz 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FilePicker.svelte +37 -20
- package/dist/Icon.svelte +2 -2
- package/dist/MillerIndexInput.svelte +60 -0
- package/dist/MillerIndexInput.svelte.d.ts +7 -0
- package/dist/app.css +38 -2
- package/dist/brillouin/BrillouinZone.svelte +20 -62
- package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
- package/dist/brillouin/BrillouinZoneExportPane.svelte +12 -20
- package/dist/brillouin/BrillouinZoneScene.svelte +2 -2
- package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
- package/dist/chempot-diagram/ChemPotDiagram.svelte +192 -0
- package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +13 -0
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte +677 -0
- package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +16 -0
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte +2688 -0
- package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +16 -0
- package/dist/chempot-diagram/ChemPotScene3D.svelte +8 -0
- package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +7 -0
- package/dist/chempot-diagram/color.d.ts +10 -0
- package/dist/chempot-diagram/color.js +33 -0
- package/dist/chempot-diagram/compute.d.ts +38 -0
- package/dist/chempot-diagram/compute.js +650 -0
- package/dist/chempot-diagram/index.d.ts +5 -0
- package/dist/chempot-diagram/index.js +5 -0
- package/dist/chempot-diagram/pointer.d.ts +16 -0
- package/dist/chempot-diagram/pointer.js +40 -0
- package/dist/chempot-diagram/temperature.d.ts +15 -0
- package/dist/chempot-diagram/temperature.js +37 -0
- package/dist/chempot-diagram/types.d.ts +83 -0
- package/dist/chempot-diagram/types.js +27 -0
- package/dist/colors/index.d.ts +3 -1
- package/dist/colors/index.js +4 -0
- package/dist/composition/BarChart.svelte +13 -22
- package/dist/composition/BubbleChart.svelte +5 -3
- package/dist/composition/FormulaFilter.svelte +770 -90
- package/dist/composition/FormulaFilter.svelte.d.ts +37 -1
- package/dist/composition/PieChart.svelte +43 -18
- package/dist/composition/PieChart.svelte.d.ts +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +2 -0
- package/dist/convex-hull/ConvexHull.svelte +14 -1
- package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull2D.svelte +14 -45
- package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull3D.svelte +396 -134
- package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHull4D.svelte +93 -42
- package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
- package/dist/convex-hull/ConvexHullControls.svelte +94 -31
- package/dist/convex-hull/ConvexHullControls.svelte.d.ts +4 -2
- package/dist/convex-hull/ConvexHullStats.svelte +697 -128
- package/dist/convex-hull/ConvexHullStats.svelte.d.ts +6 -1
- package/dist/convex-hull/ConvexHullTooltip.svelte +1 -0
- package/dist/convex-hull/GasPressureControls.svelte +72 -38
- package/dist/convex-hull/GasPressureControls.svelte.d.ts +2 -1
- package/dist/convex-hull/TemperatureSlider.svelte +46 -19
- package/dist/convex-hull/TemperatureSlider.svelte.d.ts +2 -1
- package/dist/convex-hull/demo-temperature.d.ts +6 -0
- package/dist/convex-hull/demo-temperature.js +36 -0
- package/dist/convex-hull/gas-thermodynamics.js +16 -5
- package/dist/convex-hull/helpers.d.ts +7 -1
- package/dist/convex-hull/helpers.js +45 -15
- package/dist/convex-hull/index.d.ts +15 -1
- package/dist/convex-hull/index.js +1 -0
- package/dist/convex-hull/thermodynamics.d.ts +8 -21
- package/dist/convex-hull/thermodynamics.js +106 -17
- package/dist/convex-hull/types.d.ts +7 -0
- package/dist/convex-hull/types.js +11 -0
- package/dist/coordination/CoordinationBarPlot.svelte +29 -46
- package/dist/element/BohrAtom.svelte +1 -1
- package/dist/element/data.js +2 -14
- package/dist/element/data.json.gz +0 -0
- package/dist/element/index.d.ts +1 -1
- package/dist/element/index.js +1 -0
- package/dist/element/types.d.ts +1 -0
- package/dist/fermi-surface/FermiSurface.svelte +21 -65
- package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte +1 -1
- package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
- package/dist/fermi-surface/compute.js +1 -21
- package/dist/fermi-surface/marching-cubes.d.ts +2 -13
- package/dist/fermi-surface/marching-cubes.js +2 -519
- package/dist/fermi-surface/parse.js +17 -23
- package/dist/heatmap-matrix/HeatmapMatrix.svelte +1273 -0
- package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +110 -0
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +171 -0
- package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +31 -0
- package/dist/heatmap-matrix/index.d.ts +53 -0
- package/dist/heatmap-matrix/index.js +100 -0
- package/dist/heatmap-matrix/shared.d.ts +2 -0
- package/dist/heatmap-matrix/shared.js +4 -0
- package/dist/icons.d.ts +119 -0
- package/dist/icons.js +119 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +6 -1
- package/dist/io/export.js +15 -3
- package/dist/io/file-drop.d.ts +7 -0
- package/dist/io/file-drop.js +43 -0
- package/dist/io/index.d.ts +2 -2
- package/dist/io/index.js +2 -112
- package/dist/io/types.d.ts +1 -0
- package/dist/io/url-drop.d.ts +2 -0
- package/dist/io/url-drop.js +118 -0
- package/dist/isosurface/Isosurface.svelte +231 -0
- package/dist/isosurface/Isosurface.svelte.d.ts +8 -0
- package/dist/isosurface/IsosurfaceControls.svelte +273 -0
- package/dist/isosurface/IsosurfaceControls.svelte.d.ts +9 -0
- package/dist/isosurface/index.d.ts +5 -0
- package/dist/isosurface/index.js +6 -0
- package/dist/isosurface/parse.d.ts +6 -0
- package/dist/isosurface/parse.js +548 -0
- package/dist/isosurface/slice.d.ts +11 -0
- package/dist/isosurface/slice.js +145 -0
- package/dist/isosurface/types.d.ts +55 -0
- package/dist/isosurface/types.js +178 -0
- package/dist/labels.d.ts +2 -1
- package/dist/labels.js +1 -0
- package/dist/layout/InfoTag.svelte +62 -62
- package/dist/layout/SubpageGrid.svelte +74 -0
- package/dist/layout/SubpageGrid.svelte.d.ts +14 -0
- package/dist/layout/index.d.ts +1 -0
- package/dist/layout/index.js +1 -0
- package/dist/layout/json-tree/JsonNode.svelte +226 -53
- package/dist/layout/json-tree/JsonTree.svelte +425 -51
- package/dist/layout/json-tree/JsonTree.svelte.d.ts +1 -1
- package/dist/layout/json-tree/JsonValue.svelte +218 -97
- package/dist/layout/json-tree/types.d.ts +27 -2
- package/dist/layout/json-tree/utils.d.ts +14 -1
- package/dist/layout/json-tree/utils.js +254 -0
- package/dist/marching-cubes.d.ts +14 -0
- package/dist/marching-cubes.js +519 -0
- package/dist/math.d.ts +8 -0
- package/dist/math.js +374 -7
- package/dist/overlays/ContextMenu.svelte +3 -2
- package/dist/overlays/DraggablePane.svelte +163 -58
- package/dist/overlays/DraggablePane.svelte.d.ts +2 -0
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +232 -77
- package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -2
- package/dist/phase-diagram/PhaseDiagramControls.svelte +32 -11
- package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +3 -2
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +103 -0
- package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +15 -0
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte +102 -95
- package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +7 -0
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte +100 -26
- package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +6 -3
- package/dist/phase-diagram/index.d.ts +2 -0
- package/dist/phase-diagram/index.js +2 -0
- package/dist/phase-diagram/svg-to-diagram.d.ts +2 -0
- package/dist/phase-diagram/svg-to-diagram.js +865 -0
- package/dist/phase-diagram/types.d.ts +10 -0
- package/dist/phase-diagram/utils.d.ts +7 -4
- package/dist/phase-diagram/utils.js +149 -59
- package/dist/plot/AxisLabel.svelte +26 -0
- package/dist/plot/AxisLabel.svelte.d.ts +16 -0
- package/dist/plot/BarPlot.svelte +473 -228
- package/dist/plot/BarPlot.svelte.d.ts +3 -3
- package/dist/plot/BarPlotControls.svelte +3 -2
- package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ColorBar.svelte +54 -54
- package/dist/plot/ColorBar.svelte.d.ts +1 -1
- package/dist/plot/ElementScatter.svelte +4 -3
- package/dist/plot/FillArea.svelte +4 -1
- package/dist/plot/Histogram.svelte +320 -230
- package/dist/plot/Histogram.svelte.d.ts +2 -2
- package/dist/plot/HistogramControls.svelte +29 -10
- package/dist/plot/HistogramControls.svelte.d.ts +6 -2
- package/dist/plot/InteractiveAxisLabel.svelte.d.ts +2 -2
- package/dist/plot/PlotControls.svelte +109 -27
- package/dist/plot/PlotControls.svelte.d.ts +1 -1
- package/dist/plot/PlotLegend.svelte +1 -1
- package/dist/plot/PortalSelect.svelte +2 -1
- package/dist/plot/ReferenceLine.svelte +2 -1
- package/dist/plot/ReferenceLine.svelte.d.ts +1 -0
- package/dist/plot/ReferencePlane.svelte +1 -3
- package/dist/plot/ScatterPlot.svelte +343 -209
- package/dist/plot/ScatterPlot.svelte.d.ts +3 -3
- package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlot3DControls.svelte +203 -250
- package/dist/plot/ScatterPlot3DScene.svelte +4 -7
- package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
- package/dist/plot/ScatterPlotControls.svelte +95 -55
- package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
- package/dist/plot/ZeroLines.svelte +44 -0
- package/dist/plot/ZeroLines.svelte.d.ts +32 -0
- package/dist/plot/ZoomRect.svelte +21 -0
- package/dist/plot/ZoomRect.svelte.d.ts +8 -0
- package/dist/plot/axis-utils.d.ts +1 -1
- package/dist/plot/data-cleaning.js +1 -5
- package/dist/plot/index.d.ts +6 -2
- package/dist/plot/index.js +6 -2
- package/dist/plot/interactions.d.ts +8 -10
- package/dist/plot/interactions.js +10 -19
- package/dist/plot/layout.d.ts +7 -1
- package/dist/plot/layout.js +12 -4
- package/dist/plot/reference-line.d.ts +4 -21
- package/dist/plot/reference-line.js +7 -81
- package/dist/plot/types.d.ts +42 -17
- package/dist/plot/types.js +10 -0
- package/dist/plot/utils/label-placement.js +14 -11
- package/dist/plot/utils.d.ts +1 -0
- package/dist/plot/utils.js +14 -0
- package/dist/rdf/RdfPlot.svelte +55 -66
- package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
- package/dist/rdf/index.d.ts +1 -1
- package/dist/rdf/index.js +1 -1
- package/dist/settings.d.ts +5 -0
- package/dist/settings.js +37 -3
- package/dist/spectral/Bands.svelte +515 -143
- package/dist/spectral/Bands.svelte.d.ts +22 -2
- package/dist/spectral/helpers.d.ts +23 -1
- package/dist/spectral/helpers.js +65 -9
- package/dist/spectral/types.d.ts +2 -0
- package/dist/structure/AtomLegend.svelte +31 -10
- package/dist/structure/AtomLegend.svelte.d.ts +1 -1
- package/dist/structure/CellSelect.svelte +92 -22
- package/dist/structure/Lattice.svelte +2 -0
- package/dist/structure/Structure.svelte +716 -173
- package/dist/structure/Structure.svelte.d.ts +7 -2
- package/dist/structure/StructureControls.svelte +26 -14
- package/dist/structure/StructureControls.svelte.d.ts +5 -1
- package/dist/structure/StructureInfoPane.svelte +7 -1
- package/dist/structure/StructureScene.svelte +386 -95
- package/dist/structure/StructureScene.svelte.d.ts +15 -4
- package/dist/structure/atom-properties.d.ts +6 -2
- package/dist/structure/atom-properties.js +38 -25
- package/dist/structure/export.js +10 -7
- package/dist/structure/ferrox-wasm-types.d.ts +3 -2
- package/dist/structure/ferrox-wasm-types.js +0 -3
- package/dist/structure/ferrox-wasm.d.ts +3 -2
- package/dist/structure/ferrox-wasm.js +1 -2
- package/dist/structure/index.d.ts +7 -0
- package/dist/structure/index.js +22 -0
- package/dist/structure/parse.js +19 -16
- package/dist/structure/partial-occupancy.d.ts +25 -0
- package/dist/structure/partial-occupancy.js +102 -0
- package/dist/structure/validation.js +6 -3
- package/dist/symmetry/SymmetryStats.svelte +18 -4
- package/dist/symmetry/WyckoffTable.svelte +18 -10
- package/dist/symmetry/index.d.ts +7 -4
- package/dist/symmetry/index.js +83 -18
- package/dist/table/HeatmapTable.svelte +468 -69
- package/dist/table/HeatmapTable.svelte.d.ts +13 -1
- package/dist/table/ToggleMenu.svelte +291 -44
- package/dist/table/ToggleMenu.svelte.d.ts +4 -1
- package/dist/table/index.d.ts +3 -0
- package/dist/tooltip/index.d.ts +1 -1
- package/dist/tooltip/index.js +1 -0
- package/dist/trajectory/Trajectory.svelte +147 -145
- package/dist/trajectory/TrajectoryExportPane.svelte +13 -9
- package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +1 -1
- package/dist/trajectory/constants.d.ts +6 -0
- package/dist/trajectory/constants.js +7 -0
- package/dist/trajectory/extract.js +3 -5
- package/dist/trajectory/format-detect.d.ts +9 -0
- package/dist/trajectory/format-detect.js +76 -0
- package/dist/trajectory/frame-reader.d.ts +17 -0
- package/dist/trajectory/frame-reader.js +339 -0
- package/dist/trajectory/helpers.d.ts +15 -0
- package/dist/trajectory/helpers.js +187 -0
- package/dist/trajectory/index.d.ts +1 -0
- package/dist/trajectory/index.js +11 -4
- package/dist/trajectory/parse/ase.d.ts +2 -0
- package/dist/trajectory/parse/ase.js +76 -0
- package/dist/trajectory/parse/hdf5.d.ts +2 -0
- package/dist/trajectory/parse/hdf5.js +121 -0
- package/dist/trajectory/parse/index.d.ts +12 -0
- package/dist/trajectory/parse/index.js +304 -0
- package/dist/trajectory/parse/lammps.d.ts +5 -0
- package/dist/trajectory/parse/lammps.js +169 -0
- package/dist/trajectory/parse/vasp.d.ts +2 -0
- package/dist/trajectory/parse/vasp.js +65 -0
- package/dist/trajectory/parse/xyz.d.ts +2 -0
- package/dist/trajectory/parse/xyz.js +109 -0
- package/dist/trajectory/types.d.ts +11 -0
- package/dist/trajectory/types.js +1 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +4 -0
- package/dist/xrd/XrdPlot.svelte +6 -4
- package/dist/xrd/calc-xrd.js +0 -1
- package/package.json +33 -23
- package/readme.md +4 -4
- package/dist/trajectory/parse.d.ts +0 -42
- package/dist/trajectory/parse.js +0 -1267
- /package/dist/element/{data.json.d.ts → data.json.gz.d.ts} +0 -0
|
@@ -4,7 +4,12 @@ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
|
|
|
4
4
|
phase_stats: PhaseStats | null;
|
|
5
5
|
stable_entries: ConvexHullEntry[];
|
|
6
6
|
unstable_entries: ConvexHullEntry[];
|
|
7
|
+
layout?: `toggle` | `side-by-side`;
|
|
8
|
+
on_entry_click?: (entry: ConvexHullEntry) => void;
|
|
9
|
+
highlighted_entry_id?: string;
|
|
10
|
+
min_n_elements?: number;
|
|
11
|
+
entry_href?: (entry: ConvexHullEntry) => string | null;
|
|
7
12
|
};
|
|
8
|
-
declare const ConvexHullStats: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
13
|
+
declare const ConvexHullStats: import("svelte").Component<$$ComponentProps, {}, "min_n_elements">;
|
|
9
14
|
type ConvexHullStats = ReturnType<typeof ConvexHullStats>;
|
|
10
15
|
export default ConvexHullStats;
|
|
@@ -1,55 +1,70 @@
|
|
|
1
1
|
<script lang="ts">import { tooltip } from 'svelte-multiselect';
|
|
2
2
|
import { compute_gas_chemical_potential, format_chemical_potential, get_default_gas_provider, get_effective_pressures, } from './gas-thermodynamics';
|
|
3
|
-
let { config, pressures = $bindable({}), temperature, position = `top-right`, } = $props();
|
|
3
|
+
let { config, pressures = $bindable({}), temperature, position = `top-right`, ...rest } = $props();
|
|
4
4
|
// Log scale range for pressure slider: 10^-10 to 10^2 bar
|
|
5
5
|
const LOG_P_MIN = -10;
|
|
6
6
|
const LOG_P_MAX = 2;
|
|
7
7
|
const LOG_P_RANGE = LOG_P_MAX - LOG_P_MIN;
|
|
8
8
|
const MIN_PRESSURE = 1e-15; // Safe minimum to avoid log(0) or NaN
|
|
9
|
+
const THROTTLE_MS = 100;
|
|
10
|
+
// Local preview state for smooth slider interaction without causing full hull re-renders
|
|
11
|
+
let preview_pressures = $state({});
|
|
12
|
+
let last_update_time = 0;
|
|
9
13
|
// Get provider for chemical potential calculations
|
|
10
14
|
const provider = $derived(config.provider ?? get_default_gas_provider());
|
|
11
15
|
// Get enabled gases from config
|
|
12
16
|
const enabled_gases = $derived(config.enabled_gases ?? []);
|
|
13
17
|
// Effective pressures including defaults
|
|
14
18
|
const effective_pressures = $derived(get_effective_pressures(config));
|
|
15
|
-
// Get current pressure for a gas (
|
|
19
|
+
// Get current pressure for a gas (preview during drag, committed, or default)
|
|
16
20
|
function get_pressure(gas) {
|
|
17
|
-
const P = pressures[gas] ?? effective_pressures[gas];
|
|
21
|
+
const P = preview_pressures[gas] ?? pressures[gas] ?? effective_pressures[gas];
|
|
18
22
|
return Number.isFinite(P) && P > 0 ? P : MIN_PRESSURE;
|
|
19
23
|
}
|
|
20
24
|
// Compute chemical potential μ(T,P) for a gas at current temperature and pressure
|
|
21
|
-
|
|
22
|
-
return compute_gas_chemical_potential(provider, gas, temperature, get_pressure(gas));
|
|
23
|
-
}
|
|
25
|
+
const get_mu = (gas) => compute_gas_chemical_potential(provider, gas, temperature, get_pressure(gas));
|
|
24
26
|
// Convert pressure to log scale slider position (0-100)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return ((Math.max(LOG_P_MIN, Math.min(LOG_P_MAX, log_P)) - LOG_P_MIN) /
|
|
28
|
-
LOG_P_RANGE) * 100;
|
|
29
|
-
}
|
|
27
|
+
const pressure_to_slider = (P) => ((Math.max(LOG_P_MIN, Math.min(LOG_P_MAX, Math.log10(P))) - LOG_P_MIN) /
|
|
28
|
+
LOG_P_RANGE) * 100;
|
|
30
29
|
// Convert slider position (0-100) to pressure
|
|
31
|
-
|
|
32
|
-
const log_P = LOG_P_MIN + (value / 100) * LOG_P_RANGE;
|
|
33
|
-
return Math.pow(10, log_P);
|
|
34
|
-
}
|
|
30
|
+
const slider_to_pressure = (value) => Math.pow(10, LOG_P_MIN + (value / 100) * LOG_P_RANGE);
|
|
35
31
|
// Format gas name for display (subscript numbers)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const log_P = Math.log10(P), exp = Math.round(log_P); // P already normalized
|
|
32
|
+
const format_gas_name = (gas) => gas.replace(/(\d+)/g, `<sub>$1</sub>`);
|
|
33
|
+
// Format pressure as plain text (no HTML) for the number input
|
|
34
|
+
function format_pressure(P) {
|
|
35
|
+
const log_P = Math.log10(P);
|
|
36
|
+
const exp = Math.round(log_P);
|
|
42
37
|
if (Math.abs(log_P - exp) < 0.1)
|
|
43
|
-
return `
|
|
44
|
-
|
|
38
|
+
return `1e${exp}`;
|
|
39
|
+
if (P >= 0.01 && P < 100)
|
|
40
|
+
return P.toPrecision(2);
|
|
41
|
+
return P.toExponential(1);
|
|
45
42
|
}
|
|
46
43
|
function set_pressure(gas, value) {
|
|
47
|
-
|
|
44
|
+
const P = slider_to_pressure(value);
|
|
45
|
+
preview_pressures = { ...preview_pressures, [gas]: P };
|
|
46
|
+
// Throttle parent updates during drag to prevent hull recomputation on every pixel
|
|
47
|
+
const now = Date.now();
|
|
48
|
+
if (now - last_update_time >= THROTTLE_MS) {
|
|
49
|
+
last_update_time = now;
|
|
50
|
+
pressures = { ...pressures, [gas]: P };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function handle_slider_end(gas, event) {
|
|
54
|
+
const P = slider_to_pressure(+event.currentTarget.value);
|
|
55
|
+
pressures = { ...pressures, [gas]: P };
|
|
56
|
+
// Clear only this gas's preview (don't reset other sliders being dragged simultaneously)
|
|
57
|
+
const { [gas]: _, ...rest } = preview_pressures;
|
|
58
|
+
preview_pressures = rest;
|
|
59
|
+
}
|
|
60
|
+
function set_pressure_direct(gas, value) {
|
|
61
|
+
const clamped = Math.max(Math.pow(10, LOG_P_MIN), Math.min(Math.pow(10, LOG_P_MAX), value));
|
|
62
|
+
pressures = { ...pressures, [gas]: clamped };
|
|
48
63
|
}
|
|
49
64
|
</script>
|
|
50
65
|
|
|
51
66
|
{#if enabled_gases.length > 0}
|
|
52
|
-
<div class="pressure-controls {position}">
|
|
67
|
+
<div {...rest} class="pressure-controls {position} {rest.class ?? ``}">
|
|
53
68
|
{#each enabled_gases as gas (gas)}
|
|
54
69
|
{@const P = get_pressure(gas)}
|
|
55
70
|
{@const mu = get_mu(gas)}
|
|
@@ -61,12 +76,21 @@ function set_pressure(gas, value) {
|
|
|
61
76
|
}`,
|
|
62
77
|
})}
|
|
63
78
|
>
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
79
|
+
<label class="pressure-label">
|
|
80
|
+
<input
|
|
81
|
+
type="text"
|
|
82
|
+
class="pressure-input"
|
|
83
|
+
value={format_pressure(P)}
|
|
84
|
+
onchange={(evt) => {
|
|
85
|
+
const val = Number(evt.currentTarget.value)
|
|
86
|
+
if (Number.isFinite(val) && val > 0) set_pressure_direct(gas, val)
|
|
87
|
+
else evt.currentTarget.value = format_pressure(P)
|
|
88
|
+
}}
|
|
89
|
+
aria-label="{gas} pressure (bar)"
|
|
90
|
+
/>
|
|
67
91
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
68
92
|
<span class="gas-name">{@html format_gas_name(gas)}</span>
|
|
69
|
-
</
|
|
93
|
+
</label>
|
|
70
94
|
<div class="slider-wrapper">
|
|
71
95
|
<span class="pressure-range">
|
|
72
96
|
10<sup>{LOG_P_MIN}</sup>–10<sup>{LOG_P_MAX}</sup>
|
|
@@ -78,6 +102,9 @@ function set_pressure(gas, value) {
|
|
|
78
102
|
step="0.5"
|
|
79
103
|
value={pressure_to_slider(P)}
|
|
80
104
|
oninput={(evt) => set_pressure(gas, +evt.currentTarget.value)}
|
|
105
|
+
onchange={(evt) => handle_slider_end(gas, evt)}
|
|
106
|
+
onmouseup={(evt) => handle_slider_end(gas, evt)}
|
|
107
|
+
ontouchend={(evt) => handle_slider_end(gas, evt)}
|
|
81
108
|
aria-label="{gas} partial pressure"
|
|
82
109
|
/>
|
|
83
110
|
</div>
|
|
@@ -126,16 +153,17 @@ function set_pressure(gas, value) {
|
|
|
126
153
|
.pressure-slider {
|
|
127
154
|
display: flex;
|
|
128
155
|
flex-direction: column;
|
|
129
|
-
align-items: center;
|
|
156
|
+
align-items: var(--pressure-slider-align, center);
|
|
130
157
|
gap: 4px;
|
|
131
158
|
background: color-mix(in srgb, var(--hull-bg, transparent) 80%, transparent);
|
|
132
|
-
padding:
|
|
133
|
-
border-radius: var(--border-radius,
|
|
134
|
-
backdrop-filter: blur(
|
|
159
|
+
padding: 3px 5px;
|
|
160
|
+
border-radius: var(--border-radius, 6pt);
|
|
161
|
+
backdrop-filter: blur(2px);
|
|
135
162
|
}
|
|
136
163
|
.slider-wrapper {
|
|
137
164
|
display: flex;
|
|
138
165
|
place-items: center;
|
|
166
|
+
justify-content: var(--slider-justify, center);
|
|
139
167
|
line-height: 1;
|
|
140
168
|
}
|
|
141
169
|
.pressure-slider input[type='range'] {
|
|
@@ -145,13 +173,19 @@ function set_pressure(gas, value) {
|
|
|
145
173
|
.pressure-label {
|
|
146
174
|
display: flex;
|
|
147
175
|
align-items: center;
|
|
148
|
-
gap:
|
|
176
|
+
gap: 2px;
|
|
149
177
|
}
|
|
150
|
-
.pressure-
|
|
151
|
-
|
|
178
|
+
.pressure-input {
|
|
179
|
+
width: 5.5ch;
|
|
180
|
+
border: 1px solid color-mix(in srgb, currentColor 5%, transparent);
|
|
181
|
+
border-radius: 3px;
|
|
182
|
+
background: transparent;
|
|
183
|
+
text-align: center;
|
|
152
184
|
}
|
|
153
|
-
.pressure-
|
|
154
|
-
|
|
185
|
+
.pressure-input::-webkit-outer-spin-button,
|
|
186
|
+
.pressure-input::-webkit-inner-spin-button {
|
|
187
|
+
-webkit-appearance: none;
|
|
188
|
+
margin: 0;
|
|
155
189
|
}
|
|
156
190
|
.gas-name {
|
|
157
191
|
font-size: 0.9em;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { GasControlPosition, GasSpecies, GasThermodynamicsConfig } from './types';
|
|
2
|
-
type
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
|
|
3
4
|
config: GasThermodynamicsConfig;
|
|
4
5
|
pressures: Partial<Record<GasSpecies, number>>;
|
|
5
6
|
temperature: number;
|
|
@@ -1,15 +1,36 @@
|
|
|
1
1
|
<script lang="ts">import { tooltip } from 'svelte-multiselect';
|
|
2
|
-
let { available_temperatures, temperature = $bindable(), } = $props();
|
|
2
|
+
let { available_temperatures, temperature = $bindable(), ...rest } = $props();
|
|
3
|
+
// Local preview state for smooth slider interaction without causing full re-renders
|
|
4
|
+
let preview_index = $state(null);
|
|
5
|
+
let last_update_time = 0;
|
|
6
|
+
const THROTTLE_MS = 100;
|
|
3
7
|
const temp_index = $derived(Math.max(0, available_temperatures.indexOf(temperature)));
|
|
4
|
-
const
|
|
5
|
-
|
|
8
|
+
const display_index = $derived(preview_index ?? temp_index);
|
|
9
|
+
const display_temp = $derived(available_temperatures[display_index] ?? temperature);
|
|
10
|
+
function handle_slider_input(event) {
|
|
11
|
+
const new_index = +event.currentTarget.value;
|
|
12
|
+
preview_index = new_index;
|
|
13
|
+
// Throttle parent updates during drag to prevent scene flashing
|
|
14
|
+
const now = Date.now();
|
|
15
|
+
if (now - last_update_time >= THROTTLE_MS) {
|
|
16
|
+
last_update_time = now;
|
|
17
|
+
temperature = available_temperatures[new_index] ?? temperature;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function handle_slider_end(event) {
|
|
21
|
+
const new_temp = available_temperatures[+event.currentTarget.value];
|
|
22
|
+
if (new_temp !== undefined)
|
|
23
|
+
temperature = new_temp;
|
|
24
|
+
preview_index = null;
|
|
25
|
+
}
|
|
6
26
|
function set_closest_temp(value) {
|
|
7
27
|
temperature = available_temperatures.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev), temperature);
|
|
8
28
|
}
|
|
9
29
|
</script>
|
|
10
30
|
|
|
11
31
|
<div
|
|
12
|
-
|
|
32
|
+
{...rest}
|
|
33
|
+
class="temperature-slider {rest.class ?? ``}"
|
|
13
34
|
{@attach tooltip({ content: `Temperature for G(T) free energies` })}
|
|
14
35
|
>
|
|
15
36
|
<label class="temp-label">
|
|
@@ -24,21 +45,24 @@ function set_closest_temp(value) {
|
|
|
24
45
|
/>
|
|
25
46
|
<span>K</span>
|
|
26
47
|
</label>
|
|
27
|
-
|
|
28
|
-
|
|
48
|
+
{#if available_temperatures.length > 0}
|
|
49
|
+
<div class="slider-wrapper">
|
|
29
50
|
<span class="temp-range">
|
|
30
51
|
{available_temperatures[0]}–{available_temperatures.at(-1)} K
|
|
31
52
|
</span>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
53
|
+
<input
|
|
54
|
+
type="range"
|
|
55
|
+
min="0"
|
|
56
|
+
max={available_temperatures.length - 1}
|
|
57
|
+
value={display_index}
|
|
58
|
+
oninput={handle_slider_input}
|
|
59
|
+
onchange={handle_slider_end}
|
|
60
|
+
onmouseup={handle_slider_end}
|
|
61
|
+
ontouchend={handle_slider_end}
|
|
62
|
+
aria-label="Temperature (Kelvin)"
|
|
63
|
+
/>
|
|
64
|
+
</div>
|
|
65
|
+
{/if}
|
|
42
66
|
</div>
|
|
43
67
|
|
|
44
68
|
<style>
|
|
@@ -46,18 +70,21 @@ function set_closest_temp(value) {
|
|
|
46
70
|
position: absolute;
|
|
47
71
|
top: calc(1ex + 50px);
|
|
48
72
|
right: 1ex;
|
|
73
|
+
z-index: 2;
|
|
74
|
+
pointer-events: auto;
|
|
49
75
|
display: flex;
|
|
50
76
|
flex-direction: column;
|
|
51
77
|
align-items: center;
|
|
52
78
|
gap: 4px;
|
|
53
79
|
background: color-mix(in srgb, var(--hull-bg, transparent) 80%, transparent);
|
|
54
|
-
padding:
|
|
55
|
-
border-radius: var(--border-radius,
|
|
56
|
-
backdrop-filter: blur(
|
|
80
|
+
padding: 3px 5px;
|
|
81
|
+
border-radius: var(--border-radius, 6pt);
|
|
82
|
+
backdrop-filter: blur(2px);
|
|
57
83
|
}
|
|
58
84
|
.slider-wrapper {
|
|
59
85
|
display: flex;
|
|
60
86
|
place-items: center;
|
|
87
|
+
justify-content: var(--slider-justify, center);
|
|
61
88
|
line-height: 1;
|
|
62
89
|
}
|
|
63
90
|
.temperature-slider input[type='range'] {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { PhaseData } from './types';
|
|
2
|
+
export declare const demo_temperatures: number[];
|
|
3
|
+
type Composition = Record<string, number>;
|
|
4
|
+
export declare function make_demo_phase(composition: Composition, seed: number, entropy_boost?: number): PhaseData;
|
|
5
|
+
export declare function create_temp_ternary_entries_li_fe_o(): PhaseData[];
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const demo_temperatures = Array.from({ length: 13 }, (_, idx) => 300 + idx * 100);
|
|
2
|
+
function seeded_random(seed) {
|
|
3
|
+
const x_val = Math.sin(seed * 9999) * 10000;
|
|
4
|
+
return x_val - Math.floor(x_val);
|
|
5
|
+
}
|
|
6
|
+
export function make_demo_phase(composition, seed, entropy_boost = 0) {
|
|
7
|
+
const n_elements = Object.keys(composition).length;
|
|
8
|
+
const energy = -0.3 * n_elements - seeded_random(seed) * 0.5;
|
|
9
|
+
const entropy_coef = 0.5 + n_elements * 0.3 + seeded_random(seed + 1) * 2 +
|
|
10
|
+
entropy_boost;
|
|
11
|
+
return {
|
|
12
|
+
composition,
|
|
13
|
+
energy,
|
|
14
|
+
temperatures: demo_temperatures,
|
|
15
|
+
free_energies: demo_temperatures.map((temp_kelvin) => energy + entropy_coef * temp_kelvin * 0.0001 -
|
|
16
|
+
0.00005 * temp_kelvin * Math.log(temp_kelvin)),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export function create_temp_ternary_entries_li_fe_o() {
|
|
20
|
+
return [
|
|
21
|
+
...[`Li`, `Fe`, `O`].map((element, idx) => make_demo_phase({ [element]: 1 }, idx)),
|
|
22
|
+
...[[`Li`, `Fe`], [`Li`, `O`], [`Fe`, `O`]].flatMap(([element_a, element_b], idx) => [0.33, 0.5, 0.67].flatMap((fraction, jdx) => [
|
|
23
|
+
make_demo_phase({ [element_a]: fraction, [element_b]: 1 - fraction }, 100 + idx * 10 + jdx),
|
|
24
|
+
make_demo_phase({ [element_a]: fraction, [element_b]: 1 - fraction }, 200 + idx * 10 + jdx, 3),
|
|
25
|
+
])),
|
|
26
|
+
...[
|
|
27
|
+
{ Li: 0.33, Fe: 0.33, O: 0.34 },
|
|
28
|
+
{ Li: 0.5, Fe: 0.25, O: 0.25 },
|
|
29
|
+
{ Li: 0.25, Fe: 0.5, O: 0.25 },
|
|
30
|
+
{ Li: 0.25, Fe: 0.25, O: 0.5 },
|
|
31
|
+
].flatMap((composition, idx) => [
|
|
32
|
+
make_demo_phase(composition, 300 + idx),
|
|
33
|
+
make_demo_phase(composition, 400 + idx, 4),
|
|
34
|
+
]),
|
|
35
|
+
];
|
|
36
|
+
}
|
|
@@ -146,7 +146,8 @@ export function compute_gas_chemical_potential(provider, gas, T, P) {
|
|
|
146
146
|
// μ_per_atom(T, P) = μ°_per_atom(T) + k_B·T·ln(P/P₀) / num_atoms
|
|
147
147
|
// The RT·ln(P) term must be divided by num_atoms to match PIRO's per-atom convention
|
|
148
148
|
const num_atoms = GAS_NUM_ATOMS[gas];
|
|
149
|
-
return mu_standard +
|
|
149
|
+
return mu_standard +
|
|
150
|
+
(R_EV_PER_K * T * Math.log(effective_P / P_REF)) / num_atoms;
|
|
150
151
|
}
|
|
151
152
|
// Compute chemical potential per atom of a specific element from a gas
|
|
152
153
|
// Since compute_gas_chemical_potential returns per-atom of gas molecule,
|
|
@@ -178,7 +179,10 @@ export function analyze_gas_data(entries, config) {
|
|
|
178
179
|
};
|
|
179
180
|
}
|
|
180
181
|
// Get element-to-gas mapping
|
|
181
|
-
const element_to_gas = {
|
|
182
|
+
const element_to_gas = {
|
|
183
|
+
...DEFAULT_ELEMENT_TO_GAS,
|
|
184
|
+
...config.element_to_gas,
|
|
185
|
+
};
|
|
182
186
|
// Find all elements in the chemical system
|
|
183
187
|
const all_elements = new Set();
|
|
184
188
|
for (const entry of entries) {
|
|
@@ -226,7 +230,10 @@ export function get_effective_pressures(config) {
|
|
|
226
230
|
// This shifts the formation energy based on the gas atmosphere.
|
|
227
231
|
export function compute_gas_correction(entry, config, T, pressures) {
|
|
228
232
|
const provider = config.provider ?? get_default_gas_provider();
|
|
229
|
-
const element_to_gas = {
|
|
233
|
+
const element_to_gas = {
|
|
234
|
+
...DEFAULT_ELEMENT_TO_GAS,
|
|
235
|
+
...config.element_to_gas,
|
|
236
|
+
};
|
|
230
237
|
const enabled_gases = new Set(config.enabled_gases ?? []);
|
|
231
238
|
let correction = 0;
|
|
232
239
|
const n_atoms = count_atoms_in_composition(entry.composition);
|
|
@@ -280,10 +287,14 @@ export function apply_gas_corrections(entries, config, T) {
|
|
|
280
287
|
// If no correction needed, return entry unchanged
|
|
281
288
|
if (Math.abs(correction) < 1e-12)
|
|
282
289
|
return entry;
|
|
283
|
-
// Apply correction to energy
|
|
290
|
+
// Apply correction to energy (update both energy and energy_per_atom
|
|
291
|
+
// so downstream formation energy calculations use the corrected value)
|
|
292
|
+
// Both fields store per-atom values, and correction is also per-atom
|
|
293
|
+
const corrected_energy = entry.energy + correction;
|
|
284
294
|
return {
|
|
285
295
|
...entry,
|
|
286
|
-
energy:
|
|
296
|
+
energy: corrected_energy,
|
|
297
|
+
energy_per_atom: corrected_energy,
|
|
287
298
|
};
|
|
288
299
|
});
|
|
289
300
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type D3InterpolateName } from '../colors';
|
|
2
2
|
import type { EnergyModeInfo } from './';
|
|
3
|
+
import type { ElementSymbol } from '../element';
|
|
3
4
|
import type { ConvexHullConfig, GasAnalysis, GasThermodynamicsConfig, HighlightStyle, MarkerSymbol, PhaseData } from './types';
|
|
4
5
|
import { DEFAULT_GAS_TEMP } from './types';
|
|
5
6
|
export { DEFAULT_GAS_TEMP };
|
|
@@ -86,3 +87,8 @@ export declare function get_gas_corrected_entries(entries: PhaseData[], gas_conf
|
|
|
86
87
|
analysis: GasAnalysis;
|
|
87
88
|
merged_config: GasThermodynamicsConfig | undefined;
|
|
88
89
|
};
|
|
90
|
+
export declare function get_entry_label(entry: {
|
|
91
|
+
reduced_formula?: string;
|
|
92
|
+
name?: string;
|
|
93
|
+
composition: Record<string, number>;
|
|
94
|
+
}, elements?: ElementSymbol[]): string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { get_d3_interpolator } from '../colors';
|
|
1
2
|
import { ELEM_SYMBOL_TO_NAME } from '../composition';
|
|
2
3
|
import { format_fractional, format_num, symbol_map } from '../labels';
|
|
3
4
|
import { scaleSequential } from 'd3-scale';
|
|
4
|
-
import * as d3_sc from 'd3-scale-chromatic';
|
|
5
5
|
import { symbol } from 'd3-shape';
|
|
6
6
|
import { analyze_gas_data as _analyze_gas_data, apply_gas_corrections as _apply_gas_corrections, } from './gas-thermodynamics';
|
|
7
7
|
import { DEFAULT_GAS_TEMP, is_unary_entry } from './types';
|
|
@@ -18,9 +18,7 @@ export function get_energy_color_scale(color_mode, color_scale, plot_entries) {
|
|
|
18
18
|
const lo = Math.min(...hull_distances);
|
|
19
19
|
const hi_raw = Math.max(...hull_distances, 0.1);
|
|
20
20
|
const hi = Math.max(hi_raw, lo + 1e-6);
|
|
21
|
-
|
|
22
|
-
const interpolator = d3_sc[color_scale] ||
|
|
23
|
-
d3_sc.interpolateViridis;
|
|
21
|
+
const interpolator = get_d3_interpolator(color_scale);
|
|
24
22
|
return scaleSequential(interpolator).domain([lo, hi]);
|
|
25
23
|
}
|
|
26
24
|
// Point color resolver (shared)
|
|
@@ -59,7 +57,8 @@ export function calc_max_hull_dist_in_data(processed_entries) {
|
|
|
59
57
|
const hull_distances = processed_entries
|
|
60
58
|
.map((e) => e.e_above_hull)
|
|
61
59
|
.filter((v) => typeof v === `number` && Number.isFinite(v));
|
|
62
|
-
const max_val = (hull_distances.length ? Math.max(...hull_distances) : 0) +
|
|
60
|
+
const max_val = (hull_distances.length ? Math.max(...hull_distances) : 0) +
|
|
61
|
+
0.001;
|
|
63
62
|
return Math.max(0.1, max_val);
|
|
64
63
|
}
|
|
65
64
|
// Smart threshold for showing unstable entries based on entry count.
|
|
@@ -89,8 +88,9 @@ export function build_entry_tooltip_text(entry) {
|
|
|
89
88
|
const fractions = Object.entries(entry.composition)
|
|
90
89
|
.filter(([, amt]) => amt > 0)
|
|
91
90
|
.map(([el, amt]) => `${el}: ${format_fractional(amt / total)}`);
|
|
92
|
-
if (fractions.length > 1)
|
|
91
|
+
if (fractions.length > 1) {
|
|
93
92
|
text += `Composition: ${fractions.join(`, `)}\n`;
|
|
93
|
+
}
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
if (entry.e_above_hull !== undefined) {
|
|
@@ -122,7 +122,8 @@ export function find_hull_entry_at_mouse(canvas, event, plot_entries, project_po
|
|
|
122
122
|
continue;
|
|
123
123
|
const projected = project_point(entry.x, entry.y, entry.z);
|
|
124
124
|
const distance = Math.hypot(mouse_x - projected.x, mouse_y - projected.y);
|
|
125
|
-
const base = entry.size ??
|
|
125
|
+
const base = entry.size ??
|
|
126
|
+
((entry.is_stable || entry.e_above_hull === 0) ? 6 : 4);
|
|
126
127
|
if (distance < base * container_scale + 5)
|
|
127
128
|
return entry;
|
|
128
129
|
}
|
|
@@ -266,11 +267,13 @@ function select_group_energy_metric(polymorphs) {
|
|
|
266
267
|
return `e_form_per_atom`;
|
|
267
268
|
}
|
|
268
269
|
// Try energy_per_atom (either direct field or computed from total energy)
|
|
269
|
-
if (polymorphs.every((entry) => is_finite(entry.energy_per_atom) ||
|
|
270
|
+
if (polymorphs.every((entry) => is_finite(entry.energy_per_atom) ||
|
|
271
|
+
compute_energy_per_atom(entry) !== null))
|
|
270
272
|
return `energy_per_atom`;
|
|
271
273
|
// Last resort: e_above_hull (will fail to differentiate stable polymorphs with e_above_hull=0)
|
|
272
|
-
if (polymorphs.every((entry) => is_finite(entry.e_above_hull)))
|
|
274
|
+
if (polymorphs.every((entry) => is_finite(entry.e_above_hull))) {
|
|
273
275
|
return `e_above_hull`;
|
|
276
|
+
}
|
|
274
277
|
return null; // No valid metric available for this group
|
|
275
278
|
}
|
|
276
279
|
// Pre-compute polymorph statistics for all entries at once (O(n²) but done once)
|
|
@@ -444,7 +447,10 @@ export function analyze_temperature_data(entries) {
|
|
|
444
447
|
.filter(entry_has_temp_data)
|
|
445
448
|
.flatMap((entry) => entry.temperatures ?? []);
|
|
446
449
|
const available_temperatures = [...new Set(valid_temps)].sort((a, b) => a - b);
|
|
447
|
-
return {
|
|
450
|
+
return {
|
|
451
|
+
has_temp_data: available_temperatures.length > 0,
|
|
452
|
+
available_temperatures,
|
|
453
|
+
};
|
|
448
454
|
}
|
|
449
455
|
// Check if an entry has valid temperature-dependent data (matching array lengths, non-empty)
|
|
450
456
|
function entry_has_temp_data(entry) {
|
|
@@ -455,15 +461,17 @@ function entry_has_temp_data(entry) {
|
|
|
455
461
|
}
|
|
456
462
|
// Check if entry has data at exact temperature T
|
|
457
463
|
export function entry_has_temperature(entry, T) {
|
|
458
|
-
return entry_has_temp_data(entry) &&
|
|
464
|
+
return entry_has_temp_data(entry) &&
|
|
465
|
+
(entry.temperatures?.includes(T) ?? false);
|
|
459
466
|
}
|
|
460
467
|
// Get energy at temperature T (throws if T not found - validate with entry_has_temperature first)
|
|
461
468
|
export function get_energy_at_temperature(entry, T) {
|
|
462
469
|
const temps = entry.temperatures ?? [];
|
|
463
470
|
const energies = entry.free_energies ?? [];
|
|
464
471
|
const idx = temps.indexOf(T);
|
|
465
|
-
if (idx === -1)
|
|
472
|
+
if (idx === -1) {
|
|
466
473
|
throw new Error(`Temperature ${T}K not found in entry temperatures`);
|
|
474
|
+
}
|
|
467
475
|
return energies[idx];
|
|
468
476
|
}
|
|
469
477
|
// Find bracketing temperatures for interpolation (T_low < T < T_high)
|
|
@@ -532,14 +540,21 @@ export function filter_entries_at_temperature(entries, T, options = {}) {
|
|
|
532
540
|
if (!entry_has_temp_data(entry))
|
|
533
541
|
return [entry];
|
|
534
542
|
// Exact temperature match - use G(T)
|
|
543
|
+
// Set both energy and energy_per_atom so downstream formation energy
|
|
544
|
+
// calculations use the temperature-dependent value (not stale 0K energy_per_atom)
|
|
535
545
|
if (entry_has_temperature(entry, T)) {
|
|
536
|
-
|
|
546
|
+
// free_energies stores per-atom values (E_0K/atom + F_vib/atom),
|
|
547
|
+
// so energy is already per-atom — set both fields to the same value
|
|
548
|
+
const energy = get_energy_at_temperature(entry, T);
|
|
549
|
+
return [{ ...entry, energy, energy_per_atom: energy }];
|
|
537
550
|
}
|
|
538
551
|
// Try interpolation if enabled
|
|
539
552
|
if (interpolate) {
|
|
540
553
|
const energy = interpolate_energy_at_temperature(entry, T, max_interpolation_gap);
|
|
541
|
-
if (energy !== null)
|
|
542
|
-
|
|
554
|
+
if (energy !== null) {
|
|
555
|
+
// interpolated energy is also per-atom (interpolated from per-atom free_energies)
|
|
556
|
+
return [{ ...entry, energy, energy_per_atom: energy }];
|
|
557
|
+
}
|
|
543
558
|
}
|
|
544
559
|
// Exclude entry (has temp data but can't get energy at T)
|
|
545
560
|
return [];
|
|
@@ -596,3 +611,18 @@ export function get_gas_corrected_entries(entries, gas_config, gas_pressures, te
|
|
|
596
611
|
merged_config,
|
|
597
612
|
};
|
|
598
613
|
}
|
|
614
|
+
// Derive a display label for a convex hull entry, falling back to composition
|
|
615
|
+
// when reduced_formula and name are both missing.
|
|
616
|
+
export function get_entry_label(entry, elements) {
|
|
617
|
+
if (entry.reduced_formula)
|
|
618
|
+
return entry.reduced_formula;
|
|
619
|
+
if (entry.name)
|
|
620
|
+
return entry.name;
|
|
621
|
+
let pairs = Object.entries(entry.composition).filter(([, amt]) => amt > 0);
|
|
622
|
+
if (elements) {
|
|
623
|
+
pairs = pairs.sort(([el1], [el2]) => elements.indexOf(el1) - elements.indexOf(el2));
|
|
624
|
+
}
|
|
625
|
+
return pairs
|
|
626
|
+
.map(([el, amt]) => Math.abs(amt - 1) < 1e-6 ? el : `${el}${format_num(amt, `.2~`)}`)
|
|
627
|
+
.join(``);
|
|
628
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { D3InterpolateName } from '../colors';
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
-
import type { ConvexHullConfig, ConvexHullControlsType, GasSpecies, GasThermodynamicsConfig, HighlightStyle, HoverData3D, PhaseData, PhaseStats } from './types';
|
|
4
|
+
import type { ConvexHullConfig, ConvexHullControlsType, GasSpecies, GasThermodynamicsConfig, HighlightStyle, HoverData3D, HullFaceColorMode, PhaseData, PhaseStats } from './types';
|
|
5
5
|
export * from './barycentric-coords';
|
|
6
6
|
export { default as ConvexHull } from './ConvexHull.svelte';
|
|
7
7
|
export { default as ConvexHull2D } from './ConvexHull2D.svelte';
|
|
@@ -11,6 +11,7 @@ export { default as ConvexHullControls } from './ConvexHullControls.svelte';
|
|
|
11
11
|
export { default as ConvexHullInfoPane } from './ConvexHullInfoPane.svelte';
|
|
12
12
|
export { default as ConvexHullStats } from './ConvexHullStats.svelte';
|
|
13
13
|
export { default as ConvexHullTooltip } from './ConvexHullTooltip.svelte';
|
|
14
|
+
export * from './demo-temperature';
|
|
14
15
|
export * from './gas-thermodynamics';
|
|
15
16
|
export { default as GasPressureControls } from './GasPressureControls.svelte';
|
|
16
17
|
export * from './helpers';
|
|
@@ -76,7 +77,20 @@ export interface BaseConvexHullProps<AnyDimEntry = PhaseData> extends Omit<HTMLA
|
|
|
76
77
|
export interface Hull3DProps {
|
|
77
78
|
show_hull_faces?: boolean;
|
|
78
79
|
hull_face_opacity?: number;
|
|
80
|
+
hull_face_color_mode?: HullFaceColorMode;
|
|
81
|
+
element_colors?: Record<string, string>;
|
|
82
|
+
gizmo?: boolean | ConvexHullGizmoOptions;
|
|
79
83
|
}
|
|
84
|
+
export type GizmoPlacement = `top-right` | `bottom-right` | `top-left` | `bottom-left`;
|
|
85
|
+
export type ConvexHullGizmoOptions = Record<string, unknown> & {
|
|
86
|
+
placement?: GizmoPlacement;
|
|
87
|
+
size?: number;
|
|
88
|
+
background?: {
|
|
89
|
+
enabled?: boolean;
|
|
90
|
+
color?: number;
|
|
91
|
+
opacity?: number;
|
|
92
|
+
};
|
|
93
|
+
};
|
|
80
94
|
export interface MergedCHConfig {
|
|
81
95
|
controls: ConvexHullControlsType;
|
|
82
96
|
config: ConvexHullConfig;
|
|
@@ -7,6 +7,7 @@ export { default as ConvexHullControls } from './ConvexHullControls.svelte';
|
|
|
7
7
|
export { default as ConvexHullInfoPane } from './ConvexHullInfoPane.svelte';
|
|
8
8
|
export { default as ConvexHullStats } from './ConvexHullStats.svelte';
|
|
9
9
|
export { default as ConvexHullTooltip } from './ConvexHullTooltip.svelte';
|
|
10
|
+
export * from './demo-temperature';
|
|
10
11
|
export * from './gas-thermodynamics';
|
|
11
12
|
export { default as GasPressureControls } from './GasPressureControls.svelte';
|
|
12
13
|
export * from './helpers';
|