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: + *

+ * + *

+ * Dependencies: + *

+ */ +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); + + } + +}