Initial Commit
This commit is contained in:
746
HP_POC.swift
Normal file
746
HP_POC.swift
Normal file
@@ -0,0 +1,746 @@
|
||||
//: Playground - noun: a place where people can play
|
||||
|
||||
import UIKit
|
||||
|
||||
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;
|
||||
for (var i = 0; i < NumColumns; i++)
|
||||
{
|
||||
topPosArray.append(Array(count:NumRows, repeatedValue:Double()))
|
||||
topLoadArray.append(Array(count:NumRows, repeatedValue:Double()))
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
init(){
|
||||
|
||||
}
|
||||
|
||||
// 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, '&');
|
||||
//}
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
760
POC.playground/Contents.swift
Normal file
760
POC.playground/Contents.swift
Normal file
@@ -0,0 +1,760 @@
|
||||
//: 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);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
3
POC.playground/Sources/SupportCode.swift
Normal file
3
POC.playground/Sources/SupportCode.swift
Normal file
@@ -0,0 +1,3 @@
|
||||
//
|
||||
// This file (and all other Swift source files in the Sources directory of this playground) will be precompiled into a framework which is automatically made available to POC.playground.
|
||||
//
|
||||
4
POC.playground/contents.xcplayground
Normal file
4
POC.playground/contents.xcplayground
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<playground version='5.0' target-platform='osx'>
|
||||
<timeline fileName='timeline.xctimeline'/>
|
||||
</playground>
|
||||
7
POC.playground/playground.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
POC.playground/playground.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:../../Dropbox (Henry Pump)/Patrick McDonagh/POC/Swift POC/POC.playground">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
|
||||
<false/>
|
||||
<key>IDESourceControlProjectIdentifier</key>
|
||||
<string>F63752C8-BC3A-4E8B-83CF-87055B0E471D</string>
|
||||
<key>IDESourceControlProjectName</key>
|
||||
<string>playground</string>
|
||||
<key>IDESourceControlProjectOriginsDictionary</key>
|
||||
<dict>
|
||||
<key>7BF837D10FB421D5AEF1283459C27C2BF38FFB44</key>
|
||||
<string>http://192.168.2.45/Bonobo.Git.Server/Swift_POC.git</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectPath</key>
|
||||
<string>POC.playground/playground.xcworkspace</string>
|
||||
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
|
||||
<dict>
|
||||
<key>7BF837D10FB421D5AEF1283459C27C2BF38FFB44</key>
|
||||
<string>../..</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectURL</key>
|
||||
<string>http://192.168.2.45/Bonobo.Git.Server/Swift_POC.git</string>
|
||||
<key>IDESourceControlProjectVersion</key>
|
||||
<integer>111</integer>
|
||||
<key>IDESourceControlProjectWCCIdentifier</key>
|
||||
<string>7BF837D10FB421D5AEF1283459C27C2BF38FFB44</string>
|
||||
<key>IDESourceControlProjectWCConfigurations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
|
||||
<string>public.vcs.git</string>
|
||||
<key>IDESourceControlWCCIdentifierKey</key>
|
||||
<string>7BF837D10FB421D5AEF1283459C27C2BF38FFB44</string>
|
||||
<key>IDESourceControlWCCName</key>
|
||||
<string>Swift%20POC</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
POC.playground/playground.xcworkspace/xcuserdata/patrickjmcd.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
BIN
POC.playground/playground.xcworkspace/xcuserdata/patrickjmcd.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
Binary file not shown.
6
POC.playground/timeline.xctimeline
Normal file
6
POC.playground/timeline.xctimeline
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Timeline
|
||||
version = "3.0">
|
||||
<TimelineItems>
|
||||
</TimelineItems>
|
||||
</Timeline>
|
||||
755
TestPlayground.playground/Contents.swift
Normal file
755
TestPlayground.playground/Contents.swift
Normal file
@@ -0,0 +1,755 @@
|
||||
//: Playground - noun: a place where people can play
|
||||
|
||||
import UIKit
|
||||
|
||||
|
||||
println("hello world");
|
||||
|
||||
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;
|
||||
for(var i = 0; i < NumColumns; i++)
|
||||
{
|
||||
topPosArray.append(Array(count:NumRows, repeatedValue:Double()))
|
||||
topLoadArray.append(Array(count:NumRows, repeatedValue:Double()))
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
init(){
|
||||
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
3
TestPlayground.playground/Sources/SupportCode.swift
Normal file
3
TestPlayground.playground/Sources/SupportCode.swift
Normal file
@@ -0,0 +1,3 @@
|
||||
//
|
||||
// This file (and all other Swift source files in the Sources directory of this playground) will be precompiled into a framework which is automatically made available to TestPlayground.playground.
|
||||
//
|
||||
2
TestPlayground.playground/contents.xcplayground
Normal file
2
TestPlayground.playground/contents.xcplayground
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<playground version='5.0' target-platform='ios' auto-termination-delay='9'/>
|
||||
7
TestPlayground.playground/playground.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
TestPlayground.playground/playground.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:../../Dropbox (Henry Pump)/Patrick McDonagh/POC/Swift POC/TestPlayground.playground">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
|
||||
<false/>
|
||||
<key>IDESourceControlProjectIdentifier</key>
|
||||
<string>EDEEFAB5-5519-4B14-9908-8C3055C0C758</string>
|
||||
<key>IDESourceControlProjectName</key>
|
||||
<string>playground</string>
|
||||
<key>IDESourceControlProjectOriginsDictionary</key>
|
||||
<dict>
|
||||
<key>7BF837D10FB421D5AEF1283459C27C2BF38FFB44</key>
|
||||
<string>http://192.168.2.45/Bonobo.Git.Server/Swift_POC.git</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectPath</key>
|
||||
<string>TestPlayground.playground/playground.xcworkspace</string>
|
||||
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
|
||||
<dict>
|
||||
<key>7BF837D10FB421D5AEF1283459C27C2BF38FFB44</key>
|
||||
<string>../..</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectURL</key>
|
||||
<string>http://192.168.2.45/Bonobo.Git.Server/Swift_POC.git</string>
|
||||
<key>IDESourceControlProjectVersion</key>
|
||||
<integer>111</integer>
|
||||
<key>IDESourceControlProjectWCCIdentifier</key>
|
||||
<string>7BF837D10FB421D5AEF1283459C27C2BF38FFB44</string>
|
||||
<key>IDESourceControlProjectWCConfigurations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
|
||||
<string>public.vcs.git</string>
|
||||
<key>IDESourceControlWCCIdentifierKey</key>
|
||||
<string>7BF837D10FB421D5AEF1283459C27C2BF38FFB44</string>
|
||||
<key>IDESourceControlWCCName</key>
|
||||
<string>Swift%20POC</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
Binary file not shown.
34
wellParamsIn_1.csv
Normal file
34
wellParamsIn_1.csv
Normal file
@@ -0,0 +1,34 @@
|
||||
dt,0.06
|
||||
tubingHeadPressure,200
|
||||
fluidGradient,0.45
|
||||
sbfriction,300
|
||||
numTapers,2
|
||||
c,0&0.08&0.08&0&0&0&0&0&0&0&
|
||||
rodLength,0&10095&300&0&0&0&0&0&0&0&
|
||||
rodDiameter,0&0.75&1.5&0&0&0&0&0&0&0&
|
||||
rodYM,0&30.5&30.5&0&0&0&0&0&0&0&
|
||||
rodWeightPerFoot,0&1.634&6&0&0&0&0&0&0&0&
|
||||
a,0&16295.1376523724&17007.4197367572&0&0&0&0&0&0&0&
|
||||
area,0&0.441786466911065&1.76714586764426&0&0&0&0&0&0&0&0&
|
||||
pressure,200&200&200&0&0&0&0&0&0&0&
|
||||
buoyantForce,0&265.071880146639&-353.429173528852&0&0&0&0&0&0&0&
|
||||
buoyantForceTotal,-2510.562045
|
||||
stretch,0&0&0&0&0&0&0&0&0&0&
|
||||
weightData,0&1800&0&0&0&0&0&0&0&0&
|
||||
weightDataTotal,1800
|
||||
annularForceData,0&-6815.99205812064&0&0&0&0&0&0&0&0&
|
||||
annularForceDataTotal,-19652.76053
|
||||
force,0&0&-353.429173528852&0&0&0&0&0&0&0&
|
||||
alpha,0&0&-6.55737704918033E-06&0&0&0&0&0&0&0&
|
||||
xOverA,0&0&0&0&0&0&0&0&0&0&
|
||||
factorArray,0&0&0&0&0&0&0&0&0&0&
|
||||
lagIndexArray,0&0&0&0&0&0&0&0&0&0&
|
||||
centerPoint,0&2&2&0&0&0&0&0&0&0&
|
||||
sumCenterPoint,0&2&0&0&0&0&0&0&0&0&
|
||||
lengthRequired,0&3&3&0&0&0&0&0&0&0&
|
||||
rodDepth,0&0&0&0&0&0&0&0&0&0&
|
||||
rodDepthTotal,10395
|
||||
rodWeightAir,0&0&0&0&0&0&0&0&0&0&
|
||||
rodWeightAirTotal,18295.23
|
||||
rodWeightFluid,0&265.071880146639&-353.429173528852&0&0&0&0&0&0&0&
|
||||
rodWeightFluidTotal,-176.7145868
|
||||
|
Reference in New Issue
Block a user