Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions src/modifiers/modifier.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,100 @@
import { ModifierInput, ModifierOutput } from "./types";
import { LMPModifier, Data1D } from "../types";

interface ModifierProps {
name: string;
active: boolean;
}

export interface ProcessedData1D {
data1D: Data1D | undefined;
hasData1D: boolean;
clearPerSync: boolean;
}

/**
* Shared helper function to process Data1D from LMPModifier.
* Extracts common logic for syncing computes, fixes, and variables.
*/
export function processData1D(
lmpModifier: LMPModifier,
data1D: Data1D | undefined,
input: ModifierInput,
everything: boolean,
syncDataPoints: boolean
): ProcessedData1D {
// Get data1DNamesWrapper and extract size, then delete immediately
const data1DNamesWrapper = lmpModifier.getData1DNames();
const data1DNamesSize = data1DNamesWrapper.size();
const hasData1D = data1DNamesSize > 0;
data1DNamesWrapper.delete(); // Delete WASM wrapper to prevent memory leak

if (data1DNamesSize === 0) {
return { data1D, hasData1D, clearPerSync: false };
}

const clearPerSync = lmpModifier.getClearPerSync();

if (data1D == null) {
data1D = {
data: [],
labels: [],
};
}

if (everything || syncDataPoints) {
// Data points is only for plotting figures
if (clearPerSync) {
// For histograms (compute rdf etc) we don't have time as x axis, so we clear every time
data1D.data = [];
}

const lengthBeforeWeStart = data1D.data.length; // Used to avoid copying all data every time

if (data1D.labels.length === 0) {
// First label is never visible
data1D.labels.push("x");
}

// Get data1DVector once before the loop for better performance
const data1DVector = lmpModifier.getData1D();

for (let j = 0; j < data1DNamesSize; j++) {
const lmpData = data1DVector.get(j);

if (data1D.labels.length - 1 === j) {
// Add missing labels
data1D.labels.push(lmpData.getLabel());
}

const xValuesPointer = lmpData.getXValuesPointer() / 4;
const yValuesPointer = lmpData.getYValuesPointer() / 4;
const xValues = input.wasm.HEAPF32.subarray(
xValuesPointer,
xValuesPointer + lmpData.getNumPoints(),
) as Float32Array;
const yValues = input.wasm.HEAPF32.subarray(
yValuesPointer,
yValuesPointer + lmpData.getNumPoints(),
) as Float32Array;
for (let k = lengthBeforeWeStart; k < xValues.length; k++) {
if (j === 0) {
data1D.data.push([xValues[k]]);
}
data1D.data[k].push(yValues[k]);
}

// Delete the Data1D copy to prevent memory leak
lmpData.delete();
}

// Delete the vector wrapper after the loop to prevent memory leak
data1DVector.delete();
}

return { data1D, hasData1D, clearPerSync };
}

class Modifier {
public name: string;
public key: string;
Expand Down
77 changes: 11 additions & 66 deletions src/modifiers/synccomputesmodifier.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Modifier from "./modifier";
import { ModifierInput, ModifierOutput } from "./types";
import { processData1D } from "./modifier";

interface SyncComputesModifierProps {
name: string;
Expand Down Expand Up @@ -52,72 +53,16 @@ class SyncComputesModifier extends Modifier {
compute.yLabel = compute.lmpCompute.getYLabel();
compute.scalarValue = compute.lmpCompute.getScalarValue();

// Get data1DNamesWrapper and extract size, then delete immediately
const data1DNamesWrapper = compute.lmpCompute.getData1DNames();
compute.hasData1D = data1DNamesWrapper.size() > 0;
const data1DNamesSize = data1DNamesWrapper.size();
data1DNamesWrapper.delete(); // Delete WASM wrapper to prevent memory leak

if (data1DNamesSize > 0) {
compute.clearPerSync = compute.lmpCompute.getClearPerSync();

if (compute.data1D == null) {
compute.data1D = {
data: [],
labels: [],
};
}

if ((everything || compute.syncDataPoints) && compute.data1D) {
// Data points is only for plotting figures
if (compute.clearPerSync) {
// For histograms (compute rdf etc) we don't have time as x axis, so we clear every time
compute.data1D.data = [];
}

const lengthBeforeWeStart = compute.data1D.data.length; // Used to avoid coping all data every time

if (compute.data1D.labels.length === 0) {
// First label is never visible
compute.data1D.labels.push("x");
}

// Get data1DVector once before the loop for better performance
const data1DVector = compute.lmpCompute.getData1D();

for (let j = 0; j < data1DNamesSize; j++) {
const lmpData = data1DVector.get(j);

if (compute.data1D.labels.length - 1 === j) {
// Add missing labels
compute.data1D.labels.push(lmpData.getLabel());
}

const xValuesPointer = lmpData.getXValuesPointer() / 4;
const yValuesPointer = lmpData.getYValuesPointer() / 4;
const xValues = input.wasm.HEAPF32.subarray(
xValuesPointer,
xValuesPointer + lmpData.getNumPoints(),
) as Float32Array;
const yValues = input.wasm.HEAPF32.subarray(
yValuesPointer,
yValuesPointer + lmpData.getNumPoints(),
) as Float32Array;
for (let k = lengthBeforeWeStart; k < xValues.length; k++) {
if (j === 0) {
compute.data1D.data.push([xValues[k]]);
}
compute.data1D.data[k].push(yValues[k]);
}

// Delete the Data1D copy to prevent memory leak
lmpData.delete();
}

// Delete the vector wrapper after the loop to prevent memory leak
data1DVector.delete();
}
}
const { data1D, hasData1D, clearPerSync } = processData1D(
compute.lmpCompute,
compute.data1D,
input,
everything,
compute.syncDataPoints,
);
compute.data1D = data1D;
compute.hasData1D = hasData1D;
compute.clearPerSync = clearPerSync;
}
output.computes[name] = compute;
}
Expand Down
76 changes: 11 additions & 65 deletions src/modifiers/syncfixesmodifier.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Modifier from "./modifier";
import { ModifierInput, ModifierOutput } from "./types";
import { processData1D } from "./modifier";

interface SyncFixesModifierProps {
name: string;
Expand Down Expand Up @@ -49,71 +50,16 @@ class SyncFixesModifier extends Modifier {
fix.yLabel = fix.lmpFix.getYLabel();
fix.scalarValue = fix.lmpFix.getScalarValue();

// Get data1DNamesWrapper and extract size, then delete immediately
const data1DNamesWrapper = fix.lmpFix.getData1DNames();
fix.hasData1D = data1DNamesWrapper.size() > 0;
const data1DNamesSize = data1DNamesWrapper.size();
data1DNamesWrapper.delete(); // Delete WASM wrapper to prevent memory leak

if (data1DNamesSize > 0) {
fix.clearPerSync = fix.lmpFix.getClearPerSync();
if (fix.data1D == null) {
fix.data1D = {
data: [],
labels: [],
};
}

if ((everything || fix.syncDataPoints) && fix.data1D) {
// Data points is only for plotting figures
if (fix.clearPerSync) {
// For histograms (compute rdf etc) we don't have time as x axis, so we clear every time
fix.data1D.data = [];
}

const lengthBeforeWeStart = fix.data1D.data.length; // Used to avoid coping all data every time

if (fix.data1D.labels.length === 0) {
// First label is never visible
fix.data1D.labels.push("x");
}

// Get data1DVector once before the loop for better performance
const data1DVector = fix.lmpFix.getData1D();

for (let j = 0; j < data1DNamesSize; j++) {
const lmpData = data1DVector.get(j);

if (fix.data1D.labels.length - 1 === j) {
// Add missing labels
fix.data1D.labels.push(lmpData.getLabel());
}

const xValuesPointer = lmpData.getXValuesPointer() / 4;
const yValuesPointer = lmpData.getYValuesPointer() / 4;
const xValues = input.wasm.HEAPF32.subarray(
xValuesPointer,
xValuesPointer + lmpData.getNumPoints(),
) as Float32Array;
const yValues = input.wasm.HEAPF32.subarray(
yValuesPointer,
yValuesPointer + lmpData.getNumPoints(),
) as Float32Array;
for (let k = lengthBeforeWeStart; k < xValues.length; k++) {
if (j === 0) {
fix.data1D.data.push([xValues[k]]);
}
fix.data1D.data[k].push(yValues[k]);
}

// Delete the Data1D copy to prevent memory leak
lmpData.delete();
}

// Delete the vector wrapper after the loop to prevent memory leak
data1DVector.delete();
}
}
const { data1D, hasData1D, clearPerSync } = processData1D(
fix.lmpFix,
fix.data1D,
input,
everything,
fix.syncDataPoints,
);
fix.data1D = data1D;
fix.hasData1D = hasData1D;
fix.clearPerSync = clearPerSync;
output.fixes[name] = fix;
}
};
Expand Down
76 changes: 11 additions & 65 deletions src/modifiers/syncvariablesmodifier.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Modifier from "./modifier";
import { ModifierInput, ModifierOutput } from "./types";
import { processData1D } from "./modifier";

interface SyncVariablesModifierProps {
name: string;
Expand Down Expand Up @@ -51,71 +52,16 @@ class SyncVariablesModifier extends Modifier {
variable.scalarValue = variable.lmpVariable.getScalarValue();
variable.hasScalarData = variable.lmpVariable.hasScalarData();

// Get data1DNamesWrapper and extract size, then delete immediately
const data1DNamesWrapper = variable.lmpVariable.getData1DNames();
variable.hasData1D = data1DNamesWrapper.size() > 0;
const data1DNamesSize = data1DNamesWrapper.size();
data1DNamesWrapper.delete(); // Delete WASM wrapper to prevent memory leak

if (data1DNamesSize > 0) {
variable.clearPerSync = variable.lmpVariable.getClearPerSync();
if (variable.data1D == null) {
variable.data1D = {
data: [],
labels: [],
};
}

if ((everything || variable.syncDataPoints) && variable.data1D) {
// Data points is only for plotting figures
if (variable.clearPerSync) {
// For histograms (compute rdf etc) we don't have time as x axis, so we clear every time
variable.data1D.data = [];
}

const lengthBeforeWeStart = variable.data1D.data.length; // Used to avoid coping all data every time

if (variable.data1D.labels.length === 0) {
// First label is never visible
variable.data1D.labels.push("x");
}

// Get data1DVector once before the loop for better performance
const data1DVector = variable.lmpVariable.getData1D();

for (let j = 0; j < data1DNamesSize; j++) {
const lmpData = data1DVector.get(j);

if (variable.data1D.labels.length - 1 === j) {
// Add missing labels
variable.data1D.labels.push(lmpData.getLabel());
}

const xValuesPointer = lmpData.getXValuesPointer() / 4;
const yValuesPointer = lmpData.getYValuesPointer() / 4;
const xValues = input.wasm.HEAPF32.subarray(
xValuesPointer,
xValuesPointer + lmpData.getNumPoints(),
) as Float32Array;
const yValues = input.wasm.HEAPF32.subarray(
yValuesPointer,
yValuesPointer + lmpData.getNumPoints(),
) as Float32Array;
for (let k = lengthBeforeWeStart; k < xValues.length; k++) {
if (j === 0) {
variable.data1D.data.push([xValues[k]]);
}
variable.data1D.data[k].push(yValues[k]);
}

// Delete the Data1D copy to prevent memory leak
lmpData.delete();
}

// Delete the vector wrapper after the loop to prevent memory leak
data1DVector.delete();
}
}
const { data1D, hasData1D, clearPerSync } = processData1D(
variable.lmpVariable,
variable.data1D,
input,
everything,
variable.syncDataPoints,
);
variable.data1D = data1D;
variable.hasData1D = hasData1D;
variable.clearPerSync = clearPerSync;
output.variables[name] = variable;
}
};
Expand Down