Skip to content

Commit abc6176

Browse files
jorgesicachanrAudunSektnanNR
authored andcommitted
CCS-393: Add flexibility by learning CO2 position for Cirrus EOS cases (#416)
* Add flexibility after INFO file parsing
1 parent 0d5595b commit abc6176

1 file changed

Lines changed: 54 additions & 37 deletions

File tree

src/ccs_scripts/co2_containment/co2_calculation.py

Lines changed: 54 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -255,14 +255,22 @@ def _extract_comp_molar_masses(
255255
info_data = pd.read_csv(cirrus_info_file)
256256
info_data.columns = info_data.columns.str.strip()
257257
info_data["Mnemonic"] = info_data["Mnemonic"].str.strip()
258-
259-
molar_weights = (
260-
info_data.loc[info_data["Mnemonic"].str.startswith("MW_", na=False), ["Value"]]
261-
.assign(Value=lambda df: df["Value"].astype(float))
258+
mw_df = (
259+
info_data.loc[
260+
info_data["Mnemonic"].str.startswith("MW_", na=False),
261+
["Mnemonic", "Value"],
262+
]
263+
.assign(
264+
Value=lambda df: df["Value"].astype(float),
265+
Component=lambda df: df["Mnemonic"].str.replace("MW_", "", regex=False),
266+
)
262267
.reset_index(drop=True)
263-
.rename(index=lambda i: i + 1)["Value"]
264-
.to_dict()
265268
)
269+
molar_weights = {
270+
row["Component"]: (i + 1, row["Value"]) for i, row in mw_df.iterrows()
271+
}
272+
if "CO2" not in molar_weights:
273+
raise ValueError("CO2 molar mass not found in cirrus info file")
266274
return molar_weights
267275

268276

@@ -365,12 +373,12 @@ def _n_components(active_props: List):
365373

366374
def _compute_phases_avg_mol_weight(
367375
source_data,
368-
comps_molar_mass: Optional[Dict[str, float]],
376+
comp_molar_masses: Optional[Dict[str, Tuple[int, float]]],
369377
water_molar_mass: float = DEFAULT_WATER_MOLAR_MASS,
370378
):
371-
if comps_molar_mass is None:
379+
if comp_molar_masses is None:
372380
raise ValueError(
373-
"comps_molar_masses cannot be None when computing phase average molar "
381+
"comp_molar_masses cannot be None when computing phase average molar "
374382
"mass weight"
375383
)
376384
dates = source_data.DATES
@@ -381,19 +389,17 @@ def _compute_phases_avg_mol_weight(
381389
water_avg_mol_weight_at_date = {}
382390
gas_avg_mol_weight_at_date = {}
383391
oil_avg_mol_weight_at_date = {}
384-
for comp in comps_molar_mass:
385-
ymf_tmp_date = getattr(source_data, f"YMF{comp}")[date]
386-
xmf_tmp_date = getattr(source_data, f"XMF{comp}")[date]
387-
gas_avg_mol_weight_at_date[comp] = comps_molar_mass[comp] * ymf_tmp_date
388-
oil_avg_mol_weight_at_date[comp] = (
389-
comps_molar_mass[comp] * xmf_tmp_date
390-
if Scenario.DEPLETED_OIL_GAS_FIELD
391-
else None
392+
for idx, molar_mass in comp_molar_masses.values():
393+
ymf_tmp_date = getattr(source_data, f"YMF{idx}")[date]
394+
xmf_tmp_date = getattr(source_data, f"XMF{idx}")[date]
395+
gas_avg_mol_weight_at_date[idx] = molar_mass * ymf_tmp_date
396+
oil_avg_mol_weight_at_date[idx] = (
397+
molar_mass * xmf_tmp_date if Scenario.DEPLETED_OIL_GAS_FIELD else None
392398
)
393-
water_avg_mol_weight_at_date[comp] = (
394-
comps_molar_mass[comp] * xmf_tmp_date
399+
water_avg_mol_weight_at_date[idx] = (
400+
molar_mass * xmf_tmp_date
395401
if not Scenario.DEPLETED_OIL_GAS_FIELD
396-
else (water_molar_mass / len(comps_molar_mass))
402+
else (water_molar_mass / len(comp_molar_masses))
397403
* np.ones_like(xmf_tmp_date)
398404
)
399405
gas_avg_mol_weight[date] = np.sum(
@@ -410,13 +416,11 @@ def _compute_phases_avg_mol_weight(
410416

411417
def _convert_phase_density_from_mass_to_mole(
412418
source_data,
413-
comps_molar_masses: Optional[Dict[str, float]],
419+
comp_molar_masses: Optional[Dict[str, Tuple[int, float]]],
414420
water_molar_mass: float = DEFAULT_WATER_MOLAR_MASS,
415421
):
416422
water_avg_mol_weight, gas_avg_mol_weight, oil_avg_mol_weight = (
417-
_compute_phases_avg_mol_weight(
418-
source_data, comps_molar_masses, water_molar_mass
419-
)
423+
_compute_phases_avg_mol_weight(source_data, comp_molar_masses, water_molar_mass)
420424
)
421425
dates = source_data.DATES
422426
dwat = source_data.DWAT
@@ -884,8 +888,10 @@ def _pflotran_co2mass(
884888
def _compositional_co2mass(
885889
source_data,
886890
scenario: Scenario,
891+
source: str,
887892
pore_volume_prop: str,
888893
co2_molar_mass: Optional[float] = None,
894+
co2_position: Optional[float] = None,
889895
) -> Dict[str, List[np.ndarray]]:
890896
"""
891897
Calculates CO2 mass based on molar weight and mole fraction of the components
@@ -905,17 +911,19 @@ def _compositional_co2mass(
905911
bgas = source_data.BGAS
906912
bwat = source_data.BWAT
907913
boil = source_data.BOIL
908-
xmf2 = source_data.XMF2
909-
ymf2 = source_data.YMF2
910-
zmf2 = source_data.ZMF2 if scenario == Scenario.DEPLETED_OIL_GAS_FIELD else None
911914
sgas = source_data.SGAS
912915
swat = source_data.SWAT
913916
sgtrh = source_data.SGTRH
914917
sgstrand = source_data.SGSTRAND
915918
soil = source_data.SOIL
916919
eff_vols = source_data.RPORV if pore_volume_prop == "RPORV" else source_data.PORV
917920
conv_fact = co2_molar_mass
918-
921+
if co2_position is not None and source != "PFlotran COMP":
922+
xmf_co2 = getattr(source_data, f"XMF{co2_position}")
923+
ymf_co2 = getattr(source_data, f"YMF{co2_position}")
924+
else:
925+
xmf_co2 = source_data.XMF2
926+
ymf_co2 = source_data.YMF2
919927
phase_moles = {}
920928
co2_mass = {}
921929
for date in dates:
@@ -930,20 +938,24 @@ def _compositional_co2mass(
930938
if scenario != Scenario.DEPLETED_OIL_GAS_FIELD:
931939
phase_moles[date].extend([np.zeros_like(phase_moles[date][0])])
932940
co2_mass[date] = [
933-
conv_fact * phase_moles[date][0] * xmf2[date],
934-
conv_fact * phase_moles[date][1] * ymf2[date],
941+
conv_fact * phase_moles[date][0] * xmf_co2[date],
942+
conv_fact * phase_moles[date][1] * ymf_co2[date],
935943
phase_moles[date][2],
936944
]
937945
else:
938-
zmf2 = source_data.ZMF2
946+
zmf_co2 = (
947+
getattr(source_data, f"ZMF{co2_position}")
948+
if co2_position is not None and source != "PFlotran COMP"
949+
else source_data.ZMF2
950+
)
939951
phase_moles[date].extend([boil[date] * soil[date] * eff_vols[date]])
940952
total_moles = (
941953
phase_moles[date][0] + phase_moles[date][1] + phase_moles[date][2]
942954
)
943-
total_co2_mass = total_moles * zmf2[date] * conv_fact
955+
total_co2_mass = total_moles * zmf_co2[date] * conv_fact
944956
co2_mass[date] = [
945-
phase_moles[date][1] * ymf2[date] * conv_fact,
946-
phase_moles[date][2] * xmf2[date] * conv_fact,
957+
phase_moles[date][1] * ymf_co2[date] * conv_fact,
958+
phase_moles[date][2] * xmf_co2[date] * conv_fact,
947959
]
948960
co2_mass[date].insert(
949961
0, total_co2_mass - co2_mass[date][0] - co2_mass[date][1]
@@ -1312,7 +1324,7 @@ def _calculate_co2_data_from_source_data(
13121324
comp_molar_masses = None
13131325
if source == "PFlotran COMP":
13141326
if cirrus_info_file is None:
1315-
error_text = "Source: PFlotran EOS COMP"
1327+
error_text = "Source: PFlotran COMP"
13161328
error_text += f"\nScenario: {scenario.name}."
13171329
error_text += (
13181330
"\nTo compute mass or actual volume in this scenario "
@@ -1433,7 +1445,7 @@ def _calc_co2_amount(
14331445
water_molar_mass: float,
14341446
gas_molar_mass: Optional[float],
14351447
oil_molar_mass: Optional[float],
1436-
comp_molar_masses: Optional[Dict[str, float]],
1448+
comp_molar_masses: Optional[Dict[str, Tuple[int, float]]],
14371449
) -> Co2Data:
14381450
if source == "PFlotran":
14391451
co2_mass_cell = _pflotran_co2mass(
@@ -1446,7 +1458,8 @@ def _calc_co2_amount(
14461458
oil_molar_mass,
14471459
)
14481460
else:
1449-
if source == "PFlotran COMP":
1461+
co2_position = None
1462+
if source == "PFlotran COMP" and comp_molar_masses is not None:
14501463
bwat, bgas, boil = _convert_phase_density_from_mass_to_mole(
14511464
source_data,
14521465
comp_molar_masses,
@@ -1455,11 +1468,15 @@ def _calc_co2_amount(
14551468
source_data.BWAT = bwat
14561469
source_data.BGAS = bgas
14571470
source_data.BOIL = boil
1471+
co2_position = comp_molar_masses["CO2"][0]
1472+
14581473
co2_mass_cell = _compositional_co2mass(
14591474
source_data,
14601475
scenario,
1476+
source,
14611477
pore_volume_prop,
14621478
co2_molar_mass,
1479+
co2_position,
14631480
)
14641481
co2_mass_output = Co2Data(
14651482
source_data.x_coord,

0 commit comments

Comments
 (0)