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- * 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
.
*
- * Setter for the field elevation
.
+ * Setter for the field 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
.
*
- * setOutPressure.
+ * Setter for the field numberOfIncrements
.
*
- * convertSystemUnitToImperial. + * The conversions applied are: *
+ *- * convertSystemUnitToMetric. + * The conversions applied are the inverse of those in the {@link #convertSystemUnitToImperial()} + * method: *
+ ** 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
.
- *
- * Setter for the field 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
.
*
- * Setter for the field pipeWallRoughness
.
+ * Getter for the field totalPressureDrop
.
*
- * Getter for the field inletElevation
.
+ * Getter for the field PressureProfile
.
*
- * Getter for the field pressureDrop
.
+ * getSegmentPressure
*
- * Setter for the field inletElevation
.
- *
- * Getter for the field outletElevation
.
- *
- * Setter for the field outletElevation
.
- *
- * 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
- * Getter for the field pressureOutLimit
.
- *
- * Setter for the field pressureOutLimit
.
- *
- * Setter for the field flowLimit
.
- *