/* * JaamSim Discrete Event Simulation * Copyright (C) 2013 Ausenco Engineering Canada Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.jaamsim.FluidObjects; import com.jaamsim.Graphics.PolylineInfo; import com.jaamsim.input.ColourInput; import com.jaamsim.input.Input; import com.jaamsim.input.Keyword; import com.jaamsim.input.Output; import com.jaamsim.input.ValueInput; import com.jaamsim.units.DimensionlessUnit; import com.jaamsim.units.DistanceUnit; /** * FluidPipe is a pipe through which fluid can flow. * @author Harry King * */ public class FluidPipe extends FluidComponent { @Keyword(description = "The length of the pipe.", example = "Pipe1 Length { 10.0 m }") private final ValueInput lengthInput; @Keyword(description = "The height change over the length of the pipe. " + "Equal to (outlet height - inlet height).", example = "Pipe1 HeightChange { 0.0 }") private final ValueInput heightChangeInput; @Keyword(description = "The roughness height of the inside pipe surface. " + "Used to calculate the Darcy friction factor for the pipe.", example = "Pipe1 Roughness { 0.01 m }") private final ValueInput roughnessInput; @Keyword(description = "The pressure loss coefficient or 'K-factor' for the pipe. " + "The factor multiplies the dynamic pressure and is applied as a loss at the pipe outlet.", example = "Pipe1 PressureLossCoefficient { 0.5 }") private final ValueInput pressureLossCoefficientInput; @Keyword(description = "The width of the pipe segments in pixels.", example = "Pipe1 Width { 1 }") private final ValueInput widthInput; @Keyword(description = "The colour of the pipe, defined using a colour keyword or RGB values.", example = "Pipe1 Colour { red }") private final ColourInput colourInput; private double darcyFrictionFactor; // The Darcy Friction Factor for the pipe flow. { lengthInput = new ValueInput( "Length", "Key Inputs", 1.0d); lengthInput.setValidRange( 0.0, Double.POSITIVE_INFINITY); lengthInput.setUnitType( DistanceUnit.class ); this.addInput( lengthInput); heightChangeInput = new ValueInput( "HeightChange", "Key Inputs", 0.0d); heightChangeInput.setValidRange( Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); heightChangeInput.setUnitType( DistanceUnit.class ); this.addInput( heightChangeInput); roughnessInput = new ValueInput( "Roughness", "Key Inputs", 0.0d); roughnessInput.setValidRange( 0.0, Double.POSITIVE_INFINITY); roughnessInput.setUnitType( DistanceUnit.class ); this.addInput( roughnessInput); pressureLossCoefficientInput = new ValueInput( "PressureLossCoefficient", "Key Inputs", 0.0d); pressureLossCoefficientInput.setValidRange( 0.0, Double.POSITIVE_INFINITY); pressureLossCoefficientInput.setUnitType( DimensionlessUnit.class ); this.addInput( pressureLossCoefficientInput); widthInput = new ValueInput("Width", "Key Inputs", 1.0d); widthInput.setValidRange(1.0d, Double.POSITIVE_INFINITY); widthInput.setUnitType( DimensionlessUnit.class ); this.addInput(widthInput); colourInput = new ColourInput("Colour", "Key Inputs", ColourInput.BLACK); this.addInput(colourInput); this.addSynonym(colourInput, "Color"); } @Override public double calcOutletPressure( double inletPres, double flowAccel ) { double dyn = this.getDynamicPressure(); // Note that dynamic pressure is negative for negative velocities double pres = inletPres; pres -= this.getFluid().getDensityxGravity() * heightChangeInput.getValue(); if( Math.abs(dyn) > 0.0 && this.getFluid().getViscosity() > 0.0 ) { this.setDarcyFrictionFactor(); pres -= darcyFrictionFactor * dyn * this.getLength() / this.getDiameter(); } else { darcyFrictionFactor = 0.0; } pres -= pressureLossCoefficientInput.getValue() * dyn; pres -= flowAccel * this.getFluid().getDensity() * lengthInput.getValue() / this.getFlowArea(); return pres; } @Override public double getLength() { return lengthInput.getValue(); } private void setDarcyFrictionFactor() { double reynoldsNumber = this.getReynoldsNumber(); // Laminar Flow if( reynoldsNumber < 2300.0 ) { darcyFrictionFactor = this.getLaminarFrictionFactor( reynoldsNumber ); } // Turbulent Flow else if( reynoldsNumber > 4000.0 ) { darcyFrictionFactor = this.getTurbulentFrictionFactor( reynoldsNumber ); } // Transitional Flow else { darcyFrictionFactor = 0.5 * ( this.getLaminarFrictionFactor(reynoldsNumber) + this.getTurbulentFrictionFactor(reynoldsNumber) ); } } /* * Return the Darcy Friction Factor for a laminar flow. */ private double getLaminarFrictionFactor( double reynoldsNumber ) { return 64.0 / reynoldsNumber; } /* * Return the Darcy Friction Factor for a turbulent flow. */ private double getTurbulentFrictionFactor( double reynoldsNumber ) { double x = 1.0; // The present value for x = 1 / sqrt( frictionfactor ). double lastx = 0.0; double a = ( roughnessInput.getValue() / this.getDiameter() ) / 3.7; double b = 2.51 / reynoldsNumber; int n = 0; while( Math.abs(x-lastx)/lastx > 1.0e-10 && n < 20 ) { lastx = x; x = -2.0 * Math.log10( a + b*lastx ); n++; } if( n >= 20 ) { error("Darcy Friction Factor iterations did not converge: lastx = %f x = %f n = %d", lastx, x, n); } return 1.0 / ( x * x ); } @Override public void updateForInput( Input<?> in ) { super.updateForInput(in); // If Points were input, then use them to set the start and end coordinates if( in == pointsInput || in == colourInput || in == widthInput ) { invalidateScreenPoints(); return; } } @Override public PolylineInfo[] buildScreenPoints(double simTime) { int w = Math.max(1, widthInput.getValue().intValue()); PolylineInfo[] ret = new PolylineInfo[1]; ret[0] = new PolylineInfo(pointsInput.getValue(), getCurveType(), colourInput.getValue(), w); return ret; } @Output(name = "DarcyFrictionFactor", description = "The Darcy Friction Factor for the pipe.", unitType = DimensionlessUnit.class) public double getDarcyFrictionFactor(double simTime) { return darcyFrictionFactor; } }