Skip to content

Commit

Permalink
Merge branch 'develop' into subhourly-clipping-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
mjprilliman committed Oct 30, 2023
2 parents 8f6e4fd + e4bed34 commit f053cc9
Show file tree
Hide file tree
Showing 11 changed files with 1,014 additions and 80 deletions.
322 changes: 274 additions & 48 deletions shared/lib_geothermal.cpp

Large diffs are not rendered by default.

35 changes: 33 additions & 2 deletions shared/lib_geothermal.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ struct SGeothermal_Inputs
md_TemperatureEGSAmbientC = md_RatioInjectionToProduction = 0.0;
md_AdditionalPressure = 1.0;
md_dtProdWell = md_dtProdWellChoice = 0.0;
md_NumberOfWellsProdExp = md_NumberOfWellsInjDrilled = md_NumberOfWellsProdDrilled = md_FailedWells = md_StimSuccessRate = md_DrillSuccessRate = 0;
md_FailedInjFlowRatio = md_FailedProdFlowRatio = md_InjWellFriction = md_ProdWellFriction = md_InjWellPressurePSI = md_InjectivityIndex = md_ExplorationWellsProd = 0;
md_UseWeatherFileConditions = 0.0;
}

calculationBasis me_cb; // { NO_CALCULATION_BASIS, POWER_SALES, NUMBER_OF_WELLS };
Expand All @@ -91,23 +94,37 @@ struct SGeothermal_Inputs
size_t mi_TotalMakeupCalculations; // mi_ProjectLifeYears * mi_MakeupCalculationsPerYear

double md_DesiredSalesCapacityKW; // entered or calculated, linked to 'cb'
double md_NumberOfWellsProdExp;
double md_NumberOfWellsProdDrilled;
double md_NumberOfWellsInjDrilled;
double md_FailedWells;
double md_FailedInjFlowRatio;
double md_FailedProdFlowRatio;
double md_StimSuccessRate;
double md_DrillSuccessRate;
double md_InjWellFriction;
double md_InjWellPressurePSI;
double md_ProdWellFriction;
double md_NumberOfWells; // entered or calculated, depending on 'cb'
double md_NumberofWellsInj;
double md_PlantEfficiency; // not in GETEM - essentially the ratio of plant brine effectiveness to max possible brine effectiveness
double md_TemperatureDeclineRate; // '% per year, 3% is default
double md_MaxTempDeclineC; // degrees C, default = 30
double md_TemperatureWetBulbC; // degrees celcius - used in Flash brine effectiveness
double md_PressureAmbientPSI; // psi, default=14.7, mostly for use in calculating flash brine effectiveness, but also pump work
double md_ProductionFlowRateKgPerS; // 70 kilograms per second in one well (default FlowRate in GETEM)
int md_UseWeatherFileConditions;
double md_ProductionFlowRateKgPerS; // 70 kilograms per second in one well (default FlowRate in GETEM)
double md_GFPumpEfficiency; // default=0.6 or 60%
double md_PressureChangeAcrossSurfaceEquipmentPSI; // default 25 psi
double md_ExcessPressureBar; // default 3.5 bar, [2B.Resource&Well Input].D205
double md_DiameterProductionWellInches; // default 10 inches
double md_ProductionWellType; // 0 open hole, 1 liner
double md_ProductionWellDiam;
double md_DiameterPumpCasingInches; // default 9.925 inches
double md_DiameterInjPumpCasingInches;
double md_DiameterInjectionWellInches; // default 10 inches
double md_InjectionWellType; // 0 open hole, 1 liner
double md_InjectionWellDiam;
double md_UserSpecifiedPumpWorkKW;
double md_PotentialResourceMW; // MW, default = 200 MW, determines how many times reservoir can be replaced
double md_ResourceDepthM; // meters, default 2000
Expand All @@ -118,6 +135,8 @@ struct SGeothermal_Inputs
double md_EGSSpecificHeatConstant; // default 950 Joules per kg-C, [2B.Resource&Well Input].D241
double md_EGSRockDensity; // default 2600 kg per cubic meter, [2B.Resource&Well Input].D242
double md_ReservoirDeltaPressure; // default 0.35 psi-h per 1000lb, [2B.Resource&Well Input].D171
double md_InjectivityIndex;
double md_ExplorationWellsProd;
double md_ReservoirWidthM;
double md_ReservoirHeightM;
double md_ReservoirPermeability;
Expand Down Expand Up @@ -151,12 +170,22 @@ struct SGeothermal_Outputs
maf_timestep_power = maf_timestep_test_values = maf_timestep_pressure = maf_timestep_dry_bulb = maf_timestep_wet_bulb = NULL;
mb_BrineEffectivenessCalculated = mb_FlashPressuresCalculated = false;
maf_hourly_power = NULL;
ElapsedHours = 0;
md_NumberOfWellsProdExp = md_NumberOfWellsProdDrilled = md_NumberOfWellsInjDrilled = md_FailedWells = md_StimSuccessRate = md_DrillSuccessRate = 0;
md_FailedInjFlowRatio = md_FailedProdFlowRatio = 0;
ElapsedHours = ElapsedMonths = 0;

}

//Following list of variables used as inputs in cmod_geothermal_costs.cpp for calculating direct geothermal plant cost:
double md_NumberOfWells;
double md_NumberOfWellsProdExp;
double md_NumberOfWellsProdDrilled;
double md_NumberOfWellsInjDrilled;
double md_FailedWells;
double md_FailedInjFlowRatio;
double md_FailedProdFlowRatio;
double md_StimSuccessRate;
double md_DrillSuccessRate;
double md_NumberOfWellsInj;
double md_PumpWorkKW;
double eff_secondlaw; //Overall Plant 2nd Law Efficiency
Expand Down Expand Up @@ -184,6 +213,7 @@ struct SGeothermal_Outputs
double flash_count;
double max_secondlaw; //Max 2nd Law efficiency
double ElapsedHours;
double ElapsedMonths;


// single values used in calculations, some also used in UI
Expand Down Expand Up @@ -393,6 +423,7 @@ class CGeothermalAnalyzer
double calculateDH1(double pressureIn);
double calculateDH2(double pressureIn);
double TemperatureWetBulbF(void);
double calc_twet(double T, double RH, double P);
double temperatureCondF(void); // D72 - deg F
double pressureSaturation(void); // D72 - psi
double pressureCondenser(void); // D74 - psi
Expand Down
31 changes: 26 additions & 5 deletions ssc/cmod_geothermal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ static var_info _cm_vtab_geothermal[] = {
{ SSC_INPUT, SSC_NUMBER, "ui_calculations_only", "If = 1, only run UI calculations", "", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "system_use_lifetime_output", "Geothermal lifetime simulation", "0/1", "0=SingleYearRepeated,1=RunEveryYear", "GeoHourly", "?=0", "BOOLEAN", "" },
{ SSC_INPUT, SSC_NUMBER, "geotherm.cost.inj_prod_well_ratio", "Ratio of injection wells to production wells", "", "", "GeoHourly", "", "", "" },
{ SSC_INPUT, SSC_NUMBER, "drilling_success_rate", "Drilling success rate", "%", "", "GeoHourly", "", "", "" },
{ SSC_INPUT, SSC_NUMBER, "stim_success_rate", "Stimulation success rate", "%", "", "GeoHourly", "", "", "" },
{ SSC_INPUT, SSC_NUMBER, "failed_prod_flow_ratio", "Failed production well flow ratio", "", "", "GeoHourly", "", "", "" },

//{ SSC_INOUT, SSC_NUMBER, "baseline_cost", "Baseline cost", "$/kW", "", "GeoHourly", "?=0", "", "" },

Expand Down Expand Up @@ -77,17 +80,22 @@ static var_info _cm_vtab_geothermal[] = {
{ SSC_INPUT, SSC_NUMBER, "prod_well_choice", "Temperature loss in production well choice", "0/1", "", "GeoHourly", "*", "", "" },

{ SSC_INPUT, SSC_NUMBER, "wet_bulb_temp", "Wet Bulb Temperature", "C", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "use_weather_file_conditions", "Use weather file ambient temperature", "0/1", "", "GeoHourly", "?=0", "", "" },
{ SSC_INPUT, SSC_NUMBER, "ambient_pressure", "Ambient pressure", "psi", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "well_flow_rate", "Production flow rate per well", "kg/s", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "pump_efficiency", "Pump efficiency", "%", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "delta_pressure_equip", "Delta pressure across surface equipment", "psi", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "excess_pressure_pump", "Excess pressure @ pump suction", "psi", "", "GeoHourly", "*", "", "" },
/*
{ SSC_INPUT, SSC_NUMBER, "well_diameter", "Production well diameter", "in", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "casing_size", "Production pump casing size", "in", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "inj_casing_size", "Injection pump casing size", "in", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "inj_well_diam", "Injection well diameter", "in", "", "GeoHourly", "*", "", "" },
*/
{ SSC_INPUT, SSC_NUMBER, "geotherm.cost.inj_cost_curve_welltype", "Injection well type", "0/1", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "geotherm.cost.prod_cost_curve_welltype", "Production well type", "0/1", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "geotherm.cost.inj_cost_curve_welldiam", "Injection well diameter type", "0/1", "0=LargerDiameter,1=SmallerDiameter", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "geotherm.cost.prod_cost_curve_welldiam", "Production well diameter type", "0/1", "0=LargerDiameter,1=SmallerDiameter", "GeoHourly", "*", "", "" },

{ SSC_INPUT, SSC_NUMBER, "design_temp", "Power block design temperature", "C", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "specify_pump_work", "Did user specify pump work?", "0 or 1", "", "GeoHourly", "*", "INTEGER", "" },
Expand All @@ -98,6 +106,8 @@ static var_info _cm_vtab_geothermal[] = {
{ SSC_INPUT, SSC_NUMBER, "rock_density", "Rock density", "kg/m^3", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "reservoir_pressure_change_type", "Reservoir pressure change type", "", "", "GeoHourly", "*", "INTEGER", "" },
{ SSC_INPUT, SSC_NUMBER, "reservoir_pressure_change", "Pressure change", "psi-h/1000lb", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "injectivity_index", "Injectivity index", "lb/hr-psi", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "exploration_wells_production", "Exploration wells used for production", "", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "reservoir_width", "Reservoir width", "m", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "reservoir_height", "Reservoir height", "m", "", "GeoHourly", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "reservoir_permeability", "Reservoir Permeability", "darcys", "", "GeoHourly", "*", "", "" },
Expand Down Expand Up @@ -260,7 +270,10 @@ class cm_geothermal : public compute_module
// set the geothermal model inputs -------------------------------------
SGeothermal_Inputs geo_inputs;
geo_inputs.md_RatioInjectionToProduction = as_double("geotherm.cost.inj_prod_well_ratio"); // THIS SHOULD BE AN INPUT. ALTHOUGH IT'S FROM THE COST PAGE, IT'S USED IN NON-COST EQUATION
geo_inputs.md_DesiredSalesCapacityKW = as_double("nameplate");
geo_inputs.md_DrillSuccessRate = as_double("drilling_success_rate") / 100.0;
geo_inputs.md_StimSuccessRate = as_double("stim_success_rate") / 100.0;
geo_inputs.md_FailedProdFlowRatio = as_double("failed_prod_flow_ratio");
geo_inputs.md_DesiredSalesCapacityKW = as_double("nameplate");
geo_inputs.md_NumberOfWells = as_double("num_wells");
if ( as_integer("analysis_type") == 0)
geo_inputs.me_cb = POWER_SALES;
Expand Down Expand Up @@ -294,18 +307,22 @@ class cm_geothermal : public compute_module
// flash inputs
geo_inputs.md_TemperatureWetBulbC = as_double("wet_bulb_temp");
geo_inputs.md_PressureAmbientPSI = as_double("ambient_pressure" );
geo_inputs.md_UseWeatherFileConditions = 0; //initially set to zero for UI calculations

//pumping parameters
geo_inputs.md_ProductionFlowRateKgPerS = as_double("well_flow_rate");
geo_inputs.md_GFPumpEfficiency = as_double("pump_efficiency")/100;
geo_inputs.md_PressureChangeAcrossSurfaceEquipmentPSI = as_double("delta_pressure_equip");
geo_inputs.md_ExcessPressureBar = physics::PsiToBar( as_double("excess_pressure_pump") );
geo_inputs.md_DiameterProductionWellInches = as_double("well_diameter");
geo_inputs.md_DiameterProductionWellInches = 0.0;
geo_inputs.md_ProductionWellType = as_double("geotherm.cost.prod_cost_curve_welltype");
geo_inputs.md_DiameterPumpCasingInches = as_double("casing_size");
geo_inputs.md_DiameterInjPumpCasingInches = as_double("inj_casing_size");
geo_inputs.md_DiameterInjectionWellInches = as_double("inj_well_diam");
geo_inputs.md_ProductionWellDiam = as_double("geotherm.cost.prod_cost_curve_welldiam");

geo_inputs.md_DiameterPumpCasingInches = 0.0;
geo_inputs.md_DiameterInjPumpCasingInches = 0.0;
geo_inputs.md_DiameterInjectionWellInches = 0.0;
geo_inputs.md_InjectionWellType = as_double("geotherm.cost.inj_cost_curve_welltype");
geo_inputs.md_InjectionWellDiam = as_double("geotherm.cost.inj_cost_curve_welldiam");
geo_inputs.mb_CalculatePumpWork = ( 1 != as_integer("specify_pump_work") );
geo_inputs.md_UserSpecifiedPumpWorkKW = as_double("specified_pump_work_amount") * 1000; // entered in MW

Expand Down Expand Up @@ -334,6 +351,8 @@ class cm_geothermal : public compute_module
case 3: geo_inputs.me_pc = USER_TEMP; break;
}
geo_inputs.md_ReservoirDeltaPressure = as_double("reservoir_pressure_change");
geo_inputs.md_InjectivityIndex = as_double("injectivity_index");
geo_inputs.md_ExplorationWellsProd = as_double("exploration_wells_production");
geo_inputs.md_ReservoirWidthM = as_double("reservoir_width");
geo_inputs.md_ReservoirHeightM = as_double("reservoir_height");
geo_inputs.md_ReservoirPermeability = as_double("reservoir_permeability");
Expand Down Expand Up @@ -400,6 +419,8 @@ class cm_geothermal : public compute_module
// running the model, we need to specify other inputs
geo_inputs.md_PotentialResourceMW = as_double("resource_potential");

geo_inputs.md_UseWeatherFileConditions = as_integer("use_weather_file_conditions");

// we need to create the SPowerBlockInputs & SPowerBlockParameters and set the inputs

// Set the power block input values that won't change hourly in geothermal model
Expand Down
Loading

0 comments on commit f053cc9

Please sign in to comment.