POC class is working and threadable
This commit is contained in:
@@ -1,5 +1,14 @@
|
||||
package com.henrypump.poc;
|
||||
|
||||
import de.vandermeer.asciitable.v2.RenderedTable;
|
||||
import de.vandermeer.asciitable.v2.V2_AsciiTable;
|
||||
import de.vandermeer.asciitable.v2.render.V2_AsciiTableRenderer;
|
||||
import de.vandermeer.asciitable.v2.render.WidthAbsoluteEven;
|
||||
import de.vandermeer.asciitable.v2.themes.V2_E_TableThemes;
|
||||
import static java.lang.Math.abs;
|
||||
import static java.lang.Math.pow;
|
||||
import static java.lang.Math.sqrt;
|
||||
|
||||
/**
|
||||
* Created by patrickjmcd on 1/31/17.
|
||||
*/
|
||||
@@ -10,10 +19,48 @@ public class Card {
|
||||
private double[] downholePosition = new double[maxPoints];
|
||||
private double[] surfaceLoad = new double[maxPoints];
|
||||
private double[] downholeLoad = new double[maxPoints];
|
||||
private int numPointsUsed;
|
||||
|
||||
//Card
|
||||
private int strokeNumber;
|
||||
private LPPair surfacePositionMax;
|
||||
private LPPair surfacePositionMin;
|
||||
private LPPair surfaceLoadMax;
|
||||
private LPPair surfaceLoadMin;
|
||||
private LPPair downholePositionMax;
|
||||
private LPPair downholePositionMin;
|
||||
private LPPair downholeLoadMax;
|
||||
private LPPair downholeLoadMin;
|
||||
|
||||
private LPPair topCorner;
|
||||
private LPPair bottomCorner;
|
||||
|
||||
private double surfaceStrokeLength;
|
||||
private double downholeNetStrokeLength;
|
||||
private double downholeGrossStrokeLength;
|
||||
private double downholeAdjustedGrossStrokeLength;
|
||||
private double downholeLoadSpan;
|
||||
private double fluidLoad;
|
||||
private double pumpIntakePressure;
|
||||
private double fluidLevel;
|
||||
private double fillageEstimated;
|
||||
private double fillageCalculated;
|
||||
private double tubingMovement;
|
||||
private double strokeSpeed;
|
||||
|
||||
private double plungerTravel;
|
||||
private double dailyProduction;
|
||||
private double structuralLoading;
|
||||
|
||||
private double polishedRodHorsepower;
|
||||
private double pumpHorsepower;
|
||||
|
||||
private long strokeStartTime;
|
||||
|
||||
Card(int strokeNumber){
|
||||
this.strokeNumber = strokeNumber;
|
||||
strokeStartTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void setSurfacePosition(int i, double position){
|
||||
this.surfacePosition[i] = position;
|
||||
@@ -50,4 +97,281 @@ public class Card {
|
||||
public LPPair getSurfacePositionMax() {
|
||||
return this.surfacePositionMax;
|
||||
}
|
||||
|
||||
public int getStrokeNumber() {
|
||||
return strokeNumber;
|
||||
}
|
||||
|
||||
public double getSurfaceStrokeLength() {
|
||||
return surfaceStrokeLength;
|
||||
}
|
||||
|
||||
public double getDownholeNetStrokeLength() {
|
||||
return downholeNetStrokeLength;
|
||||
}
|
||||
|
||||
public double getDownholeGrossStrokeLength() {
|
||||
return downholeGrossStrokeLength;
|
||||
}
|
||||
|
||||
public double getDownholeAdjustedGrossStrokeLength() {
|
||||
return downholeAdjustedGrossStrokeLength;
|
||||
}
|
||||
|
||||
public double getDownholeLoadSpan() {
|
||||
return downholeLoadSpan;
|
||||
}
|
||||
|
||||
public double getFluidLoad() {
|
||||
return fluidLoad;
|
||||
}
|
||||
|
||||
public double getFillageEstimated() {
|
||||
return fillageEstimated;
|
||||
}
|
||||
|
||||
public double getFillageCalculated() {
|
||||
return fillageCalculated;
|
||||
}
|
||||
|
||||
public double getTubingMovement() {
|
||||
return tubingMovement;
|
||||
}
|
||||
|
||||
public double getPlungerTravel() {
|
||||
return plungerTravel;
|
||||
}
|
||||
|
||||
public double getDailyProduction() {
|
||||
return dailyProduction;
|
||||
}
|
||||
|
||||
public double getStructuralLoading() {
|
||||
return structuralLoading;
|
||||
}
|
||||
|
||||
public int getNumPointsUsed() {
|
||||
return numPointsUsed;
|
||||
}
|
||||
|
||||
public void setNumPointsUsed(int numPointsUsed) {
|
||||
this.numPointsUsed = numPointsUsed;
|
||||
}
|
||||
|
||||
private void calculateSPM(){
|
||||
long now = System.currentTimeMillis();
|
||||
long strokeMillis = now - strokeStartTime;
|
||||
strokeSpeed = 60000.0 / (double)(now - strokeStartTime);
|
||||
}
|
||||
|
||||
private static double lineResolve(double x1, double x2, double y1, double y2, double xTest)
|
||||
{
|
||||
double line_m = (y2 - y1) / (x2 - x1);
|
||||
double line_b = y1 - line_m * x1;
|
||||
double yTest = line_m * xTest + line_b;
|
||||
return yTest;
|
||||
}
|
||||
|
||||
private static LPPair positionMax(double[] positionArr, double[] loadArr, int arrSize) {
|
||||
double maxPos = positionArr[0];
|
||||
double loadAtMaxP = Double.MIN_VALUE;
|
||||
|
||||
for(int i = 0; i < arrSize; i++) {
|
||||
maxPos = Math.max(maxPos, positionArr[i]);
|
||||
if (maxPos == positionArr[i]) loadAtMaxP = loadArr[i];
|
||||
}
|
||||
return new LPPair(maxPos, loadAtMaxP);
|
||||
}
|
||||
|
||||
private static LPPair positionMin(double[] positionArr, double[] loadArr, int arrSize) {
|
||||
double minPos = positionArr[0];
|
||||
double loadAtMinP = Double.MAX_VALUE;
|
||||
|
||||
for(int i = 0; i < arrSize; i++) {
|
||||
minPos = Math.min(minPos, positionArr[i]);
|
||||
if (minPos == positionArr[i]) loadAtMinP = loadArr[i];
|
||||
}
|
||||
return new LPPair(minPos, loadAtMinP);
|
||||
}
|
||||
|
||||
private static LPPair loadMax(double[] positionArr, double[] loadArr, int arrSize) {
|
||||
double maxLoad = loadArr[0];
|
||||
double posAtMaxL = Double.MIN_VALUE;
|
||||
|
||||
for(int i = 0; i < arrSize; i++) {
|
||||
maxLoad = Math.max(maxLoad, loadArr[i]);
|
||||
if (maxLoad == positionArr[i]) posAtMaxL = positionArr[i];
|
||||
}
|
||||
return new LPPair(posAtMaxL, maxLoad);
|
||||
}
|
||||
|
||||
private static LPPair loadMin(double[] positionArr, double[] loadArr, int arrSize) {
|
||||
double minLoad = loadArr[0];
|
||||
double posAtMinL = Double.MAX_VALUE;
|
||||
|
||||
for(int i = 0; i < arrSize; i++) {
|
||||
minLoad = Math.min(minLoad, loadArr[i]);
|
||||
if (minLoad == positionArr[i]) posAtMinL = positionArr[i];
|
||||
}
|
||||
return new LPPair(posAtMinL, minLoad);
|
||||
}
|
||||
|
||||
private double distanceToLine(double pos, double load)
|
||||
{
|
||||
double x1 = downholePositionMin.getPosition();
|
||||
double x2 = downholePositionMax.getPosition();
|
||||
double y1 = downholeLoadMin.getLoad();
|
||||
double y2 = downholeLoadMax.getLoad();
|
||||
|
||||
return abs((y2-y1)*pos - (x2-x1)*load + x2*y1 - y2*x1) / sqrt(pow(y2-y1, 2) + pow(x2-x1,2));
|
||||
};
|
||||
|
||||
void calcStrokeData(int numSlices, double fluidGradient, double rodDepth, double anchorDepth, double tubingCSA,
|
||||
double pumpArea, double frictionEstimate, double structuralRating)
|
||||
{
|
||||
calculateSPM();
|
||||
surfacePositionMax = positionMax(surfacePosition, surfaceLoad, numPointsUsed);
|
||||
surfaceLoadMax = loadMax(surfacePosition, surfaceLoad, numPointsUsed);
|
||||
surfacePositionMin = positionMin(surfacePosition, surfaceLoad, numPointsUsed);
|
||||
surfaceLoadMin = loadMin(surfacePosition, surfaceLoad, numPointsUsed);
|
||||
|
||||
downholePositionMax = positionMax(downholePosition, downholeLoad, numPointsUsed);
|
||||
downholeLoadMax = loadMax(downholePosition, downholeLoad, numPointsUsed);
|
||||
downholePositionMin = positionMin(downholePosition, downholeLoad, numPointsUsed);
|
||||
downholeLoadMin = loadMin(downholePosition, downholeLoad, numPointsUsed);
|
||||
|
||||
surfaceStrokeLength = surfacePositionMax.getPosition() - surfacePositionMin.getPosition();
|
||||
downholeGrossStrokeLength = downholePositionMax.getPosition() - downholePositionMin.getPosition();
|
||||
downholeLoadSpan = downholeLoadMax.getLoad() - downholeLoadMin.getLoad();
|
||||
|
||||
double dxSurf = (surfacePositionMax.getPosition() - surfacePositionMin.getPosition()) / (float) numSlices;
|
||||
double dxDown = (downholePositionMax.getPosition() - downholePositionMin.getPosition()) / (float) numSlices;
|
||||
|
||||
pumpHorsepower = 0.0;
|
||||
polishedRodHorsepower = 0.0;
|
||||
double dhDistanceTop = 0.0;
|
||||
double dhDistanceBottom = 0.0;
|
||||
|
||||
for (int i = 1; i < numSlices+1; i++)
|
||||
{
|
||||
double suPosTarget = surfacePositionMin.getPosition() + ((double) i * dxSurf);
|
||||
double dhPosTarget = downholePositionMin.getPosition() + ((double) i * dxDown);
|
||||
double suLoadAtTargetTop = 0.0;
|
||||
double suLoadAtTargetBottom = 0.0;
|
||||
double dhLoadAtTargetTop = 0.0;
|
||||
double dhLoadAtTargetBottom = 0.0;
|
||||
|
||||
for(int j = 0; j < numPointsUsed - 1; j++)
|
||||
{
|
||||
if (downholePosition[j] <= dhPosTarget && downholePosition[j+1] > dhPosTarget){
|
||||
dhLoadAtTargetTop = lineResolve(downholePosition[j], downholePosition[j+1], downholeLoad[j], downholeLoad[j+1], dhPosTarget);
|
||||
}
|
||||
|
||||
if (downholePosition[j] > dhPosTarget && downholePosition[j+1] >= dhPosTarget){
|
||||
dhLoadAtTargetBottom = lineResolve(downholePosition[j], downholePosition[j+1], downholeLoad[j], downholeLoad[j+1], dhPosTarget);
|
||||
}
|
||||
|
||||
if (surfacePosition[j] <= suPosTarget && surfacePosition[j+1] > suPosTarget){
|
||||
suLoadAtTargetTop = lineResolve(surfacePosition[j], surfacePosition[j+1], surfaceLoad[j], surfaceLoad[j+1], suPosTarget);
|
||||
}
|
||||
|
||||
if (surfacePosition[j] > suPosTarget && surfacePosition[j+1] >= suPosTarget){
|
||||
suLoadAtTargetBottom = lineResolve(surfacePosition[j], surfacePosition[j+1], surfaceLoad[j], surfaceLoad[j+1], suPosTarget);
|
||||
}
|
||||
}
|
||||
|
||||
polishedRodHorsepower += (dxSurf / 12.0) * (suLoadAtTargetTop - suLoadAtTargetBottom) * (strokeSpeed / 33000.0);
|
||||
pumpHorsepower += (dxDown / 12.0) * (dhLoadAtTargetTop - dhLoadAtTargetBottom) * (strokeSpeed / 33000.0);
|
||||
|
||||
double tDistance = distanceToLine(dhPosTarget, dhLoadAtTargetTop);
|
||||
double bDistance = distanceToLine(dhPosTarget, dhLoadAtTargetBottom);
|
||||
|
||||
if (tDistance > dhDistanceTop)
|
||||
{
|
||||
dhDistanceTop = tDistance;
|
||||
topCorner = new LPPair(dhPosTarget, dhLoadAtTargetTop);
|
||||
}
|
||||
|
||||
if (bDistance > dhDistanceBottom)
|
||||
{
|
||||
dhDistanceBottom = bDistance;
|
||||
bottomCorner = new LPPair(dhPosTarget, dhLoadAtTargetBottom);
|
||||
}
|
||||
}
|
||||
|
||||
downholeAdjustedGrossStrokeLength = downholePositionMax.getPosition() - topCorner.getPosition();
|
||||
downholeNetStrokeLength = bottomCorner.getPosition() - downholePositionMin.getPosition();
|
||||
fillageCalculated = (downholeNetStrokeLength / downholeAdjustedGrossStrokeLength) * 100.0;
|
||||
fillageEstimated =(downholeNetStrokeLength / downholeGrossStrokeLength) * 100.0;
|
||||
|
||||
if (fillageEstimated > 100)
|
||||
fillageEstimated = 100.0;
|
||||
|
||||
if (fillageCalculated > 100)
|
||||
fillageCalculated = 100.0;
|
||||
|
||||
fluidLoad = (downholeLoadMax.getLoad() - downholeLoadMin.getLoad()) - frictionEstimate;
|
||||
pumpIntakePressure = fluidGradient * rodDepth - (fluidLoad / pumpArea);
|
||||
//printf("PIP = %f * %f - (%f / %f) = %f\n", fluidGradient, rodDepth, fluidLoad, pumpArea, pumpIntakePressure);
|
||||
fluidLevel = pumpIntakePressure / fluidGradient;
|
||||
tubingMovement = 12 * (rodDepth - anchorDepth) * fluidLoad / (30500000 * tubingCSA);
|
||||
structuralLoading = (surfaceLoadMax.getLoad() / (structuralRating * 100)) * 100;
|
||||
};
|
||||
|
||||
public void printCard(String printType, boolean printDataTableToo){
|
||||
if(printType.toLowerCase().equals("table")) {
|
||||
V2_AsciiTable pointsTable = new V2_AsciiTable();
|
||||
pointsTable.addRule();
|
||||
pointsTable.addRow("Surface Position", "Surface Load", "Downhole Position", "Downhole Load");
|
||||
pointsTable.addRule();
|
||||
for (int i = 0; i < numPointsUsed; i++) {
|
||||
pointsTable.addRow(surfacePosition[i], surfaceLoad[i], downholePosition[i], downholeLoad[i]);
|
||||
}
|
||||
pointsTable.addRule();
|
||||
V2_AsciiTableRenderer rend = new V2_AsciiTableRenderer();
|
||||
rend.setTheme(V2_E_TableThemes.UTF_LIGHT.get());
|
||||
rend.setWidth(new WidthAbsoluteEven(100));
|
||||
RenderedTable rt = rend.render(pointsTable);
|
||||
System.out.println(rt);
|
||||
System.out.println();
|
||||
} else if (printType.toLowerCase().equals("csv")){
|
||||
System.out.println("surf_pos,surf_load,down_pos,down_load");
|
||||
for (int i = 0; i < numPointsUsed; i++) {
|
||||
System.out.printf("%f,%f,%f,%f\n", surfacePosition[i], surfaceLoad[i], downholePosition[i], downholeLoad[i]);
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
if(printDataTableToo){
|
||||
V2_AsciiTable dataTable = new V2_AsciiTable();
|
||||
dataTable.addRule();
|
||||
dataTable.addRow("Card " + strokeNumber, "Value");
|
||||
dataTable.addStrongRule();
|
||||
dataTable.addRow("Fill % (Est.)", fillageEstimated);
|
||||
dataTable.addRow("Fill % (Calc.)", fillageCalculated);
|
||||
dataTable.addRule();
|
||||
dataTable.addRow("Surf. Stroke Length", surfaceStrokeLength);
|
||||
dataTable.addRow("Down. Gross Stroke", downholeGrossStrokeLength);
|
||||
dataTable.addRow("Down. Net Stroke", downholeNetStrokeLength);
|
||||
dataTable.addRow("Tubing Movement", tubingMovement);
|
||||
dataTable.addRule();
|
||||
dataTable.addRow("Polished Rod HP", polishedRodHorsepower);
|
||||
dataTable.addRow("Pump HP", pumpHorsepower);
|
||||
dataTable.addRule();
|
||||
dataTable.addRow("Stroke Speed", strokeSpeed);
|
||||
dataTable.addRule();
|
||||
dataTable.addRow("Fluid Load", fluidLoad);
|
||||
dataTable.addRow("Pump Intake Pressure", pumpIntakePressure);
|
||||
dataTable.addRow("Fluid Level", fluidLevel);
|
||||
dataTable.addRule();
|
||||
dataTable.addRow("Structural Loading", structuralLoading);
|
||||
dataTable.addRule();
|
||||
V2_AsciiTableRenderer rend = new V2_AsciiTableRenderer();
|
||||
rend.setTheme(V2_E_TableThemes.UTF_LIGHT.get());
|
||||
rend.setWidth(new WidthAbsoluteEven(50));
|
||||
RenderedTable rt = rend.render(dataTable);
|
||||
System.out.println(rt);
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user