From 7f96b1e18aa4388ca4e854a30040976e17558f95 Mon Sep 17 00:00:00 2001 From: Patrick McDonagh Date: Fri, 14 Jul 2017 17:21:34 -0500 Subject: [PATCH] Adding more to Well.cpp --- Makefile | 4 +- POCpp.xcodeproj/project.pbxproj | 6 +- .../UserInterfaceState.xcuserstate | Bin 52675 -> 87014 bytes src/AnalogIn.cpp | 5 + src/AnalogIn.h | 1 + src/Database.cpp | 42 + src/Database.h | 3 + src/Well.cpp | 835 +++++++++++++++++- src/Well.h | 105 +++ 9 files changed, 994 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 65ee15c..4609711 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ CC := g++ -INC := -I include -I include/wiringPi -I /usr/local/include +INC := -I ./include -I ./include/mraa -I /usr/local/include -I/usr/local/Cellar/nlohmann_json/2.1.1/include CFLAGS := -c --std=c++11 -Wall $(shell pkg-config --cflags --libs libmongocxx) -LIB := -L /usr/local/lib -lmongocxx -lbsoncxx -lmraa +LIB := -L /usr/local/lib -lmongocxx -lbsoncxx SRCDIR := src diff --git a/POCpp.xcodeproj/project.pbxproj b/POCpp.xcodeproj/project.pbxproj index a30d013..d7d2825 100644 --- a/POCpp.xcodeproj/project.pbxproj +++ b/POCpp.xcodeproj/project.pbxproj @@ -333,6 +333,7 @@ C568AEC81F13D1F800524D66 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; DEVELOPMENT_TEAM = JNP6SX52H9; HEADER_SEARCH_PATHS = ""; LIBRARY_SEARCH_PATHS = ( @@ -340,13 +341,14 @@ "$(PROJECT_DIR)/include/mraa", ); PRODUCT_NAME = "$(TARGET_NAME)"; - USER_HEADER_SEARCH_PATHS = "/usr/local/include/libmongoc-1.0/** /usr/local/include/mongocxx/v_noabi/** /usr/local/include/bsoncxx/v_noabi/** /usr/local/include/libbson-1.0/** ./include ./include/mraa"; + USER_HEADER_SEARCH_PATHS = "./include ./include/mraa /usr/local/include/mongocxx/v_noabi /usr/local/include /usr/local/include/libmongoc-1.0 /usr/local/include/bsoncxx/v_noabi /usr/local/include/libbson-1.0 /usr/local/Cellar/nlohmann_json/2.1.1/include"; }; name = Debug; }; C568AEC91F13D1F800524D66 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; DEVELOPMENT_TEAM = JNP6SX52H9; HEADER_SEARCH_PATHS = ""; LIBRARY_SEARCH_PATHS = ( @@ -354,7 +356,7 @@ "$(PROJECT_DIR)/include/mraa", ); PRODUCT_NAME = "$(TARGET_NAME)"; - USER_HEADER_SEARCH_PATHS = "/usr/local/include/libmongoc-1.0/** /usr/local/include/mongocxx/v_noabi/** /usr/local/include/bsoncxx/v_noabi/** /usr/local/include/libbson-1.0/** ./include ./include/mraa"; + USER_HEADER_SEARCH_PATHS = "./include ./include/mraa /usr/local/include/mongocxx/v_noabi /usr/local/include /usr/local/include/libmongoc-1.0 /usr/local/include/bsoncxx/v_noabi /usr/local/include/libbson-1.0 /usr/local/Cellar/nlohmann_json/2.1.1/include"; }; name = Release; }; diff --git a/POCpp.xcodeproj/project.xcworkspace/xcuserdata/patrickjmcd.xcuserdatad/UserInterfaceState.xcuserstate b/POCpp.xcodeproj/project.xcworkspace/xcuserdata/patrickjmcd.xcuserdatad/UserInterfaceState.xcuserstate index 13357af75a38db3a2004ab3fb6dc3cda8810e645..1b898c089a2ddb34ff3e5732433f842aa3d12e00 100644 GIT binary patch literal 87014 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 = rawMin; + this->rawMax = rawMax; +} + AnalogIn::~AnalogIn() { // TODO Auto-generated destructor stub } diff --git a/src/AnalogIn.h b/src/AnalogIn.h index 5424563..646f4dd 100644 --- a/src/AnalogIn.h +++ b/src/AnalogIn.h @@ -22,6 +22,7 @@ public: double setValue(int value); double read(MuxSetup *mux); double readSim(double simRaw); + void setRawScaling(int rawMin, int rawMax); virtual ~AnalogIn(); private: diff --git a/src/Database.cpp b/src/Database.cpp index a9c591a..381e5e3 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -395,6 +395,48 @@ long Database::newRunStatus(std::string runStatus, std::string initiator){ return runStatusCollection.count({}); } +long Database::storeSetpoint(std::string setpointName, double setpointValue){ + + bsoncxx::types::b_date timestamp = bsoncxx::types::b_date {std::chrono::duration_cast< std::chrono::milliseconds >(std::chrono::system_clock::now().time_since_epoch())}; + + + bsoncxx::builder::stream::document spBuilder, filterBuilder; + + filterBuilder << "name" << setpointName; + + spBuilder << "name" << setpointName; + spBuilder << "value" << setpointValue; + spBuilder << "lastStored" << timestamp; + spBuilder << "storedBy" << "poc"; + + mongocxx::options::update updOptions; + updOptions.upsert(true); + + setpointCollection.update_one(filterBuilder.view(), spBuilder.view(), updOptions); + + return setpointCollection.count({}); + +} + +double Database::getSetpoint(std::string setpointName){ + double setpointValue = -__DBL_MAX__; + std::string storedBy = "NONE"; + bsoncxx::builder::stream::document filterBuilder; + filterBuilder << "name" << setpointName; + + mongocxx::cursor spCursor = setpointCollection.find(filterBuilder.view()); + for (auto&& doc : spCursor) { + try { + setpointValue = doc["value"].get_double(); + storedBy = doc["storedBy"].get_utf8().value.to_string(); + std::cout << "Setpoint retrieved from database: [" << setpointName << " = " << setpointValue << " stored by " << storedBy << "]"; + } catch (std::exception) { + std::cout << "Could not find a value for " << setpointName << " in the database."; + } + } + + return setpointValue; +} // FUNCTION TESTS diff --git a/src/Database.h b/src/Database.h index 731fb5e..c02177e 100644 --- a/src/Database.h +++ b/src/Database.h @@ -63,6 +63,9 @@ public: long newFluidShot(FluidShot inp); double getLatestFrictionEstimate(); long newRunStatus(std::string runStatus, std::string initiator); + long storeSetpoint(std::string setpointName, double setpointValue); + double getSetpoint(std::string setpointName); + }; diff --git a/src/Well.cpp b/src/Well.cpp index 5271a82..cf246b4 100644 --- a/src/Well.cpp +++ b/src/Well.cpp @@ -31,15 +31,844 @@ Well::Well(): surfaceStrokeLength("Surface Stroke Length"), tubingMovement("Tubing Movement"), pumpFillPercent("Pump Fill Percent"){ - + + initializeSetpoints(); } int Well::calibrateInclinometer(){ std::cout << "Calibrating inclinometer..." << std::endl; - long now = std::chrono::duration_cast< std::chrono::milliseconds >(std::chrono::system_clock::now().time_since_epoch()).count(); + long now = std::chrono::duration_cast< std::chrono::seconds >(std::chrono::system_clock::now().time_since_epoch()).count(); + long start = now; + int maxRaw = -__INT_MAX__; + int minRaw = __INT_MAX__; - + while (now - start > 30){ + inclinometer.read(&ioMux); + if (inclinometer.getRawValue() > maxRaw){ + maxRaw = inclinometer.getRawValue(); + } + + if (inclinometer.getRawValue() < minRaw){ + minRaw = inclinometer.getRawValue(); + } + + now = std::chrono::duration_cast< std::chrono::seconds >(std::chrono::system_clock::now().time_since_epoch()).count(); + + } + + std::cout << "Inclinometer Min: " << minRaw << ", Inclinometer Max: " << maxRaw; + inclinometer.setRawScaling(minRaw, maxRaw); + return 1; }; + +void Well::setRunMode(int runMode) { + this->runMode = runMode; +} + +std::string Well::getRunModeString(){ + switch (runMode){ + case RUNMODE_POC: + return "POC"; + case RUNMODE_MANUAL: + return "MANUAL"; + case RUNMODE_TIMER: + return "TIMER"; + default: + return "UNKNOWN"; + } +} + +void Well::initializeSetpoints(){ + double dbPumpOffFillPercentSetpoint = db.getSetpoint("pumpOffFillPercentSetpoint"); + if (dbPumpOffFillPercentSetpoint == -__DBL_MAX__){ + pumpOffFillPercentSetpoint = 65.0; // DEFAULT VALUE + db.storeSetpoint("pumpOffFillPercentSetpoint", pumpOffFillPercentSetpoint); + } else { + pumpOffFillPercentSetpoint = dbPumpOffFillPercentSetpoint; + } + + double dbPumpOffStrokes = db.getSetpoint("pumpOffStrokesSetpoint"); + if (dbPumpOffStrokes == -__DBL_MAX__){ + pumpOffStrokesSetpoint = 5; // DEFAULT VALUE + std::cout << "Using default value of " << pumpOffStrokesSetpoint << " for pumpOffStrokesSetpoint."; + db.storeSetpoint("pumpOffStrokesSetpoint", (double) pumpOffStrokesSetpoint); + } else { + pumpOffStrokesSetpoint = (int) dbPumpOffStrokes; + } + + double dbPumpOffDowntimeMinutesSetpoint = db.getSetpoint("pumpOffDowntimeMinutesSetpoint"); + if (dbPumpOffDowntimeMinutesSetpoint == -__DBL_MAX__){ + pumpOffDowntimeMinutesSetpoint = 30; // DEFAULT VALUE + std::cout << "Using default value of " << pumpOffDowntimeMinutesSetpoint << " for pumpOffDowntimeMinutesSetpoint."; + db.storeSetpoint("pumpOffDowntimeMinutesSetpoint", (double) pumpOffDowntimeMinutesSetpoint); + } else { + pumpOffDowntimeMinutesSetpoint = (long) dbPumpOffDowntimeMinutesSetpoint; + } + + double dbTimerRunMinutesSetpoint = db.getSetpoint("timerRunMinutesSetpoint"); + if (dbTimerRunMinutesSetpoint == -__DBL_MAX__){ + timerRunMinutesSetpoint = 45; // DEFAULT VALUE + std::cout << "Using default value of " << timerRunMinutesSetpoint << " for timerRunMinutesSetpoint."; + db.storeSetpoint("timerRunMinutesSetpoint", (double) timerRunMinutesSetpoint); + } else { + timerRunMinutesSetpoint = (long) dbTimerRunMinutesSetpoint; + } + + double dbTimerOffMinutesSetpoint = db.getSetpoint("timerOffMinutesSetpoint"); + if (dbTimerOffMinutesSetpoint == -__DBL_MAX__){ + timerOffMinutesSetpoint = 15; // DEFAULT VALUE + std::cout << "Using default value of " << timerOffMinutesSetpoint << " for timerOffMinutesSetpoint."; + db.storeSetpoint("timerOffMinutesSetpoint", (double) timerOffMinutesSetpoint); + } else { + timerOffMinutesSetpoint = (long) dbTimerOffMinutesSetpoint; + } + + double dbFluidOilRatio = db.getSetpoint("fluidOilRatio"); + if (dbFluidOilRatio == -__DBL_MAX__){ + fluidOilRatio = 0.5; // DEFAULT VALUE + std::cout << "Using default value of " << fluidOilRatio << " for fluidOilRatio."; + db.storeSetpoint("fluidOilRatio", (double) fluidOilRatio); + } else { + fluidOilRatio = dbFluidOilRatio; + } + + double dbFluidWaterRatio = db.getSetpoint("fluidWaterRatio"); + if (dbFluidWaterRatio == -__DBL_MAX__){ + fluidWaterRatio = 0.5; // DEFAULT VALUE + std::cout << "Using default value of " << fluidWaterRatio << " for fluidWaterRatio."; + db.storeSetpoint("fluidWaterRatio", (double) fluidWaterRatio); + } else { + fluidWaterRatio = dbFluidWaterRatio; + } + + double dbFluidGasRatio = db.getSetpoint("fluidGasRatio"); + if (dbFluidGasRatio == -__DBL_MAX__){ + fluidGasRatio = 2; // DEFAULT VALUE + std::cout << "Using default value of " << fluidGasRatio << " for fluidGasRatio."; + db.storeSetpoint("fluidGasRatio", (double) fluidGasRatio); + } else { + fluidGasRatio = dbFluidGasRatio; + } + + double dbRunMode = db.getSetpoint("runMode"); + if (dbRunMode == -__DBL_MAX__){ + runMode = RUNMODE_MANUAL; // DEFAULT VALUE + std::cout << "Using default value of " << runMode << " for runMode."; + db.storeSetpoint("runMode", (double) runMode); + } else { + setRunMode((int) dbRunMode); + std::cout << "Run Mode set to " << getRunModeString(); + } +} + +void Well::initializeMeasurements(){ + if (strokeSpeed.getUnits() == "") { + strokeSpeed.setUnits("SPM"); + strokeSpeed.setSendDelta(0.5); + strokeSpeed.setSendTimeDelta(600); + strokeSpeed.setUseAverage(true); + strokeSpeed.setUseTotal(false); + } + + if (downholeGrossStroke.getUnits() == "") { + downholeGrossStroke.setUnits("in."); + downholeGrossStroke.setSendDelta(0.5); + downholeGrossStroke.setSendTimeDelta(600); + downholeGrossStroke.setUseAverage(true); + downholeGrossStroke.setUseTotal(false); + } + + if (downholeNetStroke.getUnits() == "") { + downholeNetStroke.setUnits("in."); + downholeNetStroke.setSendDelta(0.5); + downholeNetStroke.setSendTimeDelta(600); + downholeNetStroke.setUseAverage(true); + downholeNetStroke.setUseTotal(false); + } + + if (fluidLevel.getUnits() == "") { + fluidLevel.setUnits("ft."); + fluidLevel.setSendDelta(10.0); + fluidLevel.setSendTimeDelta(600); + fluidLevel.setUseAverage(true); + fluidLevel.setUseTotal(false); + } + + if (fluidLoad.getUnits() == "") { + fluidLoad.setUnits("lbs."); + fluidLoad.setSendDelta(20.0); + fluidLoad.setSendTimeDelta(600); + fluidLoad.setUseAverage(true); + fluidLoad.setUseTotal(false); + } + + if (inflowRate.getUnits() == "") { + inflowRate.setUnits("BBL/day"); + inflowRate.setSendDelta(0.5); + inflowRate.setSendTimeDelta(600); + inflowRate.setUseAverage(true); + inflowRate.setUseTotal(false); + } + + if (peakPolishedRodLoad.getUnits() == "") { + peakPolishedRodLoad.setUnits("lbs."); + peakPolishedRodLoad.setSendDelta(50); + peakPolishedRodLoad.setSendTimeDelta(600); + peakPolishedRodLoad.setUseAverage(true); + peakPolishedRodLoad.setUseTotal(false); + } + + if (minPolishedRodLoad.getUnits() == "") { + minPolishedRodLoad.setUnits("lbs."); + minPolishedRodLoad.setSendDelta(50.0); + minPolishedRodLoad.setSendTimeDelta(600); + minPolishedRodLoad.setUseAverage(true); + minPolishedRodLoad.setUseTotal(false); + } + + if (percentRun.getUnits() == "") { + percentRun.setUnits("%"); + percentRun.setSendDelta(0.5); + percentRun.setSendTimeDelta(600); + percentRun.setUseAverage(false); + percentRun.setUseTotal(false); + } + + if (polishedRodHP.getUnits() == "") { + polishedRodHP.setUnits("HP"); + polishedRodHP.setSendDelta(0.25); + polishedRodHP.setSendTimeDelta(600); + polishedRodHP.setUseAverage(true); + polishedRodHP.setUseTotal(false); + } + + if (pumpHP.getUnits() == "") { + pumpHP.setUnits("HP"); + pumpHP.setSendDelta(0.25); + pumpHP.setSendTimeDelta(600); + pumpHP.setUseAverage(true); + pumpHP.setUseTotal(false); + } + + if (fluidProduced.getUnits() == "") { + fluidProduced.setUnits("BBL"); + fluidProduced.setSendDelta(1.0); + fluidProduced.setSendTimeDelta(600); + fluidProduced.setUseAverage(true); + fluidProduced.setUseTotal(true); + } + + if (fluidProducedAdjusted.getUnits() == "") { + fluidProducedAdjusted.setUnits("BBL"); + fluidProducedAdjusted.setSendDelta(1.0); + fluidProducedAdjusted.setSendTimeDelta(600); + fluidProducedAdjusted.setUseAverage(true); + fluidProducedAdjusted.setUseTotal(true); + } + + if (oilProduced.getUnits() == "") { + oilProduced.setUnits("BBL"); + oilProduced.setSendDelta(0.5); + oilProduced.setSendTimeDelta(600); + oilProduced.setUseAverage(true); + oilProduced.setUseTotal(true); + } + + if (waterProduced.getUnits() == "") { + waterProduced.setUnits("BBL"); + waterProduced.setSendDelta(1.0); + waterProduced.setSendTimeDelta(600); + waterProduced.setUseAverage(true); + waterProduced.setUseTotal(true); + } + + if (gasProduced.getUnits() == "") { + gasProduced.setUnits("MCF"); + gasProduced.setSendDelta(1.0); + gasProduced.setSendTimeDelta(600); + gasProduced.setUseAverage(true); + gasProduced.setUseTotal(true); + } + + if (pumpIntakePressure.getUnits() == "") { + pumpIntakePressure.setUnits("PSI"); + pumpIntakePressure.setSendDelta(5.0); + pumpIntakePressure.setSendTimeDelta(600); + pumpIntakePressure.setUseAverage(true); + pumpIntakePressure.setUseTotal(false); + } + + if (surfaceStrokeLength.getUnits() == "") { + surfaceStrokeLength.setUnits("in."); + surfaceStrokeLength.setSendDelta(0.5); + surfaceStrokeLength.setSendTimeDelta(600); + surfaceStrokeLength.setUseAverage(true); + surfaceStrokeLength.setUseTotal(false); + } + + if (tubingMovement.getUnits() == "") { + tubingMovement.setUnits("in."); + tubingMovement.setSendDelta(0.5); + tubingMovement.setSendTimeDelta(600); + tubingMovement.setUseAverage(true); + tubingMovement.setUseTotal(false); + } + + if (pumpFillPercent.getUnits() == "") { + pumpFillPercent.setUnits("%"); + pumpFillPercent.setSendDelta(1.0); + pumpFillPercent.setSendTimeDelta(600); + pumpFillPercent.setUseAverage(true); + pumpFillPercent.setUseTotal(false); + } +} + +double Well::getDt() { + return dt; +} + +void Well::setDt(double dt) { + this->dt = dt; +} + +double Well::getTubingHeadPressure() { + return tubingHeadPressure; +} + +void Well::setTubingHeadPressure(double tubingHeadPressure) { + this->tubingHeadPressure = tubingHeadPressure; +} + +double Well::getFluidGradient() { + return fluidGradient; +} + +void Well::setFluidGradient(double fluidGradient) { + this->fluidGradient = fluidGradient; +} + +double Well::getSbfriction() { + return stuffingBoxFriction; +} + +void Well::setSbfriction(double stuffingBoxFriction) { + this->stuffingBoxFriction = stuffingBoxFriction; +} + +int Well::getNumTapers() { + return numTapers; +} + +void Well::setNumTapers(int numTapers) { + this->numTapers = numTapers; +} + +double Well::getTubingAnchorDepth() { + return tubingAnchorDepth; +} + +void Well::setTubingAnchorDepth(double tubingAnchorDepth) { + this->tubingAnchorDepth = tubingAnchorDepth; +} + +double Well::getPumpDiameter() { + return pumpDiameter; +} + +void Well::setPumpDiameter(double pumpDiameter) { + this->pumpDiameter = pumpDiameter; + this->pumpArea = pow(pumpDiameter, 2) * M_PI; +} + +double Well::getTubingInnerDiameter() { + return tubingInnerDiameter; +} + +void Well::setTubingInnerDiameter(double tubingInnerDiameter) { + this->tubingInnerDiameter = tubingInnerDiameter; + this->tubingCrossSectionalArea = (M_PI / 4) * (pow(this->tubingOuterDiameter, 2) - pow(this->tubingInnerDiameter,2)); +} + +double Well::getTubingOuterDiameter() { + return tubingOuterDiameter; +} + +void Well::setTubingOuterDiameter(double tubingOuterDiameter){ + this->tubingOuterDiameter = tubingOuterDiameter; + this->tubingCrossSectionalArea = (M_PI / 4) * (pow(this->tubingOuterDiameter, 2) - pow(tubingInnerDiameter,2)); + +} + +void Well::setDampingFactor(int i, double c) { + this->c[i] = c; +} + +double Well::getDampingFactor(int i){ return c[i]; } + +void Well::setRodLength(int i, double rodLength) { + this->rodLength[i] = rodLength; +} + +double Well::getRodLength(int i){ return rodLength[i]; } + +void Well::setRodDiameter(int i, double rodDiameter) { + this->rodDiameter[i] = rodDiameter; +} + +double Well::getRodDiameter(int i){ return rodDiameter[i]; } + +void Well::setRodYM(int i, std::string material) { + std::transform(material.begin(), material.end(), material.begin(), ::tolower); + if (material == "steel"){ + rodYM[i] = YM_STEEL; + } else if (material == "fiberglass"){ + rodYM[i] = YM_FIBERGLASS; + } +} + +double Well::getRodYM(int i){ return rodYM[i]; } + +std::string Well::getRodMaterial(int i){ + if(rodYM[i] == YM_STEEL) + return "steel"; + if(rodYM[i] == YM_FIBERGLASS) + return "fiberglass"; + return "unknown"; +} + +double Well::getFrictionEstimate() { + return frictionEstimate; +} + +void Well::setFrictionEstimate(double frictionEstimate) { + this->frictionEstimate = frictionEstimate; +} + +double Well::getRodDepthTotal() { + return rodDepthTotal; +} + +double Well::getPumpArea() { + return pumpArea; +} + +double Well::getTubingCrossSectionalArea() { + return tubingCrossSectionalArea; +} + +double Well::getStructuralRating() { + return structuralRating; +} + +void Well::setStructuralRating(double structuralRating) { + this->structuralRating = structuralRating; +} + +void Well::setWellName(std::string wellName) { + this->wellName = wellName; +} + +std::string Well::getWellName() { + return wellName; +} + +bool Well::isPermissiveOK() { + return permissiveOK; +} + +int Well::getRunStatus() { + return runStatus; +} + +std::string Well::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"; + } +} + +int Well::getRunMode() { + return runMode; +} + +void Well::setRunModeString(std::string runModeString){ + if (runModeString == "POC"){ + runMode = RUNMODE_POC; + std::cout << "Run Mode has been set to POC" << std::endl; + } else if (runModeString == "MANUAL"){ + std::cout << "Run Mode has been set to MANUAL" << std::endl; + runMode = RUNMODE_MANUAL; + } else if (runModeString == "TIMER"){ + std::cout << "Run Mode has been set to TIMER" << std::endl; + runMode = RUNMODE_TIMER; + } +} + +double Well::getCurrentSurfacePosition() { + return currentSurfacePosition; +} + +double Well::getCurrentSurfaceLoad() { + return currentSurfaceLoad; +} + +double Well::getCurrentDownholePosition() { + return currentDownholePosition; +} + +double Well::getCurrentDownholeLoad() { + return currentDownholeLoad; +} + +long Well::getStartupStrokes() { + return startupStrokes; +} + +void Well::setStartupStrokes(long startupStrokes) { + this->startupStrokes = startupStrokes; +} + +long Well::getStrokesSinceStart() { + return strokesSinceStart; +} + +long Well::getStrokesToday() { + return strokesToday; +} + +long Well::getStrokesLifetime() { + return strokesLifetime; +} + +int Well::getDirection() { + return direction; +} + +void Well::setFluidOilRatio(double fluidOilRatio) { + this->fluidOilRatio = fluidOilRatio; +} + +void Well::setFluidWaterRatio(double fluidWaterRatio) { + this->fluidWaterRatio = fluidWaterRatio; +} + +void Well::setFluidGasRatio(double fluidGasRatio) { + this->fluidGasRatio = fluidGasRatio; +} + +double Well::getFluidOilRatio() { + return fluidOilRatio; +} + +double Well::getFluidWaterRatio() { + return fluidWaterRatio; +} + +double Well::getFluidGasRatio() { + return fluidGasRatio; +} + +double Well::getkFactor() { + return kFactor; +} + +void Well::setkFactor(double kFactor) { + this->kFactor = kFactor; +} + +int Well::getLowFillageStrokes() { + return lowFillageStrokes; +} + +std::chrono::milliseconds Well::getPumpedOffTime() { + return pumpedOffTime; +} + +long Well::getMinutesSincePumpOff() { + return minutesSincePumpOff; +} + +double Well::getPumpOffFillPercentSetpoint() { + return pumpOffFillPercentSetpoint; +} + +void Well::setPumpOffFillPercentSetpoint(double pumpOffFillPercentSetpoint) { + this->pumpOffFillPercentSetpoint = pumpOffFillPercentSetpoint; +} + +int Well::getPumpOffStrokesSetpoint() { + return pumpOffStrokesSetpoint; +} + +void Well::setPumpOffStrokesSetpoint(int pumpOffStrokesSetpoint) { + this->pumpOffStrokesSetpoint = pumpOffStrokesSetpoint; +} + +long Well::getPumpOffDowntimeMinutesSetpoint() { + return pumpOffDowntimeMinutesSetpoint; +} + +void Well::setPumpOffDowntimeMinutesSetpoint(long pumpOffDowntimeMinutesSetpoint) { + this->pumpOffDowntimeMinutesSetpoint = pumpOffDowntimeMinutesSetpoint; +} + +void Well::setupFluidRatio(double oilRatio, double waterRatio, double gasRatio){ + fluidOilRatio = oilRatio; + fluidWaterRatio = waterRatio; + fluidGasRatio = gasRatio; +} + +long Well::getTimerRunMinutesSetpoint() { + return timerRunMinutesSetpoint; +} + +void Well::setTimerRunMinutesSetpoint(long timerRunMinutesSetpoint) { + this->timerRunMinutesSetpoint = timerRunMinutesSetpoint; +} + +long Well::getTimerOffMinutesSetpoint() { + return timerOffMinutesSetpoint; +} + +void Well::setTimerOffMinutesSetpoint(long timerOffMinutesSetpoint) { + this->timerOffMinutesSetpoint = timerOffMinutesSetpoint; +} + +// WELL COMMAND FUNCTIONS +void Well::start(std::string initiator){ + if (runStatus == RUNSTATUS_STOPPED && permissiveOK){ + std::cout << "Starting " << wellName << " from " << initiator << "..." << std::endl; + runStatus = RUNSTATUS_STARTING; + strokesSinceStart = 0; + pumpStartTime = std::chrono::duration_cast< std::chrono::milliseconds >(std::chrono::system_clock::now().time_since_epoch()); + db.newRunStatus(getRunStatusString(), initiator); + calibrateInclinometer(); + } +} + +void Well::stop(std::string initiator){ + if (runStatus == RUNSTATUS_STARTING || runStatus == RUNSTATUS_RUNNING || runStatus == RUNSTATUS_PUMPEDOFF){ + std::cout << "Stopping " << wellName << " from " << initiator << "..." << std::endl; + runStatus = RUNSTATUS_STOPPED; + db.newRunStatus(getRunStatusString(), initiator); + } +} + +void Well::restart(std::string initiator){ + if (runStatus == RUNSTATUS_PUMPEDOFF && permissiveOK){ + std::cout << "Restarting after pump-off from " << initiator << "..." << std::endl; + runStatus = RUNSTATUS_STARTING; + strokesSinceStart = 0; + pumpStartTime = std::chrono::duration_cast< std::chrono::milliseconds >(std::chrono::system_clock::now().time_since_epoch()); + db.newRunStatus(getRunStatusString(), initiator); + } +} + +void Well::pumpOff(std::string initiator){ + if (runStatus == RUNSTATUS_RUNNING){ + std::cout << "Pumping off from " << initiator << "..." << std::endl; + if (runMode == RUNMODE_POC) { + std::cout << "Restarting in " << pumpOffDowntimeMinutesSetpoint << " minutes." << std::endl; + pumpedOffTime = std::chrono::duration_cast< std::chrono::milliseconds >(std::chrono::system_clock::now().time_since_epoch()); + } else if (runMode == RUNMODE_TIMER){ + std::cout << "Restarting in " << timerOffMinutesSetpoint << " minutes." << std::endl; + timerStopTime = std::chrono::duration_cast< std::chrono::milliseconds >(std::chrono::system_clock::now().time_since_epoch()); + } + runStatus = RUNSTATUS_PUMPEDOFF; + db.newRunStatus(getRunStatusString(), initiator); + } +} + +void Well::checkSafeties(){ + permissiveOK = true; +} + +// WELL CALCULATION FUNCTIONS +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 Well::getWellSetup(){ + std::string jsonFilename = "wellSetup.json"; + std::ifstream i(jsonFilename); + json jsonData; + i >> jsonData; + + try { + wellName = jsonData["wellName"]; + dt = jsonData["dt"]; + setPumpDiameter(jsonData["pumpDiameter"]); + fluidGradient = jsonData["fluidGradient"]; + setTubingInnerDiameter(jsonData["tubingID"]); + setTubingOuterDiameter(jsonData["tubingOD"]); + tubingAnchorDepth = jsonData["] + + } + + + + + + try { + + 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); + } + + Path fromFile = Paths.get(jsonFilename); + Path toFile = Paths.get(jsonFilename + ".bak"); + try { + Files.move(fromFile, toFile); + } catch (FileAlreadyExistsException e) { + Files.delete(toFile); + Files.move(fromFile, toFile); + } + updateTapers(true); + + } catch (FileNotFoundException e) { + System.out.println("No configuration file found. Pulling latest value from database."); + Document newConfigDoc = db.getLatestWellConfiguration(); + + Object newWellName = newConfigDoc.get("wellName"); + if (newWellName != null) wellName = (String) newWellName; + + Object newDeltaT = newConfigDoc.get("deltaT"); + if (newDeltaT != null) dt = (Double) newDeltaT; + + Object newPumpDiameter = newConfigDoc.get("pumpDiameter"); + if (newPumpDiameter != null) setPumpDiameter((Double) newPumpDiameter); + + Object newFluidGradient = newConfigDoc.get("fluidGradient"); + if (newFluidGradient != null) fluidGradient = (Double) newFluidGradient; + + Object newTubingID = newConfigDoc.get("tubingID"); + if (newTubingID != null) setTubingID((Double) newTubingID); + + Object newTubingOD = newConfigDoc.get("tubingOD"); + if (newTubingOD != null) setTubingOD((Double) newTubingOD); + + Object newTubingAnchorDepth = newConfigDoc.get("tubingAnchorDepth"); + if (newTubingAnchorDepth != null) tubingAnchorDepth = (Double) newTubingAnchorDepth; + + Object newStructuralRating = newConfigDoc.get("structuralRating"); + if (newStructuralRating != null) structuralRating = (Double) newStructuralRating; + + Object newStuffingBoxFriction = newConfigDoc.get("stuffingBoxFriction"); + if (newStuffingBoxFriction != null) setSbfriction((Double) newStuffingBoxFriction); + + Object newTubingHeadPressure = newConfigDoc.get("tubingOD"); + if (newTubingHeadPressure != null) setTubingOD((Double) newTubingHeadPressure); + + ArrayList tapers = (ArrayList) newConfigDoc.get("tapers"); + numTapers = tapers.size(); + for (int i = 0; i < numTapers; i++) { + int currentTaperNum = i + 1; + Document taperObj = 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); + } + updateTapers(false); + } catch (IOException | ParseException e) { + e.printStackTrace(); + System.exit(3); + } + + +} diff --git a/src/Well.h b/src/Well.h index e2a0705..265efd2 100644 --- a/src/Well.h +++ b/src/Well.h @@ -12,12 +12,18 @@ #include #include +#include + +#include "json.hpp" +using json = nlohmann::json; #include "AnalogIn.h" #include "Card.h" #include "Measurement.h" #include "Database.h" + + const static double YM_STEEL = 30.5; const static double YM_FIBERGLASS = 7.2; @@ -184,9 +190,108 @@ private: long minutesSinceTimerStart_last = 0; + void initializeMeasurements(); + + public: Well(); int calibrateInclinometer(); + void initializeSetpoints(); + void setRunMode(int runMode); + std::string getRunModeString(); + double getDt(); + void setDt(double dt); + double getTubingHeadPressure(); + void setTubingHeadPressure(double tubingHeadPressure); + double getFluidGradient(); + void setFluidGradient(double fluidGradient); + double getSbfriction(); + void setSbfriction(double sbfriction); + int getNumTapers(); + void setNumTapers(int numTapers); + double getTubingAnchorDepth(); + void setTubingAnchorDepth(double tubingAnchorDepth); + double getPumpDiameter(); + void setPumpDiameter(double pumpDiameter); + double getTubingInnerDiameter(); + void setTubingInnerDiameter(double tubingInnerDiameter); + double getTubingOuterDiameter(); + void setTubingOuterDiameter(double tubingOuterDiameter); + void setDampingFactor(int i, double c); + double getDampingFactor(int i); + void setRodLength(int i, double rodLength); + double getRodLength(int i); + void setRodDiameter(int i, double rodDiameter); + double getRodDiameter(int i); + void setRodYM(int i, std::string material); + double getRodYM(int i); + std::string getRodMaterial(int i); + double getFrictionEstimate(); + void setFrictionEstimate(double frictionEstimate); + double getRodDepthTotal(); + double getPumpArea(); + double getTubingCrossSectionalArea(); + double getStructuralRating(); + void setStructuralRating(double structuralRating); + void setWellName(std::string wellName); + std::string getWellName(); + bool isPermissiveOK(); + int getRunStatus(); + std::string getRunStatusString(); + int getRunMode(); + void setRunModeString(std::string runModeString); + double getCurrentSurfacePosition(); + double getCurrentSurfaceLoad(); + double getCurrentDownholePosition(); + double getCurrentDownholeLoad(); + long getStartupStrokes(); + void setStartupStrokes(long startupStrokes); + long getStrokesSinceStart(); + long getStrokesToday(); + long getStrokesLifetime(); + int getDirection(); + void setFluidOilRatio(double fluidOilRatio); + void setFluidWaterRatio(double fluidWaterRatio); + void setFluidGasRatio(double fluidGasRatio); + double getFluidOilRatio(); + double getFluidWaterRatio(); + double getFluidGasRatio(); + double getkFactor(); + void setkFactor(double kFactor); + int getLowFillageStrokes(); + std::chrono::milliseconds getPumpedOffTime(); + long getMinutesSincePumpOff(); + double getPumpOffFillPercentSetpoint(); + void setPumpOffFillPercentSetpoint(double pumpOffFillPercentSetpoint); + int getPumpOffStrokesSetpoint(); + void setPumpOffStrokesSetpoint(int pumpOffStrokesSetpoint); + long getPumpOffDowntimeMinutesSetpoint(); + void setPumpOffDowntimeMinutesSetpoint(long pumpOffDowntimeMinutesSetpoint); + void setupFluidRatio(double oilRatio, double waterRatio, double gasRatio); + long getTimerRunMinutesSetpoint(); + void setTimerRunMinutesSetpoint(long timerRunMinutesSetpoint); + long getTimerOffMinutesSetpoint(); + void setTimerOffMinutesSetpoint(long timerOffMinutesSetpoint); + + // WELL COMMAND FUNCTIONS + void start(std::string initiator); + void stop(std::string initiator); + void restart(std::string initiator); + void pumpOff(std::string initiator); + void checkSafeties(); + void getWellSetup(); + + + + + + + + + + + + }; #endif /* Well_h */