Skip to content

Commit bebb736

Browse files
authored
Merge pull request #78 from daavid00/dev
Bug fix for coarsening and -t 1 or -t 2 for models with TRANNNC
2 parents 16c0289 + 5b6ee4f commit bebb736

3 files changed

Lines changed: 210 additions & 87 deletions

File tree

examples/decks/MODEL5.DATA

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
-- This reservoir simulation deck is made available under the Open Database
2+
-- License: http://opendatacommons.org/licenses/odbl/1.0/. Any rights in
3+
-- individual contents of the database are licensed under the Database Contents
4+
-- License: http://opendatacommons.org/licenses/dbcl/1.0/
5+
-- Copyright (C) 2026 NORCE Research AS
6+
----------------------------------------------------------------------------
7+
RUNSPEC
8+
----------------------------------------------------------------------------
9+
DIMENS
10+
4 1 2 /
11+
12+
EQLDIMS
13+
/
14+
15+
TABDIMS
16+
/
17+
18+
CO2STORE
19+
GAS
20+
WATER
21+
22+
METRIC
23+
24+
START
25+
1 JAN 2025 /
26+
27+
WELLDIMS
28+
/
29+
30+
UNIFIN
31+
UNIFOUT
32+
----------------------------------------------------------------------------
33+
GRID
34+
----------------------------------------------------------------------------
35+
INIT
36+
37+
COORD
38+
0 0 0 0 0 2E3
39+
2.5E3 0 0 2.5E3 0 2E3
40+
5E3 0 0 5E3 0 2E3
41+
7.5E3 0 0 7.5E3 0 2E3
42+
10E3 0 0 10E3 0 2E3
43+
0 1E3 0 0 1E3 2E3
44+
2.5E3 1E3 0 2.5E3 1E3 2E3
45+
5E3 1E3 0 5E3 1E3 2E3
46+
7.5E3 1E3 0 7.5E3 1E3 2E3
47+
10E3 1E3 0 10E3 1E3 2E3 /
48+
49+
ZCORN
50+
16*0
51+
10E2 10E2 4*5E2 10E2 10E2 10E2 10E2 4*5E2 10E2 10E2
52+
10E2 10E2 4*5E2 10E2 10E2 10E2 10E2 4*5E2 10E2 10E2
53+
16*10E2 /
54+
55+
PORO
56+
8*1 /
57+
58+
PERMX
59+
8*10.13 /
60+
61+
COPY
62+
PERMX PERMY /
63+
PERMX PERMZ /
64+
/
65+
----------------------------------------------------------------------------
66+
PROPS
67+
----------------------------------------------------------------------------
68+
SGWFN
69+
0 0 1 0
70+
1 1 0 0 /
71+
72+
ROCK
73+
276 4.934e-05 /
74+
----------------------------------------------------------------------------
75+
SOLUTION
76+
----------------------------------------------------------------------------
77+
EQUIL
78+
0 200.0 0 0 0 0 1 1 0 /
79+
80+
RPTRST
81+
BASIC=2 /
82+
----------------------------------------------------------------------------
83+
SUMMARY
84+
----------------------------------------------------------------------------
85+
----------------------------------------------------------------------------
86+
SCHEDULE
87+
----------------------------------------------------------------------------
88+
RPTRST
89+
BASIC=2 /
90+
91+
SOURCE
92+
1 1 1 WATER 8.015165E+06 /
93+
/
94+
TSTEP
95+
1 /

src/pycopm/utils/generate_files.py

Lines changed: 78 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,10 @@ def create_deck(dic):
417417
print("\nThis is needed for the nnctrans, please wait.\n")
418418
os.chdir(dic["fol"])
419419
os.system(f"{dic['flow']} {dic['fol']}/{dic['write']}.DATA {dic['flags']}")
420-
dic["ogrid"] = OpmFile(dic["write"] + ".EGRID")
421-
if dic["ogrid"].count("NNC1") and dic["trans"] > 0:
420+
if (
421+
OpmFile(dic["write"] + ".EGRID").count("NNC1")
422+
or OpmFile(dic["deck"] + ".EGRID").count("NNC1")
423+
) and dic["trans"] > 0:
422424
handle_nnc_trans(dic)
423425
else:
424426
print("\nNo nnctrans found.")
@@ -562,7 +564,10 @@ def initialize_variables(dic):
562564
dic["mults"] += [name]
563565
for name in ["multnum", "fluxnum"]:
564566
if dic["ini"].count(name.upper()):
565-
if np.max(dic["ini"][name.upper()]) > 1:
567+
if (
568+
np.max(dic["ini"][name.upper()]) > 1
569+
or np.min(dic["ini"][name.upper()]) < 1
570+
):
566571
dic["grids"] += [name]
567572
for name in ["thconr", "disperc"]:
568573
if dic["ini"].count(name.upper()):
@@ -633,51 +638,47 @@ def handle_nnc_trans(dic):
633638
dic (dict): Modified global dictionary
634639
635640
"""
636-
nncdeck, withlines = [], False
637-
with open(dic["write"] + ".DATA", "r", encoding=dic["encoding"]) as file:
638-
for row in csv.reader(file):
639-
nrwo = str(row)[2:-2].strip()
640-
nncdeck.append(nrwo)
641-
if withlines:
642-
nncdeck.append("INCLUDE")
643-
nncdeck.append(f"'{dic['label']}EDITNNC.INC' /\n")
644-
withlines = False
645-
elif nrwo == "EDIT":
646-
if not dic["lines"]:
647-
nncdeck.append("INCLUDE")
648-
nncdeck.append(f"'{dic['label']}EDITNNC.INC' /\n")
649-
else:
650-
withlines = True
651-
with open(
652-
f"{dic['fol']}/{dic['write']}.DATA",
653-
"w",
654-
encoding="utf8",
655-
) as file:
656-
for row in nncdeck:
657-
file.write(row + "\n")
658641
temp = OpmFile(dic["deck"] + ".EGRID")
659642
coa = OpmFile(dic["write"] + ".INIT")
660-
coag = OpmFile(dic["write"] + ".EGRID")
643+
editnnc = OpmFile(dic["write"] + ".EGRID").count("NNC1")
644+
if editnnc:
645+
nncdeck, indel, withlines = [], [], False
646+
dic["coa_editnnc"] = []
647+
dic["nnct"] = [[[] for _ in range(dic["yn"])] for _ in range(dic["xn"])]
648+
with open(dic["write"] + ".DATA", "r", encoding=dic["encoding"]) as file:
649+
for row in csv.reader(file):
650+
nrwo = str(row)[2:-2].strip()
651+
nncdeck.append(nrwo)
652+
if withlines:
653+
nncdeck.append("INCLUDE")
654+
nncdeck.append(f"'{dic['label']}EDITNNC.INC' /\n")
655+
withlines = False
656+
elif nrwo == "EDIT":
657+
if not dic["lines"]:
658+
nncdeck.append("INCLUDE")
659+
nncdeck.append(f"'{dic['label']}EDITNNC.INC' /\n")
660+
else:
661+
withlines = True
662+
with open(
663+
f"{dic['fol']}/{dic['write']}.DATA",
664+
"w",
665+
encoding="utf8",
666+
) as file:
667+
for row in nncdeck:
668+
file.write(row + "\n")
669+
coag = OpmFile(dic["write"] + ".EGRID")
670+
cnnc1 = np.array(coag["NNC1"])
671+
cnnc2 = np.array(coag["NNC2"])
672+
cnnct = np.array(coa["TRANNNC"])
673+
coag = OpmGrid(dic["write"] + ".EGRID")
661674
rnnc1 = np.array(temp["NNC1"])
662675
rnnc2 = np.array(temp["NNC2"])
663676
rnnct = np.array(dic["ini"]["TRANNNC"])
664-
cnnc1 = np.array(coag["NNC1"])
665-
cnnc2 = np.array(coag["NNC2"])
666-
cnnct = np.array(coa["TRANNNC"])
667-
coag = OpmGrid(dic["write"] + ".EGRID")
668-
refpv = np.array(dic["ini"]["PORV"])
669677
coapv = np.array(coa["PORV"])
670-
coa_dz = np.zeros(len(coapv))
671-
ref_dz = np.zeros(len(refpv))
672678
dic["coa_tranx"] = np.zeros(len(coapv))
673679
dic["coa_trany"] = np.zeros(len(coapv))
674680
dic["coa_tranx"][coapv > 0] = np.array(coa["TRANX"])
675681
dic["coa_trany"][coapv > 0] = np.array(coa["TRANY"])
676-
coa_dz[coapv > 0] = np.array(coa["DZ"])
677-
ref_dz[refpv > 0] = np.array(dic["ini"]["DZ"])
678-
dic["coa_editnnc"] = []
679-
dic["nnct"] = [[[] for _ in range(dic["yn"])] for _ in range(dic["xn"])]
680-
indel = []
681682
for r1, r2, trn in zip(rnnc1, rnnc2, rnnct):
682683
rijk1 = dic["grid"].ijk_from_global_index(r1 - 1)
683684
rijk2 = dic["grid"].ijk_from_global_index(r2 - 1)
@@ -690,61 +691,61 @@ def handle_nnc_trans(dic):
690691
+ (dic["jc"][rijk1[1] + 1] - 1) * dic["nx"]
691692
+ (dic["kc"][rijk1[2] + 1] - 1) * dic["nx"] * dic["ny"]
692693
)
693-
if coa_dz[ind] > 0:
694-
dic["coa_tranx"][ind] += trn * ref_dz[r1 - 1] / coa_dz[ind]
694+
dic["coa_tranx"][ind] += trn
695695
elif rijk1[1] + 1 == rijk2[1]:
696696
ind = (
697697
(dic["ic"][rijk1[0] + 1] - 1)
698698
+ (dic["jc"][rijk1[1] + 1] - 1) * dic["nx"]
699699
+ (dic["kc"][rijk1[2] + 1] - 1) * dic["nx"] * dic["ny"]
700700
)
701-
if coa_dz[ind] > 0:
702-
dic["coa_trany"][ind] += trn * ref_dz[r1 - 1] / coa_dz[ind]
701+
dic["coa_trany"][ind] += trn
703702
elif rijk1[0] == rijk2[0] + 1:
704703
ind = (
705704
(dic["ic"][rijk2[0] + 1] - 1)
706705
+ (dic["jc"][rijk2[1] + 1] - 1) * dic["nx"]
707706
+ (dic["kc"][rijk2[2] + 1] - 1) * dic["nx"] * dic["ny"]
708707
)
709-
if coa_dz[ind] > 0:
710-
dic["coa_tranx"][ind] += trn * ref_dz[r2 - 1] / coa_dz[ind]
708+
dic["coa_tranx"][ind] += trn
711709
elif rijk1[1] == rijk2[1] + 1:
712710
ind = (
713711
(dic["ic"][rijk2[0] + 1] - 1)
714712
+ (dic["jc"][rijk2[1] + 1] - 1) * dic["nx"]
715713
+ (dic["kc"][rijk2[2] + 1] - 1) * dic["nx"] * dic["ny"]
716714
)
717-
if coa_dz[ind] > 0:
718-
dic["coa_trany"][ind] += trn * ref_dz[r2 - 1] / coa_dz[ind]
719-
else:
715+
dic["coa_trany"][ind] += trn
716+
elif editnnc:
720717
dic["nnct"][rijk1[0]][rijk1[1]].append([rijk1[2], rijk2[2], trn])
721-
print("Processing the transmissibilities")
722-
with alive_bar(len(cnnc1)) as bar_animation:
723-
for n, (n1, n2) in enumerate(zip(cnnc1, cnnc2)):
724-
bar_animation()
725-
ijk1 = coag.ijk_from_global_index(n1 - 1)
726-
ijk2 = coag.ijk_from_global_index(n2 - 1)
727-
fip1, fip2 = ijk1[2] + 1, ijk2[2] + 1
728-
rtran, found, indel = 0, 0, []
729-
if fip1 != fip2 and (ijk1[0] != ijk2[0] or ijk1[1] != ijk2[1]):
730-
for i, val in enumerate(dic["nnct"][ijk1[0]][ijk1[1]]):
731-
rfip1 = dic["kc"][val[0] + 1]
732-
rfip2 = dic["kc"][val[1] + 1]
733-
if fip1 == rfip1 and fip2 == rfip2:
734-
rtran += val[2]
735-
found = 1
736-
indel.append(i)
737-
for ind in indel[::-1]:
738-
del dic["nnct"][ijk1[0]][ijk1[1]][ind]
739-
if found == 1:
740-
mult = rtran / cnnct[n]
741-
else:
742-
mult = 0
743-
dic["coa_editnnc"].append(
744-
f"{ijk1[0]+1} {ijk1[1]+1} {ijk1[2]+1} {ijk2[0]+1} "
745-
f"{ijk2[1]+1} {ijk2[2]+1} {mult} /"
746-
)
747-
for name in ["tranx", "trany", "editnnc"]:
718+
if editnnc:
719+
print("Processing the transmissibilities")
720+
with alive_bar(len(cnnc1)) as bar_animation:
721+
for n, (n1, n2) in enumerate(zip(cnnc1, cnnc2)):
722+
bar_animation()
723+
ijk1 = coag.ijk_from_global_index(n1 - 1)
724+
ijk2 = coag.ijk_from_global_index(n2 - 1)
725+
fip1, fip2 = ijk1[2] + 1, ijk2[2] + 1
726+
rtran, found, indel = 0, 0, []
727+
if fip1 != fip2 and (ijk1[0] != ijk2[0] or ijk1[1] != ijk2[1]):
728+
for i, val in enumerate(dic["nnct"][ijk1[0]][ijk1[1]]):
729+
rfip1 = dic["kc"][val[0] + 1]
730+
rfip2 = dic["kc"][val[1] + 1]
731+
if fip1 == rfip1 and fip2 == rfip2:
732+
rtran += val[2]
733+
found = 1
734+
indel.append(i)
735+
for ind in indel[::-1]:
736+
del dic["nnct"][ijk1[0]][ijk1[1]][ind]
737+
if found == 1:
738+
mult = rtran / cnnct[n]
739+
else:
740+
mult = 0
741+
dic["coa_editnnc"].append(
742+
f"{ijk1[0]+1} {ijk1[1]+1} {ijk1[2]+1} {ijk2[0]+1} "
743+
f"{ijk2[1]+1} {ijk2[2]+1} {mult} /"
744+
)
745+
cases = ["tranx", "trany"]
746+
if editnnc:
747+
cases += ["editnnc"]
748+
for name in cases:
748749
if name == "editnnc":
749750
dic[f"coa_{name}"] = [f"{val}\n" for val in dic[f"coa_{name}"]]
750751
else:
@@ -853,7 +854,9 @@ def write_props(dic):
853854
for name in names:
854855
bar_animation()
855856
dic[f"{name}_c"] = compact_format(dic[f"{name}_c"])
856-
if "*" in dic[f"{name}_c"][0]:
857+
if "*" in dic[f"{name}_c"][0] and not (
858+
dic["trans"] > 0 and name in ["tranx", "trany"]
859+
):
857860
if int(dic[f"{name}_c"][0].split("*")[0]) == dic["ntot"]:
858861
whr = dic["lol"].index(f"'{dic['label']}{name.upper()}.INC' /\n")
859862
del dic["lol"][whr]

tests/test_7_transmissibilities.py

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,12 @@
1515

1616

1717
def test_transmissibilities(flow):
18-
"""See examples/decks/MODEL4.DATA"""
18+
"""See examples/decks/MODEL4.DATA and MODEL5.DATA"""
1919
if not os.path.exists(f"{testpth}/output"):
2020
os.system(f"mkdir {testpth}/output")
21-
subprocess.run(
22-
[
23-
flow,
24-
f"{mainpth}/examples/decks/MODEL4.DATA",
25-
f"--output-dir={testpth}/output/transmissibilities",
26-
],
27-
check=True,
28-
)
2921
values = [
30-
[523.75178, 706.33996, 5008.1327, 106.21933],
31-
[523.75178, 706.33996, 0, 106.21933],
22+
[696.14886, 774.826, 5008.1323, 106.21955],
23+
[696.14886, 774.826, 0, 106.21955],
3224
]
3325
for i, sub in enumerate(["1", "2"]):
3426
subprocess.run(
@@ -58,5 +50,38 @@ def test_transmissibilities(flow):
5850
init = OpmFile(f"{testpth}/output/transmissibilities/COARSER{sub}.INIT")
5951
for j, n in enumerate(["X", "Y", "Z", "NNC"]):
6052
assert (
61-
abs(np.sum(np.array(init[f"TRAN{n}"])) - values[i][j]) < 1e-2
53+
abs(np.sum(np.array(init[f"TRAN{n}"])) - values[i][j]) < 1e-5
6254
), f"Issue in TRAN{n} with -t {i}"
55+
subprocess.run(
56+
[
57+
"pycopm",
58+
"-f",
59+
flow,
60+
"-o",
61+
f"{testpth}/output/transmissibilities",
62+
"-i",
63+
f"{mainpth}/examples/decks/MODEL5.DATA",
64+
"-z",
65+
"1:2",
66+
"-w",
67+
"COARSER_MODEL5",
68+
"-l",
69+
"CM5",
70+
"-t",
71+
"2",
72+
"-a",
73+
"max",
74+
"-m",
75+
"all",
76+
],
77+
check=True,
78+
)
79+
ref = "MODEL5_PREP_PYCOPM_DRYRUN.INIT"
80+
init_ref = OpmFile(f"{testpth}/output/transmissibilities/{ref}")
81+
init = OpmFile(f"{testpth}/output/transmissibilities/COARSER_MODEL5.INIT")
82+
assert (
83+
abs(init["TRANX"][0] - 2 * init_ref["TRANX"][0]) < 1e-5
84+
), "Issue in TRANX with MODEL5 (NNCTRAN[0])"
85+
assert (
86+
abs(init["TRANX"][-2] - 2 * init_ref["TRANX"][0]) < 1e-5
87+
), "Issue in TRANX with MODEL5 (NNCTRAN[-2])"

0 commit comments

Comments
 (0)