-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmodel_inputs_process.jl
More file actions
381 lines (263 loc) · 15.3 KB
/
model_inputs_process.jl
File metadata and controls
381 lines (263 loc) · 15.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
#using JSON
using CSV
using DataFrames
#using Shapefile
using Geodesy
#using PrettyTables
using InlineStrings
include("TexNetWebToolLauncherHelperJulia.jl")
include("graphs/julia_fsp_graphs.jl")
include("core/utilities.jl")
using .TexNetWebToolLauncherHelperJulia
using .JuliaFSPGraphs
using .Utilities
const ARGS_FILE_NAME = "args.json"
const RESULTS_FILE_NAME = "results.json"
# TO DO: read this from the 'stress_field_mode' parameter
# it will be either 'all_gradients' or 'aphi_model'
function get_stress_model_type(stress_inputs::Dict)
if stress_inputs["aphi_value"] !== nothing
if stress_inputs["min_horizontal_stress_gradient"] !== nothing
return "aphi_min"
else
return "aphi_no_min"
end
else
return "gradients"
end
end
function get_injection_dataset_path(helper::TexNetWebToolLaunchHelperJulia, step_index::Int)
#println("DEBUG: get_injection_dataset_path called with step_index = $step_index")
for param_name in ["injection_wells_annual", "injection_wells_monthly", "injection_tool_data"]
#println("DEBUG: Trying to get file path for param_name = $param_name")
filepath = get_dataset_file_path(helper, step_index, param_name)
#println("DEBUG: filepath = $filepath, type = $(typeof(filepath))")
if filepath !== nothing
if param_name == "injection_wells_annual"
injection_data_type = "annual_fsp"
#println("DEBUG: Returning filepath = $filepath, type = $(typeof(filepath)), injection_data_type = $injection_data_type")
return filepath, injection_data_type
elseif param_name == "injection_wells_monthly"
injection_data_type = "monthly_fsp"
#println("DEBUG: Returning filepath = $filepath, type = $(typeof(filepath)), injection_data_type = $injection_data_type")
return filepath, injection_data_type
elseif param_name == "injection_tool_data"
injection_data_type = "injection_tool_data"
#println("DEBUG: Returning filepath = $filepath, type = $(typeof(filepath)), injection_data_type = $injection_data_type")
return filepath, injection_data_type
end
end
end
error("No injection dataset found.")
return nothing, nothing
end
function get_fault_dataset_path(helper::TexNetWebToolLaunchHelperJulia, step_index::Int, randomized_faults::Bool=false, num_faults::Int=20, strike_min::Float64=240.0, strike_max::Float64=330.0, dip_min::Float64=45.0, dip_max::Float64=90.0)
if randomized_faults
fault_type = "fsp_native"
faults_df = generate_randomized_faults_csv(num_faults, strike_min, strike_max, dip_min, dip_max)
return faults_df, fault_type
else
for param_name in ["faults", "FaultDataShapefile"]
filepath = get_dataset_file_path(helper, step_index, param_name)
if filepath !== nothing
if param_name == "faults"
fault_type = "fsp_native"
return filepath, fault_type
elseif param_name == "FaultDataShapefile"
fault_type = "shapefile"
return filepath, fault_type
end
end
end
error("No fault dataset found.")
return nothing, nothing
end
end
function main()
#println("\n=== Starting Deterministic Geomechanics Process ===")
scratchPath = ARGS[1]
helper = TexNetWebToolLaunchHelperJulia(scratchPath)
# Check if the user requested randomized faults
randomize_faults = get_parameter_value(helper, 1, "randomize_faults")
# (Upcoming feature) default to false since that parameter is not set up in the UI yet
if randomize_faults === nothing
randomize_faults = false
end
#random_faults = true
println("randomize_faults: $randomize_faults")
if randomize_faults
# if the user wants to randomize the faults, we also need to read the randomization parameters from the args.json file
num_random_faults = get_parameter_value(helper, 1, "num_random_faults")
#println("Generating $num_random_faults random faults...")
# these if statements are being used for testing since we don't have input from the UI yet
# TODO: remove before pushing
if num_random_faults === nothing
num_random_faults = 10
end
random_strike_range = get_parameter_value(helper, 1, "random_strike_range")
if random_strike_range["min"] === nothing && random_strike_range["max"] === nothing
add_message_with_step_index!(helper, 1, "Strike range for random fault generation was not provided, using default value of 240.0-330.0", 1)
#println("random_strike_range for random fault generation is nothing, using default value of 240.0-330.0")
strike_min = 240.0
strike_max = 330.0
else
strike_min = parse(Float64, random_strike_range["min"])
strike_max = parse(Float64, random_strike_range["max"])
end
random_dip_range = get_parameter_value(helper, 1, "random_dip_range")
if random_dip_range["min"] === nothing && random_dip_range["max"] === nothing
add_message_with_step_index!(helper, 1, "Dip range for random fault generation was not provided, using default value of 45.0-90.0", 1)
#println("random_dip_range for random fault generation is nothing, using default value of 45.0-90.0")
dip_min = 45.0
dip_max = 90.0
else
dip_min = parse(Float64, random_dip_range["min"])
dip_max = parse(Float64, random_dip_range["max"])
#println("random_dip_range received from the portal: $dip_min-$dip_max")
end
faults_csv_filepath = nothing
fault_csv_type = "fsp_native"
else
faults_csv_filepath, fault_csv_type = get_fault_dataset_path(helper, 1, randomize_faults, 0)
end
#faults_csv_filepath, fault_csv_type = get_fault_dataset_path(helper, 1, random_faults)
if faults_csv_filepath !== nothing
if fault_csv_type == "fsp_native" && !randomize_faults
faults_df = CSV.read(faults_csv_filepath, DataFrame, types=Dict("FaultID" => String))
elseif fault_csv_type == "shapefile" && !randomize_faults
faults_df = shapefile_to_fsp_csv(faults_csv_filepath)
end
elseif faults_csv_filepath === nothing && fault_csv_type === "fsp_native" && randomize_faults
faults_df = generate_randomized_faults_csv(num_random_faults, strike_min, strike_max, dip_min, dip_max)
else
error("No fault dataset provided.")
end
#println("fault CSV type: $fault_csv_type")
#println("faults_df: ")
#pretty_table(faults_df)
#error("stop here")
# get file path for faults dataset using the helper
#faults_csv_filepath = get_dataset_file_path(helper, 1, "faults")
if faults_csv_filepath !== nothing || randomize_faults
#faults_df = CSV.read(faults_csv_filepath, DataFrame, types=Dict("FaultID" => String))
#get all the unique faults from the FaultID column
unique_faults_num = unique(faults_df[!, "FaultID"])
if length(unique_faults_num) > 10000
add_message_with_step_index!(helper, 1, "Number of faults provided is greater than 10000. Please provide a smaller number of faults.", 2)
error("Number of faults provided is greater than 1000. Please provide a smaller number of faults.")
end
#=
# Ensure the column exists and is of the correct type
# we create it if it doesn't exist
if !("FrictionCoefficient" in names(faults_df))
faults_df[!, "FrictionCoefficient"] = Vector{Union{Missing, Float64}}(missing, nrow(faults_df))
end
=#
#=
# TO DO: make this a single input parameter from the portal
# get friction coefficient from the first fault
mu = faults_df[1, "FrictionCoefficient"]
# assign this friction coefficient to all faults
faults_df[!, "FrictionCoefficient"] .= mu
=#
# convert lat/lon to wkt format and add to the dataframe
latlon_to_wkt(faults_df)
# append the new columns with no data (will be filled in later processes)
faults_df[!, :slip_pressure] = Vector{Union{Missing, Float64}}(missing, nrow(faults_df))
faults_df[!, :coulomb_failure_function] = Vector{Union{Missing, Float64}}(missing, nrow(faults_df))
faults_df[!, :summary_end_year] = Vector{Union{Missing, Int64}}(missing, nrow(faults_df))
faults_df[!, :summary_fsp] = Vector{Union{Missing, Float64}}(missing, nrow(faults_df))
faults_df[!, :summary_pressure] = Vector{Union{Missing, Float64}}(missing, nrow(faults_df))
faults_df[!, :prob_hydro_fsp] = Vector{Union{Missing, Float64}}(missing, nrow(faults_df))
save_dataframe_as_parameter!(helper, 1, "faults_model_inputs_output", faults_df)
else
error("No faults dataset provided.")
end
# read injection wells CSV into a DataFrame
#println("Extracting injection well data from the CSV at the scratch path...")
injection_wells_csv_filepath, injection_data_type = get_injection_dataset_path(helper, 1)
if injection_wells_csv_filepath !== nothing
# if we have injection tool data format, read the 'API Number' column as a string
# TO DO: we might have to do this for the rest of the formats
# parsing it as a string allows us to keep any leading zeros in the API numbers. If we parse it as an integer, the leading zeros are stripped.
if injection_data_type == "injection_tool_data"
injection_wells_df = CSV.read(injection_wells_csv_filepath, DataFrame; types=Dict("API Number" => String))
else
injection_wells_df = CSV.read(injection_wells_csv_filepath, DataFrame, types=Dict("WellID" => String), pool=false)
#=
#println("column types:")
for col in names(injection_wells_df)
#println("$col: $(eltype(injection_wells_df[!, col]))")
end
=#
end
# Prepare standardized dataframe for d3 visualization of injection rate over time
if injection_data_type == "annual_fsp"
# get unique values from the 'WellID' column
unique_well_ids = unique(injection_wells_df[!, "WellID"])
if length(unique_well_ids) > 200
add_message_with_step_index!(helper, 1, "Number of wells provided is greater than 200. Please provide a smaller number of wells.", 2)
error("Number of wells provided is greater than 500. Please provide a smaller number of wells.")
end
#injection_rate_data = injection_rate_data_to_d3(injection_wells_df, injection_data_type)
injection_rate_data = injection_rate_data_to_d3_bbl_day(injection_wells_df, injection_data_type)
save_dataframe_as_parameter!(helper, 1, "injection_rate_d3_data", injection_rate_data)
#println("DEBUG: Saved annual injection rate data for visualization")
save_dataframe_as_parameter!(helper, 1, "injection_wells_annual_output", injection_wells_df)
elseif injection_data_type == "monthly_fsp"
# get unique values from the 'WellID' column
unique_well_ids = unique(injection_wells_df[!, "WellID"])
if length(unique_well_ids) > 200
add_message_with_step_index!(helper, 1, "Number of wells provided is greater than 200. Please provide a smaller number of wells.", 2)
error("Number of wells provided is greater than 200. Please provide a smaller number of wells.")
end
#injection_rate_data = injection_rate_data_to_d3_bbl_day(injection_wells_df, injection_data_type)
injection_rate_data = injection_rate_data_to_d3_bbl_day(injection_wells_df, injection_data_type)
save_dataframe_as_parameter!(helper, 1, "injection_rate_d3_data", injection_rate_data)
#println("DEBUG: Saved monthly injection rate data for visualization")
# print the type of each column in the injection_rate_data dataframe
#println("Type of each column in the injection_rate_data dataframe:")
save_dataframe_as_parameter!(helper, 1, "injection_wells_monthly_output", injection_wells_df)
elseif injection_data_type == "injection_tool_data"
# get unique values from the 'WellID' column
unique_well_ids = unique(injection_wells_df[!, "API Number"])
if length(unique_well_ids) > 200
add_message_with_step_index!(helper, 1, "Number of wells provided is greater than 200. Please provide a smaller number of wells.", 2)
error("Number of wells provided is greater than 200. Please provide a smaller number of wells.")
end
#injection_rate_data = injection_rate_data_to_d3(injection_wells_df, injection_data_type)
injection_rate_data = injection_rate_data_to_d3_bbl_day(injection_wells_df, injection_data_type)
save_dataframe_as_parameter!(helper, 1, "injection_rate_d3_data", injection_rate_data)
# we also need to filter this so we can create a map layer
# keep only the first row for each unique API Number
injection_wells_df_filtered = unique(injection_wells_df, "API Number")
# only keep the columns we need
injection_wells_df_filtered = injection_wells_df_filtered[!, ["API Number", "Surface Latitude", "Surface Longitude"]]
# rename "API Number" to "UWI"
rename!(injection_wells_df_filtered, "API Number" => :UWI)
# rename "Surface Latitude" to "Latitude(WGS84)"
rename!(injection_wells_df_filtered, "Surface Latitude" => :"Latitude(WGS84)")
# rename "Surface Longitude" to "Longitude(WGS84)"
rename!(injection_wells_df_filtered, "Surface Longitude" => :"Longitude(WGS84)")
save_dataframe_as_parameter!(helper, 1, "injection_tool_data_filtered_map_layer", injection_wells_df_filtered)
save_dataframe_as_parameter!(helper, 1, "injection_tool_data_output", injection_wells_df)
#println("DEBUG: Saved injection tool data for visualization")
end
else
error("No injection wells dataset provided.")
end
#println("Generating D3.js visualization data...")
#faults_csv, wells_csv = fault_surface_map_data_to_d3(faults_df, injection_wells_df)
# CONTINUE FROM HERE FIX THIS (DEOSN'T READ CORRECT FILE)
# save_dataframe_as_parameter!(helper, 1, "fault_surface_map_faults", faults_csv)
# save_dataframe_as_parameter!(helper, 1, "fault_surface_map_injection_wells", wells_csv)
# Write the modified args_data back to file.
write_final_args_file(helper, joinpath(helper.scratch_path, ARGS_FILE_NAME))
# explicitly set this step's success state to true
set_success_for_step_index!(helper, 1, true)
write_results_file(helper)
#println("Model Inputs process: Completed successfully.")
end
if abspath(PROGRAM_FILE) == @__FILE__
main()
end