diff --git a/src/main/java/neqsim/processSimulation/processEquipment/pipeline/PipeBeggsAndBrills.java b/src/main/java/neqsim/processSimulation/processEquipment/pipeline/PipeBeggsAndBrills.java index 323116848..09ea1f5b9 100644 --- a/src/main/java/neqsim/processSimulation/processEquipment/pipeline/PipeBeggsAndBrills.java +++ b/src/main/java/neqsim/processSimulation/processEquipment/pipeline/PipeBeggsAndBrills.java @@ -1,95 +1,130 @@ package neqsim.processSimulation.processEquipment.pipeline; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; - -import neqsim.fluidMechanics.flowSystem.FlowSystemInterface; -import neqsim.processSimulation.processEquipment.stream.Stream; import neqsim.processSimulation.processEquipment.stream.StreamInterface; import neqsim.thermo.system.SystemInterface; import neqsim.thermodynamicOperations.ThermodynamicOperations; -/* - * https://www.ihsenergy.ca/support/documentation_ca/Piper/2018_1/Content/HTML_Files/Reference% - * 20materials/Pressure_loss_correlations/c-te-pressure.htm - * - */ - -/* - * For multiphase flow, many of the published correlations are applicable for "vertical flow" only, - * while others apply for "horizontal flow" only. Few correlations apply to the whole spectrum of - * flow situations that may be encountered in oil and gas operations, namely uphill, downhill, - * horizontal, inclined and vertical flow. The Beggs and Brill (1973) correlation, is one of the few - * published correlations capable of handling all these flow directions. It was developed using - * 1" and 1-1/2" sections of pipe that could be inclined at any angle from the horizontal. - * - * The Beggs and Brill multiphase correlation deals with both the friction pressure loss and the - * hydrostatic pressure difference. First the appropriate flow regime for the particular combination - * of gas and liquid rates (Segregated, Intermittent or Distributed) is determined. The liquid - * holdup, and hence, the in-situ density of the gas-liquid mixture is then calculated according to - * the appropriate flow regime, to obtain the hydrostatic pressure difference. A two-phase friction - * factor is calculated based on the "input" gas-liquid ratio and the Fanning friction factor. From - * this the friction pressure loss is calculated using "input" gas-liquid mixture properties. A more - * detailed discussion of each step is given in the following documentation. - * - * If only a single-phase fluid is flowing, the Beggs and Brill multiphase correlation devolves to - * the Fanning Gas or Fanning Liquid correlation. - */ /** *

- * AdiabaticTwoPhasePipe class. + * PipeBeggsAndBrills class. *

* - * @author Even Solbraa + * @author Even Solbraa , Sviatoslav Eroshkin * @version $Id: $Id */ public class PipeBeggsAndBrills extends Pipeline { private static final long serialVersionUID = 1001; + // Inlet pressure of the pipeline (initialization) double inletPressure = 0; + double totalPressureDrop = 0; - boolean setTemperature = false; - - boolean setPressureOut = false; - + // Outlet properties initialization [K] and [bar] protected double temperatureOut = 270; - protected double pressureOut = 0.0; - private double pressureOutLimit = 0.0; - - double length = 100.0; - - double flowLimit = 1e20; - + // Unit for maximum flow String maxflowunit = "kg/hr"; + + // Inside diameter of the pipe [m] double insideDiameter = 0.1; - double velocity = 1.0; + + // Roughness of the pipe wall [m] double pipeWallRoughness = 1e-5; - private double inletElevation = 0; - private double outletElevation = 0; - double dH = 0.0; - private String flowPattern = "unknown"; + + + // Flow pattern of the fluid in the pipe + private String regime = "unknown"; + + // Volume fraction of liquid in the input mixture double inputVolumeFractionLiquid; + + // Froude number of the mixture double mixtureFroudeNumber; + + // Specification of the pipe String pipeSpecification = "AP02"; + + // Ref. Beggs and Brills double A; + + // Area of the pipe [m2] double area; + + // Superficial gas velocity in the pipe [m/s] double supGasVel; + + // Superficial liquid velocity in the pipe [m/s] double supLiquidVel; - double elevation = 0; - double angle; - boolean setPipeElevation; + + // Density of the mixture [kg/m3] double mixtureDensity; + + // Hydrostatic pressure drop in the pipe [bar] double hydrostaticPressureDrop; + + // Holdup ref. Beggs and Brills double El = 0; + + // Superficial mixture velocity in the pipe [m/s] double supMixVel; + + // Frictional pressure loss in the pipe [bar] double frictionPressureLoss; + + // Total pressure drop in the pipe [bar] double pressureDrop; - int numberOfIncrements = 1; + + // Number of pipe increments for calculations + int numberOfIncrements = 5; + + // Length of the pipe [m] + double length = Double.NaN; + + // Elevation of the pipe [m] + double elevation = Double.NaN; + + // Angle of the pipe [degrees] + double angle = Double.NaN; + + // Density of the liquid in the mixture in case of water and oil phases present together + double mixtureLiquidDensity; + + // Viscosity of the liquid in the mixture in case of water and oil phases present together + double mixtureLiquidViscosity; + + // Mass fraction of oil in the mixture in case of water and oil phases present together + double mixtureOilMassFraction; + + // Volume fraction of oil in the mixture in case of water and oil phases present together + double mixtureOilVolumeFraction; + + + // Results initialization (for each segment) + + List pressureProfile = new ArrayList<>(); + List temperatureProfile = new ArrayList<>(); + List pressureDropProfile = new ArrayList<>(); + List flowRegimeProfile = new ArrayList<>(); + + List liquidSuperficialVelocityProfile = new ArrayList<>(); + List gasSuperficialVelocityProfile = new ArrayList<>(); + List mixtureSuperficialVelocityProfile = new ArrayList<>(); + + List mixtureViscosityProfile = new ArrayList<>(); + List mixtureDensityProfile = new ArrayList<>(); + List liquidHoldupProfile = new ArrayList<>(); + List mixtureReynoldsNumber = new ArrayList<>(); + + List lengthProfile = new ArrayList<>(); + List elevationProfile = new ArrayList<>(); /** *

- * Constructor for AdiabaticTwoPhasePipe. + * Constructor for PipeBeggsAndBrills. *

*/ @Deprecated @@ -97,7 +132,7 @@ public PipeBeggsAndBrills() {} /** *

- * Constructor for AdiabaticTwoPhasePipe. + * Constructor for PipeBeggsAndBrills. *

* * @param inStream a {@link neqsim.processSimulation.processEquipment.stream.StreamInterface} @@ -109,7 +144,7 @@ public PipeBeggsAndBrills(StreamInterface inStream) { } /** - * Constructor for AdiabaticTwoPhasePipe. + * Constructor for PipeBeggsAndBrills. * * @param name name of pipe */ @@ -118,7 +153,7 @@ public PipeBeggsAndBrills(String name) { } /** - * Constructor for AdiabaticTwoPhasePipe. + * Constructor for PipeBeggsAndBrills. * * @param name name of pipe * @param inStream input stream @@ -148,28 +183,39 @@ public SystemInterface getThermoSystem() { /** *

- * setOutTemperature. + * Setter for the field elevation. *

* - * @param temperature a double + * @param elevation a double */ - public void setOutTemperature(double temperature) { - setTemperature = true; - this.temperatureOut = temperature; + public void setElevation(double elevation) { + this.elevation = elevation; } + /** *

- * Setter for the field elevation. + * Setter for the field length. *

* - * @param elevation a double + * @param length the length to set */ - public void setElevation(double elevation) { - setPipeElevation = true; - this.elevation = elevation; + public void setLength(double length) { + this.length = length; } + /** + *

+ * setDiameter. + *

+ * + * @param diameter the diameter to set + */ + public void setDiameter(double diameter) { + insideDiameter = diameter; + } + + /** *

* Setter for the field angle. @@ -183,31 +229,40 @@ public void setAngle(double angle) { /** *

- * Setter for the field numberOfIncrements. + * Setter for the field pipeWallRoughness. *

* - * @param numberOfIncrements a int + * @param pipeWallRoughness the pipeWallRoughness to set */ - public void setNumberOfIncrements(int numberOfIncrements) { - this.numberOfIncrements = numberOfIncrements; + public void setPipeWallRoughness(double pipeWallRoughness) { + this.pipeWallRoughness = pipeWallRoughness; } /** *

- * setOutPressure. + * Setter for the field numberOfIncrements. *

* - * @param pressure a double + * @param numberOfIncrements a int */ - public void setOutPressure(double pressure) { - setPressureOut = true; - this.pressureOut = pressure; + public void setNumberOfIncrements(int numberOfIncrements) { + this.numberOfIncrements = numberOfIncrements; } + /** + * Converts the input values from the system measurement units to imperial units. Needed because + * the main equations and coefficients are developed for imperial system *

- * convertSystemUnitToImperial. + * The conversions applied are: *

+ *
    + *
  • Inside Diameter (m) - (feet): multiplied by 3.2808399
  • + *
  • Angle (m) - (feet): multiplied by 0.01745329
  • + *
  • Elevation (m) - (feet): multiplied by 3.2808399
  • + *
  • Length (m) - (feet): multiplied by 3.2808399
  • + *
  • Pipe Wall Roughness (m) - (feet): multiplied by 3.2808399
  • + *
*/ public void convertSystemUnitToImperial() { insideDiameter = insideDiameter * 3.2808399; @@ -218,9 +273,20 @@ public void convertSystemUnitToImperial() { } /** + * Converts the input values from imperial units to the system measurement units. Needed because + * the main equations and coefficients are developed for imperial system *

- * convertSystemUnitToMetric. + * The conversions applied are the inverse of those in the {@link #convertSystemUnitToImperial()} + * method: *

+ *
    + *
  • Inside Diameter (ft - m): divided by 3.2808399
  • + *
  • Angle (ft - m): divided by 0.01745329
  • + *
  • Elevation (ft - m): divided by 3.2808399
  • + *
  • Length (ft - m): divided by 3.2808399
  • + *
  • Pipe Wall Roughness (ft - m): divided by 3.2808399
  • + *
  • Pressure Drop (lb/inch) -(bar): multiplied by 1.48727E-05
  • + *
*/ public void convertSystemUnitToMetric() { insideDiameter = insideDiameter / 3.2808399; @@ -232,7 +298,54 @@ public void convertSystemUnitToMetric() { } + + public void calculateMissingValue() { + if (Double.isNaN(length)) { + length = calculateLength(); + } else if (Double.isNaN(elevation)) { + elevation = calculateElevation(); + } else if (Double.isNaN(angle)) { + angle = calculateAngle(); + } + if (Math.abs(elevation) > Math.abs(length)) { + throw new RuntimeException( + new neqsim.util.exception.InvalidInputException("PipeBeggsAndBrills", "calcMissingValue", + "elevation", "- cannot be higher than length of the pipe" + length)); + } + } + + /** + * Calculates the length based on the elevation and angle. + * + * @return the calculated length. + */ + private double calculateLength() { + return elevation / Math.sin(Math.toRadians(angle)); + } + + /** + * + * Calculates the elevation based on the length and angle. + * + * @return the calculated elevation. + */ + private double calculateElevation() { + return length * Math.sin(Math.toRadians(angle)); + } + + /** + * + * Calculates the angle based on the length and elevation. + * + * @return the calculated angle. + */ + private double calculateAngle() { + return Math.toDegrees(Math.asin(elevation / length)); + } + /** + * + * /** *

* calcFlowRegime. *

@@ -243,30 +356,34 @@ public String calcFlowRegime() { // Calc input volume fraction area = (Math.PI / 4.0) * Math.pow(insideDiameter, 2.0); if (system.getNumberOfPhases() != 1) { - supLiquidVel = system.getPhase(1).getFlowRate("ft3/sec") / area; + if (system.getNumberOfPhases() == 3) { + supLiquidVel = + (system.getPhase(1).getFlowRate("ft3/sec") + system.getPhase(2).getFlowRate("ft3/sec")) + / area; + } else { + supLiquidVel = system.getPhase(1).getFlowRate("ft3/sec") / area; + } supGasVel = system.getPhase(0).getFlowRate("ft3/sec") / area; supMixVel = supLiquidVel + supGasVel; + + liquidSuperficialVelocityProfile.add(supLiquidVel / 3.2808399); // to meters + gasSuperficialVelocityProfile.add(supGasVel / 3.2808399); + mixtureSuperficialVelocityProfile.add(supMixVel / 3.2808399); + mixtureFroudeNumber = Math.pow(supMixVel, 2) / (32.174 * insideDiameter); inputVolumeFractionLiquid = supLiquidVel / supMixVel; - /* - * Unlike the Gray or the Hagedorn and Brown correlations, the Beggs and Brill correlation - * requires that a flow pattern be determined. Since the original flow pattern map was - * created, it has been modified. We have used this modified flow pattern map for our - * calculations. The transition lines for the modified correlation are defined as follows - */ } else { if (system.hasPhaseType("gas")) { supGasVel = system.getPhase(0).getFlowRate("ft3/sec") / area; supMixVel = supGasVel; inputVolumeFractionLiquid = 0.0; - flowPattern = "Single Phase"; + regime = "Single Phase"; } else { supLiquidVel = system.getPhase(1).getFlowRate("ft3/sec") / area; supMixVel = supLiquidVel; inputVolumeFractionLiquid = 1.0; - flowPattern = "Single Phase"; + regime = "Single Phase"; } - System.out.println("Only one phase in the pipe"); } double L1 = 316 * Math.pow(inputVolumeFractionLiquid, 0.302); @@ -274,25 +391,22 @@ public String calcFlowRegime() { double L3 = 0.1 * Math.pow(inputVolumeFractionLiquid, -1.4516); double L4 = 0.5 * Math.pow(inputVolumeFractionLiquid, -6.738); - if (flowPattern != "Single Phase") { - // The flow type can then be readily determined either from a representative flow pattern map - // or - // according to the following conditions + if (regime != "Single Phase") { if ((inputVolumeFractionLiquid < 0.01 && mixtureFroudeNumber < L1) || (inputVolumeFractionLiquid >= 0.01 && mixtureFroudeNumber < L2)) { - flowPattern = "SEGREGATED"; + regime = "SEGREGATED"; } else if ((inputVolumeFractionLiquid < 0.4 && inputVolumeFractionLiquid >= 0.01 && mixtureFroudeNumber <= L1 && mixtureFroudeNumber > L3) || (inputVolumeFractionLiquid >= 0.4 && mixtureFroudeNumber <= L4 && mixtureFroudeNumber > L3)) { - flowPattern = "INTERMITTENT"; + regime = "INTERMITTENT"; } else if ((inputVolumeFractionLiquid < 0.4 && mixtureFroudeNumber >= L4) || (inputVolumeFractionLiquid >= 0.4 && mixtureFroudeNumber > L4)) { - flowPattern = "DISTRIBUTED"; + regime = "DISTRIBUTED"; } else if (mixtureFroudeNumber > L2 && mixtureFroudeNumber < L3) { - flowPattern = "TRANSITION"; + regime = "TRANSITION"; } else if (inputVolumeFractionLiquid < 0.1 || inputVolumeFractionLiquid > 0.9) { - flowPattern = "Single Phase"; + regime = "Single Phase"; } else { logger.debug("Flow regime is not found"); } @@ -300,43 +414,39 @@ public String calcFlowRegime() { A = (L3 - mixtureFroudeNumber) / (L3 - L2); - return flowPattern; + flowRegimeProfile.add(regime); + return regime; } + + /** *

- * calcHydrostaticPressureDifference. + * calcHydrostaticPressureDifference *

* * @return a double */ public double calcHydrostaticPressureDifference() { - /* - * Once the flow type has been determined then the liquid holdup can be calculated. Beggs and - * Brill divided the liquid holdup calculation into two parts. First the liquid holdup for - * horizontal flow, EL(0), is determined, and then this holdup is modified for inclined flow. - * EL(0) must be ≥ CL and therefore when EL(0) is smaller than CL, EL(0) is assigned a value of - * CL. There is a separate calculation of liquid holdup (EL(0)) for each flow type - */ double B = 1 - A; double BThetta; - if (flowPattern == "SEGREGATED") { + if (regime == "SEGREGATED") { El = 0.98 * Math.pow(inputVolumeFractionLiquid, 0.4846) / Math.pow(mixtureFroudeNumber, 0.0868); - } else if (flowPattern == "INTERMITTENT") { + } else if (regime == "INTERMITTENT") { El = 0.845 * Math.pow(inputVolumeFractionLiquid, 0.5351) / (Math.pow(mixtureFroudeNumber, 0.0173)); - } else if (flowPattern == "DISTRIBUTED") { + } else if (regime == "DISTRIBUTED") { El = 1.065 * Math.pow(inputVolumeFractionLiquid, 0.5824) / (Math.pow(mixtureFroudeNumber, 0.0609)); - } else if (flowPattern == "TRANSITION") { + } else if (regime == "TRANSITION") { El = A * 0.98 * Math.pow(inputVolumeFractionLiquid, 0.4846) / Math.pow(mixtureFroudeNumber, 0.0868) + B * 0.845 * Math.pow(inputVolumeFractionLiquid, 0.5351) / (Math.pow(mixtureFroudeNumber, 0.0173)); - } else if (flowPattern == "Single Phase") { + } else if (regime == "Single Phase") { if (inputVolumeFractionLiquid < 0.1) { El = inputVolumeFractionLiquid; } else { @@ -344,9 +454,26 @@ public double calcHydrostaticPressureDifference() { } } - if (flowPattern != "Single Phase") { - // Oil surface tension - double SG = system.getPhase(1).getDensity("lb/ft3") / (1000 * 0.0624279606); + if (regime != "Single Phase") { + + double SG; + if (system.getNumberOfPhases() == 3) { + mixtureOilMassFraction = system.getPhase(1).getFlowRate("kg/hr") + / (system.getPhase(1).getFlowRate("kg/hr") + system.getPhase(2).getFlowRate("kg/hr")); + mixtureOilVolumeFraction = system.getPhase(1).getVolume() + / (system.getPhase(1).getVolume() + system.getPhase(2).getVolume()); + + mixtureLiquidViscosity = system.getPhase(1).getViscosity("cP") * mixtureOilVolumeFraction + + (system.getPhase(2).getViscosity("cP")) * (1 - mixtureOilVolumeFraction); + + mixtureLiquidDensity = (system.getPhase(1).getDensity("lb/ft3") * mixtureOilMassFraction + + system.getPhase(2).getDensity("lb/ft3") * (1 - mixtureOilMassFraction)); + + SG = (mixtureLiquidDensity) / (1000 * 0.0624279606); + } else { + SG = system.getPhase(1).getDensity("lb/ft3") / (1000 * 0.0624279606); + } + double APIgrav = (141.5 / (SG)) - 131.0; double sigma68 = 39.0 - 0.2571 * APIgrav; @@ -368,15 +495,15 @@ public double calcHydrostaticPressureDifference() { double betta = 0; if (elevation > 0) { - if (flowPattern == "SEGREGATED") { + if (regime == "SEGREGATED") { betta = (1 - inputVolumeFractionLiquid) * Math.log(0.011 * Math.pow(Nvl, 3.539) / (Math.pow(inputVolumeFractionLiquid, 3.768) * Math.pow(mixtureFroudeNumber, 1.614))); - } else if (flowPattern == "INTERMITTENT") { + } else if (regime == "INTERMITTENT") { betta = (1 - inputVolumeFractionLiquid) * Math.log(2.96 * Math.pow(inputVolumeFractionLiquid, 0.305) * Math.pow(mixtureFroudeNumber, 0.0978) / (Math.pow(Nvl, 0.4473))); - } else if (flowPattern == "DISTRIBUTED") { + } else if (regime == "DISTRIBUTED") { betta = 0; } } else { @@ -387,10 +514,15 @@ public double calcHydrostaticPressureDifference() { betta = (betta > 0) ? betta : 0; BThetta = 1 + betta * (Math.sin(1.8 * angle * 0.01745329) - (1.0 / 3.0) * Math.pow(Math.sin(1.8 * angle * 0.01745329), 3.0)); - El = BThetta * El; - mixtureDensity = - system.getPhase(1).getDensity("lb/ft3") * El + system.getPhase(0).getDensity() * (1 - El); + El = BThetta * El; + if (system.getNumberOfPhases() == 3) { + mixtureDensity = + mixtureLiquidDensity * El + system.getPhase(0).getDensity("lb/ft3") * (1 - El); + } else { + mixtureDensity = system.getPhase(1).getDensity("lb/ft3") * El + + system.getPhase(0).getDensity("lb/ft3") * (1 - El); + } } else { if (system.hasPhaseType("gas")) { mixtureDensity = system.getPhase(0).getDensity("lb/ft3"); @@ -398,8 +530,10 @@ public double calcHydrostaticPressureDifference() { mixtureDensity = system.getPhase(1).getDensity("lb/ft3"); } } + hydrostaticPressureDrop = mixtureDensity * 32.2 * elevation; // 32.2 - g + + liquidHoldupProfile.add(El); - hydrostaticPressureDrop = mixtureDensity * 32.2 * elevation; return hydrostaticPressureDrop; } @@ -416,9 +550,15 @@ public double calcFrictionPressureLoss() { double muNoSlip = 0; if (system.getNumberOfPhases() != 1) { - if (flowPattern != "Single Phase") { + if (regime != "Single Phase") { double y = Math.log(inputVolumeFractionLiquid / (Math.pow(El, 2))); S = y / (-0.0523 + 3.18 * y - 0.872 * Math.pow(y, 2.0) + 0.01853 * Math.pow(y, 4)); + if (system.getNumberOfPhases() == 3) { + rhoNoSlip = mixtureLiquidDensity * inputVolumeFractionLiquid + + (system.getPhase(0).getDensity("lb/ft3")) * (1 - inputVolumeFractionLiquid); + muNoSlip = mixtureLiquidViscosity * inputVolumeFractionLiquid + + (system.getPhase(0).getViscosity("cP")) * (1 - inputVolumeFractionLiquid); + } rhoNoSlip = (system.getPhase(1).getDensity("lb/ft3")) * inputVolumeFractionLiquid + (system.getPhase(0).getDensity("lb/ft3")) * (1 - inputVolumeFractionLiquid); muNoSlip = system.getPhase(1).getViscosity("cP") * inputVolumeFractionLiquid @@ -439,9 +579,14 @@ public double calcFrictionPressureLoss() { } } + mixtureViscosityProfile.add(muNoSlip); + mixtureDensityProfile.add(rhoNoSlip * 16.01846); + double ReNoSlip = rhoNoSlip * supMixVel * insideDiameter * (16 / (3.28 * 3.28)) / (0.001 * muNoSlip); + mixtureReynoldsNumber.add(ReNoSlip); + double E = pipeWallRoughness / insideDiameter; // Haaland equation @@ -473,31 +618,40 @@ public double calcPressureDrop() { /** {@inheritDoc} */ @Override public void run(UUID id) { + calculateMissingValue(); length = length / numberOfIncrements; + elevation = elevation / numberOfIncrements; system = inStream.getThermoSystem().clone(); + system.setMultiPhaseCheck(true); ThermodynamicOperations testOps = new ThermodynamicOperations(system); testOps.TPflash(); system.initProperties(); double enthalpyInlet = system.getEnthalpy(); + double pipeInletPressure = system.getPressure(); for (int i = 1; i <= numberOfIncrements; i++) { - System.out.println(system.getNumberOfPhases()); - System.out.println(system.hasPhaseType("gas")); - System.out.println(system.hasPhaseType("oil")); - System.out.println(system.getFlowRate("kg/hr")); - System.out.println(system.getComponent("methane").getz()); - // System.out.println(system.getComponent("n-heptane").getz()); + + lengthProfile.add(length); + elevationProfile.add(elevation); + inletPressure = system.getPressure(); pressureDrop = calcPressureDrop(); - + pressureDropProfile.add(pressureDrop); pressureOut = inletPressure - pressureDrop; + pressureProfile.add(pressureOut); + if (pressureOut < 0) { + throw new RuntimeException(new neqsim.util.exception.InvalidInputException( + "PipeBeggsAndBrills", "run: calcOutletPressure", "pressure out", + "- Outlet pressure is negative" + pressureOut)); + } + system.setPressure(pressureOut); testOps.PHflash(enthalpyInlet); system.initProperties(); - System.out.println(system.getTemperature("C")); + temperatureProfile.add(system.getTemperature()); } + totalPressureDrop = pipeInletPressure - system.getPressure(); outStream.setThermoSystem(system); outStream.setCalculationIdentifier(id); - System.out.println(pressureOut); } /** {@inheritDoc} */ @@ -519,38 +673,14 @@ public double getSuperficialVelocity() { / (Math.PI / 4.0 * Math.pow(insideDiameter, 2.0)); } - /** {@inheritDoc} */ - @Override - public FlowSystemInterface getPipe() { - return null; - } - - /** {@inheritDoc} */ - @Override - public void setInitialFlowPattern(String flowPattern) {} /** - *

- * Getter for the field length. - *

- * - * @return the length + * @return total length in meter */ public double getLength() { return length; } - /** - *

- * Setter for the field length. - *

- * - * @param length the length to set - */ - public void setLength(double length) { - this.length = length; - } - /** *

* getDiameter. @@ -570,150 +700,329 @@ public double getDiameter() { * @return a {@link java.lang.String} object */ public String getFlowRegime() { - return flowPattern; + return regime; } + /** *

- * setDiameter. + * Getter for the field LastSegmentPressureDrop. *

* - * @param diameter the diameter to set + * @return pressure drop last segment */ - public void setDiameter(double diameter) { - insideDiameter = diameter; + public double getLastSegmentPressureDrop() { + return pressureDrop; } /** *

- * Setter for the field pipeWallRoughness. + * Getter for the field totalPressureDrop. *

* - * @param pipeWallRoughness the pipeWallRoughness to set + * @return total pressure drop */ - public void setPipeWallRoughness(double pipeWallRoughness) { - this.pipeWallRoughness = pipeWallRoughness; + public double getPressureDrop() { + return totalPressureDrop; } + /** *

- * Getter for the field inletElevation. + * Getter for the field PressureProfile. *

* - * @return the inletElevation + * @return a list double */ - public double getInletElevation() { - return inletElevation; + public List getPressureProfile() { + return new ArrayList<>(pressureProfile); } + + /** *

- * Getter for the field pressureDrop. + * getSegmentPressure *

* - * @return a double + * @param index segment number + * @return segment pressure as double */ - public double getPressureDrop() { - return pressureDrop; + public Double getSegmentPressure(int index) { + if (index >= 1 && index < pressureProfile.size() + 1) { + return pressureProfile.get(index - 1); + } else { + throw new IndexOutOfBoundsException("Index is out of bounds."); + } } + /** - *

- * Setter for the field inletElevation. - *

- * - * @param inletElevation the inletElevation to set + * + * @return list of results + * */ - public void setInletElevation(double inletElevation) { - this.inletElevation = inletElevation; + public List getPressureDropProfile() { + return new ArrayList<>(pressureDropProfile); } + /** - *

- * Getter for the field outletElevation. - *

- * - * @return the outletElevation + * @param index segment number + * @return Double */ - public double getOutletElevation() { - return outletElevation; + public Double getSegmentPressureDrop(int index) { + if (index >= 1 && index < pressureDropProfile.size() + 1) { + return pressureDropProfile.get(index - 1); + } else { + throw new IndexOutOfBoundsException("Index is out of bounds."); + } } + /** - *

- * Setter for the field outletElevation. - *

- * - * @param outletElevation the outletElevation to set + * @return list of temperatures */ - public void setOutletElevation(double outletElevation) { - this.outletElevation = outletElevation; + public List getTemperatureProfile() { + return new ArrayList<>(temperatureProfile); } + /** - *

- * main. - *

- * - * @param name an array of {@link java.lang.String} objects + * @param index segment number + * @return Double */ - public static void main(String[] name) { - neqsim.thermo.system.SystemInterface testSystem = - new neqsim.thermo.system.SystemSrkEos((273.15 + 15.0), 10); - testSystem.addComponent("methane", 5, "MSm^3/day"); - testSystem.addComponent("n-heptane", 5, "MSm^3/day"); - testSystem.setMixingRule(2); - testSystem.init(0); + public Double getSegmentTemperature(int index) { + if (index >= 1 && index < temperatureProfile.size() + 1) { + return temperatureProfile.get(index - 1); + } else { + throw new IndexOutOfBoundsException("Index is out of bounds."); + } + } + - Stream stream_1 = new Stream("Stream1", testSystem); + /** + * @return list of flow regime names + */ + public List getFlowRegimeProfile() { + return new ArrayList<>(flowRegimeProfile); + } - PipeBeggsAndBrills pipe = new PipeBeggsAndBrills(stream_1); - pipe.setDiameter(1.017112); - pipe.setPipeWallRoughness(5e-6); - pipe.setLength(10000); - pipe.setElevation(0.0); - pipe.setAngle(0); - pipe.setNumberOfIncrements(2); - neqsim.processSimulation.processSystem.ProcessSystem operations = - new neqsim.processSimulation.processSystem.ProcessSystem(); - operations.add(stream_1); - operations.add(pipe); - operations.run(); + /** + * @param index segment number + * @return String + */ + public String getSegmentFlowRegime(int index) { + if (index >= 1 && index < flowRegimeProfile.size() + 1) { + return flowRegimeProfile.get(index - 1); + } else { + throw new IndexOutOfBoundsException("Index is out of bounds."); + } } + + /** - *

- * Getter for the field pressureOutLimit. - *

- * - * @return a double + * @return list of liquid superficial velocity profile */ - public double getPressureOutLimit() { - return pressureOutLimit; + public List getLiquidSuperficialVelocityProfile() { + return new ArrayList<>(liquidSuperficialVelocityProfile); } + + /** - *

- * Setter for the field pressureOutLimit. - *

- * - * @param pressureOutLimit a double + * @return list of gas superficial velocities */ - public void setPressureOutLimit(double pressureOutLimit) { - this.pressureOutLimit = pressureOutLimit; + public List getGasSuperficialVelocityProfile() { + return new ArrayList<>(gasSuperficialVelocityProfile); } + /** - *

- * Setter for the field flowLimit. - *

- * - * @param flowLimit a double - * @param unit a {@link java.lang.String} object + * @return list of mixture superficial velocity profile */ - public void setFlowLimit(double flowLimit, String unit) { - this.flowLimit = flowLimit; - maxflowunit = unit; + public List getMixtureSuperficialVelocityProfile() { + return new ArrayList<>(mixtureSuperficialVelocityProfile); } + + + + /** + * @return list of mixture viscosity + */ + public List getMixtureViscosityProfile() { + return new ArrayList<>(mixtureViscosityProfile); + } + + + + /** + * @return list of density profile + */ + public List getMixtureDensityProfile() { + return new ArrayList<>(mixtureDensityProfile); + } + + + + /** + * @return list of hold-up + */ + public List getLiquidHoldupProfile() { + return new ArrayList<>(liquidHoldupProfile); + } + + + + /** + * @return list of reynold numbers + */ + public List getMixtureReynoldsNumber() { + return new ArrayList<>(mixtureReynoldsNumber); + } + + + + /** + * @return list of length profile + */ + public List getLengthProfile() { + return new ArrayList<>(lengthProfile); + } + + + + /** + * @return list of elevation profile + */ + public List getElevationProfile() { + return new ArrayList<>(elevationProfile); + } + + + + /** + * @param index segment number + * @return Double + */ + public Double getSegmentLiquidSuperficialVelocity(int index) { + if (index >= 1 && index <= liquidSuperficialVelocityProfile.size()) { + return liquidSuperficialVelocityProfile.get(index - 1); + } else { + throw new IndexOutOfBoundsException("Index is out of bounds."); + } + } + + + + /** + * @param index segment number + * @return Double + */ + public Double getSegmentGasSuperficialVelocity(int index) { + if (index >= 1 && index <= gasSuperficialVelocityProfile.size()) { + return gasSuperficialVelocityProfile.get(index - 1); + } else { + throw new IndexOutOfBoundsException("Index is out of bounds."); + } + } + + + + /** + * @param index segment number + * @return Double + */ + public Double getSegmentMixtureSuperficialVelocity(int index) { + if (index >= 1 && index <= mixtureSuperficialVelocityProfile.size()) { + return mixtureSuperficialVelocityProfile.get(index - 1); + } else { + throw new IndexOutOfBoundsException("Index is out of bounds."); + } + } + + + /** + * @param index segment number + * @return Double + */ + public Double getSegmentMixtureViscosity(int index) { + if (index >= 1 && index <= mixtureViscosityProfile.size()) { + return mixtureViscosityProfile.get(index - 1); + } else { + throw new IndexOutOfBoundsException("Index is out of bounds."); + } + } + + + + /** + * @param index segment number + * @return Double + */ + public Double getSegmentMixtureDensity(int index) { + if (index >= 1 && index <= mixtureDensityProfile.size()) { + return mixtureDensityProfile.get(index - 1); + } else { + throw new IndexOutOfBoundsException("Index is out of bounds."); + } + } + + + /** + * @param index segment number + * @return Double + */ + public Double getSegmentLiquidHoldup(int index) { + if (index >= 1 && index <= liquidHoldupProfile.size()) { + return liquidHoldupProfile.get(index - 1); + } else { + throw new IndexOutOfBoundsException("Index is out of bounds."); + } + } + + + + /** + * @param index segment number + * @return Double + */ + public Double getSegmentMixtureReynoldsNumber(int index) { + if (index >= 1 && index <= mixtureReynoldsNumber.size()) { + return mixtureReynoldsNumber.get(index - 1); + } else { + throw new IndexOutOfBoundsException("Index is out of bounds."); + } + } + + + + /** + * @param index segment number + * @return Double + */ + public Double getSegmentLength(int index) { + if (index >= 1 && index <= lengthProfile.size()) { + return lengthProfile.get(index - 1); + } else { + throw new IndexOutOfBoundsException("Index is out of bounds."); + } + } + + + + /** + * @param index segment number + * @return Double + */ + public Double getSegmentElevation(int index) { + if (index >= 1 && index <= elevationProfile.size()) { + return elevationProfile.get(index - 1); + } else { + throw new IndexOutOfBoundsException("Index is out of bounds."); + } + } + } diff --git a/src/test/java/neqsim/processSimulation/processEquipment/pipeline/BeggsAndBrillsPipeTest.java b/src/test/java/neqsim/processSimulation/processEquipment/pipeline/BeggsAndBrillsPipeTest.java index 838d9c997..eea7b861d 100644 --- a/src/test/java/neqsim/processSimulation/processEquipment/pipeline/BeggsAndBrillsPipeTest.java +++ b/src/test/java/neqsim/processSimulation/processEquipment/pipeline/BeggsAndBrillsPipeTest.java @@ -2,6 +2,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import neqsim.processSimulation.processEquipment.stream.Stream; import neqsim.thermodynamicOperations.ThermodynamicOperations; public class BeggsAndBrillsPipeTest { @@ -41,4 +42,287 @@ public void testFlowVolumeCorrection() { testSystem.getFlowRate("m3/hr"), 1e-4); } + @Test + public void testPipeLineBeggsAndBrills() { + + double pressure = 50; // bara + double temperature = 40; // C + double massFlowRate = 1100000.000000000; + + neqsim.thermo.system.SystemInterface testSystem = + new neqsim.thermo.system.SystemSrkEos((273.15 + 45), 1.01325); + + testSystem.addComponent("methane", 0.5); + testSystem.addComponent("nC10", 0.5); + testSystem.setMixingRule(2); + testSystem.init(0); + testSystem.useVolumeCorrection(true); + testSystem.setPressure(pressure, "bara"); + testSystem.setTemperature(temperature, "C"); + testSystem.setTotalFlowRate(massFlowRate, "kg/hr"); + + ThermodynamicOperations testOps = new ThermodynamicOperations(testSystem); + testOps.TPflash(); + testSystem.initPhysicalProperties(); + + Stream stream_1 = new Stream("Stream1", testSystem); + stream_1.setFlowRate(massFlowRate, "kg/hr"); + + PipeBeggsAndBrills pipe = new PipeBeggsAndBrills(stream_1); + pipe.setPipeWallRoughness(5e-6); + pipe.setLength(10.0); + pipe.setAngle(0); + pipe.setDiameter(0.125); + pipe.setNumberOfIncrements(20); + + neqsim.processSimulation.processSystem.ProcessSystem operations = + new neqsim.processSimulation.processSystem.ProcessSystem(); + operations.add(stream_1); + operations.add(pipe); + operations.run(); + + double pressureOut = pipe.getOutletPressure(); + double temperatureOut = pipe.getOutletTemperature() - 273.15; + + Assertions.assertEquals(pressureOut, 27.5402, 1e-4); + Assertions.assertEquals(temperatureOut, 39.3374, 1e-4); + + } + + + @Test + public void testPipeLineBeggsAndBrills2() { + + double pressure = 50; // bara + double temperature = 40; // C + double massFlowRate = 110000.000000000; + + neqsim.thermo.system.SystemInterface testSystem = + new neqsim.thermo.system.SystemSrkEos((273.15 + 45), 1.01325); + + testSystem.addComponent("methane", 0.5); + testSystem.addComponent("nC10", 0.5); + testSystem.setMixingRule(2); + testSystem.init(0); + testSystem.useVolumeCorrection(true); + testSystem.setPressure(pressure, "bara"); + testSystem.setTemperature(temperature, "C"); + testSystem.setTotalFlowRate(massFlowRate, "kg/hr"); + + ThermodynamicOperations testOps = new ThermodynamicOperations(testSystem); + testOps.TPflash(); + testSystem.initPhysicalProperties(); + + Stream stream_1 = new Stream("Stream1", testSystem); + stream_1.setFlowRate(massFlowRate, "kg/hr"); + + PipeBeggsAndBrills pipe = new PipeBeggsAndBrills(stream_1); + pipe.setPipeWallRoughness(0); + pipe.setLength(750.0); + pipe.setAngle(90); + pipe.setDiameter(0.125); + pipe.setNumberOfIncrements(50); + + neqsim.processSimulation.processSystem.ProcessSystem operations = + new neqsim.processSimulation.processSystem.ProcessSystem(); + operations.add(stream_1); + operations.add(pipe); + operations.run(); + + double pressureOut = pipe.getOutletPressure(); + double temperatureOut = pipe.getOutletTemperature() - 273.15; + + Assertions.assertEquals(pressureOut, 13.735508907175728, 1e-4); + Assertions.assertEquals(temperatureOut, 38.82331519652632, 1e-4); + + } + + + + @Test + public void testPipeLineBeggsAndBrills3() { + + double pressure = 50; // bara + double temperature = 80; // C + double massFlowRate = 110000.000000000; + + neqsim.thermo.system.SystemInterface testSystem = + new neqsim.thermo.system.SystemSrkEos((273.15 + 45), 1.01325); + + testSystem.addComponent("methane", 0.3); + testSystem.addComponent("nC10", 0.4); + testSystem.addComponent("water", 0.3); + testSystem.setMixingRule(2); + testSystem.init(0); + testSystem.useVolumeCorrection(true); + testSystem.setPressure(pressure, "bara"); + testSystem.setTemperature(temperature, "C"); + testSystem.setTotalFlowRate(massFlowRate, "kg/hr"); + + + ThermodynamicOperations testOps = new ThermodynamicOperations(testSystem); + testOps.TPflash(); + testSystem.initPhysicalProperties(); + + Stream stream_1 = new Stream("Stream1", testSystem); + stream_1.setFlowRate(massFlowRate, "kg/hr"); + + PipeBeggsAndBrills pipe = new PipeBeggsAndBrills(stream_1); + pipe.setPipeWallRoughness(0); + pipe.setLength(410.0); + pipe.setElevation(300); + pipe.setDiameter(0.125); + pipe.setNumberOfIncrements(10); + + neqsim.processSimulation.processSystem.ProcessSystem operations = + new neqsim.processSimulation.processSystem.ProcessSystem(); + operations.add(stream_1); + operations.add(pipe); + operations.run(); + + double pressureOut = pipe.getOutletPressure(); + double temperatureOut = pipe.getOutletTemperature() - 273.15; + + Assertions.assertEquals(pressureOut, 34.4716898025371, 1e-4); + Assertions.assertEquals(temperatureOut, 79.80343, 1e-4); + Assertions.assertEquals(pipe.getPressureDrop(), 15.5283101974629, 1e-4); + Assertions.assertEquals(pipe.getSegmentPressure(10), 34.4716898025371, 1e-4); + Assertions.assertEquals(pipe.getSegmentPressureDrop(10), 1.5468048987983438, 1e-4); + Assertions.assertEquals(pipe.getSegmentTemperature(10) - 273.15, 79.80343029302054, 1e-4); + Assertions.assertEquals(pipe.getSegmentFlowRegime(10), "INTERMITTENT"); + Assertions.assertEquals(pipe.getSegmentMixtureDensity(10), 233.1155792052253, 1e-4); + Assertions.assertEquals(pipe.getSegmentLiquidSuperficialVelocity(10), 3.357338501138603, 1e-4); + Assertions.assertEquals(pipe.getSegmentGasSuperficialVelocity(10), 7.109484383317198, 1e-4); + Assertions.assertEquals(pipe.getSegmentMixtureSuperficialVelocity(10), 10.466822884455802, 1e-4); + Assertions.assertEquals(pipe.getSegmentMixtureViscosity(10), 0.14329203901478244, 1e-4); + Assertions.assertEquals(pipe.getSegmentLiquidHoldup(10), 0.42601098053163294, 1e-4); + Assertions.assertEquals(pipe.getSegmentMixtureReynoldsNumber(10), 2127138.3343691113, 1e-4); + Assertions.assertEquals(pipe.getSegmentLength(10), 41.0, 1e-4); + Assertions.assertEquals(pipe.getSegmentElevation(10), 29.999999999999996, 1e-4); + } + + + + @Test + public void testPipeLineBeggsAndBrills4() { + // One phase + double pressure = 150; // bara + double temperature = 80; // C + double massFlowRate = 110000.000000000; + + neqsim.thermo.system.SystemInterface testSystem = + new neqsim.thermo.system.SystemSrkEos((273.15 + 45), 1.01325); + + testSystem.addComponent("methane", 1); + testSystem.setMixingRule(2); + testSystem.init(0); + testSystem.useVolumeCorrection(true); + testSystem.setPressure(pressure, "bara"); + testSystem.setTemperature(temperature, "C"); + testSystem.setTotalFlowRate(massFlowRate, "kg/hr"); + testSystem.initPhysicalProperties(); + + Stream stream_1 = new Stream("Stream1", testSystem); + stream_1.setFlowRate(massFlowRate, "kg/hr"); + + PipeBeggsAndBrills pipe = new PipeBeggsAndBrills(stream_1); + pipe.setPipeWallRoughness(0); + pipe.setLength(1500.0); + pipe.setElevation(-1000); + pipe.setDiameter(0.125); + pipe.setNumberOfIncrements(10); + + // test with only water phase + neqsim.processSimulation.processSystem.ProcessSystem operations = + new neqsim.processSimulation.processSystem.ProcessSystem(); + operations.add(stream_1); + operations.add(pipe); + operations.run(); + + double pressureOut = pipe.getOutletPressure(); + double temperatureOut = pipe.getOutletTemperature() - 273.15; + + Assertions.assertEquals(temperatureOut, 75.0748, 1e-4); + Assertions.assertEquals(pressureOut, 124.04439, 1e-4); + + + neqsim.thermo.system.SystemInterface testSystem2 = + new neqsim.thermo.system.SystemSrkEos((273.15 + 45), 1.01325); + + testSystem2.addComponent("water", 1); + testSystem2.setMixingRule(2); + testSystem2.init(0); + testSystem2.useVolumeCorrection(true); + testSystem2.setPressure(pressure, "bara"); + testSystem2.setTemperature(temperature, "C"); + testSystem2.setTotalFlowRate(massFlowRate, "kg/hr"); + testSystem2.initPhysicalProperties(); + + Stream stream_2 = new Stream("Stream1", testSystem2); + stream_2.setFlowRate(massFlowRate, "kg/hr"); + + PipeBeggsAndBrills pipe2 = new PipeBeggsAndBrills(stream_2); + pipe2.setPipeWallRoughness(0); + pipe2.setLength(1500.0); + pipe2.setElevation(-1000); + pipe2.setDiameter(0.125); + pipe2.setNumberOfIncrements(10); + + neqsim.processSimulation.processSystem.ProcessSystem operations2 = + new neqsim.processSimulation.processSystem.ProcessSystem(); + operations2.add(stream_2); + operations2.add(pipe2); + operations2.run(); + + double pressureOut2 = pipe2.getOutletPressure(); + + + Assertions.assertEquals(pressureOut2, 238.8205556280226, 1e-4); + + + + neqsim.thermo.system.SystemInterface testSystem3 = + new neqsim.thermo.system.SystemSrkEos((273.15 + 45), 1.01325); + + testSystem3.addComponent("ethane", 1); + testSystem3.setMixingRule(2); + testSystem3.init(0); + testSystem3.useVolumeCorrection(true); + testSystem3.setPressure(pressure, "bara"); + testSystem3.setTemperature(temperature, "C"); + testSystem3.setTotalFlowRate(massFlowRate, "kg/hr"); + testSystem3.initPhysicalProperties(); + + ThermodynamicOperations testOps2 = new ThermodynamicOperations(testSystem3); + testOps2.TPflash(); + testSystem3.initPhysicalProperties(); + + Assertions.assertEquals(testSystem3.hasPhaseType("oil"), true); + + Stream stream_3 = new Stream("Stream1", testSystem3); + stream_3.setFlowRate(massFlowRate, "kg/hr"); + + PipeBeggsAndBrills pipe3 = new PipeBeggsAndBrills(stream_3); + pipe3.setPipeWallRoughness(0); + pipe3.setLength(10000.0); + pipe3.setElevation(1500); + pipe3.setDiameter(0.125); + pipe3.setNumberOfIncrements(10); + + neqsim.processSimulation.processSystem.ProcessSystem operations3 = + new neqsim.processSimulation.processSystem.ProcessSystem(); + operations3.add(stream_3); + operations3.add(pipe3); + operations3.run(); + + double pressureOut3 = pipe3.getOutletPressure(); + double temperatureOut3 = pipe3.getOutletTemperature() - 273.15; + + Assertions.assertEquals(testSystem3.hasPhaseType("gas"), true); + + Assertions.assertEquals(temperatureOut3, -11.04463, 1e-4); + Assertions.assertEquals(pressureOut3, 18.3429, 1e-4); + + } + }