Skip to content

Examples

Step through the hydraulic simulation

Use the openH - initH - runH - nextH - closeH series of functions to step through the simulation one hydraulic time step at a time.

Run this example on CodeSandbox

const { Project, Workspace } = require("epanet-js");
var fs = require("fs");

const net1 = fs.readFileSync("net1.inp");

const ws = new Workspace();
const model = new Project(ws);

ws.writeFile("net1.inp", net1);

model.open("net1.inp", "report.rpt", "out.bin");

const n11Index = model.getNodeIndex("11");

model.openH();
model.initH(11);

let tStep = Infinity;
do {
  const cTime = model.runH();
  const pressure = model.getNodeValue(n11Index, 11);
  console.log(
    `Current Time: - ${cTime}, Node 11 Pressure: ${pressure.toFixed(2)}`
  );

  tStep = model.nextH();
} while (tStep > 0);

model.saveH();
model.closeH();

New model builder API

Allows networks to be built completely from function calls instead of from an input file.

import { Project, Workspace } from "epanet-js";

const ws = new Workspace();
const model = new Project(ws);

model.init("report.rpt", "out.bin", 0, 0);

const n1Index = model.addNode("N1", NodeType.Junction);
const n2Index = model.addNode("N2", NodeType.Junction);
model.setJunctionData(n1Index, 700, 0, "");
model.setJunctionData(n2Index, 400, 0, "");

const l1Index = model.addLink("L1", LinkType.Pipe, "N1", "N2");

Fire Flow Analysis - React Example

A more complex example that uses React.

Select a node within a network, run an extended period simulation and conduct a fire flow test. Results displayed in a graph for pressure and the fire flow.

placeholder

Run this example on CodeSandbox

import React, { useState } from "react";
import { VictoryChart, VictoryLine, VictoryAxis, VictoryTheme } from "victory";
import {
  Project,
  Workspace,
  InitHydOption,
  NodeProperty,
  CountType,
  NodeType,
} from "epanet-js";
var fs = require("fs");

const net1 = fs.readFileSync("net1.inp");

const ws = new Workspace();
const model = new Project(ws);

ws.writeFile("net1.inp", net1);
model.open("net1.inp", "report.rpt", "out.bin");

function getNodes() {
  const nodeCount = model.getCount(CountType.NodeCount);
  let nodeIds = [];
  for (let i = 1; i < nodeCount; i++) {
    if (model.getNodeType(i) === NodeType.Junction) {
      const nodeId = model.getNodeId(i);
      nodeIds.push(nodeId);
    }
  }
  return nodeIds;
}

function runSim(nodeId) {
  const fireFlowNodeIndex = model.getNodeIndex(nodeId);
  const flows = [100, 250, 500, 750, 1000];

  model.openH();
  model.initH(InitHydOption.NoSave);

  let tStep = Infinity;
  let flowAndPressure = [];
  let fireResults = [];
  do {
    const cTime = model.runH();
    const pressure = model.getNodeValue(
      fireFlowNodeIndex,
      NodeProperty.Pressure
    );

    flowAndPressure.push({ x: cTime / 60 / 60, y: pressure });
    if (cTime === 46800) {
      fireResults = fireFlowAnalysis(model, fireFlowNodeIndex, flows, pressure);
      model.runH(); // Rerun original snapshot
    }

    tStep = model.nextH();
  } while (tStep > 0);

  model.closeH();

  return {
    flowAndPressure,
    fireResults,
  };
}

function fireFlowAnalysis(model, index, flows, zeroPressure) {
  const acc = [{ x: 0, y: zeroPressure }];

  const orgBaseFlow = model.getNodeValue(index, NodeProperty.BaseDemand);

  const pressures = flows.reduce((acc, flow) => {
    model.setNodeValue(index, NodeProperty.BaseDemand, orgBaseFlow + flow);
    model.runH();
    const pressure = model.getNodeValue(index, NodeProperty.Pressure);
    return acc.concat([{ x: flow, y: pressure }]);
  }, acc);

  model.setNodeValue(index, NodeProperty.BaseDemand, orgBaseFlow);
  return pressures;
}

function SmallChart(props) {
  return (
    <VictoryChart theme={VictoryTheme.material} height={175}>
      <VictoryAxis
        style={{
          axisLabel: { fontSize: 8, padding: 30 },
          tickLabels: { fontSize: 6, padding: 5 },
        }}
        label={props.xLabel}
      />
      <VictoryAxis
        style={{
          axisLabel: { fontSize: 8, padding: 30 },
          tickLabels: { fontSize: 6, padding: 5 },
        }}
        dependentAxis
        label={props.yLabel}
      />
      <VictoryLine data={props.data} />
    </VictoryChart>
  );
}

export default function App() {
  const [nodeId, setNodeId] = useState("11");

  function handleSelectChange(e) {
    setNodeId(e.target.value);
  }

  const nodeIds = getNodes();
  const { flowAndPressure, fireResults } = runSim(nodeId);

  return (
    <div className="App">
      <h1>epanet-js React Fire Flow Example</h1>
      <h2>Select a node to test</h2>
      <select value={nodeId} onChange={handleSelectChange}>
        {nodeIds.map((n, i) => {
          return (
            <option key={i} value={n}>
              {n}
            </option>
          );
        })}
      </select>
      <h3>Fireflow at Node {nodeId}</h3>
      <SmallChart
        data={fireResults}
        xLabel="Flow (GPM)"
        yLabel="Pressure (psi)"
      />

      <h3>Pressure at Node {nodeId}</h3>
      <SmallChart
        data={flowAndPressure}
        xLabel="Time (hours)"
        yLabel="Pressure (psi)"
      />
    </div>
  );
}