761 lines
26 KiB
Swift
761 lines
26 KiB
Swift
//: Playground - noun: a place where people can play
|
|
|
|
import Cocoa
|
|
|
|
var test = "Hello";
|
|
|
|
struct LoadSpan //structure to hold load spans
|
|
{
|
|
var top:Double;
|
|
var bottom:Double;
|
|
var span:Double;
|
|
};
|
|
|
|
func findMax(arr:[Double], len:Int) -> Double
|
|
// find the maximum value of a given array of length len
|
|
{
|
|
var max = arr[0];
|
|
for(var i = 0; i < len; i++)
|
|
{
|
|
if (arr[i] > max)
|
|
{
|
|
max = arr[i];
|
|
}
|
|
}
|
|
return max;
|
|
};
|
|
|
|
func findMin(arr:[Double], len:Int) -> Double
|
|
// find the min value of a given array of length len
|
|
{
|
|
var min = arr[0];
|
|
for(var i = 0; i < len; i++)
|
|
{
|
|
if(arr[i] < min)
|
|
{
|
|
min = arr[i];
|
|
}
|
|
}
|
|
return min;
|
|
};
|
|
|
|
func updAverage(prevAverage:Double, currentMeasurement:Double, numMeasurements:Int) -> Double
|
|
{
|
|
var newAverage:Double;
|
|
newAverage = prevAverage * ((Double(numMeasurements) - 1)/Double(numMeasurements)) + (currentMeasurement / Double(numMeasurements));
|
|
return newAverage;
|
|
};
|
|
|
|
class LPPair //structure to hold Load and Position
|
|
{
|
|
var load:Double;
|
|
var position:Double;
|
|
func clr()
|
|
{
|
|
load = 0;
|
|
position = 0;
|
|
}
|
|
|
|
init(){
|
|
clr();
|
|
}
|
|
};
|
|
|
|
|
|
class WellData
|
|
{
|
|
var polishedRodHorsepower:Double;
|
|
var pumpHorsepower:Double;
|
|
var pumpIntakePressure:Double;
|
|
var fluidLevel:Double;
|
|
var strokeSPM:Double;
|
|
var strokeNumber:Int;
|
|
|
|
var surfacePositionMax: LPPair;
|
|
var surfacePositionMin: LPPair;
|
|
var surfaceLoadMax: LPPair;
|
|
var surfaceLoadMin: LPPair;
|
|
var downholePositionMax: LPPair;
|
|
var downholePositionMin: LPPair;
|
|
var downholeLoadMax: LPPair;
|
|
var downholeLoadMin: LPPair;
|
|
|
|
var topRight: LPPair;
|
|
var topLeft: LPPair;
|
|
var fillPoint: LPPair;
|
|
var fullFillPoint: LPPair;
|
|
var bottomLeft: LPPair;
|
|
|
|
var surfaceStrokeLength:Double;
|
|
var downholeNetStrokeLength:Double;
|
|
var downholeGrossStrokeLength:Double;
|
|
var downholeAdjustedGrossStrokeLength:Double;
|
|
var downholeLoadSpan:Double;
|
|
var fluidLoad:Double;
|
|
var fillageEstimated:Double;
|
|
var fillageCalculated:Double;
|
|
var tubingMovement:Double;
|
|
|
|
var plungerTravel:Double;
|
|
var dailyProduction:Double;
|
|
var structuralLoading:Double;
|
|
|
|
func clearAll()
|
|
{
|
|
polishedRodHorsepower = 0;
|
|
pumpHorsepower = 0;
|
|
pumpIntakePressure = 0;
|
|
fluidLevel = 0;
|
|
strokeSPM = 0;
|
|
strokeNumber = 1;
|
|
|
|
surfacePositionMax.clr();
|
|
surfacePositionMin.clr();
|
|
surfaceLoadMax.clr();
|
|
surfaceLoadMin.clr();
|
|
downholePositionMax.clr();
|
|
downholePositionMin.clr();
|
|
downholeLoadMax.clr();
|
|
downholeLoadMin.clr();
|
|
|
|
topRight.clr();
|
|
topLeft.clr();
|
|
fillPoint.clr();
|
|
fullFillPoint.clr();
|
|
bottomLeft.clr();
|
|
|
|
surfaceStrokeLength = 0;
|
|
downholeNetStrokeLength = 0;
|
|
downholeGrossStrokeLength = 0;
|
|
downholeAdjustedGrossStrokeLength = 0;
|
|
downholeLoadSpan = 0;
|
|
fluidLoad = 0;
|
|
fillageEstimated = 0;
|
|
fillageCalculated = 0;
|
|
tubingMovement = 0;
|
|
plungerTravel = 0;
|
|
dailyProduction = 0;
|
|
structuralLoading = 0;
|
|
};
|
|
init(){
|
|
clearAll();
|
|
}
|
|
|
|
};
|
|
|
|
class Card
|
|
//Object for card calculations and data
|
|
{
|
|
var surfacePosition = [Double](count: 1000, repeatedValue: 0.0);;
|
|
var downholePosition = [Double](count: 1000, repeatedValue: 0.0);;
|
|
var surfaceLoad = [Double](count: 1000, repeatedValue: 0.0);;
|
|
var downholeLoad = [Double](count: 1000, repeatedValue: 0.0);;
|
|
|
|
var data:WellData;
|
|
var pointCounter:Int;
|
|
|
|
func findLoadAtPosition(pos:Double, posArray:[Double], loadArray: [Double], size:Int) -> Double
|
|
{
|
|
|
|
for(var i = 0; i < size; i++)
|
|
{
|
|
if(posArray[i] == pos){
|
|
return loadArray[i];
|
|
}
|
|
}
|
|
};
|
|
|
|
func findPositionAtLoad(load:Double, posArray:[Double], loadArray: [Double], size:Int) -> Double
|
|
{
|
|
|
|
for(var i = 0; i < size; i++)
|
|
{
|
|
if(loadArray[i] == load){
|
|
return posArray[i];
|
|
}
|
|
}
|
|
};
|
|
|
|
func findLimits()
|
|
{
|
|
//find maximum values of the arrays
|
|
data.surfacePositionMax.position = findMax(surfacePosition, pointCounter);
|
|
data.surfacePositionMax.load = findLoadAtPosition(data.surfacePositionMax.position, posArray: surfacePosition,loadArray: surfaceLoad ,size: pointCounter);
|
|
|
|
data.surfaceLoadMax.load = findMax(surfaceLoad, pointCounter);
|
|
data.surfaceLoadMax.position = findPositionAtLoad(data.surfaceLoadMax.load, posArray: surfacePosition, loadArray: surfaceLoad ,size: pointCounter);
|
|
|
|
data.downholePositionMax.position = findMax(downholePosition, pointCounter);
|
|
data.downholePositionMax.load = findLoadAtPosition(data.downholePositionMax.position, posArray: downholePosition, loadArray: downholeLoad ,size: pointCounter);
|
|
|
|
data.downholeLoadMax.load = findMax(downholeLoad, pointCounter);
|
|
data.downholeLoadMax.position = findPositionAtLoad(data.downholeLoadMax.load, posArray: downholePosition, loadArray: downholeLoad, size: pointCounter);
|
|
|
|
//find minimum values of the arrays
|
|
data.surfacePositionMin.position = findMin(surfacePosition, pointCounter);
|
|
data.surfacePositionMin.load = findLoadAtPosition(data.surfacePositionMin.position, posArray: surfacePosition, loadArray: surfaceLoad, size: pointCounter);
|
|
|
|
data.surfaceLoadMin.load = findMin(surfaceLoad, pointCounter);
|
|
data.surfaceLoadMin.position = findPositionAtLoad(data.surfaceLoadMin.load, posArray: surfacePosition, loadArray: surfaceLoad, size: pointCounter);
|
|
|
|
data.downholePositionMin.position = findMin(downholePosition, pointCounter);
|
|
data.downholePositionMin.load = findLoadAtPosition(data.downholePositionMin.position, posArray: downholePosition, loadArray: downholeLoad, size: pointCounter);
|
|
|
|
data.downholeLoadMin.load = findMin(downholeLoad, pointCounter);
|
|
data.downholeLoadMin.position = findPositionAtLoad(data.downholeLoadMin.load, posArray: downholePosition, loadArray: downholeLoad, size: pointCounter);
|
|
|
|
data.surfaceStrokeLength = data.surfacePositionMax.position - data.surfacePositionMin.position;
|
|
data.downholeGrossStrokeLength = data.downholePositionMax.position - data.downholePositionMin.position;
|
|
data.downholeLoadSpan = data.downholeLoadMax.load - data.downholeLoadMin.load;
|
|
};
|
|
|
|
func findNearestPointToLoad(direction:String, cardHalf:String, targetLoad:Double, posArray:[Double], loadArray:[Double], size:Int) -> LPPair
|
|
{
|
|
var posMin = findMin(posArray, size);
|
|
var posMax = findMax(posArray, size);
|
|
var leftIgnore = posMin + (posMax - posMin)*(0.75);
|
|
var rightIgnore = posMin + (posMax - posMin)*(0.25);
|
|
var foundPoint:LPPair;
|
|
|
|
if (direction=="up")
|
|
{
|
|
for(var i = 1; i < size; i++)
|
|
{
|
|
if(cardHalf == "right" && posArray[i] >= rightIgnore)
|
|
{
|
|
if(loadArray[i] <= targetLoad && loadArray[i-1] > targetLoad)
|
|
{
|
|
foundPoint.position = posArray[i];
|
|
foundPoint.load = loadArray[i];
|
|
return foundPoint;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(loadArray[i] >= targetLoad && loadArray[i-1] < targetLoad)
|
|
{
|
|
foundPoint.position = posArray[i];
|
|
foundPoint.load = loadArray[i];
|
|
return foundPoint;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for(var i = 1; i < size; i++)
|
|
{
|
|
if(cardHalf == "right" && posArray[i] >= rightIgnore)
|
|
{
|
|
if(loadArray[i] >= targetLoad && loadArray[i-1] < targetLoad)
|
|
{
|
|
foundPoint.position = posArray[i];
|
|
foundPoint.load = loadArray[i];
|
|
return foundPoint;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(loadArray[i] <= targetLoad && loadArray[i-1] > targetLoad)
|
|
{
|
|
foundPoint.position = posArray[i];
|
|
foundPoint.load = loadArray[i];
|
|
return foundPoint;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func findIncrementalLoad(targetPosition:Double, posArray:[Double], loadArray:[Double], size:Int) -> LoadSpan
|
|
{
|
|
var result:LoadSpan;
|
|
var upPointGreater:LPPair;
|
|
var upPointLesser:LPPair;
|
|
var downPointGreater:LPPair;
|
|
var downPointLesser:LPPair;
|
|
|
|
for(var i = 1; i < size; i++)
|
|
{
|
|
if ((posArray[i] >= targetPosition) && (posArray[i-1] < targetPosition))
|
|
{
|
|
upPointGreater.position = posArray[i];
|
|
upPointGreater.load = loadArray[i];
|
|
upPointLesser.position = posArray[i-1];
|
|
upPointLesser.load = loadArray[i-1];
|
|
}
|
|
if ((posArray[i] <= targetPosition) && (posArray[i-1] > targetPosition))
|
|
{
|
|
downPointGreater.position = posArray[i];
|
|
downPointGreater.load = loadArray[i];
|
|
downPointLesser.position = posArray[i-1];
|
|
downPointLesser.load = loadArray[i-1];
|
|
}
|
|
|
|
var mUp = (upPointGreater.load - upPointLesser.load) / (upPointGreater.position - upPointLesser.position);
|
|
var bUp = upPointGreater.load - (mUp * upPointGreater.position);
|
|
result.top = (mUp * targetPosition) + bUp;
|
|
|
|
var mDown = (downPointGreater.load - downPointLesser.load) / (downPointGreater.position - downPointLesser.position);
|
|
var bDown = downPointGreater.load - (mDown * downPointGreater.position);
|
|
result.bottom = (mDown * targetPosition) + bDown;
|
|
|
|
|
|
result.span = result.top - result.bottom;
|
|
return result;
|
|
}
|
|
|
|
}
|
|
|
|
func findCorners(pctTop:Double, pctBottom:Double)
|
|
{
|
|
var halfLoadLine = data.downholeLoadMin.load + data.downholeLoadSpan/2;
|
|
var halfLoad:LPPair;
|
|
halfLoad = findNearestPointToLoad("up", cardHalf: "left", targetLoad: halfLoadLine, posArray: downholePosition, loadArray: downholeLoad, size: pointCounter);
|
|
var topLoadLine = data.downholeLoadMax.load - (data.downholeLoadSpan * (pctTop/100));
|
|
var bottomLoadLine = data.downholeLoadMin.load + (data.downholeLoadSpan * (pctBottom/100));
|
|
|
|
if(data.downholePositionMin.position < halfLoad.position)
|
|
{
|
|
data.bottomLeft = data.downholePositionMin;
|
|
data.topLeft = findNearestPointToLoad("up", cardHalf: "left", targetLoad: topLoadLine, posArray: downholePosition, loadArray: downholeLoad, size: pointCounter);
|
|
}
|
|
else
|
|
{
|
|
data.bottomLeft = findNearestPointToLoad("up", cardHalf: "left", targetLoad: bottomLoadLine, posArray: downholePosition, loadArray: downholeLoad, size: pointCounter);
|
|
data.topLeft = data.downholePositionMin;
|
|
}
|
|
|
|
data.topRight = data.downholePositionMax;
|
|
data.fillPoint = findNearestPointToLoad("up", cardHalf: "right", targetLoad: bottomLoadLine, posArray: downholePosition, loadArray: downholeLoad, size: pointCounter);
|
|
data.fullFillPoint.position = data.bottomLeft.position + data.topRight.position - data.topLeft.position;
|
|
data.fullFillPoint.load = data.bottomLeft.load;
|
|
};
|
|
|
|
func calcFillage(anchorDepth:Double, rodDepth:Double, tubingCSA:Double)
|
|
{
|
|
data.tubingMovement = 12 * (rodDepth - anchorDepth)*data.fluidLoad / (30500000 * tubingCSA);
|
|
data.downholeAdjustedGrossStrokeLength = data.downholeGrossStrokeLength - data.tubingMovement;
|
|
data.downholeNetStrokeLength = data.fillPoint.position - data.bottomLeft.position;
|
|
data.fillageEstimated = ((data.fillPoint.position - data.bottomLeft.position)/(data.fullFillPoint.position - data.bottomLeft.position))*100.0;
|
|
data.fillageCalculated = ((data.downholeNetStrokeLength + data.tubingMovement)/data.downholeGrossStrokeLength)*100.0;
|
|
if (data.fillageEstimated > 100)
|
|
{
|
|
data.fillageEstimated = 100.0;
|
|
}
|
|
|
|
if (data.fillageCalculated > 100)
|
|
{
|
|
data.fillageCalculated = 100.0;
|
|
}
|
|
|
|
};
|
|
|
|
func calcHorsepower (riemannSlices:Int)
|
|
{
|
|
data.polishedRodHorsepower = 0.0;
|
|
data.pumpHorsepower = 0.0;
|
|
var topSlices = [Double](count: riemannSlices, repeatedValue: 0.0);
|
|
var bottomSlices = [Double](count: riemannSlices, repeatedValue: 0.0);
|
|
|
|
var dxSurface = data.surfaceStrokeLength / (Double(riemannSlices) + 1);
|
|
var dxDownhole = data.downholeNetStrokeLength / (Double(riemannSlices) + 1);
|
|
|
|
for (var i = 1; i < riemannSlices; i++)
|
|
{
|
|
var targetSurface = dxSurface * Double(i) + data.surfacePositionMin.position;
|
|
var targetDownhole = dxDownhole * Double(i) + data.downholePositionMin.position;
|
|
var sliceSurface:LoadSpan;
|
|
var sliceDownhole:LoadSpan;
|
|
sliceSurface = findIncrementalLoad(targetSurface, posArray: surfacePosition, loadArray: surfaceLoad, size: pointCounter);
|
|
sliceDownhole = findIncrementalLoad(targetDownhole, posArray: downholePosition, loadArray: downholeLoad, size: pointCounter);
|
|
|
|
topSlices[i] = sliceDownhole.top;
|
|
bottomSlices[i] = sliceDownhole.bottom;
|
|
|
|
data.polishedRodHorsepower += (dxSurface/12) * sliceSurface.span * data.strokeSPM / 33000;
|
|
data.pumpHorsepower += abs((dxDownhole / 12) * sliceDownhole.span * data.strokeSPM / 33000);
|
|
}
|
|
};
|
|
|
|
func calcFluidLevel(fluidGradient:Double, rodDepth:Double, pumpArea:Double, frictionEstimate:Double)
|
|
{
|
|
data.fluidLoad = (data.downholeLoadMax.load - data.downholeLoadMin.load) - frictionEstimate;
|
|
data.pumpIntakePressure = fluidGradient * rodDepth - (data.fluidLoad / pumpArea);
|
|
//printf("PIP = %f * %f - (%f / %f) = %f\n", fluidGradient, rodDepth, data.fluidLoad, pumpArea, data.pumpIntakePressure);
|
|
data.fluidLevel = data.pumpIntakePressure / fluidGradient;
|
|
};
|
|
|
|
func calcLoading(structuralRating:Double)
|
|
{
|
|
data.structuralLoading = (data.surfaceLoadMax.load / (structuralRating * 100)) * 100;
|
|
}
|
|
|
|
init(){
|
|
|
|
}
|
|
};
|
|
|
|
class Well
|
|
//well object holding all pertinant calculations for the well
|
|
{
|
|
|
|
var currentCard:Card;
|
|
var topPosArray = Array<Array<Double>>();
|
|
var topLoadArray = Array<Array<Double>>();
|
|
|
|
var NumColumns = 100;
|
|
var NumRows = 10;
|
|
|
|
|
|
var loadBefore:Double;
|
|
var loadAfter:Double;
|
|
var loadBefore3:Double;
|
|
var loadAfter3:Double;
|
|
|
|
var dt:Double; //delta T for measurements
|
|
var tubingHeadPressure:Double; //Tubing Head Pressure (PSI)
|
|
var fluidGradient:Double; //Tubing Fluid Gradient (PSI/ft)
|
|
var sbfriction:Double; //Stuffing Box Friction (lbs)
|
|
var numTapers:Int; //Number of Rod String Tapers
|
|
var nT1:Int; //number of tapers + 1
|
|
|
|
var anchorDepth:Double;
|
|
var pumpDiameter:Double;
|
|
var pumpArea:Double;
|
|
var tubingID:Double;
|
|
var tubingOD:Double;
|
|
var tubingCrossSectionalArea:Double;
|
|
var frictionEstimate:Double;
|
|
var theoreticalMaxFluidLoad:Double;
|
|
var structuralRating:Double;
|
|
|
|
//arrays of size nT1 due to addresses starting at 0
|
|
//Rod String Inputs
|
|
var c = [Double](count: 11, repeatedValue: 0.0); //User-Defined damping constant per taper (1/sec)
|
|
var rodLength = [Double](count: 11, repeatedValue: 0.0); //Length of each rod taper (top to bottom)(ft)
|
|
var rodDiameter = [Double](count: 11, repeatedValue: 0.0); //Diameter of each rod taper (top to bottom)(in)
|
|
var rodYM = [Double](count: 11, repeatedValue: 0.0); //Youngs modulus of each rod taper (top to bottom)(PSI) Steel=30.5, fiberglass=7.2
|
|
var rodWeightPerFoot = [Double](count: 11, repeatedValue: 0.0); //Weight per foot of each rod (ft/lb)
|
|
|
|
var a = [Double](count: 11, repeatedValue: 0.0);
|
|
var area = [Double](count: 12, repeatedValue: 0.0);
|
|
var pressure = [Double](count: 11, repeatedValue: 0.0);
|
|
var buoyantForce = [Double](count: 11, repeatedValue: 0.0);
|
|
var buoyantForceTotal:Double;
|
|
var stretch = [Double](count: 11, repeatedValue: 0.0);
|
|
var weightData = [Double](count: 11, repeatedValue: 0.0);
|
|
var weightDataTotal:Double;
|
|
var annularForceData = [Double](count: 11, repeatedValue: 0.0);
|
|
var annularForceDataTotal:Double;
|
|
var force = [Double](count: 11, repeatedValue: 0.0);
|
|
var alpha = [Double](count: 11, repeatedValue: 0.0);
|
|
var xOverA = [Double](count: 11, repeatedValue: 0.0);
|
|
var factorArray = [Double](count: 11, repeatedValue: 0);
|
|
var lagIndexArray = [Int](count: 11, repeatedValue: 0);
|
|
var centerPoint = [Int](count: 11, repeatedValue: 0);
|
|
var sumCenterPoint = [Int](count: 11, repeatedValue: 0);
|
|
var lengthRequired = [Int](count: 11, repeatedValue: 0);
|
|
var rodDepth = [Double](count: 11, repeatedValue: 0.0);
|
|
var rodDepthTotal:Double;
|
|
var rodWeightAir = [Double](count: 11, repeatedValue: 0.0);
|
|
var rodWeightAirTotal:Double;
|
|
var rodWeightFluid = [Double](count: 11, repeatedValue: 0.0);
|
|
var rodWeightFluidTotal:Double;
|
|
|
|
var count = [Int](count: 11, repeatedValue: 0);
|
|
var sPositionPrevious:Double;
|
|
|
|
init(){
|
|
topArraySetup()
|
|
}
|
|
|
|
func topArraySetup(){
|
|
for (var i = 0; i < NumColumns; i++)
|
|
{
|
|
topPosArray.append(Array(count:NumRows, repeatedValue:Double()))
|
|
topLoadArray.append(Array(count:NumRows, repeatedValue:Double()))
|
|
}
|
|
|
|
}
|
|
|
|
|
|
func printTaperSetup()
|
|
//prints the current taper setup to the console
|
|
//TODO: update this to print to a file.
|
|
{
|
|
println("Taper Parameters");
|
|
println(NSString(format: "dt: %.2f", dt))
|
|
println(NSString(format: "tubingHeadPressure: %.2f", tubingHeadPressure))
|
|
println(NSString(format: "fluidGradient: %.2f", fluidGradient))
|
|
println(NSString(format: "sbfriction: %.2f", sbfriction))
|
|
println(NSString(format: "numTapers: %.2f", numTapers))
|
|
|
|
println("c:")
|
|
dump(c);
|
|
|
|
println("rodLength:")
|
|
dump(rodLength)
|
|
|
|
println("rodDiameter:")
|
|
dump(rodDiameter);
|
|
|
|
println("rodYM:")
|
|
dump(rodYM);
|
|
|
|
println("rodWeightPerFoot:")
|
|
dump(rodWeightPerFoot)
|
|
|
|
println("a:");
|
|
dump(a);
|
|
|
|
println("area:")
|
|
dump(area)
|
|
|
|
|
|
println("pressure:")
|
|
dump(pressure)
|
|
|
|
println("buoyantForce:")
|
|
dump(buoyantForce)
|
|
|
|
println("stretch")
|
|
dump(stretch)
|
|
|
|
println("weightData")
|
|
dump(weightData)
|
|
|
|
println("annularForceData:")
|
|
dump(annularForceData)
|
|
|
|
println("force:")
|
|
dump(force)
|
|
|
|
println("alpha:")
|
|
dump(alpha)
|
|
|
|
println("xOverA:")
|
|
dump(xOverA)
|
|
|
|
println("factorArray")
|
|
dump(factorArray)
|
|
|
|
println("lagIndexArray")
|
|
dump(lagIndexArray)
|
|
|
|
println("centerPoint:")
|
|
dump(centerPoint)
|
|
|
|
println("sumCenterPoint:")
|
|
dump(sumCenterPoint)
|
|
|
|
println("lengthRequired:")
|
|
dump(lengthRequired)
|
|
|
|
println("rodDepth")
|
|
dump(rodDepth)
|
|
|
|
println("rodWeightAir")
|
|
dump(rodWeightAir)
|
|
|
|
println("rodWeightFluid")
|
|
dump(rodWeightFluid)
|
|
|
|
|
|
println(NSString(format: "buoyantForceTotal: %.2f", buoyantForceTotal))
|
|
println(NSString(format: "weightDataTotal: %.2f", weightDataTotal))
|
|
println(NSString(format: "annularForceDataTotal: %.2f", annularForceDataTotal))
|
|
println(NSString(format: "rodDepthTotal: %.2f", rodDepthTotal))
|
|
println(NSString(format: "rodWeightAirTotal: %.2f", rodWeightAirTotal))
|
|
println(NSString(format: "rodWeightFluidTotal: %.2f", rodWeightFluidTotal))
|
|
println(NSString(format: "tubingID: %.2f", tubingID))
|
|
println(NSString(format: "tubingOD: %.2f", tubingOD))
|
|
println(NSString(format: "tubingCSA: %.2f", tubingCrossSectionalArea))
|
|
println(NSString(format: "structuralRating: %.2f", structuralRating))
|
|
|
|
}
|
|
|
|
func lookupRodWeightPerFoot(i_ym:Double, i_diam:Double) -> Double
|
|
//looks up rod Weight per foot
|
|
{
|
|
var wtPerFt:Double;
|
|
if (i_ym == 30.5)
|
|
{
|
|
if (i_diam <= 2 && i_diam > 1.75)
|
|
{
|
|
wtPerFt = 10.7;
|
|
}
|
|
else if (i_diam <= 1.75 && i_diam > 1.65)
|
|
{
|
|
wtPerFt = 8.2;
|
|
}
|
|
else if (i_diam <= 1.65 && i_diam > 1.5)
|
|
{
|
|
wtPerFt = 7;
|
|
}
|
|
else if (i_diam <= 1.5 && i_diam > 1.375)
|
|
{
|
|
wtPerFt = 6;
|
|
}
|
|
else if (i_diam <= 1.375 && i_diam > 1.125)
|
|
{
|
|
wtPerFt = 5;
|
|
}
|
|
else if (i_diam <= 1.125 && i_diam > 1)
|
|
{
|
|
wtPerFt = 3.676;
|
|
}
|
|
else if (i_diam <= 1 && i_diam > 0.875)
|
|
{
|
|
wtPerFt = 2.904;
|
|
}
|
|
else if (i_diam <= 0.875 && i_diam > 0.75)
|
|
{
|
|
wtPerFt = 2.224;
|
|
}
|
|
else if (i_diam <= 0.75 && i_diam > 0.625)
|
|
{
|
|
wtPerFt = 1.634;
|
|
}
|
|
else if (i_diam <= 0.625 && i_diam > 0.5)
|
|
{
|
|
wtPerFt = 1.13;
|
|
}
|
|
else if (i_diam <= 0.5)
|
|
{
|
|
wtPerFt = 0.72;
|
|
}
|
|
else
|
|
{
|
|
wtPerFt = 0;
|
|
}
|
|
}
|
|
else if (i_ym == 7.2)
|
|
{
|
|
if (i_diam <= 1.25 && i_diam > 1.125)
|
|
{
|
|
wtPerFt = 1.2879;
|
|
}
|
|
else if (i_diam <= 1.125 && i_diam > 1)
|
|
{
|
|
wtPerFt = 1.09;
|
|
}
|
|
else if (i_diam <= 1 && i_diam > 0.875)
|
|
{
|
|
wtPerFt = 0.8188;
|
|
}
|
|
else if (i_diam <= 0.875 && i_diam > 0.75)
|
|
{
|
|
wtPerFt = 0.6108;
|
|
}
|
|
else if (i_diam <= 0.75)
|
|
{
|
|
wtPerFt = 0.484;
|
|
}
|
|
else
|
|
{
|
|
wtPerFt = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wtPerFt = 0;
|
|
}
|
|
|
|
return wtPerFt;
|
|
}
|
|
|
|
// func readTaperCSV(filename:String)
|
|
// //reads the rod string configuration from a CSV
|
|
// {
|
|
//
|
|
// let csvURL = NSURL(string: "/Users/patrickjmcd/wellParamsIn_1.csv")!
|
|
// var error: NSErrorPointer = nil
|
|
// let csv = CSV(contentsOfURL: csvURL, error: error)
|
|
//
|
|
// // Rows
|
|
// let rows = csv.rows
|
|
//
|
|
// for(var row in csv.rows){
|
|
//
|
|
// }
|
|
// Float parseFloat(std::string dblStr);
|
|
// Float parseFloatString(Float *arr, std::string dblStr, int len, char delim );
|
|
//
|
|
// std::ifstream file (filename.c_str());
|
|
//
|
|
// while ( file.good() )
|
|
// {
|
|
// std::string key;
|
|
// std::string value;
|
|
// getline( file, key, ',' );
|
|
// getline( file, value, '\n');
|
|
//
|
|
// if(key.compare("dt")==0){
|
|
// dt = parseFloat(value);
|
|
// }
|
|
// else if (key.compare("tubingHeadPressure")==0)
|
|
// {
|
|
// tubingHeadPressure = parseFloat(value);
|
|
// }
|
|
// else if (key.compare("fluidGradient")==0)
|
|
// {
|
|
// fluidGradient = parseFloat(value);
|
|
// }
|
|
// else if (key.compare("sbfriction")==0)
|
|
// {
|
|
// sbfriction = parseFloat(value);
|
|
// }
|
|
// else if (key.compare("tubingID")==0)
|
|
// {
|
|
// tubingID = parseFloat(value);
|
|
// }
|
|
// else if (key.compare("tubingOD")==0)
|
|
// {
|
|
// tubingOD = parseFloat(value);
|
|
// }
|
|
// else if (key.compare("numTapers")==0)
|
|
// {
|
|
// std::istringstream(value) >> numTapers;
|
|
// }
|
|
// else if (key.compare("anchorDepth")==0)
|
|
// {
|
|
// anchorDepth = parseFloat(value);
|
|
// }
|
|
// else if (key.compare("pumpDiameter")==0)
|
|
// {
|
|
// pumpDiameter = parseFloat(value);
|
|
// pumpArea = pow(pumpDiameter,2) * M_PI;
|
|
// }
|
|
// else if (key.compare("structuralRating")==0)
|
|
// {
|
|
// structuralRating = parseFloat(value);
|
|
// }
|
|
// else if (key.compare("c")==0)
|
|
// {
|
|
// parseFloatString(c, value, 10, '&');
|
|
//}
|
|
//else if (key.compare("rodLength")==0)
|
|
//{
|
|
// parseFloatString(rodLength, value, 10, '&');
|
|
//}
|
|
//else if (key.compare("rodDiameter")==0)
|
|
//{
|
|
// parseFloatString(rodDiameter, value, 10, '&');
|
|
//}
|
|
//else if (key.compare("rodYM")==0)
|
|
//{
|
|
// parseFloatString(rodYM, value, 10, '&');
|
|
//}
|
|
//}
|
|
}
|
|
|
|
var well:Well;
|
|
well.printTaperSetup();
|
|
println(well.numTapers);
|
|
|
|
|
|
|
|
|
|
|
|
|