diff --git a/src/main/java/neqsim/fluidmechanics/flownode/fluidboundary/heatmasstransfercalc/FluidBoundary.java b/src/main/java/neqsim/fluidmechanics/flownode/fluidboundary/heatmasstransfercalc/FluidBoundary.java index 372e73840..07f9ac500 100644 --- a/src/main/java/neqsim/fluidmechanics/flownode/fluidboundary/heatmasstransfercalc/FluidBoundary.java +++ b/src/main/java/neqsim/fluidmechanics/flownode/fluidboundary/heatmasstransfercalc/FluidBoundary.java @@ -83,7 +83,10 @@ public FluidBoundary(SystemInterface system) { jFlux = new Matrix(system.getPhases()[0].getNumberOfComponents() - 1, 1); nFlux = new Matrix(system.getPhases()[0].getNumberOfComponents(), 1); nFlux.set(0, 0, 0.0); - nFlux.set(1, 0, 0.0); + if (system.getPhases()[0].getNumberOfComponents() > 1) { + nFlux.set(1, 0, 0.0); + } + //nFlux.set(1, 0, 0.0); heatTransferCoefficient = new double[2]; heatTransferCorrection = new double[2]; thermodynamicCorrections = new boolean[2]; diff --git a/src/main/java/neqsim/physicalproperties/system/PhysicalProperties.java b/src/main/java/neqsim/physicalproperties/system/PhysicalProperties.java index b2318fe81..88f5371e9 100644 --- a/src/main/java/neqsim/physicalproperties/system/PhysicalProperties.java +++ b/src/main/java/neqsim/physicalproperties/system/PhysicalProperties.java @@ -341,15 +341,18 @@ public void init(PhaseInterface phase) { try { density = densityCalc.calcDensity(); viscosity = viscosityCalc.calcViscosity(); + System.out.println(density); kinematicViscosity = this.calcKinematicViscosity(); diffusivityCalc.calcDiffusionCoefficients(binaryDiffusionCoefficientMethod, multicomponentDiffusionMethod); // diffusivityCalc.calcEffectiveDiffusionCoefficients(); conductivity = conductivityCalc.calcConductivity(); } catch (Exception ex) { + viscosity = viscosityCalc.calcViscosity(); + // might be a chance that entering here ends in an infinite loop... - phase.resetPhysicalProperties(); - phase.initPhysicalProperties(); + //phase.resetPhysicalProperties(); + //phase.initPhysicalProperties(); } } diff --git a/src/main/java/neqsim/thermo/component/ComponentFundamentalEOS.java b/src/main/java/neqsim/thermo/component/ComponentFundamentalEOS.java new file mode 100644 index 000000000..caabdc9d5 --- /dev/null +++ b/src/main/java/neqsim/thermo/component/ComponentFundamentalEOS.java @@ -0,0 +1,216 @@ +package neqsim.thermo.component; + +import neqsim.thermo.phase.PhaseFundamentalEOS; +import neqsim.thermo.phase.PhaseInterface; + +/** + * Component class for use with fundamental Helmholtz equations of state. + */ +public abstract class ComponentFundamentalEOS extends Component implements ComponentFundamentalEOSInterface { + private static final long serialVersionUID = 1L; + + /** + *
+ * Constructor for ComponentFundamentalEos. + *
+ * + * @param name Name of component. + * @param moles Total number of moles of component. + * @param molesInPhase Number of moles in phase. + * @param compIndex Index number of component in phase object component array. + */ + public ComponentFundamentalEOS(String name, double moles, double molesInPhase, int compIndex) { + super(name, moles, molesInPhase, compIndex); + } + + + /** {@inheritDoc} */ + @Override + public void init(double temperature, double pressure, double totalNumberOfMoles, double beta, int initType) { + super.init(temperature, pressure, totalNumberOfMoles, beta, initType); + //For gerg get pure component contributions + + } + + /** {@inheritDoc} */ + @Override + public void Finit(PhaseInterface phase, double temp, double pres, double totMoles, double beta, + int numberOfComponents, int initType) { + //Multicomponent EOS + //double dPdN = phase.getDensity() * R * temp * (1.0 + phase.getalpharesMatrix()[0][1].val * (2 - 1 / rho_r * numberOfMolesInPhase * drhordn) + ) + //voli = - dPdN / phase.getdPdVTn(); + //Single component EOS + voli = phase.getVolume() / getNumberOfMolesInPhase(); + } + + + /** + * Get reduced temperature. + * + * @param temperature temperature of fluid + * @return double reduced temperature T/TC + */ + double reducedTemperature(double temperature) { + return temperature / criticalTemperature; + } + + /** + *+ * Get reduced pressure. + *
+ * + * @param pressure pressure in unit bara + * @return double + */ + double reducedPressure(double pressure) { + return pressure / criticalPressure; + } + + /** {@inheritDoc} */ + @Override + public double dFdN(PhaseInterface phase, int numberOfComponents, double temperature, + double pressure) { + PhaseFundamentalEOS fundPhase = (PhaseFundamentalEOS) phase; + return fundPhase.getAlpharesMatrix()[0][0].val + ndAlphaResdN(phase, numberOfComponents, temperature, pressure); + } + + /** {@inheritDoc} */ + @Override + public double ndAlphaResdN(PhaseInterface phase, int numberOfComponents, double temperature, + double pressure) { + //MulticomponentEOS + //double rho_r = reducedDensity(phase.getDensity()); + //return + //single component EOS + PhaseFundamentalEOS fundPhase = (PhaseFundamentalEOS) phase; + return fundPhase.getAlpharesMatrix()[0][1].val; + } + + /** {@inheritDoc} */ + @Override + public double dFdNdT(PhaseInterface phase, int numberOfComponents, double temperature, + double pressure) { + PhaseFundamentalEOS fundPhase = (PhaseFundamentalEOS) phase; + return -(fundPhase.getAlpharesMatrix()[1][0].val + fundPhase.getAlpharesMatrix()[1][1].val) + / phase.getTemperature(); + } + + /** {@inheritDoc} */ + @Override + public double dFdNdV(PhaseInterface phase, int numberOfComponents, double temperature, + double pressure) { + PhaseFundamentalEOS fundPhase = (PhaseFundamentalEOS) phase; + + return -(2 * fundPhase.getAlpharesMatrix()[0][1].val + fundPhase.getAlpharesMatrix()[0][2].val) + / phase.getVolume(); + } + + + /** {@inheritDoc} */ + @Override + public double dFdNdN(int j, PhaseInterface phase, int numberOfComponents, double temperature, + double pressure) { + PhaseFundamentalEOS fundPhase = (PhaseFundamentalEOS) phase; + return (2 * fundPhase.getAlpharesMatrix()[0][1].val + fundPhase.getAlpharesMatrix()[0][2].val) + / phase.getNumberOfMolesInPhase(); //single component EOS + } + + + + + + + @Override + public double fugcoef(PhaseInterface phase) { + if (!(phase instanceof PhaseFundamentalEOS)) { + throw new IllegalArgumentException("Phase must be of type PhaseFundamentalEOS"); + } + PhaseFundamentalEOS fundPhase = (PhaseFundamentalEOS) phase; + double temperature = phase.getTemperature(); + double pressure = phase.getPressure(); + double Z = phase.getZ(); + double logFugacityCoefficient = dFdN(fundPhase, phase.getNumberOfComponents(), temperature, pressure) + - Math.log(Z); + + fugacityCoefficient = Math.exp(logFugacityCoefficient); + + return fugacityCoefficient; + } + + /** {@inheritDoc} */ + @Override + public double logfugcoefdP(PhaseInterface phase) { + double temperature = phase.getTemperature(); + double pressure = phase.getPressure(); + dfugdp = getVoli() / R / temperature - 1.0 / pressure; + return dfugdp; + } + + /** {@inheritDoc} */ + @Override + public double logfugcoefdT(PhaseInterface phase) { + double temperature = phase.getTemperature(); + double pressure = phase.getPressure(); + int numberOfComponents = phase.getNumberOfComponents(); + dfugdt = (this.dFdNdT(phase, numberOfComponents, temperature, pressure) + 1.0 / temperature + - getVoli() / R / temperature + * (-R * temperature * phase.dFdTdV() + pressure / temperature)); + return dfugdt; + } + + /** {@inheritDoc} */ + @Override + public double[] logfugcoefdN(PhaseInterface phase) { + double temperature = phase.getTemperature(); + double pressure = phase.getPressure(); + int numberOfComponents = phase.getNumberOfComponents(); + ComponentInterface[] compArray = phase.getComponents(); + for (int i = 0; i < numberOfComponents; i++) { + ComponentFundamentalEOSInterface comp = (ComponentFundamentalEOSInterface) compArray[i]; + dfugdn[i] = (this.dFdNdN(i, phase, numberOfComponents, temperature, pressure) + + 1.0 / phase.getNumberOfMolesInPhase() + - getVoli() / R / temperature + * (-R * temperature + * comp.dFdNdV(phase, numberOfComponents, temperature, pressure) + + R * temperature / phase.getTotalVolume())); + dfugdx[i] = dfugdn[i] * phase.getNumberOfMolesInPhase(); + } + // System.out.println("diffN: " + 1 + dfugdn[0]); + return dfugdn; + } + + // Method added by Neeraj + /* + * public double getdfugdn(int i){ double[] dfugdnv = this.logfugcoefdN(phase); //return 0.0001; + * return dfugdnv[i]; } + */ + // Added By Neeraj + /** {@inheritDoc} */ + @Override + public double logfugcoefdNi(PhaseInterface phase, int k) { + double temperature = phase.getTemperature(); + double pressure = phase.getPressure(); + int numberOfComponents = phase.getNumberOfComponents(); + double vol; + double voli; + ComponentEosInterface[] comp_Array = (ComponentEosInterface[]) phase.getcomponentArray(); + vol = phase.getMolarVolume(); + voli = getVoli(); + + dfugdn[k] = (this.dFdNdN(k, phase, numberOfComponents, temperature, pressure) + + 1.0 / phase.getNumberOfMolesInPhase() + - voli / R / temperature + * (-R * temperature + * comp_Array[k].dFdNdV(phase, numberOfComponents, temperature, pressure) + + R * temperature / (vol * phase.getNumberOfMolesInPhase()))); + dfugdx[k] = dfugdn[k] * (phase.getNumberOfMolesInPhase()); + // System.out.println("Main dfugdn "+dfugdn[k]); + return dfugdn[k]; + } + + + @Override + public ComponentFundamentalEOS clone() { + return (ComponentFundamentalEOS) super.clone(); + } +} diff --git a/src/main/java/neqsim/thermo/component/ComponentFundamentalEOSInterface.java b/src/main/java/neqsim/thermo/component/ComponentFundamentalEOSInterface.java new file mode 100644 index 000000000..f5c020514 --- /dev/null +++ b/src/main/java/neqsim/thermo/component/ComponentFundamentalEOSInterface.java @@ -0,0 +1,81 @@ +package neqsim.thermo.component; + +import neqsim.thermo.phase.PhaseInterface; + +public interface ComponentFundamentalEOSInterface { + + /** + *+ * dFdN. + *
+ * + * @param phase a {@link neqsim.thermo.phase.PhaseInterface} object + * @param numberOfComponents a int + * @param temperature a double + * @param pressure a double + * @return a double + */ + public double dFdN(PhaseInterface phase, int numberOfComponents, double temperature, + double pressure); + + /** + *+ * dFdNdT. + *
+ * + * @param phase a {@link neqsim.thermo.phase.PhaseInterface} object + * @param numberOfComponents a int + * @param temperature a double + * @param pressure a double + * @return a double + */ + public double dFdNdT(PhaseInterface phase, int numberOfComponents, double temperature, + double pressure); + + /** + *+ * dFdNdV. + *
+ * + * @param phase a {@link neqsim.thermo.phase.PhaseInterface} object + * @param numberOfComponents a int + * @param temperature a double + * @param pressure a double + * @return a double + */ + public double dFdNdV(PhaseInterface phase, int numberOfComponents, double temperature, + double pressure); + + /** + *+ * dFdNdN. + *
+ * + * @param j a int + * @param phase a {@link neqsim.thermo.phase.PhaseInterface} object + * @param numberOfComponents a int + * @param temperature a double + * @param pressure a double + * @return a double + */ + public double dFdNdN(int j, PhaseInterface phase, int numberOfComponents, double temperature, + double pressure); + + + + /** + * + *+ * ndAlphaResdN. + *
+ * + * @param phase a {@link neqsim.thermo.phase.PhaseInterface} object + * @param numberOfComponents a int + * @param temperature a double + * @param pressure a double + * + */ + public double ndAlphaResdN(PhaseInterface phase, int numberOfComponents, double temperature, + double pressure); +} + diff --git a/src/main/java/neqsim/thermo/component/ComponentGERG2008.java b/src/main/java/neqsim/thermo/component/ComponentGERG2008.java new file mode 100644 index 000000000..e7d8af984 --- /dev/null +++ b/src/main/java/neqsim/thermo/component/ComponentGERG2008.java @@ -0,0 +1,96 @@ +package neqsim.thermo.component; + +import neqsim.thermo.phase.PhaseInterface; + +/** + * ComponentGERG2008 class. + * + *This class implements a component for use with the GERG2008 equation of state. + * It is similar to the GERG2004 component class, but is provided as a separate + * class in case any modifications or additional properties specific to GERG2008 are required.
+ * + * @author YourName + * @version 1.0 + */ +public class ComponentGERG2008 extends ComponentEos { + private static final long serialVersionUID = 1000; + + /** + * Constructor for ComponentGERG2008. + * + * @param name Name of component. + * @param moles Total number of moles of component. + * @param molesInPhase Number of moles in phase. + * @param compIndex Index number of component in phase object component array. + */ + public ComponentGERG2008(String name, double moles, double molesInPhase, int compIndex) { + super(name, moles, molesInPhase, compIndex); + } + + /** + * Constructor for ComponentGERG2008. + * + * @param number Not used. + * @param TC Critical temperature. + * @param PC Critical pressure. + * @param M Molar mass. + * @param a Acentric factor. + * @param moles Total number of moles of component. + */ + public ComponentGERG2008(int number, double TC, double PC, double M, double a, double moles) { + super(number, TC, PC, M, a, moles); + } + + @Override + public ComponentGERG2008 clone() { + ComponentGERG2008 clonedComponent = null; + try { + clonedComponent = (ComponentGERG2008) super.clone(); + } catch (Exception ex) { + logger.error("Cloning failed.", ex); + } + return clonedComponent; + } + + @Override + public double getVolumeCorrection() { + // GERG2008 does not use a volume correction term. + return 0.0; + } + + @Override + public double calca() { + // Return zero if a calculation for "a" (attraction parameter) is not needed for GERG2008. + return 0; + } + + @Override + public double calcb() { + // Return zero if a calculation for "b" (repulsion parameter) is not needed for GERG2008. + return 0; + } + + @Override + public double fugcoef(PhaseInterface phase) { + // Return the already computed fugacity coefficient. + return fugacityCoefficient; + } + + @Override + public double alpha(double temperature) { + // GERG2008 may not need a temperature-dependent alpha function; return 1. + return 1; + } + + @Override + public double diffaT(double temperature) { + // Return unity unless a temperature derivative is required. + return 1; + } + +@Override +public double diffdiffaT(double temperature) { + // Return unity unless a second derivative is needed. + return 1; + } +} diff --git a/src/main/java/neqsim/thermo/component/ComponentLeachmanEos.java b/src/main/java/neqsim/thermo/component/ComponentLeachmanEos.java new file mode 100644 index 000000000..1f2edd297 --- /dev/null +++ b/src/main/java/neqsim/thermo/component/ComponentLeachmanEos.java @@ -0,0 +1,57 @@ +package neqsim.thermo.component; + +import neqsim.thermo.phase.PhaseInterface; + +/** + *+ * ComponentLeachman class. + *
+ * + * @author Even Solbraa Leachman + * @version $Id: $Id + */ +public class ComponentLeachmanEos extends ComponentFundamentalEOS { + /** Serialization version UID. */ + private static final long serialVersionUID = 1000; + + /** + *+ * Constructor for ComponentLeachman. + *
+ * + * @param name Name of component. + * @param moles Total number of moles of component. + * @param molesInPhase Number of moles in phase. + * @param compIndex Index number of component in phase object component array. + */ + public ComponentLeachmanEos(String name, double moles, double molesInPhase, int compIndex) { + super(name, moles, molesInPhase, compIndex); + } + + + + /** {@inheritDoc} */ + @Override + public ComponentLeachmanEos clone() { + ComponentLeachmanEos clonedComponent = null; + try { + clonedComponent = (ComponentLeachmanEos) super.clone(); + } catch (Exception ex) { + logger.error("Cloning failed.", ex); + } + + return clonedComponent; + } + + + + /** {@inheritDoc} */ + @Override + public double fugcoef(PhaseInterface phase) { + return fugacityCoefficient; + } + + + + +} diff --git a/src/main/java/neqsim/thermo/component/ComponentVegaEos.java2 b/src/main/java/neqsim/thermo/component/ComponentVegaEos.java2 new file mode 100644 index 000000000..f7598e8f1 --- /dev/null +++ b/src/main/java/neqsim/thermo/component/ComponentVegaEos.java2 @@ -0,0 +1,101 @@ +package neqsim.thermo.component; + +import neqsim.thermo.phase.PhaseInterface; + +/** + *+ * ComponentVega class. + *
+ * + * @author Even Solbraa Vega + * @version $Id: $Id + */ +public class ComponentVegaEos extends ComponentEos { + /** Serialization version UID. */ + private static final long serialVersionUID = 1000; + + /** + *+ * Constructor for ComponentVega + *
+ * + * @param name Name of component. + * @param moles Total number of moles of component. + * @param molesInPhase Number of moles in phase. + * @param compIndex Index number of component in phase object component array. + */ + public ComponentVegaEos(String name, double moles, double molesInPhase, int compIndex) { + super(name, moles, molesInPhase, compIndex); + } + + /** + *+ * Constructor for ComponentVega + *
+ * + * @param number a int. Not used. + * @param TC Critical temperature + * @param PC Critical pressure + * @param M Molar mass + * @param a Acentric factor + * @param moles Total number of moles of component. + */ + public ComponentVegaEos(int number, double TC, double PC, double M, double a, double moles) { + super(number, TC, PC, M, a, moles); + } + + /** {@inheritDoc} */ + @Override + public ComponentVegaEos clone() { + ComponentVegaEos clonedComponent = null; + try { + clonedComponent = (ComponentVegaEos) super.clone(); + } catch (Exception ex) { + logger.error("Cloning failed.", ex); + } + + return clonedComponent; + } + + /** {@inheritDoc} */ + @Override + public double getVolumeCorrection() { + return 0.0; + } + + /** {@inheritDoc} */ + @Override + public double calca() { + return 0; + } + + /** {@inheritDoc} */ + @Override + public double calcb() { + return 0; + } + + /** {@inheritDoc} */ + @Override + public double fugcoef(PhaseInterface phase) { + return fugacityCoefficient; + } + + /** {@inheritDoc} */ + @Override + public double alpha(double temperature) { + return 1; + } + + /** {@inheritDoc} */ + @Override + public double diffaT(double temperature) { + return 1; + } + + /** {@inheritDoc} */ + @Override + public double diffdiffaT(double temperature) { + return 1; + } +} diff --git a/src/main/java/neqsim/thermo/phase/Phase.java b/src/main/java/neqsim/thermo/phase/Phase.java index e86d91c75..e2682466d 100644 --- a/src/main/java/neqsim/thermo/phase/Phase.java +++ b/src/main/java/neqsim/thermo/phase/Phase.java @@ -10,6 +10,7 @@ import java.util.ArrayList; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.netlib.util.doubleW; import neqsim.physicalproperties.PhysicalPropertyHandler; import neqsim.physicalproperties.PhysicalPropertyType; import neqsim.physicalproperties.system.PhysicalProperties; @@ -2320,8 +2321,95 @@ public double[] getProperties_Leachman() { throw new IllegalArgumentException("Leachman model only works for hydrogen. Found: " + compName); } } + + + /** {@inheritDoc} */ + @Override + public doubleW[] getAlpha0_Leachman(String hydrogenType) { + neqsim.thermo.util.leachman.NeqSimLeachman test = + new neqsim.thermo.util.leachman.NeqSimLeachman(this, hydrogenType); + return test.getAlpha0_Leachman(); + } + + /** + * If no hydrogentype is specified it checks the component name and chooses the correct hydrogen. + * Checks for other components in the phase and throws an exception if the phase is not pure + * + * @return a matrix of properties of type doubleW. + */ + public doubleW[] getAlpha0_Leachman() { + // Check that the phase contains exactly one component + if (this.getNumberOfComponents() != 1) { + StringBuilder compNames = new StringBuilder(); + for (int i = 0; i < this.getNumberOfComponents(); i++) { + compNames.append(this.getComponent(i).getComponentName()); + if (i < this.getNumberOfComponents() - 1) { + compNames.append(", "); + } + } + throw new IllegalArgumentException("Leachman model only works for pure hydrogen streams. Found components: " + + compNames.toString()); + } + + // Retrieve the component name from the current phase + String compName = this.getComponent(0).getComponentName(); + + // Check the component type and choose the correct hydrogen type + if (compName.equalsIgnoreCase("para-hydrogen")) { + return getAlpha0_Leachman("para"); + } else if (compName.equalsIgnoreCase("ortho-hydrogen")) { + return getAlpha0_Leachman("ortho"); + } else if (compName.equalsIgnoreCase("hydrogen")) { + return getAlpha0_Leachman("normal"); + } else { + throw new IllegalArgumentException("Leachman model only works for hydrogen. Found: " + compName); + } + } + /** {@inheritDoc} */ + @Override + public doubleW[][] getAlphares_Leachman(String hydrogenType) { + neqsim.thermo.util.leachman.NeqSimLeachman test = + new neqsim.thermo.util.leachman.NeqSimLeachman(this, hydrogenType); + return test.getAlphares_Leachman(); + } + + /** + * If no hydrogentype is specified it checks the component name and chooses the correct hydrogen. + * Checks for other components in the phase and throws an exception if the phase is not pure + * + * @return a matrix of properties of type doubleW. + */ + public doubleW[][] getAlphares_Leachman() { + // Check that the phase contains exactly one component + if (this.getNumberOfComponents() != 1) { + StringBuilder compNames = new StringBuilder(); + for (int i = 0; i < this.getNumberOfComponents(); i++) { + compNames.append(this.getComponent(i).getComponentName()); + if (i < this.getNumberOfComponents() - 1) { + compNames.append(", "); + } + } + throw new IllegalArgumentException("Leachman model only works for pure hydrogen streams. Found components: " + + compNames.toString()); + } + + // Retrieve the component name from the current phase + String compName = this.getComponent(0).getComponentName(); + + // Check the component type and choose the correct hydrogen type + if (compName.equalsIgnoreCase("para-hydrogen")) { + return getAlphares_Leachman("para"); + } else if (compName.equalsIgnoreCase("ortho-hydrogen")) { + return getAlphares_Leachman("ortho"); + } else if (compName.equalsIgnoreCase("hydrogen")) { + return getAlphares_Leachman("normal"); + } else { + throw new IllegalArgumentException("Leachman model only works for hydrogen. Found: " + compName); + } + } + /** {@inheritDoc} */ @Override public double getDensity_AGA8() { diff --git a/src/main/java/neqsim/thermo/phase/PhaseFundamentalEOS.java b/src/main/java/neqsim/thermo/phase/PhaseFundamentalEOS.java new file mode 100644 index 000000000..482b044c2 --- /dev/null +++ b/src/main/java/neqsim/thermo/phase/PhaseFundamentalEOS.java @@ -0,0 +1,325 @@ +package neqsim.thermo.phase; + +import org.netlib.util.doubleW; +import neqsim.thermo.component.ComponentFundamentalEOSInterface; +import neqsim.thermo.mixingrule.MixingRuleTypeInterface; +import neqsim.thermo.mixingrule.MixingRulesInterface; + +/** + * Abstract base class for Helmholtz-energy-based equations of state. + * Assumes subclasses use reduced Helmholtz energy (a/RT) and compute properties from it. + * + * @author victorigi + * @since 27.03.2025 + */ +public abstract class PhaseFundamentalEOS extends Phase implements PhaseFundamentalEOSInterface { + private static final long serialVersionUID = 1L; + + doubleW[][] ar; + doubleW[] a0; + double density; + double T; + double RT; + double dPdD; + double dPdT; + double d2PdTD; + double A; + double G; + double U; + double H; + double S; + double Cp; + double Cv; + double JT; + double W; + double Kappa; + double d2PdD2; + + + public PhaseFundamentalEOS() { + super(); + setType(PhaseType.GAS); // Default; subclasses can override after density calc + } + + /** + * Compute molar density [mol/m3] at specified T and P. + */ + public abstract double solveDensity(double temperature, double pressure); + + /** + * Compute reduced residual Helmholtz energy and its derivatives. + * /** + * Get reduced residual helmholtz free energy and its derivatives. + * The returned array has the following structure: + *+ * Get the derivative of pressure with respect to density. + *
+ * + * @return double + */ + public double getDPdD() { + return dPdD; + } + + /** {@inheritDoc} */ + @Override + public double getGibbsEnergy() { + return G * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getJouleThomsonCoefficient() { + return JT * 1e3; // [K/bar] + } + + /** {@inheritDoc} */ + @Override + public double getEnthalpy() { + return H * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getEntropy() { + return S * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getInternalEnergy() { + return U * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getCp() { + return Cp * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getCv() { + return Cv * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getSoundSpeed() { + return W; + } + + /** {@inheritDoc} */ + @Override + public double getKappa() { + return Kappa; + } + + /** {@inheritDoc} */ + @Override + public double molarVolume(double pressure, double temperature, double A, double B, PhaseType pt) { + return 1 / density; + } + + + + + /** {@inheritDoc} */ + @Override + public double getdPdTVn() { + return density * R * (1 + ar[0][1].val - ar[1][1].val); + } + + /** {@inheritDoc} */ + @Override + public double getdPdVTn() { + return -density * density * R * T * (1 + 2 * ar[0][1].val + ar[0][2].val) / numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getdPdrho() { + return R * T * (1 + 2 * ar[0][1].val + ar[0][2].val); + } + + /** {@inheritDoc} */ + @Override + public double getdrhodP() { + return 1.0 / getdPdrho(); + } + + /** {@inheritDoc} */ + @Override + public double getdrhodT() { + return -getdPdTVn() / getdPdrho(); + } + + /** + *+ * getF. + *
+ * + * @return a double + */ + public double getF() { + return numberOfMolesInPhase * ar[0][0].val; + } + + /** {@inheritDoc} */ + @Override + public double dFdTdV() { + return numberOfMolesInPhase * ar[1][1].val / (temperature * getVolume()); + } + + /** {@inheritDoc} */ + @Override + public double dFdN(int i) { + return ((ComponentFundamentalEOSInterface) getComponent(i)).dFdN(this, this.getNumberOfComponents(), + temperature, pressure); + } + + /** {@inheritDoc} */ + @Override + public double dFdNdN(int i, int j) { + return ((ComponentFundamentalEOSInterface) getComponent(i)).dFdNdN(j, this, this.getNumberOfComponents(), + temperature, pressure); + } + + /** {@inheritDoc} */ + @Override + public double dFdNdV(int i) { + return ((ComponentFundamentalEOSInterface) getComponent(i)).dFdNdV(this, this.getNumberOfComponents(), + temperature, pressure); + } + + /** {@inheritDoc} */ + @Override + public double dFdNdT(int i) { + return ((ComponentFundamentalEOSInterface) getComponent(i)).dFdNdT(this, this.getNumberOfComponents(), + temperature, pressure); + } + + + + // --- Provide defaults to avoid forcing subclass overrides if not needed --- + + @Override + public double getA() { + throw new UnsupportedOperationException("getA() not supported for fundamental EOS"); + } + + @Override + public double getB() { + throw new UnsupportedOperationException("getB() not supported for fundamental EOS"); + } + + @Override +public MixingRulesInterface getMixingRule() { + throw new UnsupportedOperationException("Mixing rule not implemented for PhaseFundamentalEos"); +} + + @Override + public MixingRuleTypeInterface getMixingRuleType() { + throw new UnsupportedOperationException("Mixing rule not implemented for PhaseFundamentalEos"); + } + + @Override + public void resetMixingRule(MixingRuleTypeInterface mixingRule) { + throw new UnsupportedOperationException("Mixing rule not implemented for PhaseFundamentalEos"); + } + + @Override + public void setMixingRule(MixingRuleTypeInterface mixingRule) { + throw new UnsupportedOperationException("Mixing rule not implemented for PhaseFundamentalEos"); + } + + @Override + public void setMixingRuleGEModel(String model) { + throw new UnsupportedOperationException("Mixing rule GE Model not implemented for PhaseFundamentalEos"); + } + + +} diff --git a/src/main/java/neqsim/thermo/phase/PhaseFundamentalEOSInterface.java b/src/main/java/neqsim/thermo/phase/PhaseFundamentalEOSInterface.java new file mode 100644 index 000000000..cb414cda4 --- /dev/null +++ b/src/main/java/neqsim/thermo/phase/PhaseFundamentalEOSInterface.java @@ -0,0 +1,244 @@ +package neqsim.thermo.phase; + +import org.netlib.util.doubleW; + +public interface PhaseFundamentalEOSInterface { + + + /** + * Compute molar density [mol/m3] at specified temperature and pressure. + * + * @param temperature Temperature in Kelvin. + * @param pressure Pressure (in the appropriate unit for your system). + * @return Molar density in [mol/m3]. + */ + double solveDensity(double temperature, double pressure); + + /** + * Get the reduced residual Helmholtz free energy and its derivatives. + * The returned 2D array has the following structure: + *This class upgrades the old GERG2004Eos by using the NeqSimGERG2008 routines to + * calculate thermodynamic properties. In addition, extensive properties are returned by + * multiplying the molar values by the number of moles in the phase. This version mimics the + * structure of the Leachman EOS implementation.
+ * + * @author YourName + * @version 1.1 + */ +public class PhaseGERG2008Eos extends PhaseEos { + private static final long serialVersionUID = 1000; + + int IPHASE = 0; + boolean okVolume = true; + double enthalpy = 0.0; + double entropy = 0.0; + double gibbsEnergy = 0.0; + double CpGERG = 0.0; + double CvGERG = 0.0; + double internalEnergy = 0.0; + double JTcoef = 0.0; + + // Helper for property calculations using GERG2008 + //NeqSimGERG2008 gerg2008 = new NeqSimGERG2008(); + + /** + * Constructor for PhaseGERG2008Eos. + */ + public PhaseGERG2008Eos() { + thermoPropertyModelName = "GERG-EoS 2008"; + } + + /** {@inheritDoc} */ + @Override + public PhaseGERG2008Eos clone() { + PhaseGERG2008Eos clonedPhase = null; + try { + clonedPhase = (PhaseGERG2008Eos) super.clone(); + } catch (Exception ex) { + logger.error("Cloning failed.", ex); + } + return clonedPhase; + } + + /** {@inheritDoc} */ + @Override + public void addComponent(String name, double moles, double molesInPhase, int compNumber) { + super.addComponent(name, molesInPhase, compNumber); + // Use the GERG2008-specific component. + componentArray[compNumber] = new ComponentGERG2008(name, moles, molesInPhase, compNumber); + } + + /** {@inheritDoc} */ + @Override + public void init(double totalNumberOfMoles, int numberOfComponents, int initType, PhaseType pt, double beta) { + IPHASE = pt == PhaseType.LIQUID ? -1 : -2; + super.init(totalNumberOfMoles, numberOfComponents, initType, pt, beta); + + if (!okVolume) { + IPHASE = pt == PhaseType.LIQUID ? -2 : -1; + super.init(totalNumberOfMoles, numberOfComponents, initType, pt, beta); + } + if (initType >= 1) { + // Let the GERG2008 helper map the phase composition + double[] properties = new double[18]; + properties = getProperties_GERG2008(); + // Retrieve the molar thermodynamic properties from GERG2008. + // Assumed mapping: + // properties[6]: internal energy (J/mol) + // properties[7]: enthalpy (J/mol) + // properties[8]: entropy (J/mol·K) + // properties[9]: Cv (J/mol·K) + // properties[10]: Cp (J/mol·K) + // properties[12]: Gibbs energy (J/mol) + // properties[13]: Joule-Thomson coefficient (K/kPa) + internalEnergy = properties[6]; + enthalpy = properties[7]; + entropy = properties[8]; + CvGERG = properties[9]; + CpGERG = properties[10]; + gibbsEnergy = properties[12]; + JTcoef = properties[13]; + } + super.init(totalNumberOfMoles, numberOfComponents, initType, pt, beta); + } + + @Override + public double getGibbsEnergy() { + return gibbsEnergy * numberOfMolesInPhase; + } + + @Override + public double getJouleThomsonCoefficient() { + return JTcoef * 1e3; // e.g., converting from K/kPa to K/bar + } + + @Override + public double getEnthalpy() { + return enthalpy * numberOfMolesInPhase; + } + + @Override + public double getEntropy() { + return entropy * numberOfMolesInPhase; + } + + @Override + public double getInternalEnergy() { + return internalEnergy * numberOfMolesInPhase; + } + + @Override + public double getCp() { + return CpGERG * numberOfMolesInPhase; + } + + @Override + public double getCv() { + return CvGERG * numberOfMolesInPhase; + } + + /** + * Computes the molar volume using the GERG2008 density routine. + *+ * We assume that gerg2008.getMolarDensity(this) returns the molar density in [mol/m³]. + * Then, for consistency with the Leachman approach, we define: + * + * molarVolume = 1e5 / molarDensity. + *
+ */ + @Override + public double molarVolume(double pressure, double temperature, double A, double B, PhaseType pt) + throws neqsim.util.exception.IsNaNException, neqsim.util.exception.TooManyIterationsException { + return getMolarMass() * 1e5 / getDensity_GERG2008(); + } +} diff --git a/src/main/java/neqsim/thermo/phase/PhaseInterface.java b/src/main/java/neqsim/thermo/phase/PhaseInterface.java index 2278b7005..fe94e9bbc 100644 --- a/src/main/java/neqsim/thermo/phase/PhaseInterface.java +++ b/src/main/java/neqsim/thermo/phase/PhaseInterface.java @@ -6,6 +6,7 @@ package neqsim.thermo.phase; +import org.netlib.util.doubleW; import neqsim.physicalproperties.PhysicalPropertyType; import neqsim.physicalproperties.system.PhysicalProperties; import neqsim.physicalproperties.system.PhysicalPropertyModel; @@ -15,6 +16,7 @@ import neqsim.thermo.mixingrule.MixingRuleTypeInterface; import neqsim.thermo.mixingrule.MixingRulesInterface; import neqsim.thermo.system.SystemInterface; + /** *@@ -453,6 +455,45 @@ public default void initPhysicalProperties(String name) { */ public double[] getProperties_Leachman(); + + + /** + *
+ * method to get Leachman alpha0 of a phase using the Leachman EoS. + *
+ * + * @param hydrogenType a {@link java.lang.String} object + * @return a matrix of the reduced ideal helmholtz free energy and its derivatives + */ + public doubleW[] getAlpha0_Leachman(String hydrogenType); + + + /** + * Overloaded method to get the Leachman a0matrix with default hydrogen type ('normal'). + * + * @return matrix of the reduced ideal helmholtz free energy and its derivatives + */ + public doubleW[] getAlpha0_Leachman(); + + /** + *+ * method to get Leachman alphares of a phase using the Leachman EoS. + *
+ * + * @param hydrogenType a {@link java.lang.String} object + * @return a matrix of the reduced residual helmholtz free energy and its derivatives + */ + public doubleW[][] getAlphares_Leachman(String hydrogenType); + + + /** + * Overloaded method to get the Leachman armatrix with default hydrogen type ('normal'). + * + * @return matrix of the reduced residual helmholtz free energy and its derivatives + */ + public doubleW[][] getAlphares_Leachman(); + + /** * method to get helium density of a phase using the Vega EoS. * @@ -2088,4 +2129,5 @@ public default boolean hasComponent(String name) { * @return double Z volume corrected */ public double getZvolcorr(); + } diff --git a/src/main/java/neqsim/thermo/phase/PhaseLeachmanEos copy.java2 b/src/main/java/neqsim/thermo/phase/PhaseLeachmanEos copy.java2 new file mode 100644 index 000000000..f2185e596 --- /dev/null +++ b/src/main/java/neqsim/thermo/phase/PhaseLeachmanEos copy.java2 @@ -0,0 +1,213 @@ +package neqsim.thermo.phase; + +import org.netlib.util.doubleW; +import neqsim.thermo.component.ComponentEosInterface; +import neqsim.thermo.component.ComponentLeachmanEos; + +/** + *+ * PhaseLeachmanEos class. + *
+ * + * @author Even Solbraa + * @version $Id: $Id + */ +public class PhaseLeachmanEosCopy extends PhaseEos { + /** Serialization version UID. */ + private static final long serialVersionUID = 1000; + + int IPHASE = 0; + boolean okVolume = true; + double enthalpy = 0.0; + + double entropy = 0.0; + + double gibbsEnergy = 0.0; + + double CpLeachman = 0.0; + + double CvLeachman = 0.0; + + double internalEnery = 0.0; + + double JTcoef = 0.0; + + doubleW[][] alpharesMatrix = null; + + /** + *+ * Constructor for PhaseLeachmanEos. + *
+ */ + public PhaseLeachmanEos() { + thermoPropertyModelName = "Leachman Eos"; + } + + /** {@inheritDoc} */ + @Override + public PhaseLeachmanEos clone() { + PhaseLeachmanEos clonedPhase = null; + try { + clonedPhase = (PhaseLeachmanEos) super.clone(); + } catch (Exception ex) { + logger.error("Cloning failed.", ex); + } + + return clonedPhase; + } + + /** {@inheritDoc} */ + @Override + public void addComponent(String name, double moles, double molesInPhase, int compNumber) { + super.addComponent(name, molesInPhase, compNumber); + componentArray[compNumber] = new ComponentLeachmanEos(name, moles, molesInPhase, compNumber); + } + + /** {@inheritDoc} */ + @Override + public void init(double totalNumberOfMoles, int numberOfComponents, int initType, PhaseType pt, + double beta) { + + if (initType != 0) { + alpharesMatrix = getAlphares_Leachman(); // F = alpharesMatrix[0][0].val + } + super.init(totalNumberOfMoles, numberOfComponents, initType, pt, beta); + + + + + + if (!okVolume) { + IPHASE = pt == PhaseType.LIQUID ? -2 : -1; + super.init(totalNumberOfMoles, numberOfComponents, initType, pt, beta); + } + if (initType >= 1) { + double[] temp = new double[18]; + temp = getProperties_Leachman(); + + + gibbsEnergy = temp[12]; + internalEnery = temp[6]; // .UOTPX(temperature,pressure/10.0, + // xFracGERG[0],xFracGERG[1],xFracGERG[2],xFracGERG[3],xFracGERG[4],xFracGERG[5],xFracGERG[6],xFracGERG[7],xFracGERG[8],xFracGERG[9],xFracGERG[10],xFracGERG[11],xFracGERG[12],xFracGERG[13],xFracGERG[14],xFracGERG[15],xFracGERG[16],xFracGERG[17],IPHASE); + enthalpy = temp[7]; // gergEOS.HOTPX(temperature,pressure/10.0, + // xFracGERG[0],xFracGERG[1],xFracGERG[2],xFracGERG[3],xFracGERG[4],xFracGERG[5],xFracGERG[6],xFracGERG[7],xFracGERG[8],xFracGERG[9],xFracGERG[10],xFracGERG[11],xFracGERG[12],xFracGERG[13],xFracGERG[14],xFracGERG[15],xFracGERG[16],xFracGERG[17],IPHASE); + entropy = temp[8]; // gergEOS.SOTPX(temperature,pressure/10.0, + // xFracGERG[0],xFracGERG[1],xFracGERG[2],xFracGERG[3],xFracGERG[4],xFracGERG[5],xFracGERG[6],xFracGERG[7],xFracGERG[8],xFracGERG[9],xFracGERG[10],xFracGERG[11],xFracGERG[12],xFracGERG[13],xFracGERG[14],xFracGERG[15],xFracGERG[16],xFracGERG[17],IPHASE); + CpLeachman = temp[10]; // gergEOS.CPOTPX(temperature,pressure/10.0, + // xFracGERG[0],xFracGERG[1],xFracGERG[2],xFracGERG[3],xFracGERG[4],xFracGERG[5],xFracGERG[6],xFracGERG[7],xFracGERG[8],xFracGERG[9],xFracGERG[10],xFracGERG[11],xFracGERG[12],xFracGERG[13],xFracGERG[14],xFracGERG[15],xFracGERG[16],xFracGERG[17],IPHASE); + CvLeachman = temp[9]; // gergEOS.CPOTPX(temperature,pressure/10.0, + // xFracGERG[0],xFracGERG[1],xFracGERG[2],xFracGERG[3],xFracGERG[4],xFracGERG[5],xFracGERG[6],xFracGERG[7],xFracGERG[8],xFracGERG[9],xFracGERG[10],xFracGERG[11],xFracGERG[12],xFracGERG[13],xFracGERG[14],xFracGERG[15],xFracGERG[16],xFracGERG[17],IPHASE); + JTcoef = temp[13]; + + + super.init(totalNumberOfMoles, numberOfComponents, initType, pt, beta); + } + } + + /** {@inheritDoc} */ + @Override + public double getGibbsEnergy() { + return gibbsEnergy * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getJouleThomsonCoefficient() { + return JTcoef * 1e3; // [K/bar] + } + + /** {@inheritDoc} */ + @Override + public double getEnthalpy() { + return enthalpy * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getEntropy() { + return entropy * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getInternalEnergy() { + return internalEnery * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getCp() { + return CpLeachman * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getCv() { + return CvLeachman * numberOfMolesInPhase; + } + + + /** {@inheritDoc} */ + @Override + public double molarVolume(double pressure, double temperature, double A, double B, PhaseType pt) + throws neqsim.util.exception.IsNaNException, + neqsim.util.exception.TooManyIterationsException { + return getMolarMass() * 1e5 / getDensity_Leachman(); + } + + + + /** {@inheritDoc} */ + @Override + public double getF() { + return alpharesMatrix[0][0].val; + } + + /** {@inheritDoc} */ + @Override + public double dFdT() { + return - alpharesMatrix[1][0].val / getTemperature(); + } + + /** {@inheritDoc} */ + @Override + public double dFdTdT() { + return (2 * alpharesMatrix[1][0].val + alpharesMatrix[2][0].val) / (getTemperature() * getTemperature()); + } + + + /** {@inheritDoc} */ + @Override + public double dFdV() { + return - alpharesMatrix[0][1].val / getVolume(); + } + + /** {@inheritDoc} */ + @Override + public double dFdVdV() { + return (2 * alpharesMatrix[0][1].val + alpharesMatrix[0][2].val) / (getVolume() * getVolume()); + } + + /** {@inheritDoc} */ + @Override + public double dFdTdV() { + double T = getTemperature(); + double V = getVolume(); + return alpharesMatrix[1][1].val / (T * V); + } + + /** {@inheritDoc} */ + @Override + public double dFdN(int i) { + return ((ComponentEosInterface) getComponent(i)) + .dFdN(this, this.getNumberOfComponents(), temperature, pressure); + } + + /** {@inheritDoc} */ + @Override + public double dFdNdV(int i) { + return ((ComponentEosInterface) getComponent(i)) + .dFdNdV(this, this.getNumberOfComponents(), temperature, pressure); + } + +} diff --git a/src/main/java/neqsim/thermo/phase/PhaseLeachmanEos.java b/src/main/java/neqsim/thermo/phase/PhaseLeachmanEos.java new file mode 100644 index 000000000..6c93d357c --- /dev/null +++ b/src/main/java/neqsim/thermo/phase/PhaseLeachmanEos.java @@ -0,0 +1,118 @@ +package neqsim.thermo.phase; + +import org.netlib.util.doubleW; +import neqsim.thermo.component.ComponentLeachmanEos; + +/** + *+ * PhaseLeachmanEos class. + *
+ * + * @author Even Solbraa + * @version $Id: $Id + */ +public class PhaseLeachmanEos extends PhaseFundamentalEOS implements PhaseFundamentalEOSInterface { + /** Serialization version UID. */ + private static final long serialVersionUID = 1000; + + int IPHASE = 0; + boolean okVolume = true; + double enthalpy = 0.0; + + double entropy = 0.0; + + double gibbsEnergy = 0.0; + + double CpLeachman = 0.0; + + double CvLeachman = 0.0; + + double internalEnery = 0.0; + + double JTcoef = 0.0; + + doubleW[][] alpharesMatrix = null; + + /** + *+ * Constructor for PhaseLeachmanEos. + *
+ */ + public PhaseLeachmanEos() { + thermoPropertyModelName = "Leachman Eos"; + } + + /** {@inheritDoc} */ + @Override + public PhaseLeachmanEos clone() { + PhaseLeachmanEos clonedPhase = null; + try { + clonedPhase = (PhaseLeachmanEos) super.clone(); + } catch (Exception ex) { + logger.error("Cloning failed.", ex); + } + + return clonedPhase; + } + + /** {@inheritDoc} */ + @Override + public void addComponent(String name, double moles, double molesInPhase, int compNumber) { + super.addComponent(name, molesInPhase, compNumber); + componentArray[compNumber] = new ComponentLeachmanEos(name, moles, molesInPhase, compNumber); + } + + /** {@inheritDoc} */ + @Override + public void init(double totalNumberOfMoles, int numberOfComponents, int initType, PhaseType pt, + double beta) { + + if (initType != 0) { + + } + super.init(totalNumberOfMoles, numberOfComponents, initType, pt, beta); + + + + + + if (!okVolume) { + IPHASE = pt == PhaseType.LIQUID ? -2 : -1; + super.init(totalNumberOfMoles, numberOfComponents, initType, pt, beta); + } + if (initType >= 1) { + density = solveDensity(temperature, pressure);//mol/m3 + + + + super.init(totalNumberOfMoles, numberOfComponents, initType, pt, beta); + } + } + + + /** {@inheritDoc} */ + @Override + public double solveDensity(double temperature, double pressure) { + return getDensity_Leachman(); + } + + /** {@inheritDoc} */ + @Override + public double getDensity() { + return getDensity_Leachman(); + } + + + /** {@inheritDoc} */ + @Override + public doubleW[] getAlpha0Matrix() { + return getAlpha0_Leachman(); + } + + /** {@inheritDoc} */ + @Override + public doubleW[][] getAlpharesMatrix() { + return getAlphares_Leachman(); + } + +} diff --git a/src/main/java/neqsim/thermo/phase/PhaseVegaEos.java2 b/src/main/java/neqsim/thermo/phase/PhaseVegaEos.java2 new file mode 100644 index 000000000..769fe6c9a --- /dev/null +++ b/src/main/java/neqsim/thermo/phase/PhaseVegaEos.java2 @@ -0,0 +1,143 @@ +package neqsim.thermo.phase; + +import neqsim.thermo.component.ComponentVegaEos; + +/** + *+ * PhaseVegaEos class. + *
+ * + * @author Even Solbraa + * @version $Id: $Id + */ +public class PhaseVegaEos extends PhaseFundamentalEOS { + /** Serialization version UID. */ + private static final long serialVersionUID = 1000; + + int IPHASE = 0; + boolean okVolume = true; + double enthalpy = 0.0; + + double entropy = 0.0; + + double gibbsEnergy = 0.0; + + double CpVega = 0.0; + + double CvVega = 0.0; + + double internalEnery = 0.0; + + double JTcoef = 0.0; + + /** + *+ * Constructor for PhaseVegaEos. + *
+ */ + public PhaseVegaEos() { + thermoPropertyModelName = "Vega Eos"; + } + + /** {@inheritDoc} */ + @Override + public PhaseVegaEos clone() { + PhaseVegaEos clonedPhase = null; + try { + clonedPhase = (PhaseVegaEos) super.clone(); + } catch (Exception ex) { + logger.error("Cloning failed.", ex); + } + + return clonedPhase; + } + + /** {@inheritDoc} */ + @Override + public void addComponent(String name, double moles, double molesInPhase, int compNumber) { + super.addComponent(name, molesInPhase, compNumber); + componentArray[compNumber] = new ComponentVegaEos(name, moles, molesInPhase, compNumber); + } + + /** {@inheritDoc} */ + @Override + public void init(double totalNumberOfMoles, int numberOfComponents, int initType, PhaseType pt, + double beta) { + IPHASE = pt == PhaseType.LIQUID ? -1 : -2; + super.init(totalNumberOfMoles, numberOfComponents, initType, pt, beta); + + if (!okVolume) { + IPHASE = pt == PhaseType.LIQUID ? -2 : -1; + super.init(totalNumberOfMoles, numberOfComponents, initType, pt, beta); + } + if (initType >= 1) { + double[] temp = new double[18]; + temp = getProperties_Vega(); + + + gibbsEnergy = temp[12]; + internalEnery = temp[6]; // .UOTPX(temperature,pressure/10.0, + // xFracGERG[0],xFracGERG[1],xFracGERG[2],xFracGERG[3],xFracGERG[4],xFracGERG[5],xFracGERG[6],xFracGERG[7],xFracGERG[8],xFracGERG[9],xFracGERG[10],xFracGERG[11],xFracGERG[12],xFracGERG[13],xFracGERG[14],xFracGERG[15],xFracGERG[16],xFracGERG[17],IPHASE); + enthalpy = temp[7]; // gergEOS.HOTPX(temperature,pressure/10.0, + // xFracGERG[0],xFracGERG[1],xFracGERG[2],xFracGERG[3],xFracGERG[4],xFracGERG[5],xFracGERG[6],xFracGERG[7],xFracGERG[8],xFracGERG[9],xFracGERG[10],xFracGERG[11],xFracGERG[12],xFracGERG[13],xFracGERG[14],xFracGERG[15],xFracGERG[16],xFracGERG[17],IPHASE); + entropy = temp[8]; // gergEOS.SOTPX(temperature,pressure/10.0, + // xFracGERG[0],xFracGERG[1],xFracGERG[2],xFracGERG[3],xFracGERG[4],xFracGERG[5],xFracGERG[6],xFracGERG[7],xFracGERG[8],xFracGERG[9],xFracGERG[10],xFracGERG[11],xFracGERG[12],xFracGERG[13],xFracGERG[14],xFracGERG[15],xFracGERG[16],xFracGERG[17],IPHASE); + CpVega = temp[10]; // gergEOS.CPOTPX(temperature,pressure/10.0, + // xFracGERG[0],xFracGERG[1],xFracGERG[2],xFracGERG[3],xFracGERG[4],xFracGERG[5],xFracGERG[6],xFracGERG[7],xFracGERG[8],xFracGERG[9],xFracGERG[10],xFracGERG[11],xFracGERG[12],xFracGERG[13],xFracGERG[14],xFracGERG[15],xFracGERG[16],xFracGERG[17],IPHASE); + CvVega = temp[9]; // gergEOS.CPOTPX(temperature,pressure/10.0, + // xFracGERG[0],xFracGERG[1],xFracGERG[2],xFracGERG[3],xFracGERG[4],xFracGERG[5],xFracGERG[6],xFracGERG[7],xFracGERG[8],xFracGERG[9],xFracGERG[10],xFracGERG[11],xFracGERG[12],xFracGERG[13],xFracGERG[14],xFracGERG[15],xFracGERG[16],xFracGERG[17],IPHASE); + JTcoef = temp[13]; + super.init(totalNumberOfMoles, numberOfComponents, initType, pt, beta); + } + } + + /** {@inheritDoc} */ + @Override + public double getGibbsEnergy() { + return gibbsEnergy * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getJouleThomsonCoefficient() { + return JTcoef * 1e3; // [K/bar] + } + + /** {@inheritDoc} */ + @Override + public double getEnthalpy() { + return enthalpy * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getEntropy() { + return entropy * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getInternalEnergy() { + return internalEnery * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getCp() { + return CpVega * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double getCv() { + return CvVega * numberOfMolesInPhase; + } + + /** {@inheritDoc} */ + @Override + public double molarVolume(double pressure, double temperature, double A, double B, PhaseType pt) + throws neqsim.util.exception.IsNaNException, + neqsim.util.exception.TooManyIterationsException { + return getMolarMass() * 1e5 / getDensity_Vega(); + } +} diff --git a/src/main/java/neqsim/thermo/system/SystemGERG2008Eos.java b/src/main/java/neqsim/thermo/system/SystemGERG2008Eos.java new file mode 100644 index 000000000..8bf3d3208 --- /dev/null +++ b/src/main/java/neqsim/thermo/system/SystemGERG2008Eos.java @@ -0,0 +1,91 @@ +package neqsim.thermo.system; + +import neqsim.thermo.phase.PhaseGERG2008Eos; +import neqsim.thermo.phase.PhaseHydrate; +import neqsim.thermo.phase.PhasePureComponentSolid; + +/** + * This class defines a thermodynamic system using the GERG2008 equation of state. + * It is analogous to the GERG2004 system, but uses the upgraded GERG2008 model. + * + * @author YourName + * @version 1.0 + */ +public class SystemGERG2008Eos extends SystemEos { + private static final long serialVersionUID = 1000; + + /** + * Constructor for SystemGERG2008Eos. + */ + public SystemGERG2008Eos() { + this(298.15, 1.0, false); + } + + /** + * Constructor for SystemGERG2008Eos. + * + * @param T The temperature in Kelvin. + * @param P The pressure in bara (absolute pressure). + */ + public SystemGERG2008Eos(double T, double P) { + this(T, P, false); + } + + /** + * Constructor for SystemGERG2008Eos. + * + * @param T The temperature in Kelvin. + * @param P The pressure in bara (absolute pressure). + * @param checkForSolids Set true to enable solid phase check and calculations. + */ + public SystemGERG2008Eos(double T, double P, boolean checkForSolids) { + super(T, P, checkForSolids); + modelName = "GERG2008-EOS"; + + // Initialize the phase array with GERG2008 phases. + for (int i = 0; i < numberOfPhases; i++) { + phaseArray[i] = new PhaseGERG2008Eos(); + phaseArray[i].setTemperature(T); + phaseArray[i].setPressure(P); + } + + if (solidPhaseCheck) { + setNumberOfPhases(5); + phaseArray[numberOfPhases - 1] = new PhasePureComponentSolid(); + phaseArray[numberOfPhases - 1].setTemperature(T); + phaseArray[numberOfPhases - 1].setPressure(P); + phaseArray[numberOfPhases - 1].setRefPhase(phaseArray[1].getRefPhase()); + } + + // Hydrate check (if enabled) is handled similarly. + if (hydrateCheck) { + phaseArray[numberOfPhases - 1] = new PhaseHydrate(); + phaseArray[numberOfPhases - 1].setTemperature(T); + phaseArray[numberOfPhases - 1].setPressure(P); + phaseArray[numberOfPhases - 1].setRefPhase(phaseArray[1].getRefPhase()); + } + + this.useVolumeCorrection(false); + commonInitialization(); + } + + @Override + public SystemGERG2008Eos clone() { + SystemGERG2008Eos clonedSystem = null; + try { + clonedSystem = (SystemGERG2008Eos) super.clone(); + } catch (Exception ex) { + logger.error("Cloning failed.", ex); + } + return clonedSystem; + } + + /** + * Common initialization settings for the GERG2008 EOS system. + */ + public void commonInitialization() { + setImplementedCompositionDeriativesofFugacity(false); + setImplementedPressureDeriativesofFugacity(false); + setImplementedTemperatureDeriativesofFugacity(false); + } +} diff --git a/src/main/java/neqsim/thermo/system/SystemLeachmanEos.java b/src/main/java/neqsim/thermo/system/SystemLeachmanEos.java new file mode 100644 index 000000000..ed32c148b --- /dev/null +++ b/src/main/java/neqsim/thermo/system/SystemLeachmanEos.java @@ -0,0 +1,99 @@ +package neqsim.thermo.system; + +import neqsim.thermo.phase.PhaseHydrate; +import neqsim.thermo.phase.PhaseLeachmanEos; +import neqsim.thermo.phase.PhasePureComponentSolid; + +/** + * This class defines a thermodynamic system using the LeachmanEos equation of state. + * + * @author Even Solbraa + * @version $Id: $Id + */ +public class SystemLeachmanEos extends SystemEos { + /** Serialization version UID. */ + private static final long serialVersionUID = 1000; + + /** + *+ * Constructor for SystemLeachmanEos. + *
+ */ + public SystemLeachmanEos() { + this(298.15, 1.0, false); + } + + /** + *+ * Constructor for SystemLeachmanEos. + *
+ * + * @param T The temperature in unit Kelvin + * @param P The pressure in unit bara (absolute pressure) + */ + public SystemLeachmanEos(double T, double P) { + this(T, P, false); + } + + /** + *+ * Constructor for SystemLeachmanEos. + *
+ * + * @param T The temperature in unit Kelvin + * @param P The pressure in unit bara (absolute pressure) + * @param checkForSolids Set true to do solid phase check and calculations + */ + public SystemLeachmanEos(double T, double P, boolean checkForSolids) { + super(T, P, checkForSolids); + modelName = "Leachman-EOS"; + + for (int i = 0; i < numberOfPhases; i++) { + phaseArray[i] = new PhaseLeachmanEos(); + phaseArray[i].setTemperature(T); + phaseArray[i].setPressure(P); + } + + if (solidPhaseCheck) { + setNumberOfPhases(5); + phaseArray[numberOfPhases - 1] = new PhasePureComponentSolid(); + phaseArray[numberOfPhases - 1].setTemperature(T); + phaseArray[numberOfPhases - 1].setPressure(P); + phaseArray[numberOfPhases - 1].setRefPhase(phaseArray[1].getRefPhase()); + } + + // What could set hydratecheck? Will never be true + if (hydrateCheck) { + phaseArray[numberOfPhases - 1] = new PhaseHydrate(); + phaseArray[numberOfPhases - 1].setTemperature(T); + phaseArray[numberOfPhases - 1].setPressure(P); + phaseArray[numberOfPhases - 1].setRefPhase(phaseArray[1].getRefPhase()); + } + this.useVolumeCorrection(false); + commonInitialization(); + } + + /** {@inheritDoc} */ + @Override + public SystemLeachmanEos clone() { + SystemLeachmanEos clonedSystem = null; + try { + clonedSystem = (SystemLeachmanEos) super.clone(); + } catch (Exception ex) { + logger.error("Cloning failed.", ex); + } + + return clonedSystem; + } + + /** + *+ * commonInitialization. + *
+ */ + public void commonInitialization() { + setImplementedCompositionDeriativesofFugacity(false); + setImplementedPressureDeriativesofFugacity(false); + setImplementedTemperatureDeriativesofFugacity(false); + } +} diff --git a/src/main/java/neqsim/thermo/system/SystemVegaEos.java2 b/src/main/java/neqsim/thermo/system/SystemVegaEos.java2 new file mode 100644 index 000000000..953efa7af --- /dev/null +++ b/src/main/java/neqsim/thermo/system/SystemVegaEos.java2 @@ -0,0 +1,99 @@ +package neqsim.thermo.system; + +import neqsim.thermo.phase.PhaseHydrate; +import neqsim.thermo.phase.PhasePureComponentSolid; +import neqsim.thermo.phase.PhaseVegaEos; + +/** + * This class defines a thermodynamic system using the VegaEos equation of state. + * + * @author Even Solbraa + * @version $Id: $Id + */ +public class SystemVegaEos extends SystemEos { + /** Serialization version UID. */ + private static final long serialVersionUID = 1000; + + /** + *+ * Constructor for SystemVegaEos. + *
+ */ + public SystemVegaEos() { + this(298.15, 1.0, false); + } + + /** + *+ * Constructor for SystemVegaEos. + *
+ * + * @param T The temperature in unit Kelvin + * @param P The pressure in unit bara (absolute pressure) + */ + public SystemVegaEos(double T, double P) { + this(T, P, false); + } + + /** + *+ * Constructor for SystemVegaEos. + *
+ * + * @param T The temperature in unit Kelvin + * @param P The pressure in unit bara (absolute pressure) + * @param checkForSolids Set true to do solid phase check and calculations + */ + public SystemVegaEos(double T, double P, boolean checkForSolids) { + super(T, P, checkForSolids); + modelName = "Vega-EOS"; + + for (int i = 0; i < numberOfPhases; i++) { + phaseArray[i] = new PhaseVegaEos(); + phaseArray[i].setTemperature(T); + phaseArray[i].setPressure(P); + } + + if (solidPhaseCheck) { + setNumberOfPhases(5); + phaseArray[numberOfPhases - 1] = new PhasePureComponentSolid(); + phaseArray[numberOfPhases - 1].setTemperature(T); + phaseArray[numberOfPhases - 1].setPressure(P); + phaseArray[numberOfPhases - 1].setRefPhase(phaseArray[1].getRefPhase()); + } + + // What could set hydratecheck? Will never be true + if (hydrateCheck) { + phaseArray[numberOfPhases - 1] = new PhaseHydrate(); + phaseArray[numberOfPhases - 1].setTemperature(T); + phaseArray[numberOfPhases - 1].setPressure(P); + phaseArray[numberOfPhases - 1].setRefPhase(phaseArray[1].getRefPhase()); + } + this.useVolumeCorrection(false); + commonInitialization(); + } + + /** {@inheritDoc} */ + @Override + public SystemVegaEos clone() { + SystemVegaEos clonedSystem = null; + try { + clonedSystem = (SystemVegaEos) super.clone(); + } catch (Exception ex) { + logger.error("Cloning failed.", ex); + } + + return clonedSystem; + } + + /** + *+ * commonInitialization. + *
+ */ + public void commonInitialization() { + setImplementedCompositionDeriativesofFugacity(false); + setImplementedPressureDeriativesofFugacity(false); + setImplementedTemperatureDeriativesofFugacity(false); + } +} diff --git a/src/main/java/neqsim/thermo/util/leachman/NeqSimLeachman.java b/src/main/java/neqsim/thermo/util/leachman/NeqSimLeachman.java index 4545ca9a2..4501e531c 100644 --- a/src/main/java/neqsim/thermo/util/leachman/NeqSimLeachman.java +++ b/src/main/java/neqsim/thermo/util/leachman/NeqSimLeachman.java @@ -106,6 +106,69 @@ public double getMolarDensity() { return D.val; } + public doubleW[] getAlpha0_Leachman() { + // Get temperature and molar density from the phase object + double temperature = phase.getTemperature(); + double molarDensity = getMolarDensity(phase); + + // Create and initialize a 4x4 array for the derivatives. + // Assuming doubleW is a simple wrapper with a public field 'val'. + int rows = 4; + int cols = 4; + doubleW[] a0 = new doubleW[rows]; + for (int i = 0; i < rows; i++) { + a0[i] = new doubleW(0.0); + } + + // Call the Leachman function to fill in the ar array. + // The first two parameters (itau and idelta) are set to 0. + Leachman.Alpha0Leachman(temperature, molarDensity, a0); + + // Return the computed dimensionless residual Helmholtz free energy. + // This is equivalent to alpha_res = A^r/(RT) + return a0; + } + + /** + * Get reduced residual helmholtz free energy and its derivatives. + * The returned array has the following structure: + *