From 73919d358dd4b206514c87d450bd9af77d1a67f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=85smund=20V=C3=A5ge=20Fannemel?= <34712686+asmfstatoil@users.noreply.github.com> Date: Tue, 19 Mar 2024 15:51:10 +0100 Subject: [PATCH] feat: propertyFlash - more robust input handling (#962) * fix: check that fraction belongs to current component * feat: more robust handling of input components * feat: SystemInterface.hasComponent * chore: release 2.5.20 --- pom.xml | 2 +- pomJava21.xml | 2 +- pomJava8.xml | 2 +- .../thermo/component/ComponentGeDuanSun.java | 1 - src/main/java/neqsim/thermo/phase/Phase.java | 2 + .../neqsim/thermo/phase/PhaseInterface.java | 8 ++-- .../neqsim/thermo/system/SystemInterface.java | 15 ++++++ .../ThermodynamicOperations.java | 42 ++++++++++------- .../neqsim/util/database/NeqSimDataBase.java | 12 ++--- .../util/exception/InvalidInputException.java | 8 +++- .../ThermodynamicOperationsTest.java | 47 +++++++++++++++++++ 11 files changed, 106 insertions(+), 35 deletions(-) diff --git a/pom.xml b/pom.xml index 20d0ef18c..9a64fdd5c 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ ${revision}${sha1}${changelist} - 2.5.19 + 2.5.20 UTF-8 UTF-8 diff --git a/pomJava21.xml b/pomJava21.xml index 66a614a1b..2c9c949d6 100644 --- a/pomJava21.xml +++ b/pomJava21.xml @@ -10,7 +10,7 @@ ${revision}${sha1}${changelist} - 2.5.19 + 2.5.20 UTF-8 UTF-8 diff --git a/pomJava8.xml b/pomJava8.xml index d0f26c407..0cd3e260e 100644 --- a/pomJava8.xml +++ b/pomJava8.xml @@ -10,7 +10,7 @@ ${revision}${sha1}${changelist}-Java8 - 2.5.19 + 2.5.20 UTF-8 UTF-8 diff --git a/src/main/java/neqsim/thermo/component/ComponentGeDuanSun.java b/src/main/java/neqsim/thermo/component/ComponentGeDuanSun.java index 041723bfc..cf72d8c02 100644 --- a/src/main/java/neqsim/thermo/component/ComponentGeDuanSun.java +++ b/src/main/java/neqsim/thermo/component/ComponentGeDuanSun.java @@ -58,7 +58,6 @@ public double getGamma(PhaseInterface phase, int numberOfComponents, double temp } } - /** {@inheritDoc} */ @Override public double getGamma(PhaseInterface phase, int numberOfComponents, double temperature, diff --git a/src/main/java/neqsim/thermo/phase/Phase.java b/src/main/java/neqsim/thermo/phase/Phase.java index 975edf491..3ba3218b9 100644 --- a/src/main/java/neqsim/thermo/phase/Phase.java +++ b/src/main/java/neqsim/thermo/phase/Phase.java @@ -100,6 +100,8 @@ public Phase clone() { /** *

* addcomponent. Increase number of components and add moles to phase. + * + * NB! Does not actually add component to componentarray. *

* * @param name Name of component to add. diff --git a/src/main/java/neqsim/thermo/phase/PhaseInterface.java b/src/main/java/neqsim/thermo/phase/PhaseInterface.java index f6d015a6a..60b1a1b2c 100644 --- a/src/main/java/neqsim/thermo/phase/PhaseInterface.java +++ b/src/main/java/neqsim/thermo/phase/PhaseInterface.java @@ -1904,12 +1904,10 @@ public default void setPhaseTypeName(String phaseTypeName) { public double getActivityCoefficientUnSymetric(int k); /** - *

- * hasComponent. - *

+ * Verify if phase has a component. * - * @param name a {@link String} object - * @return a boolean + * @param name Name of component to look for. + * @return True if component is found. */ public boolean hasComponent(String name); diff --git a/src/main/java/neqsim/thermo/system/SystemInterface.java b/src/main/java/neqsim/thermo/system/SystemInterface.java index 1ffcde5d9..f7e2b64bc 100644 --- a/src/main/java/neqsim/thermo/system/SystemInterface.java +++ b/src/main/java/neqsim/thermo/system/SystemInterface.java @@ -1613,6 +1613,21 @@ public default int getPhaseNumberOfPhase(String phaseTypeName) { */ public double getZ(); + /** + * Verify if system has a component. + * + * @param name Name of component to look for. + * @return True if component is found. + */ + public default boolean hasComponent(String name) { + for (String fluidComp : getComponentNames()) { + if (name == fluidComp) { + return true; + } + } + return false; + } + /** {@inheritDoc} */ @Override public int hashCode(); diff --git a/src/main/java/neqsim/thermodynamicOperations/ThermodynamicOperations.java b/src/main/java/neqsim/thermodynamicOperations/ThermodynamicOperations.java index 91931d488..f0614c656 100644 --- a/src/main/java/neqsim/thermodynamicOperations/ThermodynamicOperations.java +++ b/src/main/java/neqsim/thermodynamicOperations/ThermodynamicOperations.java @@ -2,6 +2,7 @@ import java.awt.BorderLayout; import java.awt.Container; +import java.util.Arrays; import java.util.List; import javax.swing.JFrame; import javax.swing.JScrollPane; @@ -1975,9 +1976,22 @@ public CalculationResult propertyFlash(List Spec1, List Spec2, i String[] calculationError = new String[Spec1.size()]; Double[] sum = new Double[Spec1.size()]; + String[] systemComponents = this.system.getComponentNames(); + if (components != null) { + for (String inputCompName : components) { + if (!this.system.hasComponent(inputCompName)) { + for (int t = 0; t < Spec1.size(); t++) { + calculationError[t] = "Input component list does not match fluid component list."; + } + } + } + } else { + components = Arrays.asList(systemComponents); + } // Verify that sum of fractions equals 1/100, i.e., assume percentages boolean hasOnlineFractions = onlineFractions != null; + if (hasOnlineFractions) { double range = 5; for (int t = 0; t < sum.length; t++) { @@ -2044,24 +2058,18 @@ public CalculationResult propertyFlash(List Spec1, List Spec2, i } if (hasOnlineFractions) { - /* - * // New attempt: - * - * this.system.setEmptyFluid(); - * - * // Components in system with no corresponding value in onlineFractions will be zero. - * for (int componentNumber = 0; componentNumber < onlineFractions .size(); - * componentNumber++) { this.system.addComponent(componentNumber, - * onlineFractions.get(componentNumber).get(t).doubleValue()); } - * - * if (this.system.getTotalNumberOfMoles() < 1e-5) { this.system.setTotalNumberOfMoles(1); - * } - */ - - // Remaining fractions will be set to 0.0 + // Assure that fraction is inserted for the correct component (in case of mismatch of + // component input and fluid component list) double[] fraction = new double[this.system.getNumberOfComponents()]; - for (int comp = 0; comp < onlineFractions.size(); comp++) { - fraction[comp] = onlineFractions.get(comp).get(t).doubleValue(); + // For all components defined in system + for (int compIndex = 0; compIndex < fraction.length; compIndex++) { + // Loop all input component names / fractions + for (int index = 0; index < components.size(); index++) { + if (systemComponents[compIndex] == components.get(index)) { + fraction[compIndex] = onlineFractions.get(index).get(t).doubleValue(); + break; + } + } } this.system.setMolarComposition(fraction); diff --git a/src/main/java/neqsim/util/database/NeqSimDataBase.java b/src/main/java/neqsim/util/database/NeqSimDataBase.java index 9495d05e8..cb452c3cc 100644 --- a/src/main/java/neqsim/util/database/NeqSimDataBase.java +++ b/src/main/java/neqsim/util/database/NeqSimDataBase.java @@ -394,17 +394,15 @@ public static String[] getComponentNames() { } /** - *

- * hasComponent. - *

+ * Verify if database has a component. * - * @param compName a {@link java.lang.String} object - * @return a boolean + * @param name Name of component to look for. + * @return True if component is found. */ - public static boolean hasComponent(String compName) { + public static boolean hasComponent(String name) { try (neqsim.util.database.NeqSimDataBase database = new neqsim.util.database.NeqSimDataBase(); java.sql.ResultSet dataSet = - database.getResultSet("select count(*) from comp WHERE NAME='" + compName + "'")) { + database.getResultSet("select count(*) from comp WHERE NAME='" + name + "'")) { dataSet.next(); int size = dataSet.getInt(1); if (size == 0) { diff --git a/src/main/java/neqsim/util/exception/InvalidInputException.java b/src/main/java/neqsim/util/exception/InvalidInputException.java index ed593c5ed..9be4a1582 100644 --- a/src/main/java/neqsim/util/exception/InvalidInputException.java +++ b/src/main/java/neqsim/util/exception/InvalidInputException.java @@ -22,7 +22,9 @@ public InvalidInputException(String msg) { } /** - * Constructs an InvalidInputException with a default message. + * Constructs an InvalidInputException with a default message like: + * + * Input " + inputName + " was invalid. * * @param className Class that exception is raised from * @param methodName Method that exception is raised from @@ -33,7 +35,9 @@ public InvalidInputException(String className, String methodName, String inputNa } /** - * Constructs an InvalidInputException with the specified detail message. + * Constructs an InvalidInputException with a message like: + * + * "Input " + inputName + " " + msg * * @param className Class that exception is raised from * @param methodName Method that exception is raised from diff --git a/src/test/java/neqsim/thermodynamicOperations/ThermodynamicOperationsTest.java b/src/test/java/neqsim/thermodynamicOperations/ThermodynamicOperationsTest.java index d4dde8beb..a3d1a01f6 100644 --- a/src/test/java/neqsim/thermodynamicOperations/ThermodynamicOperationsTest.java +++ b/src/test/java/neqsim/thermodynamicOperations/ThermodynamicOperationsTest.java @@ -270,6 +270,53 @@ void testpropertyFlashOnlineSingle() { Assertions.assertEquals(len, s.fluidProperties.length); } + @Test + void testpropertyFlashOnlineTooFewInputComponents() { + String[] components = {"nitrogen", "oxygen"}; + double[] fractions = {0.79, 0.21}; + int len = 10; + List> onlineFractions = createDummyRequest(fractions, len); + + Double[] pressure = {1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 4.0, 3.5, 3.0, 2.5}; + Double[] temperature = {301.0, 301.5, 302.0, 302.5, 303.0, 304.0, 304.0, 303.5, 303.0, 302.5}; + + SystemInterface fluid = new SystemSrkEos(298, 1.0); + // Add extra component C1 + fluid.addComponent("C1"); + fluid.addComponents(components); + // Add extra component iC4 + fluid.addComponent("iC4"); + + ThermodynamicOperations ops = new ThermodynamicOperations(fluid); + CalculationResult s = ops.propertyFlash(Arrays.asList(pressure), Arrays.asList(temperature), 1, + Arrays.asList(components), onlineFractions); + Assertions.assertEquals(len, s.fluidProperties.length); + Assertions.assertNull(s.calculationError[0]); + } + + @Test + void testPropertyFlashTooManyInputComponents() { + int len = 10; + String[] components_too_many = {"nitrogen", "oxygen", "water"}; + double[] fractions_to_many = {0.79, 0.21, 0.01}; + + Double[] pressure = {1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 4.0, 3.5, 3.0, 2.5}; + Double[] temperature = {301.0, 301.5, 302.0, 302.5, 303.0, 304.0, 304.0, 303.5, 303.0, 302.5}; + + List> onlineFractions_too_many = createDummyRequest(fractions_to_many, len); + SystemInterface fluid = new SystemSrkEos(298, 1.0); + + // Add only two components to fluid + String[] components = {"nitrogen", "oxygen"}; + fluid.addComponents(components); + ThermodynamicOperations ops = new ThermodynamicOperations(fluid); + CalculationResult s = ops.propertyFlash(Arrays.asList(pressure), Arrays.asList(temperature), 1, + Arrays.asList(components_too_many), onlineFractions_too_many); + Assertions.assertEquals(len, s.fluidProperties.length); + Assertions.assertEquals("Input component list does not match fluid component list.", + s.calculationError[0]); + } + @Disabled @Test @SuppressWarnings("unchecked")