From 27bf800b967bafebe753ba11af9ddac11fb5005d Mon Sep 17 00:00:00 2001
From: Even Solbraa <41290109+EvenSol@users.noreply.github.com>
Date: Mon, 16 Dec 2024 10:02:45 +0100
Subject: [PATCH] multi process model with test (#1212)
* first version of multi model with test
* update
* update
* update
* update
---
.devcontainer/devcontainer.json | 4 +-
.../process/processmodel/ProcessModel.java | 123 +++++++++++++++
.../process/processmodel/ProcessSystem.java | 23 ++-
.../processmodel/CombinedModelsTest.java | 141 ++++++++++++++++++
4 files changed, 288 insertions(+), 3 deletions(-)
create mode 100644 src/main/java/neqsim/process/processmodel/ProcessModel.java
create mode 100644 src/test/java/neqsim/process/processmodel/CombinedModelsTest.java
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 74f679ded3..b2b68262d8 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -25,7 +25,9 @@
"shengchen.vscode-checkstyle",
"mechatroner.rainbow-csv",
"redhat.vscode-xml",
- "vscjava.vscode-java-test"
+ "vscjava.vscode-java-test",
+ "GitHub.copilot",
+ "GitHub.copilot-chat"
],
"settings": {
"java.configuration.updateBuildConfiguration": "interactive",
diff --git a/src/main/java/neqsim/process/processmodel/ProcessModel.java b/src/main/java/neqsim/process/processmodel/ProcessModel.java
new file mode 100644
index 0000000000..b5804d228c
--- /dev/null
+++ b/src/main/java/neqsim/process/processmodel/ProcessModel.java
@@ -0,0 +1,123 @@
+package neqsim.process.processmodel;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ *
+ * ProcessModel class.
+ *
+ *
+ * Manages a collection of processes that can be run in steps or continuously.
+ *
+ * @author Even Solbraa
+ * @version $Id: $Id
+ */
+public class ProcessModel implements Runnable {
+ private final Map processes = new LinkedHashMap<>();
+ private boolean runStep = false;
+
+ /**
+ * Checks if the model is running in step mode.
+ *
+ * @return true if running in step mode, false otherwise.
+ */
+ public boolean isRunStep() {
+ return runStep;
+ }
+
+ /**
+ * Sets the step mode for the process.
+ *
+ * @param runStep true to enable step mode, false to disable.
+ */
+ public void setRunStep(boolean runStep) {
+ this.runStep = runStep;
+ }
+
+ /**
+ * Adds a process to the model.
+ *
+ * @param name the name of the process.
+ * @param process the process to add.
+ * @return true if the process was added successfully.
+ */
+ public boolean add(String name, ProcessSystem process) {
+ if (name == null || name.isEmpty()) {
+ throw new IllegalArgumentException("Name cannot be null or empty");
+ }
+ if (process == null) {
+ throw new IllegalArgumentException("Process cannot be null");
+ }
+ if (processes.containsKey(name)) {
+ throw new IllegalArgumentException("A process with the given name already exists");
+ }
+ processes.put(name, process);
+ return true;
+ }
+
+ /**
+ * Retrieves a process by its name.
+ *
+ * @param name the name of the process.
+ * @return the corresponding process, or null if not found.
+ */
+ public ProcessSystem get(String name) {
+ return processes.get(name);
+ }
+
+ /**
+ * Removes a process by its name.
+ *
+ * @param name the name of the process to remove.
+ * @return true if the process was removed, false otherwise.
+ */
+ public boolean remove(String name) {
+ return processes.remove(name) != null;
+ }
+
+ /**
+ * Executes all processes, either continuously or in steps based on mode.
+ */
+ @Override
+ public void run() {
+ for (ProcessSystem process : processes.values()) {
+ try {
+ if (runStep) {
+ process.run_step();
+ } else {
+ process.run();
+ }
+ } catch (Exception e) {
+ System.err.println("Error running process: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Executes all processes in a single step.
+ */
+ public void runStep() {
+ for (ProcessSystem process : processes.values()) {
+ try {
+ process.run_step();
+ } catch (Exception e) {
+ System.err.println("Error in runStep: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Runs the model as a separate thread.
+ *
+ * @return the thread running the model.
+ */
+ public Thread runAsThread() {
+ Thread processThread = new Thread(this);
+ processThread.start();
+ return processThread;
+ }
+
+}
diff --git a/src/main/java/neqsim/process/processmodel/ProcessSystem.java b/src/main/java/neqsim/process/processmodel/ProcessSystem.java
index 183cb34c81..f696cfd0a1 100644
--- a/src/main/java/neqsim/process/processmodel/ProcessSystem.java
+++ b/src/main/java/neqsim/process/processmodel/ProcessSystem.java
@@ -132,15 +132,34 @@ public void add(ProcessEquipmentInterface[] operations) {
getUnitOperations().addAll(Arrays.asList(operations));
}
+ /**
+ *
+ * Replace a unitoperation
+ *
+ *
+ * @param name Name of the object to replace
+ * @param newObject the object to replace it with
+ * @return a {@link java.lang.Boolean} object
+ */
+ public boolean replaceUnit(String name, ProcessEquipmentInterface newObject) {
+ try {
+ ProcessEquipmentInterface unit = (ProcessEquipmentInterface) getUnit(name);
+ unit = newObject;
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ }
+ return true;
+ }
+
/**
*
* Get process equipmen by name.
*
*
* @param name Name of
- * @return a {@link java.lang.Object} object
+ * @return a {@link neqsim.process.equipment.ProcessEquipmentInterface} object
*/
- public Object getUnit(String name) {
+ public ProcessEquipmentInterface getUnit(String name) {
for (int i = 0; i < getUnitOperations().size(); i++) {
if (getUnitOperations().get(i) instanceof ModuleInterface) {
for (int j = 0; j < ((ModuleInterface) getUnitOperations().get(i)).getOperations()
diff --git a/src/test/java/neqsim/process/processmodel/CombinedModelsTest.java b/src/test/java/neqsim/process/processmodel/CombinedModelsTest.java
new file mode 100644
index 0000000000..556a5f52d5
--- /dev/null
+++ b/src/test/java/neqsim/process/processmodel/CombinedModelsTest.java
@@ -0,0 +1,141 @@
+package neqsim.process.processmodel;
+
+import java.io.File;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import neqsim.process.equipment.compressor.Compressor;
+import neqsim.process.equipment.separator.ThreePhaseSeparator;
+import neqsim.process.equipment.stream.Stream;
+import neqsim.thermo.system.SystemInterface;
+
+/**
+ * CombinedModelsTest is a test class for validating the combined process model which includes an
+ * inlet model and a compressor process.
+ *
+ *
+ * The class contains methods to set up individual process systems and combine them into a single
+ * process model. It also includes a test method to verify the behavior of the combined process
+ * model.
+ *
+ *
+ * Methods:
+ *
+ * - {@link #getinletModel()}: Sets up the inlet process model including a well stream and a
+ * three-phase separator.
+ * - {@link #getCompressorProcess()}: Sets up the compressor process model including a gas feed
+ * stream and a compressor.
+ * - {@link #getCombinedModel()}: Combines the inlet process model and the compressor process
+ * model into a single process model.
+ * - {@link #testCombinedProcess()}: Tests the combined process model by configuring the
+ * temperature and pressure for the well stream and the outlet pressure for the compressor, running
+ * the process, and asserting the expected outlet temperature of the compressor.
+ *
+ *
+ *
+ * Dependencies:
+ *
+ * - Logger: Used for logging debug information.
+ * - ProcessSystem: Represents a process system containing various units.
+ * - Stream: Represents a stream in the process system.
+ * - ThreePhaseSeparator: Represents a three-phase separator unit in the process system.
+ * - Compressor: Represents a compressor unit in the process system.
+ * - ProcessModel: Represents the combined process model.
+ * - Assertions: Used for asserting expected values in the test method.
+ *
+ */
+public class CombinedModelsTest {
+ static Logger logger = LogManager.getLogger(CombinedModelsTest.class);
+
+ public ProcessSystem getinletModel() {
+ File file = new File("src/test/java/neqsim/process/processmodel");
+ String fileFluid1 = file.getAbsolutePath() + "/feedfluid.e300";
+ SystemInterface wellFluid = neqsim.thermo.util.readwrite.EclipseFluidReadWrite.read(fileFluid1);
+ // wellFluid.setMultiPhaseCheck(true);
+
+ Stream wellStreamHP = new neqsim.process.equipment.stream.Stream("HP well stream", wellFluid);
+ wellStreamHP.setFlowRate(10.0, "MSm3/day");
+
+ ThreePhaseSeparator firstStageSeparator =
+ new neqsim.process.equipment.separator.ThreePhaseSeparator("1st stage separator",
+ wellStreamHP);
+
+ ProcessSystem process1 = new ProcessSystem();
+ process1.add(wellStreamHP);
+ process1.add(firstStageSeparator);
+
+ return process1;
+ };
+
+ public ProcessSystem getCompressorProcess() {
+
+ neqsim.process.equipment.stream.Stream gasFeedStream =
+ new neqsim.process.equipment.stream.Stream("compressor feed stream");
+
+ neqsim.process.equipment.compressor.Compressor compressor1 =
+ new neqsim.process.equipment.compressor.Compressor("Compressor1", gasFeedStream);
+ compressor1.setPolytropicEfficiency(0.56);
+ compressor1.setUsePolytropicCalc(true);
+
+ ProcessSystem process1 = new ProcessSystem();
+ process1.add(gasFeedStream);
+ process1.add(compressor1);
+
+ return process1;
+ }
+
+ public ProcessModel getCombinedModel() {
+ ProcessSystem inletProcess = getinletModel();
+ ProcessSystem compressorProcess = getCompressorProcess();
+ ((Compressor) compressorProcess.getUnit("Compressor1")).setInletStream(
+ ((ThreePhaseSeparator) inletProcess.getUnit("1st stage separator")).getGasOutStream());
+
+
+ ProcessModel combinedProcess = new ProcessModel();
+ combinedProcess.add("feed process", inletProcess);
+ combinedProcess.add("compressor process", compressorProcess);
+
+ return combinedProcess;
+ }
+
+ /**
+ * Test method for the combined process model.
+ *
+ * This test sets up a combined process model, configures the temperature and pressure for the "HP
+ * well stream" in the "feed process", and sets the outlet pressure for "Compressor1" in the
+ * "compressor process". The process is then run, and the test asserts that the outlet temperature
+ * of "Compressor1" is as expected.
+ *
+ * The expected outlet temperature of "Compressor1" is 164.44139872 degrees Celsius with a
+ * tolerance of 0.1 degrees.
+ */
+ @Test
+ public void testCombinedProcess() {
+ ProcessModel fullProcess = getCombinedModel();
+ fullProcess.setRunStep(true);
+
+ // Set fullProcess properties;
+ ((Stream) (fullProcess.get("feed process")).getUnit("HP well stream")).setTemperature(80.0,
+ "C");
+ ((Stream) (fullProcess.get("feed process")).getUnit("HP well stream")).setPressure(50.0,
+ "bara");
+
+ ((Compressor) (fullProcess.get("compressor process")).getUnit("Compressor1"))
+ .setOutletPressure(100.0, "bara");
+
+
+ try {
+ fullProcess.run();
+ } catch (Exception ex) {
+ logger.debug(ex.getMessage(), ex);
+ }
+
+ Assertions.assertEquals(164.44139872,
+ ((Compressor) fullProcess.get("compressor process").getUnit("Compressor1"))
+ .getOutletStream().getTemperature("C"),
+ 0.1);
+
+ }
+
+}