1192 lines
44 KiB
Java
1192 lines
44 KiB
Java
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 org.json.simple.JSONArray;
|
|
import org.json.simple.JSONObject;
|
|
import org.json.simple.parser.JSONParser;
|
|
import org.json.simple.parser.ParseException;
|
|
|
|
import static java.lang.Math.exp;
|
|
import static java.lang.Math.pow;
|
|
import static java.lang.Math.sqrt;
|
|
|
|
import java.io.FileReader;
|
|
import java.io.IOException;
|
|
import java.time.ZonedDateTime;
|
|
import java.time.temporal.ChronoUnit;
|
|
|
|
/**
|
|
* Created by patrickjmcd on 1/31/17.
|
|
*/
|
|
public class Well {
|
|
private String wellName;
|
|
protected Simulation sim;
|
|
protected Database db;
|
|
protected WellTest wellTest;
|
|
|
|
/* IO */
|
|
AnalogIn inclinometer;
|
|
AnalogIn loadCell;
|
|
private double currentSurfacePosition;
|
|
private double currentSurfaceLoad;
|
|
private double currentDownholePosition;
|
|
private double currentDownholeLoad;
|
|
|
|
/* CARDS */
|
|
private Card currentCard;
|
|
public Card[] cardStorage = new Card[100];
|
|
|
|
// CONSTANTS
|
|
private static double YM_STEEL = 30.5;
|
|
private static double YM_FIBERGLASS = 7.2;
|
|
static final int BAD_STATUS = 0;
|
|
static final int GOOD_STATUS = 1;
|
|
|
|
/* USER INPUTS */
|
|
private double dt;
|
|
private double tubingHeadPressure;
|
|
private double fluidGradient;
|
|
private double sbfriction;
|
|
private int numTapers;
|
|
private double tubingAnchorDepth;
|
|
private double pumpDiameter;
|
|
private double tubingID, tubingOD;
|
|
private double structuralRating;
|
|
private double[] c = new double[11];
|
|
private double[] rodLength = new double[11];
|
|
private double[] rodDiameter = new double[11];
|
|
private double[] rodYM = new double[11];
|
|
private double[] rodWeightPerFoot = new double[11];
|
|
|
|
|
|
// CALCULATED TAPER PARAMETERS
|
|
private int nT1; // should always be equal to number of tapers + 1
|
|
private double frictionEstimate;
|
|
private double theoreticalMaxFluidLoad;
|
|
private double[] a = new double[11];
|
|
private double[] area = new double[11];
|
|
private double[] pressure = new double[11];
|
|
private double[] buoyantForce = new double[11];
|
|
private double buoyantForceTotal;
|
|
private double[] stretch = new double[11];
|
|
private double[] weightData = new double[11];
|
|
private double weightDataTotal;
|
|
private double[] annularForceData = new double[11];
|
|
private double annularForceDataTotal;
|
|
private double[] force = new double[11];
|
|
private double[] alpha = new double[11];
|
|
private double[] xOverA = new double[11];
|
|
private double[] factor = new double[11];
|
|
private int[] lagIndex = new int[11];
|
|
private int[] lengthRequired = new int[11];
|
|
private int[] centerPoint = new int[11];
|
|
private double[] rodDepth = new double[11];
|
|
private double rodDepthTotal;
|
|
private double[] rodWeightAir = new double[11];
|
|
private double rodWeightAirTotal;
|
|
private double[] rodWeightFluid = new double[11];
|
|
private double rodWeightFluidTotal;
|
|
private double pumpArea;
|
|
private double tubingCrossSectionalArea;
|
|
|
|
// Statuses
|
|
private volatile int runStatus;
|
|
public static final int RUNSTATUS_STOPPED = 0;
|
|
public static final int RUNSTATUS_STARTING = 1;
|
|
public static final int RUNSTATUS_RUNNING = 2;
|
|
public static final int RUNSTATUS_PUMPEDOFF = 3;
|
|
public static final int RUNSTATUS_FAULTED = 4;
|
|
public static final int RUNSTATUS_LOCKEDOUT = 5;
|
|
|
|
private boolean permissiveOK;
|
|
private long strokesSinceStart = 0;
|
|
private long startupStrokes = 1;
|
|
private long strokesToday = 0;
|
|
private long strokesLifetime;
|
|
private int pointCounter =0;
|
|
|
|
// DIRECTION
|
|
private static final int DIRECTION_UNKNOWN = 0;
|
|
private static final int DIRECTION_UP = 1;
|
|
private static final int DIRECTION_DOWN = 2;
|
|
private int direction = DIRECTION_UNKNOWN;
|
|
private int lastDirection = DIRECTION_UNKNOWN;
|
|
|
|
// Modes
|
|
private volatile int runMode;
|
|
public static final int RUNMODE_POC = 0;
|
|
public static final int RUNMODE_MANUAL = 1;
|
|
public static final int RUNMODE_TIMER = 2;
|
|
|
|
|
|
// Intermediate Variables
|
|
private double[][] topPosArray = new double[10][100];
|
|
private double[][] topLoadArray = new double[10][100];
|
|
private double loadBefore = 0.0;
|
|
private double loadAfter = 0.0;
|
|
private double loadBefore3 = 0.0;
|
|
private double loadAfter3 = 0.0;
|
|
private int[] count = new int[11];
|
|
private double sPositionPrevious;
|
|
|
|
// Fluid Makeup
|
|
private double fluidOilRatio; // BBL of oil per 1 BBL fluid
|
|
private double fluidWaterRatio; // BBL of water per 1 BBL fluid
|
|
private double fluidGasRatio; // MCF of gas per 1 BBL fluid
|
|
private double kFactor = 1.0;
|
|
|
|
// DATE & TIME PARAMETERS
|
|
private ZonedDateTime now = ZonedDateTime.now();
|
|
|
|
private boolean isNewDay(){
|
|
|
|
ZonedDateTime today = ZonedDateTime.now();
|
|
boolean ret = !(today.toLocalDate().equals(now.toLocalDate()));
|
|
now = today;
|
|
return ret;
|
|
}
|
|
|
|
// Measurements
|
|
private Measurement strokeSpeed;
|
|
private Measurement downholeGrossStroke;
|
|
private Measurement downholeNetStroke;
|
|
private Measurement fluidLevel;
|
|
private Measurement fluidLoad;
|
|
private Measurement inflowRate;
|
|
private Measurement peakPolishedRodLoad;
|
|
private Measurement minPolishedRodLoad;
|
|
private Measurement percentRun;
|
|
private Measurement polishedRodHP;
|
|
private Measurement pumpHP;
|
|
private Measurement fluidProduced;
|
|
private Measurement fluidProducedAdjusted;
|
|
private Measurement oilProduced;
|
|
private Measurement waterProduced;
|
|
private Measurement gasProduced;
|
|
private Measurement pumpIntakePressure;
|
|
private Measurement surfaceStrokeLength;
|
|
private Measurement tubingMovement;
|
|
private Measurement pumpFillPercent;
|
|
|
|
// Running Setpoints
|
|
private double pumpOffFillPercentSetpoint = 65;
|
|
private int pumpOffStrokes = 5;
|
|
private int lowFillageStrokes = 0;
|
|
private ZonedDateTime pumpedOffTime;
|
|
private long pumpOffDowntimeMinutes = 5;
|
|
private long minutesSincePumpOff = 0;
|
|
private long minutesSincePumpOff_last = 0;
|
|
|
|
Well(String dbHostname, int inclinometerChannel, int loadCellChannel, int runCommandChannel){
|
|
this.wellName = wellName;
|
|
db = new Database(dbHostname);
|
|
strokesLifetime = db.getLastStrokeNum() + 1;
|
|
currentCard = new Card(strokesLifetime);
|
|
inclinometer = new AnalogIn(inclinometerChannel, 0, 100, 0, 100);
|
|
loadCell = new AnalogIn(loadCellChannel, 0, 50000, 0, 50000);
|
|
|
|
initializeMeasurements();
|
|
db.newRunStatus("Boot", "io");
|
|
}
|
|
|
|
Well(String dbHostname, String simFileName, int inclinometerChannel, int loadCellChannel, int runCommandChannel){
|
|
this.wellName = wellName;
|
|
sim = new Simulation(simFileName);
|
|
db = new Database(dbHostname);
|
|
strokesLifetime = db.getLastStrokeNum() + 1;
|
|
currentCard = new Card(strokesLifetime);
|
|
inclinometer = new AnalogIn(inclinometerChannel, 0, 100, 0, 100);
|
|
loadCell = new AnalogIn(loadCellChannel, 0, 50000, 0, 50000);
|
|
|
|
initializeMeasurements();
|
|
db.newRunStatus("Boot", "commandline");
|
|
}
|
|
|
|
private void initializeMeasurements(){
|
|
strokeSpeed = new Measurement("Stroke Speed", db, 0.5, 600);
|
|
downholeGrossStroke = new Measurement("Downhole Gross Stroke", db, 0.5, 600);
|
|
downholeNetStroke = new Measurement("Downhole Net Stroke", db, 0.5, 600);
|
|
fluidLevel = new Measurement("Fluid Level", db, 10, 600);
|
|
fluidLoad = new Measurement("Fluid Load", db, 20, 600);
|
|
inflowRate = new Measurement("Inflow Rate", db, 0.5, 600);
|
|
peakPolishedRodLoad = new Measurement("Peak PRL", db, 50, 600);
|
|
minPolishedRodLoad = new Measurement("Min PRL", db, 50, 600);
|
|
percentRun = new Measurement("Percent Run", db, 1.0, 600);
|
|
polishedRodHP = new Measurement("Polished Rod HP", db, 0.25, 600);
|
|
pumpHP = new Measurement("Pump HP", db, 0.25, 600);
|
|
fluidProduced = new Measurement("Fluid Produced", db, 1.0, 600);
|
|
fluidProducedAdjusted = new Measurement("Fluid Produced (adjusted)", db, 1.0, 600);
|
|
oilProduced = new Measurement("Oil Produced", db, 1.0, 600);
|
|
waterProduced = new Measurement("Water Produced", db, 1.0, 600);
|
|
gasProduced = new Measurement("Gas Produced", db, 1.0, 600);
|
|
pumpIntakePressure = new Measurement("Pump Intake Pressure", db, 5.0, 600);
|
|
surfaceStrokeLength = new Measurement("Surface Stroke", db, 0.5, 1800);
|
|
tubingMovement = new Measurement("Tubing Movement", db, 0.5, 600);
|
|
pumpFillPercent = new Measurement("Pump Fill Percent", db, 0.5, 600);
|
|
}
|
|
|
|
public double getDt() {
|
|
return dt;
|
|
}
|
|
|
|
public void setDt(double dt) {
|
|
this.dt = dt;
|
|
}
|
|
|
|
public double getTubingHeadPressure() {
|
|
return tubingHeadPressure;
|
|
}
|
|
|
|
public void setTubingHeadPressure(double tubingHeadPressure) {
|
|
this.tubingHeadPressure = tubingHeadPressure;
|
|
}
|
|
|
|
public double getFluidGradient() {
|
|
return fluidGradient;
|
|
}
|
|
|
|
public void setFluidGradient(double fluidGradient) {
|
|
this.fluidGradient = fluidGradient;
|
|
}
|
|
|
|
public double getSbfriction() {
|
|
return sbfriction;
|
|
}
|
|
|
|
public void setSbfriction(double sbfriction) {
|
|
this.sbfriction = sbfriction;
|
|
}
|
|
|
|
public int getNumTapers() {
|
|
return numTapers;
|
|
}
|
|
|
|
public void setNumTapers(int numTapers) {
|
|
this.numTapers = numTapers;
|
|
}
|
|
|
|
public double getTubingAnchorDepth() {
|
|
return tubingAnchorDepth;
|
|
}
|
|
|
|
public void setTubingAnchorDepth(double tubingAnchorDepth) {
|
|
this.tubingAnchorDepth = tubingAnchorDepth;
|
|
}
|
|
|
|
public double getPumpDiameter() {
|
|
return pumpDiameter;
|
|
}
|
|
|
|
public void setPumpDiameter(double pumpDiameter) {
|
|
this.pumpDiameter = pumpDiameter;
|
|
this.pumpArea = pow(pumpDiameter, 2) * Math.PI;
|
|
}
|
|
|
|
public double getTubingID() {
|
|
return tubingID;
|
|
}
|
|
|
|
public void setTubingID(double tubingID) {
|
|
this.tubingID = tubingID;
|
|
this.tubingCrossSectionalArea = (Math.PI / 4) * (pow(this.tubingOD, 2) - pow(this.tubingID,2));
|
|
}
|
|
|
|
public double getTubingOD() {
|
|
return tubingOD;
|
|
}
|
|
|
|
public void setTubingOD(double tubingOD) {
|
|
this.tubingOD = tubingOD;
|
|
this.tubingCrossSectionalArea = (Math.PI / 4) * (pow(this.tubingOD, 2) - pow(tubingID,2));
|
|
|
|
}
|
|
|
|
public void setDampingFactor(int i, double c) {
|
|
this.c[i] = c;
|
|
}
|
|
|
|
public double getDampingFactor(int i){ return c[i]; }
|
|
|
|
public void setRodLength(int i, double rodLength) {
|
|
this.rodLength[i] = rodLength;
|
|
}
|
|
|
|
public double getRodLength(int i){ return rodLength[i]; }
|
|
|
|
public void setRodDiameter(int i, double rodDiameter) {
|
|
this.rodDiameter[i] = rodDiameter;
|
|
}
|
|
|
|
public double getRodDiameter(int i){ return rodDiameter[i]; }
|
|
|
|
public void setRodYM(int i, String material) {
|
|
|
|
if (material.toLowerCase().equals("steel")) rodYM[i] = YM_STEEL;
|
|
else if (material.toLowerCase().equals("fiberglass")) rodYM[i] = YM_FIBERGLASS;
|
|
|
|
}
|
|
|
|
public double getRodYM(int i){ return rodYM[i]; }
|
|
|
|
public String getRodMaterial(int i){
|
|
if(rodYM[i] == YM_STEEL)
|
|
return "steel";
|
|
if(rodYM[i] == YM_FIBERGLASS)
|
|
return "fiberglass";
|
|
return "unknown";
|
|
}
|
|
|
|
public double getFrictionEstimate() {
|
|
return frictionEstimate;
|
|
}
|
|
|
|
public void setFrictionEstimate(double frictionEstimate) {
|
|
this.frictionEstimate = frictionEstimate;
|
|
}
|
|
|
|
public double getRodDepthTotal() {
|
|
return rodDepthTotal;
|
|
}
|
|
|
|
public double getPumpArea() {
|
|
return pumpArea;
|
|
}
|
|
|
|
public double getTubingCrossSectionalArea() {
|
|
return tubingCrossSectionalArea;
|
|
}
|
|
|
|
public double getStructuralRating() {
|
|
return structuralRating;
|
|
}
|
|
|
|
public void setStructuralRating(double structuralRating) {
|
|
this.structuralRating = structuralRating;
|
|
}
|
|
|
|
public void setWellName(String wellName) {
|
|
this.wellName = wellName;
|
|
}
|
|
|
|
public String getWellName() {
|
|
return wellName;
|
|
}
|
|
|
|
public boolean isPermissiveOK() {
|
|
return permissiveOK;
|
|
}
|
|
|
|
public int getRunStatus() {
|
|
return runStatus;
|
|
}
|
|
|
|
public String getRunStatusString(){
|
|
switch(runStatus){
|
|
case RUNSTATUS_STOPPED:
|
|
return "Stopped";
|
|
case RUNSTATUS_STARTING:
|
|
return "Starting";
|
|
case RUNSTATUS_RUNNING:
|
|
return "Running";
|
|
case RUNSTATUS_PUMPEDOFF:
|
|
return "Pumped-Off";
|
|
case RUNSTATUS_FAULTED:
|
|
return "Faulted";
|
|
case RUNSTATUS_LOCKEDOUT:
|
|
return "Locked Out";
|
|
default:
|
|
return "Unknown";
|
|
}
|
|
}
|
|
|
|
public int getRunMode() {
|
|
return runMode;
|
|
}
|
|
|
|
public double getCurrentSurfacePosition() {
|
|
return currentSurfacePosition;
|
|
}
|
|
|
|
public double getCurrentSurfaceLoad() {
|
|
return currentSurfaceLoad;
|
|
}
|
|
|
|
public double getCurrentDownholePosition() {
|
|
return currentDownholePosition;
|
|
}
|
|
|
|
public double getCurrentDownholeLoad() {
|
|
return currentDownholeLoad;
|
|
}
|
|
|
|
public long getStartupStrokes() {
|
|
return startupStrokes;
|
|
}
|
|
|
|
public void setStartupStrokes(long startupStrokes) {
|
|
this.startupStrokes = startupStrokes;
|
|
}
|
|
|
|
public long getStrokesSinceStart() {
|
|
return strokesSinceStart;
|
|
}
|
|
|
|
public long getStrokesToday() {
|
|
return strokesToday;
|
|
}
|
|
|
|
public long getStrokesLifetime() {
|
|
return strokesLifetime;
|
|
}
|
|
|
|
public int getDirection() {
|
|
return direction;
|
|
}
|
|
|
|
public double getFluidOilRatio() {
|
|
return fluidOilRatio;
|
|
}
|
|
|
|
public double getFluidWaterRatio() {
|
|
return fluidWaterRatio;
|
|
}
|
|
|
|
public double getFluidGasRatio() {
|
|
return fluidGasRatio;
|
|
}
|
|
|
|
public double getkFactor() {
|
|
return kFactor;
|
|
}
|
|
|
|
public void setkFactor(double kFactor) {
|
|
this.kFactor = kFactor;
|
|
}
|
|
|
|
public int getLowFillageStrokes() {
|
|
return lowFillageStrokes;
|
|
}
|
|
|
|
public ZonedDateTime getPumpedOffTime() {
|
|
return pumpedOffTime;
|
|
}
|
|
|
|
public long getMinutesSincePumpOff() {
|
|
return minutesSincePumpOff;
|
|
}
|
|
|
|
public double getPumpOffFillPercentSetpoint() {
|
|
return pumpOffFillPercentSetpoint;
|
|
}
|
|
|
|
public void setPumpOffFillPercentSetpoint(double pumpOffFillPercentSetpoint) {
|
|
this.pumpOffFillPercentSetpoint = pumpOffFillPercentSetpoint;
|
|
}
|
|
|
|
public int getPumpOffStrokes() {
|
|
return pumpOffStrokes;
|
|
}
|
|
|
|
public void setPumpOffStrokes(int pumpOffStrokes) {
|
|
this.pumpOffStrokes = pumpOffStrokes;
|
|
}
|
|
|
|
public long getPumpOffDowntimeMinutes() {
|
|
return pumpOffDowntimeMinutes;
|
|
}
|
|
|
|
public void setPumpOffDowntimeMinutes(long pumpOffDowntimeMinutes) {
|
|
this.pumpOffDowntimeMinutes = pumpOffDowntimeMinutes;
|
|
}
|
|
|
|
public void setupFluidRatio(double oilRatio, double waterRatio, double gasRatio){
|
|
fluidOilRatio = oilRatio;
|
|
fluidWaterRatio = waterRatio;
|
|
fluidGasRatio = gasRatio;
|
|
}
|
|
|
|
// WELL COMMAND FUNCTIONS
|
|
public void start(String initiator){
|
|
if (runStatus == RUNSTATUS_STOPPED && permissiveOK){
|
|
System.out.println("Starting " + wellName + " from " + initiator + "...");
|
|
runStatus = RUNSTATUS_STARTING;
|
|
strokesSinceStart = 0;
|
|
db.newRunStatus(getRunStatusString(), initiator);
|
|
}
|
|
}
|
|
|
|
public void stop(String initiator){
|
|
if (runStatus == RUNSTATUS_STARTING || runStatus == RUNSTATUS_RUNNING || runStatus == RUNSTATUS_PUMPEDOFF){
|
|
System.out.println("Stopping " + wellName + " from " + initiator + "...");
|
|
runStatus = RUNSTATUS_STOPPED;
|
|
db.newRunStatus(getRunStatusString(), initiator);
|
|
}
|
|
}
|
|
|
|
public void restart(String initiator){
|
|
if (runStatus == RUNSTATUS_PUMPEDOFF && permissiveOK){
|
|
System.out.println("Restarting after pump-off from " + initiator + "...");
|
|
runStatus = RUNSTATUS_STARTING;
|
|
strokesSinceStart = 0;
|
|
db.newRunStatus(getRunStatusString(), initiator);
|
|
}
|
|
}
|
|
|
|
public void pumpOff(String initiator){
|
|
if (runStatus == RUNSTATUS_RUNNING){
|
|
System.out.println("Pumping off from " + initiator + "...");
|
|
System.out.println("Restarting in " + pumpOffDowntimeMinutes + " minutes.");
|
|
pumpedOffTime = ZonedDateTime.now();
|
|
runStatus = RUNSTATUS_PUMPEDOFF;
|
|
db.newRunStatus(getRunStatusString(), initiator);
|
|
}
|
|
}
|
|
|
|
public void checkSafeties(){
|
|
permissiveOK = true;
|
|
}
|
|
|
|
// WELL CALCULATION FUNCTIONS
|
|
|
|
private static double lookupRodWeightPerFoot(double i_ym, double i_diam) {
|
|
double wtPerFt;
|
|
if (i_ym == YM_STEEL) {
|
|
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 == YM_FIBERGLASS) {
|
|
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;
|
|
};
|
|
|
|
void parseJSONFile(String jsonFilename){
|
|
JSONParser parser = new JSONParser();
|
|
try {
|
|
Object obj = parser.parse(new FileReader(jsonFilename));
|
|
JSONObject well = (JSONObject) obj;
|
|
|
|
Object newWellName = well.get("wellName");
|
|
if (newWellName != null) wellName = (String) newWellName;
|
|
|
|
Object newDeltaT = well.get("deltaT");
|
|
if (newDeltaT != null) dt = (Double) newDeltaT;
|
|
|
|
Object newPumpDiameter = well.get("pumpDiameter");
|
|
if (newPumpDiameter != null) setPumpDiameter((Double) newPumpDiameter);
|
|
|
|
Object newFluidGradient = well.get("fluidGradient");
|
|
if (newFluidGradient != null) fluidGradient = (Double) newFluidGradient;
|
|
|
|
Object newTubingID = well.get("tubingID");
|
|
if (newTubingID != null) setTubingID((Double) newTubingID);
|
|
|
|
Object newTubingOD = well.get("tubingOD");
|
|
if (newTubingOD != null) setTubingOD((Double) newTubingOD);
|
|
|
|
Object newTubingAnchorDepth = well.get("tubingAnchorDepth");
|
|
if (newTubingAnchorDepth != null) tubingAnchorDepth = (Double) newTubingAnchorDepth;
|
|
|
|
Object newStructuralRating = well.get("structuralRating");
|
|
if (newStructuralRating != null) structuralRating = (Double) newStructuralRating;
|
|
|
|
Object newStuffingBoxFriction = well.get("stuffingBoxFriction");
|
|
if (newStuffingBoxFriction != null) setSbfriction((Double) newStuffingBoxFriction);
|
|
|
|
Object newTubingHeadPressure = well.get("tubingOD");
|
|
if (newTubingHeadPressure != null) setTubingOD((Double) newTubingHeadPressure);
|
|
|
|
JSONArray tapers = (JSONArray) well.get("tapers");
|
|
numTapers = tapers.size();
|
|
for (int i = 0; i < numTapers; i++){
|
|
int currentTaperNum = i + 1;
|
|
JSONObject taperObj = (JSONObject) tapers.get(i);
|
|
|
|
Object newLength = taperObj.get("length");
|
|
if (newLength != null) setRodLength(currentTaperNum, (Double) newLength);
|
|
|
|
Object newDiameter = taperObj.get("diameter");
|
|
if (newDiameter != null) setRodDiameter(currentTaperNum, (Double) newDiameter);
|
|
|
|
Object newMaterial = taperObj.get("material");
|
|
if (newMaterial != null) setRodYM(currentTaperNum, (String) newMaterial);
|
|
|
|
Object newDampingFactor = taperObj.get("dampingFactor");
|
|
if (newDampingFactor != null) setDampingFactor(currentTaperNum, (Double) newDampingFactor);
|
|
}
|
|
|
|
} catch (IOException | ParseException e) {
|
|
e.printStackTrace();
|
|
}
|
|
updateTapers();
|
|
|
|
}
|
|
|
|
void printTapers(){
|
|
|
|
System.out.println("===== " + wellName + " =====");
|
|
System.out.println("--- INPUT PARAMETERS ---");
|
|
|
|
V2_AsciiTable inputTable = new V2_AsciiTable();
|
|
inputTable.addRule();
|
|
inputTable.addRow("DeltaT", getDt());
|
|
inputTable.addStrongRule();
|
|
inputTable.addRow("Fluid Gradient", getFluidGradient());
|
|
inputTable.addRow("Pump Diameter", getPumpDiameter());
|
|
inputTable.addRow("Stuffing Box Friction", getSbfriction());
|
|
inputTable.addRow("Friction Estimate", getFrictionEstimate());
|
|
inputTable.addRule();
|
|
inputTable.addRow("Tubing Anchor Depth", getTubingAnchorDepth());
|
|
inputTable.addRow("Tubing ID", getTubingID());
|
|
inputTable.addRow("Tubing OD", getTubingOD());
|
|
inputTable.addRule();
|
|
inputTable.addRow("Number of Tapers", getNumTapers());
|
|
inputTable.addRule();
|
|
inputTable.addRow("Buoyant Force Total", buoyantForceTotal);
|
|
inputTable.addRow("Weight Data Total", weightDataTotal);
|
|
inputTable.addRow("Annular Force Data Total", annularForceDataTotal);
|
|
inputTable.addRow("Rod Depth Total", rodDepthTotal);
|
|
inputTable.addRow("Rod Weight Air Total", rodWeightAirTotal);
|
|
inputTable.addRow("Rod Weight Fluid Total", rodWeightFluidTotal);
|
|
inputTable.addRule();
|
|
V2_AsciiTableRenderer rend = new V2_AsciiTableRenderer();
|
|
rend.setTheme(V2_E_TableThemes.UTF_LIGHT.get());
|
|
rend.setWidth(new WidthAbsoluteEven(50));
|
|
RenderedTable rt = rend.render(inputTable);
|
|
System.out.println(rt);
|
|
System.out.println();
|
|
|
|
for(int i = 1; i <= numTapers; i++){
|
|
V2_AsciiTable taperTable = new V2_AsciiTable();
|
|
taperTable.addRule();
|
|
taperTable.addRow("Taper", i);
|
|
taperTable.addStrongRule();
|
|
taperTable.addRow("Rod Length", getRodLength(i));
|
|
taperTable.addRow("Rod Diameter", getRodDiameter(i));
|
|
taperTable.addRow("Rod Damping Factor", getDampingFactor(i));
|
|
taperTable.addRow("Rod Material", getRodMaterial(i));
|
|
taperTable.addRow("Rod Young's Modulus", getRodYM(i));
|
|
taperTable.addRule();
|
|
taperTable.addRow("a", a[i]);
|
|
taperTable.addRow("Area", area[i]);
|
|
taperTable.addRow("Pressure", pressure[i]);
|
|
taperTable.addRow("Buoyant Force", buoyantForce[i]);
|
|
taperTable.addRow("Stretch", stretch[i]);
|
|
taperTable.addRow("WeightData", weightData[i]);
|
|
taperTable.addRow("Annular Force Data", annularForceData[i]);
|
|
taperTable.addRow("force", force[i]);
|
|
taperTable.addRow("Alpha", alpha[i]);
|
|
taperTable.addRow("xOverA", xOverA[i]);
|
|
taperTable.addRow("Factor", factor[i]);
|
|
taperTable.addRow("Lag Index", lagIndex[i]);
|
|
taperTable.addRow("Length Required", lengthRequired[i]);
|
|
taperTable.addRow("Center Point", centerPoint[i]);
|
|
taperTable.addRow("Rod Depth", rodDepth[i]);
|
|
taperTable.addRow("Rod Weight in Air", rodWeightAir[i]);
|
|
taperTable.addRow("Rod Weight in Fluid", rodWeightFluid[i]);
|
|
taperTable.addRule();
|
|
rend.setTheme(V2_E_TableThemes.UTF_LIGHT.get());
|
|
rend.setWidth(new WidthAbsoluteEven(50));
|
|
rt = rend.render(taperTable);
|
|
System.out.println(rt);
|
|
System.out.println();
|
|
}
|
|
|
|
};
|
|
|
|
private void updateTapers(){
|
|
nT1 = numTapers + 1;
|
|
|
|
// start by setting everything to 0
|
|
a[0] = 0.0;
|
|
area[0] = 0.0;
|
|
area[numTapers + 1] = 0.0;
|
|
pressure[0] = tubingHeadPressure;
|
|
buoyantForce[0] = 0.0;
|
|
stretch[0] = 0.0;
|
|
weightData[0] = 0.0;
|
|
annularForceData[0] = 0.0;
|
|
force[0] = 0.0;
|
|
alpha[0] = 0.0;
|
|
xOverA[0] = 0.0;
|
|
factor[0] = 0.0;
|
|
lagIndex[0] = 0;
|
|
lengthRequired[0] = 0;
|
|
centerPoint[0] = 0;
|
|
rodDepth[0] = 0.0;
|
|
rodWeightAir[0] = 0.0;
|
|
rodWeightFluid[0] = 0.0;
|
|
buoyantForceTotal = 0.0;
|
|
weightDataTotal = 0.0;
|
|
annularForceDataTotal = 0.0;
|
|
rodDepthTotal = 0.0;
|
|
rodWeightAirTotal = 0.0;
|
|
rodWeightFluidTotal = 0.0;
|
|
|
|
for(int i = 1; i < nT1; i++){
|
|
rodWeightPerFoot[i] = lookupRodWeightPerFoot(rodYM[i], rodDiameter[i]);
|
|
}
|
|
|
|
for (int area_i = 1; area_i < nT1; area_i++)
|
|
{
|
|
area[area_i] = (Math.PI / 4) * pow(rodDiameter[area_i], 2);
|
|
}
|
|
|
|
for (int i = 1; i < nT1; i++)
|
|
{
|
|
a[i] = 1000 * sqrt(32.2 * rodYM[i] * area[i] / rodWeightPerFoot[i]);
|
|
rodDepth[i] = rodDepth[i - 1] + rodLength[i];
|
|
pressure[i] = pressure[i - 1] + fluidGradient * rodLength[i];
|
|
buoyantForce[i] = pressure[i] * (area[i + 1] - area[i]);
|
|
rodWeightAir[i] = rodWeightPerFoot[i] * rodLength[i];
|
|
rodWeightFluid[i] = rodWeightAir[i] + buoyantForce[i];
|
|
}
|
|
for (int j = 1; j < nT1; j++)
|
|
{
|
|
for (int k = j + 1; k < nT1; k++)
|
|
{
|
|
weightData[j] += rodWeightAir[k]; // how much weight is felt on each taper
|
|
}
|
|
for (int l = j; l < numTapers; l++)
|
|
{
|
|
annularForceData[j] += -buoyantForce[l]; //buoyant force exerted on each taper
|
|
}
|
|
force[j] = (-area[numTapers] * pressure[numTapers]) + weightData[j] - annularForceData[j];
|
|
alpha[j] = (force[j] + rodWeightAir[j]) / (rodYM[j] * pow(10, 6) * area[j]);
|
|
stretch[j] = (stretch[j - 1] + (alpha[j] * rodLength[j])) - ((rodWeightPerFoot[j] * pow(rodLength[j], 2)) / (2 * rodYM[j] * pow(10, 6) * area[j]));
|
|
}
|
|
|
|
for (int m = 1; m < nT1; m++)
|
|
{
|
|
xOverA[m] = rodLength[m] / a[m];
|
|
lagIndex[m] = (int)(rodLength[m] / (a[m] * dt));
|
|
factor[m] = (xOverA[m] - lagIndex[m] * dt) / dt;
|
|
centerPoint[m] = lagIndex[m] + 2;
|
|
lengthRequired[m] = 2 * (lagIndex[m] + 1) + 1;
|
|
}
|
|
|
|
for (int t = 0; t < nT1; t++)
|
|
{
|
|
buoyantForceTotal += buoyantForce[t];
|
|
rodWeightAirTotal += rodWeightAir[t];
|
|
rodWeightFluidTotal += rodWeightFluid[t];
|
|
rodDepthTotal += rodLength[t];
|
|
annularForceDataTotal += annularForceData[t];
|
|
weightDataTotal += weightData[t];
|
|
}
|
|
|
|
theoreticalMaxFluidLoad = fluidGradient* rodDepthTotal* pumpArea;
|
|
frictionEstimate = 0.10 * rodDepthTotal;
|
|
double dbFrictionEstimate = db.getLatestFrictionEstimate();
|
|
if (dbFrictionEstimate != -1){
|
|
frictionEstimate = dbFrictionEstimate;
|
|
}
|
|
}
|
|
|
|
private double position(int p)
|
|
//generate the downhole position of the given rod part
|
|
{
|
|
loadBefore = 0;
|
|
loadAfter = 0;
|
|
loadBefore3 = 0;
|
|
loadAfter3 = 0;
|
|
|
|
//Temporary Variables
|
|
double a1 = a[p];
|
|
double cd = c[p];
|
|
double fact = factor[p];
|
|
double rodLengthp = rodLength[p];
|
|
int lagInd = lagIndex[p];
|
|
double Y1 = rodYM[p] * pow(10, 6);
|
|
double A1 = area[p];
|
|
int centerOfArray = centerPoint[p];
|
|
|
|
int iBefore = centerOfArray - lagInd;
|
|
int iAfter = centerOfArray + lagInd;
|
|
|
|
double pumpPOS = 0;
|
|
//Do work
|
|
pumpPOS = exp((cd * rodLengthp) / (2 * a1)) * (topPosArray[p][iAfter] + fact * (topPosArray[p][ iAfter + 1] - topPosArray[p][iAfter]));
|
|
pumpPOS += exp(-(cd * rodLengthp) / (2 * a1)) * (topPosArray[p][iBefore] + fact * (topPosArray[p][iBefore - 1] - topPosArray[p][iBefore]));
|
|
pumpPOS = pumpPOS / 2;
|
|
double insideIntegral = 0;
|
|
int q = 1;
|
|
while (q < 2 * lagInd - 1)
|
|
{
|
|
insideIntegral += dt * (1 / (Y1 * A1)) * (exp(-(cd * (lagInd - q) * dt) / 2) * topLoadArray[p][iBefore + q]);
|
|
q++;
|
|
}
|
|
insideIntegral += 0.5 * dt * (1 / (Y1 * A1)) * (exp(-(cd * lagInd * dt) / 2) * topLoadArray[p][iBefore] + exp(-(cd * (-lagInd) * dt) / 2) * topLoadArray[p][iAfter]);
|
|
|
|
loadBefore = exp(-(cd * lagInd * dt) / 2) * topLoadArray[p][iBefore] + fact * (exp(-(cd * (lagInd + 1) * dt) / 2) * topLoadArray[p][iBefore - 1] - exp(-(cd * lagInd * dt) / 2) * topLoadArray[p][iBefore]);
|
|
loadAfter = exp(-(cd * (-lagInd) * dt) / 2) * topLoadArray[p][iAfter] + fact * (exp(-(cd * (-lagInd - 1) * dt) / 2) * topLoadArray[p][iAfter + 1] - exp(-(cd * (-lagInd) * dt) / 2) * topLoadArray[p][iAfter]);
|
|
insideIntegral += 0.5 * fact * dt * (1 / (Y1 * A1)) * (loadBefore + exp(-(cd * (lagInd) * dt) / 2) * topLoadArray[p][iBefore]);
|
|
insideIntegral += 0.5 * fact * dt * (1 / (Y1 * A1)) * (loadAfter + exp(-(cd * (-lagInd) * dt) / 2) * topLoadArray[p][iAfter]);
|
|
insideIntegral = 0.5 * a1 * insideIntegral;
|
|
pumpPOS += insideIntegral;
|
|
|
|
insideIntegral = 0;
|
|
int r = 1;
|
|
while (r < 2 * lagInd - 1)
|
|
{
|
|
insideIntegral += dt * (exp(-(cd * lagInd - r) * dt) / 2) * (topPosArray[p][iBefore + r]);
|
|
r++;
|
|
}
|
|
insideIntegral += 0.5 * dt * (exp(-(cd * lagInd * dt) / 2) * topPosArray[p][iBefore] + exp(-(cd * (-lagInd) * dt) / 2) * topPosArray[p][iAfter]);
|
|
loadBefore3 = exp(-(cd * (lagInd) * dt) / 2) * topPosArray[p][iBefore] + fact * (exp(-(cd * (lagInd + 1) * dt) / 2) * topPosArray[p][iBefore] - exp(-(cd * (lagInd) * dt) / 2) * topPosArray[p][iBefore]);
|
|
loadAfter3 = exp(-(cd * (-lagInd) * dt) / 2) * topPosArray[p][iAfter] + fact * (exp(-(cd * (-lagInd - 1) * dt) / 2) * topPosArray[p][iAfter] - exp(-(cd * (-lagInd) * dt) / 2) * topPosArray[p][iAfter]);
|
|
insideIntegral += 0.5 * fact * dt * (loadBefore3 + exp(-(cd * (lagInd) * dt) / 2) * topPosArray[p][iBefore]);
|
|
insideIntegral += 0.5 * fact * dt * (loadAfter3 + exp(-(cd * (-lagInd) * dt) / 2) * topPosArray[p][iAfter]);
|
|
insideIntegral = -((cd * rodLengthp) / 4) * (0.5 * (cd / (2 * a1))) * insideIntegral;
|
|
pumpPOS += insideIntegral;
|
|
//printf("Position: %f\n", pumpPOS);
|
|
return pumpPOS;
|
|
};
|
|
|
|
|
|
private double load(int s)
|
|
//calculate the downhole load of the given rod part
|
|
{
|
|
//temporary variables
|
|
double a1 = a[s];
|
|
double cd = c[s];
|
|
double rodLengths = rodLength[s];
|
|
int lagInd = lagIndex[s];
|
|
double Y1 = rodYM[s] * pow(10, 6);
|
|
double A1 = area[s];
|
|
int centerOfArray = centerPoint[s];
|
|
|
|
int iBefore = centerOfArray - lagInd;
|
|
int iAfter = centerOfArray + lagInd;
|
|
|
|
double pumpLOAD = 0;
|
|
pumpLOAD = 0.5 * (a1 / (Y1 * A1)) * (1 / a1) * (loadBefore + loadAfter);
|
|
pumpLOAD += -((cd * rodLengths) / 4) * (0.5 * (cd / (2 * a1))) * (1 / a1) * (loadBefore3 + loadAfter3);
|
|
|
|
double firstPart = 0;
|
|
double pointAfter = (topPosArray[s][iAfter + 1] - topPosArray[s][iAfter - 1]) / (2 * dt);
|
|
double pointBefore = (topPosArray[s][iBefore + 1] - topPosArray[s][iBefore - 1]) / (2 * dt);
|
|
firstPart = (exp((cd * rodLengths) / (2 * a1)) * pointAfter - exp(-(cd * rodLengths) / (2 * a1)) * pointBefore) / (2 * a1);
|
|
firstPart += (cd * exp((cd * rodLengths) / (2 * a1)) * topPosArray[s][iAfter] - cd * exp((-cd * rodLengths) / (2 * a1)) * topPosArray[s][iBefore]) / (4 * a1);
|
|
pumpLOAD = Y1 * A1 * (firstPart + pumpLOAD);
|
|
//printf("Load: %f\n", pumpLOAD);
|
|
return pumpLOAD;
|
|
};
|
|
|
|
private LPStatus calc(double sPosition, double sLoad){
|
|
boolean useShift = false;
|
|
int loadMult = 1;
|
|
int tapersAllowed = 1;
|
|
double dPosition = 0;
|
|
double dLoad = 0;
|
|
int status = BAD_STATUS;
|
|
for (int ii = 1; ii < lengthRequired[1] + 1; ii++)
|
|
{
|
|
topPosArray[1][ii - 1] = topPosArray[1][ii];
|
|
topLoadArray[1][ii - 1] = topLoadArray[1][ii];
|
|
}
|
|
topPosArray[1][lengthRequired[1]] = -(sPosition / 12); //stores current position in feet
|
|
|
|
if (sPosition > sPositionPrevious)
|
|
{
|
|
topLoadArray[1][lengthRequired[1]] = loadMult * (sLoad - rodWeightFluidTotal) - sbfriction;
|
|
}
|
|
else
|
|
{
|
|
topLoadArray[1][lengthRequired[1]] = loadMult * (sLoad - rodWeightFluidTotal) + sbfriction;
|
|
}
|
|
sPositionPrevious = sPosition;
|
|
int j = 1;
|
|
while (j <= tapersAllowed)
|
|
{
|
|
count[j]++;
|
|
if (count[j] >= lengthRequired[j])
|
|
{
|
|
if ((j + 1) <= numTapers)
|
|
{
|
|
for (int jj = 2; jj < lengthRequired[j + 1] + 1; jj++)
|
|
{
|
|
topPosArray[j + 1][jj - 1] = topPosArray[j + 1][jj];
|
|
topLoadArray[j + 1][jj - 1] = topLoadArray[j + 1][jj];
|
|
}
|
|
topPosArray[j + 1][lengthRequired[j + 1]] = position(j);
|
|
topLoadArray[j + 1][lengthRequired[j + 1]] = load(j);
|
|
}
|
|
else
|
|
{
|
|
if (useShift)
|
|
{
|
|
dPosition = -12 * (position(j) + stretch[numTapers]);
|
|
}
|
|
else
|
|
{
|
|
dPosition = -12 * position(j);
|
|
}
|
|
dLoad = load(j) + force[numTapers];
|
|
status = GOOD_STATUS;
|
|
}
|
|
count[j]--;
|
|
tapersAllowed += 1;
|
|
if (tapersAllowed > numTapers)
|
|
{
|
|
tapersAllowed = numTapers;
|
|
}
|
|
}
|
|
j++;
|
|
}
|
|
LPStatus downholeValues = new LPStatus(dPosition, dLoad, status);
|
|
return downholeValues;
|
|
};
|
|
|
|
public void endOfStroke(){
|
|
currentCard.setNumPointsUsed(pointCounter + 1);
|
|
currentCard.calcStrokeData(150, fluidGradient,
|
|
rodDepthTotal, tubingAnchorDepth,
|
|
tubingCrossSectionalArea, pumpArea,
|
|
frictionEstimate, structuralRating, kFactor, fluidWaterRatio, fluidOilRatio, fluidGasRatio);
|
|
|
|
System.arraycopy(cardStorage, 0, cardStorage, 1, cardStorage.length-1);
|
|
cardStorage[0] = currentCard;
|
|
currentCard.printCard("none", true);
|
|
strokesSinceStart++;
|
|
strokesToday++;
|
|
strokesLifetime++;
|
|
|
|
strokeSpeed.update(currentCard.getStrokeSpeed());
|
|
downholeGrossStroke.update(currentCard.getDownholeGrossStrokeLength());
|
|
downholeNetStroke.update(currentCard.getDownholeNetStrokeLength());
|
|
fluidLevel.update(currentCard.getFluidLevel());
|
|
fluidLoad.update(currentCard.getFluidLoad());
|
|
peakPolishedRodLoad.update(currentCard.getSurfaceLoadMax().getLoad());
|
|
minPolishedRodLoad.update(currentCard.getSurfaceLoadMin().getLoad());
|
|
polishedRodHP.update(currentCard.getPolishedRodHorsepower());
|
|
pumpHP.update(currentCard.getPumpHorsepower());
|
|
fluidProduced.update(currentCard.getFluidBBLMoved());
|
|
fluidProducedAdjusted.update(currentCard.getFluidBBLMovedAdjusted());
|
|
oilProduced.update(currentCard.getOilBBLMoved());
|
|
waterProduced.update(currentCard.getWaterBBLMoved());
|
|
gasProduced.update(currentCard.getGasMCFMoved());
|
|
pumpIntakePressure.update(currentCard.getPumpIntakePressure());
|
|
surfaceStrokeLength.update(currentCard.getSurfaceStrokeLength());
|
|
tubingMovement.update(currentCard.getTubingMovement());
|
|
pumpFillPercent.update(currentCard.getFillageCalculated());
|
|
|
|
db.newCard(currentCard);
|
|
currentCard = new Card(strokesLifetime);
|
|
pointCounter = -1;
|
|
if (strokesSinceStart > startupStrokes){
|
|
runStatus = RUNSTATUS_RUNNING;
|
|
}
|
|
|
|
if (runStatus == RUNSTATUS_RUNNING) {
|
|
if (pumpFillPercent.getCurrentValue() < pumpOffFillPercentSetpoint) {
|
|
lowFillageStrokes++;
|
|
} else {
|
|
lowFillageStrokes = 0;
|
|
}
|
|
|
|
if (lowFillageStrokes > pumpOffStrokes) {
|
|
pumpOff("lowpumpfill");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public void gaugeOff(){
|
|
strokeSpeed.endOfDay();
|
|
downholeGrossStroke.endOfDay();
|
|
downholeNetStroke.endOfDay();
|
|
fluidLevel.endOfDay();
|
|
fluidLoad.endOfDay();
|
|
inflowRate.endOfDay();
|
|
peakPolishedRodLoad.endOfDay();
|
|
minPolishedRodLoad.endOfDay();
|
|
percentRun.endOfDay();
|
|
polishedRodHP.endOfDay();
|
|
pumpHP.endOfDay();
|
|
fluidProduced.endOfDay();
|
|
fluidProducedAdjusted.endOfDay();
|
|
oilProduced.endOfDay();
|
|
waterProduced.endOfDay();
|
|
gasProduced.endOfDay();
|
|
pumpIntakePressure.endOfDay();
|
|
surfaceStrokeLength.endOfDay();
|
|
tubingMovement.endOfDay();
|
|
|
|
strokesToday = 0;
|
|
}
|
|
|
|
public void eval(){
|
|
checkSafeties();
|
|
currentSurfacePosition = inclinometer.readScaled();
|
|
currentSurfaceLoad = loadCell.readScaled();
|
|
LPStatus lastPoint = calc(currentSurfacePosition, currentSurfaceLoad);
|
|
if (lastPoint.getStatus() == GOOD_STATUS){
|
|
currentDownholePosition = lastPoint.getPosition();
|
|
currentDownholeLoad = lastPoint.getLoad();
|
|
}
|
|
if(runStatus == RUNSTATUS_STARTING || runStatus == RUNSTATUS_RUNNING) {
|
|
if (lastPoint.getStatus() == GOOD_STATUS) {
|
|
currentCard.setSurfacePosition(pointCounter, currentSurfacePosition);
|
|
currentCard.setSurfaceLoad(pointCounter, currentSurfaceLoad);
|
|
currentCard.setDownholePosition(pointCounter, currentDownholePosition);
|
|
currentCard.setDownholeLoad(pointCounter, currentDownholeLoad);
|
|
}
|
|
|
|
if (inclinometer.getHistory(0) > inclinometer.getHistory(1))
|
|
direction = DIRECTION_UP;
|
|
else if (inclinometer.getHistory(0) < inclinometer.getHistory(1))
|
|
direction = DIRECTION_DOWN;
|
|
|
|
if (direction == DIRECTION_UP && lastDirection == DIRECTION_DOWN && pointCounter > 0) {
|
|
endOfStroke();
|
|
}
|
|
lastDirection = direction;
|
|
pointCounter++;
|
|
}
|
|
|
|
if (runStatus == RUNSTATUS_PUMPEDOFF){
|
|
minutesSincePumpOff = ChronoUnit.MINUTES.between(ZonedDateTime.now(), pumpedOffTime);
|
|
if(minutesSincePumpOff_last != minutesSincePumpOff){
|
|
System.out.println("Restarting in " + (pumpOffDowntimeMinutes - minutesSincePumpOff) + " minutes.");
|
|
minutesSincePumpOff_last = minutesSincePumpOff;
|
|
}
|
|
if (minutesSincePumpOff > pumpOffDowntimeMinutes){
|
|
restart("pumpoffdowntime");
|
|
}
|
|
}
|
|
|
|
if(isNewDay()){
|
|
gaugeOff();
|
|
}
|
|
}
|
|
|
|
public void eval(int simPoint){
|
|
checkSafeties();
|
|
currentSurfacePosition = inclinometer.readScaledSim(sim.getPositionAtIndex(simPoint));
|
|
currentSurfaceLoad = loadCell.readScaledSim(sim.getLoadAtIndex(simPoint));
|
|
|
|
LPStatus lastPoint = calc(currentSurfacePosition, currentSurfaceLoad);
|
|
if (lastPoint.getStatus() == GOOD_STATUS){
|
|
currentDownholePosition = lastPoint.getPosition();
|
|
currentDownholeLoad = lastPoint.getLoad();
|
|
}
|
|
if(runStatus == RUNSTATUS_STARTING || runStatus == RUNSTATUS_RUNNING) {
|
|
if (lastPoint.getStatus() == GOOD_STATUS) {
|
|
currentCard.setSurfacePosition(pointCounter, currentSurfacePosition);
|
|
currentCard.setSurfaceLoad(pointCounter, currentSurfaceLoad);
|
|
currentCard.setDownholePosition(pointCounter, currentDownholePosition);
|
|
currentCard.setDownholeLoad(pointCounter, currentDownholeLoad);
|
|
}
|
|
|
|
if (inclinometer.getHistory(0) > inclinometer.getHistory(1))
|
|
direction = DIRECTION_UP;
|
|
else if (inclinometer.getHistory(0) < inclinometer.getHistory(1))
|
|
direction = DIRECTION_DOWN;
|
|
|
|
if (direction == DIRECTION_UP && lastDirection == DIRECTION_DOWN && pointCounter > 0) {
|
|
endOfStroke();
|
|
}
|
|
lastDirection = direction;
|
|
pointCounter++;
|
|
}
|
|
|
|
if (runStatus == RUNSTATUS_PUMPEDOFF){
|
|
minutesSincePumpOff = ChronoUnit.MINUTES.between(pumpedOffTime, ZonedDateTime.now());
|
|
if(minutesSincePumpOff_last != minutesSincePumpOff){
|
|
System.out.println("Restarting in " + (pumpOffDowntimeMinutes - minutesSincePumpOff) + " minutes.");
|
|
minutesSincePumpOff_last = minutesSincePumpOff;
|
|
}
|
|
if (minutesSincePumpOff > pumpOffDowntimeMinutes){
|
|
restart("pumpoffdowntime");
|
|
}
|
|
}
|
|
|
|
if(isNewDay()){
|
|
gaugeOff();
|
|
}
|
|
}
|
|
public void printTotals(){
|
|
|
|
V2_AsciiTable taperTable = new V2_AsciiTable();
|
|
taperTable.addRule();
|
|
taperTable.addRow("Measuremnt", "Average", "Total");
|
|
taperTable.addStrongRule();
|
|
taperTable.addRow("Stroke Speed", strokeSpeed.getAverage(), strokeSpeed.getTotal());
|
|
taperTable.addRow("DH Gross Stroke", downholeGrossStroke.getAverage(), downholeGrossStroke.getTotal());
|
|
taperTable.addRow("DH Net Stroke", downholeNetStroke.getAverage(), downholeNetStroke.getTotal());
|
|
taperTable.addRow("Fluid Level", fluidLevel.getAverage(), fluidLevel.getTotal());
|
|
taperTable.addRow("Fluid Load", fluidLoad.getAverage(), fluidLoad.getTotal());
|
|
taperTable.addRow("Peak PR Load", peakPolishedRodLoad.getAverage(), peakPolishedRodLoad.getTotal());
|
|
taperTable.addRow("Min PR Load", minPolishedRodLoad.getAverage(), minPolishedRodLoad.getTotal());
|
|
taperTable.addRow("PR HP", polishedRodHP.getAverage(), polishedRodHP.getTotal());
|
|
taperTable.addRow("Pump HP", pumpHP.getAverage(), pumpHP.getTotal());
|
|
taperTable.addRow("Fluid Produced", fluidProduced.getAverage(), fluidProduced.getTotal());
|
|
taperTable.addRow("Oil Produced", oilProduced.getAverage(), oilProduced.getTotal());
|
|
taperTable.addRow("Water Produced", waterProduced.getAverage(), waterProduced.getTotal());
|
|
taperTable.addRow("Gas Produced", gasProduced.getAverage(), gasProduced.getTotal());
|
|
taperTable.addRow("Pump Intake Pressure", pumpIntakePressure.getAverage(), pumpIntakePressure.getTotal());
|
|
taperTable.addRow("Surf Stroke Length", surfaceStrokeLength.getAverage(), surfaceStrokeLength.getTotal());
|
|
taperTable.addRow("Tubing Movement", tubingMovement.getAverage(), tubingMovement.getTotal());
|
|
taperTable.addRule();
|
|
V2_AsciiTableRenderer rend = new V2_AsciiTableRenderer();
|
|
rend.setTheme(V2_E_TableThemes.UTF_LIGHT.get());
|
|
rend.setWidth(new WidthAbsoluteEven(100));
|
|
RenderedTable rt = rend.render(taperTable);
|
|
System.out.println(rt);
|
|
System.out.println();
|
|
}
|
|
|
|
|
|
public static void main( String[] args ){
|
|
Well thisWell = new Well(args[1], 99, 99, 99);
|
|
thisWell.parseJSONFile(args[0]);
|
|
thisWell.printTapers();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|