permeability 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- permeability/__init__.py +6 -0
- permeability/mcp/ProcessResult.py +14 -0
- permeability/mcp/Prompts.py +59 -0
- permeability/mcp/Server.py +343 -0
- permeability/mcp/__init__.py +0 -0
- permeability/permeability/Capillary.py +179 -0
- permeability/permeability/Seepage.py +145 -0
- permeability/permeability/__init__.py +0 -0
- permeability/utils/UnitConverter.py +20 -0
- permeability/utils/__init__.py +0 -0
- permeability-0.1.0.dist-info/METADATA +475 -0
- permeability-0.1.0.dist-info/RECORD +15 -0
- permeability-0.1.0.dist-info/WHEEL +4 -0
- permeability-0.1.0.dist-info/entry_points.txt +2 -0
- permeability-0.1.0.dist-info/licenses/LICENSE +674 -0
permeability/__init__.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Instructions
|
|
2
|
+
mcp_instruction = """
|
|
3
|
+
Provide tools for scientific calculations related to Material Science.
|
|
4
|
+
"""
|
|
5
|
+
permeability_calculation_instruction = """
|
|
6
|
+
Calculate permeability using the seepage distance method.
|
|
7
|
+
K = L² · μ · φ / (2 · t · ΔP)
|
|
8
|
+
If you fill the p_c field that is optional to fill, you will get the result corrected by the capillary pressure:
|
|
9
|
+
K = μ · φ · L² / (2 · t · (ΔP + p_c))
|
|
10
|
+
"""
|
|
11
|
+
infiltration_time_calculation_instruction = """
|
|
12
|
+
Calculate total time for fluid to fully penetrate the sample.
|
|
13
|
+
t = μ · φ · L² / (2 · K · ΔP)
|
|
14
|
+
If you fill the p_c field that is optional to fill, you will get the result corrected by the capillary pressure:
|
|
15
|
+
t = μ · φ · L² / (2 · K · (ΔP + p_c))
|
|
16
|
+
"""
|
|
17
|
+
m22darcy_instruction = """
|
|
18
|
+
Convert m^2 to Darcy
|
|
19
|
+
"""
|
|
20
|
+
darcy2m2_instruction = """
|
|
21
|
+
Convert Darcy to m^2
|
|
22
|
+
"""
|
|
23
|
+
infiltration_front_position_instruction = """
|
|
24
|
+
Calculate infiltration front position at given time(s).
|
|
25
|
+
z(t) = sqrt(2 · K · ΔP · t / (μ · φ))
|
|
26
|
+
If you fill the p_c field that is optional to fill, you will get the result corrected by the capillary pressure:
|
|
27
|
+
z(t) = sqrt(2 · K · (ΔP + p_c) · t / (μ · φ))
|
|
28
|
+
"""
|
|
29
|
+
infiltration_front_position_multiple_time_instruction = """
|
|
30
|
+
Calculate infiltration front position at multiple times (for graph making).
|
|
31
|
+
z(t) = sqrt(2 · K · ΔP · t / (μ · φ))
|
|
32
|
+
If you fill the p_c field that is optional to fill, you will get the result corrected by the capillary pressure:
|
|
33
|
+
z(t) = sqrt(2 · K · (ΔP + p_c) · t / (μ · φ))
|
|
34
|
+
"""
|
|
35
|
+
capillary_pressure_calculation_instruction = """
|
|
36
|
+
Calculate capillary pressure using the Young-Laplace equation.
|
|
37
|
+
pc = 2 · γ · cos(θ) / r
|
|
38
|
+
"""
|
|
39
|
+
pressure_difference_calculation_instruction = """
|
|
40
|
+
Calculate pressure difference using the seepage distance method.
|
|
41
|
+
ΔP = μ · φ · L² / (2 · K · t)
|
|
42
|
+
If you fill the p_c field that is optional to fill, you will get the result corrected by the capillary pressure:
|
|
43
|
+
ΔP = μ · φ · L² / (2 · K · t) - p_c
|
|
44
|
+
"""
|
|
45
|
+
# Seepage Distance Calculation
|
|
46
|
+
L_meaning = "Sample length/thickness along flow direction (m)"
|
|
47
|
+
mu_meaning = "Dynamic viscosity of the fluid (Pa·s)"
|
|
48
|
+
phi_meaning = "Porosity of the porous medium (dimensionless, 0 < phi <= 1)"
|
|
49
|
+
t_meaning = "Total time for fluid to fully penetrate the sample (s)"
|
|
50
|
+
multi_t_meaning = "Total time recorded for multiple rounds for fluid to fully penetrate the sample (s)"
|
|
51
|
+
dP_meaning = "Constant pressure difference across the sample (Pa)"
|
|
52
|
+
K_meaning = "Permeability (m²)"
|
|
53
|
+
m2K_meaning = "Permeability in m^2"
|
|
54
|
+
darcyK_meaning = "Permeability in Darcy"
|
|
55
|
+
z_meaning = "Infiltration front position at given time(s)"
|
|
56
|
+
p_c_meaning = "Capillary pressure (Pa)"
|
|
57
|
+
theta_meaning = "Contact angle (wetting angle) (Degrees)"
|
|
58
|
+
gamma_meaning = "Surface tension of the liquid (N/m)"
|
|
59
|
+
r_meaning = "Equivalent pore radius (m)"
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
from typing import (
|
|
2
|
+
Annotated,
|
|
3
|
+
List,
|
|
4
|
+
Optional
|
|
5
|
+
)
|
|
6
|
+
import argparse
|
|
7
|
+
import numpy as np
|
|
8
|
+
# Fastmcp dependencies
|
|
9
|
+
from fastmcp import FastMCP
|
|
10
|
+
from fastmcp.exceptions import ToolError
|
|
11
|
+
# Project dependencies
|
|
12
|
+
from permeability.mcp.ProcessResult import (
|
|
13
|
+
process_mcp_calculation_result
|
|
14
|
+
)
|
|
15
|
+
from permeability.mcp.Prompts import (
|
|
16
|
+
mcp_instruction,
|
|
17
|
+
permeability_calculation_instruction,
|
|
18
|
+
infiltration_time_calculation_instruction,
|
|
19
|
+
darcy2m2_instruction,
|
|
20
|
+
m22darcy_instruction,
|
|
21
|
+
infiltration_front_position_instruction,
|
|
22
|
+
infiltration_front_position_multiple_time_instruction,
|
|
23
|
+
capillary_pressure_calculation_instruction,
|
|
24
|
+
pressure_difference_calculation_instruction,
|
|
25
|
+
L_meaning,
|
|
26
|
+
mu_meaning,
|
|
27
|
+
phi_meaning,
|
|
28
|
+
t_meaning,
|
|
29
|
+
dP_meaning,
|
|
30
|
+
K_meaning,
|
|
31
|
+
multi_t_meaning,
|
|
32
|
+
darcyK_meaning,
|
|
33
|
+
m2K_meaning,
|
|
34
|
+
z_meaning,
|
|
35
|
+
p_c_meaning,
|
|
36
|
+
gamma_meaning,
|
|
37
|
+
theta_meaning,
|
|
38
|
+
r_meaning
|
|
39
|
+
)
|
|
40
|
+
from permeability.permeability.Seepage import (
|
|
41
|
+
calculate_permeability,
|
|
42
|
+
calculate_infiltration_time,
|
|
43
|
+
calculate_infiltration_front_position,
|
|
44
|
+
calculate_infiltration_front_position_with_multiple_time,
|
|
45
|
+
calculate_pressure_difference
|
|
46
|
+
)
|
|
47
|
+
from permeability.permeability.Capillary import (
|
|
48
|
+
calculate_permeability_with_capillary_correction,
|
|
49
|
+
calculate_infiltration_time_with_capillary_correction,
|
|
50
|
+
calculate_infiltration_front_position_with_capillary_correction,
|
|
51
|
+
calculate_infiltration_front_position_with_multiple_time_with_capillary_correction,
|
|
52
|
+
calculate_capillary_pressure,
|
|
53
|
+
calculate_pressure_difference_with_capillary_correction
|
|
54
|
+
)
|
|
55
|
+
from permeability.utils.UnitConverter import (
|
|
56
|
+
darcy2m2,
|
|
57
|
+
m22darcy
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# mcp
|
|
62
|
+
mcp = FastMCP(
|
|
63
|
+
"Permeability MCP",
|
|
64
|
+
strict_input_validation=True,
|
|
65
|
+
mask_error_details=True,
|
|
66
|
+
instructions=mcp_instruction
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# Calculate permeability
|
|
71
|
+
@mcp.tool(
|
|
72
|
+
name="calculate_permeability_by_seepage_distance",
|
|
73
|
+
description=permeability_calculation_instruction,
|
|
74
|
+
tags={"permeability", "scalar_calculation"}
|
|
75
|
+
)
|
|
76
|
+
async def calculate_permeability_by_seepage_distance(
|
|
77
|
+
L: Annotated[float, L_meaning],
|
|
78
|
+
mu: Annotated[float, mu_meaning],
|
|
79
|
+
phi: Annotated[float, phi_meaning],
|
|
80
|
+
t: Annotated[float, t_meaning],
|
|
81
|
+
dP: Annotated[float, dP_meaning],
|
|
82
|
+
p_c: Optional[Annotated[float, p_c_meaning]] = None
|
|
83
|
+
) -> dict:
|
|
84
|
+
try:
|
|
85
|
+
if p_c is None:
|
|
86
|
+
calculation_result = calculate_permeability(
|
|
87
|
+
L=L,
|
|
88
|
+
mu=mu,
|
|
89
|
+
phi=phi,
|
|
90
|
+
t=t,
|
|
91
|
+
dP=dP
|
|
92
|
+
)
|
|
93
|
+
else:
|
|
94
|
+
calculation_result = calculate_permeability_with_capillary_correction(
|
|
95
|
+
L=L,
|
|
96
|
+
mu=mu,
|
|
97
|
+
phi=phi,
|
|
98
|
+
t=t,
|
|
99
|
+
dP=dP,
|
|
100
|
+
p_c=p_c
|
|
101
|
+
)
|
|
102
|
+
return process_mcp_calculation_result(
|
|
103
|
+
value=calculation_result,
|
|
104
|
+
unit="m^2",
|
|
105
|
+
meaning=K_meaning
|
|
106
|
+
)
|
|
107
|
+
except Exception as e:
|
|
108
|
+
raise ToolError(e)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
# Infiltration time calculation
|
|
112
|
+
@mcp.tool(
|
|
113
|
+
name="calculate_infiltration_time",
|
|
114
|
+
description=infiltration_time_calculation_instruction,
|
|
115
|
+
tags={"permeability", "scalar_calculation"}
|
|
116
|
+
)
|
|
117
|
+
async def calculate_infiltration_time_tool(
|
|
118
|
+
L: Annotated[float, L_meaning],
|
|
119
|
+
mu: Annotated[float, mu_meaning],
|
|
120
|
+
phi: Annotated[float, phi_meaning],
|
|
121
|
+
K: Annotated[float, K_meaning],
|
|
122
|
+
dP: Annotated[float, dP_meaning],
|
|
123
|
+
p_c: Optional[Annotated[float, p_c_meaning]] = None
|
|
124
|
+
) -> dict:
|
|
125
|
+
try:
|
|
126
|
+
if p_c is None:
|
|
127
|
+
calculation_result = calculate_infiltration_time(
|
|
128
|
+
L=L,
|
|
129
|
+
mu=mu,
|
|
130
|
+
phi=phi,
|
|
131
|
+
K=K,
|
|
132
|
+
dP=dP
|
|
133
|
+
)
|
|
134
|
+
else:
|
|
135
|
+
calculation_result = calculate_infiltration_time_with_capillary_correction(
|
|
136
|
+
L=L,
|
|
137
|
+
mu=mu,
|
|
138
|
+
phi=phi,
|
|
139
|
+
K=K,
|
|
140
|
+
dP=dP,
|
|
141
|
+
p_c=p_c
|
|
142
|
+
)
|
|
143
|
+
return process_mcp_calculation_result(
|
|
144
|
+
value=calculation_result,
|
|
145
|
+
unit="s",
|
|
146
|
+
meaning=t_meaning
|
|
147
|
+
)
|
|
148
|
+
except Exception as e:
|
|
149
|
+
raise ToolError(e)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
# Tool for converting darcy to m2
|
|
153
|
+
@mcp.tool(
|
|
154
|
+
name="darcy_to_m2_converter",
|
|
155
|
+
description=darcy2m2_instruction,
|
|
156
|
+
tags={"permeability", "unit_converter"}
|
|
157
|
+
)
|
|
158
|
+
async def darcy_to_m2_converter(
|
|
159
|
+
darcyK: Annotated[float, darcyK_meaning],
|
|
160
|
+
) -> dict:
|
|
161
|
+
calculation_result = darcy2m2(darcyK=darcyK)
|
|
162
|
+
return process_mcp_calculation_result(
|
|
163
|
+
value=calculation_result,
|
|
164
|
+
unit="m^2",
|
|
165
|
+
meaning=m2K_meaning
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
# Tool for converting m2 to darcy
|
|
170
|
+
@mcp.tool(
|
|
171
|
+
name="m2_to_darcy_converter",
|
|
172
|
+
description=m22darcy_instruction,
|
|
173
|
+
tags={"permeability", "unit_converter"}
|
|
174
|
+
)
|
|
175
|
+
async def m2_to_darcy_converter(
|
|
176
|
+
m2K: Annotated[float, m2K_meaning],
|
|
177
|
+
) -> dict:
|
|
178
|
+
calculation_result = m22darcy(m2K=m2K)
|
|
179
|
+
return process_mcp_calculation_result(
|
|
180
|
+
value=calculation_result,
|
|
181
|
+
unit="Darcy",
|
|
182
|
+
meaning=darcyK_meaning
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
# Tool for calculating infiltration front position
|
|
187
|
+
@mcp.tool(
|
|
188
|
+
name="calculate_infiltration_front_position",
|
|
189
|
+
description=infiltration_front_position_instruction,
|
|
190
|
+
tags={"permeability", "scalar_calculation"}
|
|
191
|
+
)
|
|
192
|
+
async def calculate_infiltration_front_position_tool(
|
|
193
|
+
K: Annotated[float, K_meaning],
|
|
194
|
+
mu: Annotated[float, mu_meaning],
|
|
195
|
+
phi: Annotated[float, phi_meaning],
|
|
196
|
+
dP: Annotated[float, dP_meaning],
|
|
197
|
+
t: Annotated[float, t_meaning],
|
|
198
|
+
p_c: Optional[Annotated[float, p_c_meaning]] = None
|
|
199
|
+
) -> dict:
|
|
200
|
+
try:
|
|
201
|
+
if p_c is None:
|
|
202
|
+
calculation_result = calculate_infiltration_front_position(
|
|
203
|
+
K=K,
|
|
204
|
+
mu=mu,
|
|
205
|
+
phi=phi,
|
|
206
|
+
t=t,
|
|
207
|
+
dP=dP
|
|
208
|
+
)
|
|
209
|
+
else:
|
|
210
|
+
calculation_result = calculate_infiltration_front_position_with_capillary_correction(
|
|
211
|
+
K=K,
|
|
212
|
+
mu=mu,
|
|
213
|
+
phi=phi,
|
|
214
|
+
t=t,
|
|
215
|
+
dP=dP,
|
|
216
|
+
p_c=p_c
|
|
217
|
+
)
|
|
218
|
+
return process_mcp_calculation_result(
|
|
219
|
+
value=calculation_result,
|
|
220
|
+
unit="m",
|
|
221
|
+
meaning=z_meaning
|
|
222
|
+
)
|
|
223
|
+
except Exception as e:
|
|
224
|
+
raise ToolError(e)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
# Tool for calculating infiltration front position for multiple time points
|
|
228
|
+
@mcp.tool(
|
|
229
|
+
name="calculate_infiltration_front_position4multiple_times",
|
|
230
|
+
description=infiltration_front_position_multiple_time_instruction,
|
|
231
|
+
tags={"permeability", "graph_related", "vector_calculation"}
|
|
232
|
+
)
|
|
233
|
+
async def calculate_infiltration_front_position4multiple_times_tool(
|
|
234
|
+
K: Annotated[float, K_meaning],
|
|
235
|
+
mu: Annotated[float, mu_meaning],
|
|
236
|
+
phi: Annotated[float, phi_meaning],
|
|
237
|
+
dP: Annotated[float, dP_meaning],
|
|
238
|
+
t: Annotated[List[float], multi_t_meaning],
|
|
239
|
+
p_c: Optional[Annotated[float, p_c_meaning]] = None
|
|
240
|
+
) -> dict:
|
|
241
|
+
try:
|
|
242
|
+
processed_t = np.array(t)
|
|
243
|
+
if p_c is None:
|
|
244
|
+
calculation_result = calculate_infiltration_front_position_with_multiple_time(
|
|
245
|
+
K=K,
|
|
246
|
+
mu=mu,
|
|
247
|
+
phi=phi,
|
|
248
|
+
t=processed_t,
|
|
249
|
+
dP=dP
|
|
250
|
+
)
|
|
251
|
+
else:
|
|
252
|
+
calculation_result = (
|
|
253
|
+
calculate_infiltration_front_position_with_multiple_time_with_capillary_correction(
|
|
254
|
+
K=K,
|
|
255
|
+
mu=mu,
|
|
256
|
+
phi=phi,
|
|
257
|
+
t=processed_t,
|
|
258
|
+
dP=dP,
|
|
259
|
+
p_c=p_c
|
|
260
|
+
)
|
|
261
|
+
)
|
|
262
|
+
return process_mcp_calculation_result(
|
|
263
|
+
value=calculation_result.tolist(),
|
|
264
|
+
unit="m",
|
|
265
|
+
meaning=z_meaning
|
|
266
|
+
)
|
|
267
|
+
except Exception as e:
|
|
268
|
+
raise ToolError(e)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
# Calculate capillary pressure
|
|
272
|
+
@mcp.tool(
|
|
273
|
+
name="calculate_capillary_pressure",
|
|
274
|
+
description=capillary_pressure_calculation_instruction,
|
|
275
|
+
tags={"permeability", "scalar_calculation"}
|
|
276
|
+
)
|
|
277
|
+
async def calculate_capillary_pressure_tool(
|
|
278
|
+
theta: Annotated[float, theta_meaning],
|
|
279
|
+
r: Annotated[float, r_meaning],
|
|
280
|
+
gamma: Annotated[float, gamma_meaning],
|
|
281
|
+
):
|
|
282
|
+
try:
|
|
283
|
+
calculation_result = calculate_capillary_pressure(
|
|
284
|
+
theta=theta,
|
|
285
|
+
r=r,
|
|
286
|
+
gamma=gamma
|
|
287
|
+
)
|
|
288
|
+
return process_mcp_calculation_result(
|
|
289
|
+
value=calculation_result,
|
|
290
|
+
unit="Pa",
|
|
291
|
+
meaning=p_c_meaning
|
|
292
|
+
)
|
|
293
|
+
except Exception as e:
|
|
294
|
+
raise ToolError(e)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
# Calculate pressure difference
|
|
298
|
+
@mcp.tool(
|
|
299
|
+
name="calculate_pressure_difference",
|
|
300
|
+
description=pressure_difference_calculation_instruction,
|
|
301
|
+
tags={"permeability", "scalar_calculation"}
|
|
302
|
+
)
|
|
303
|
+
async def calculate_pressure_difference_tool(
|
|
304
|
+
L: Annotated[float, L_meaning],
|
|
305
|
+
mu: Annotated[float, mu_meaning],
|
|
306
|
+
phi: Annotated[float, phi_meaning],
|
|
307
|
+
K: Annotated[float, K_meaning],
|
|
308
|
+
t: Annotated[float, t_meaning],
|
|
309
|
+
p_c: Optional[Annotated[float, p_c_meaning]] = None,
|
|
310
|
+
):
|
|
311
|
+
try:
|
|
312
|
+
if p_c is None:
|
|
313
|
+
calculation_result = calculate_pressure_difference(
|
|
314
|
+
L=L,
|
|
315
|
+
mu=mu,
|
|
316
|
+
phi=phi,
|
|
317
|
+
K=K,
|
|
318
|
+
t=t
|
|
319
|
+
)
|
|
320
|
+
else:
|
|
321
|
+
calculation_result = calculate_pressure_difference_with_capillary_correction(
|
|
322
|
+
L=L,
|
|
323
|
+
mu=mu,
|
|
324
|
+
phi=phi,
|
|
325
|
+
K=K,
|
|
326
|
+
t=t,
|
|
327
|
+
p_c=p_c
|
|
328
|
+
)
|
|
329
|
+
return process_mcp_calculation_result(
|
|
330
|
+
value=calculation_result,
|
|
331
|
+
unit="Pa",
|
|
332
|
+
meaning=dP_meaning
|
|
333
|
+
)
|
|
334
|
+
except Exception as e:
|
|
335
|
+
raise ToolError(e)
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
# Run
|
|
339
|
+
def run():
|
|
340
|
+
parser = argparse.ArgumentParser(description="My MCP Server")
|
|
341
|
+
parser.add_argument("--port", type=int, default=8000, help="Port for SSE transport")
|
|
342
|
+
args = parser.parse_args()
|
|
343
|
+
mcp.run(transport="http", host="localhost", port=args.port)
|
|
File without changes
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def calculate_capillary_pressure(
|
|
5
|
+
gamma: float,
|
|
6
|
+
theta: float,
|
|
7
|
+
r: float
|
|
8
|
+
) -> float:
|
|
9
|
+
'''
|
|
10
|
+
Calculate capillary pressure using the Young-Laplace equation.
|
|
11
|
+
p_c = 2 · γ · cos(θ) / r
|
|
12
|
+
:param gamma: Surface tension of the liquid (N/m)
|
|
13
|
+
:param theta: Contact angle (wetting angle) (Degrees)
|
|
14
|
+
:param r: Equivalent pore radius (m)
|
|
15
|
+
:return: p_c, capillary pressure (Pa)
|
|
16
|
+
'''
|
|
17
|
+
if gamma <= 0:
|
|
18
|
+
raise ValueError('gamma must be greater than 0')
|
|
19
|
+
if r <= 0:
|
|
20
|
+
raise ValueError('r must be greater than 0')
|
|
21
|
+
rad_theta = np.deg2rad(theta)
|
|
22
|
+
return (2*gamma*np.cos(rad_theta))/r
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def calculate_permeability_with_capillary_correction(
|
|
26
|
+
p_c: float,
|
|
27
|
+
L: float,
|
|
28
|
+
mu: float,
|
|
29
|
+
phi: float,
|
|
30
|
+
t: float,
|
|
31
|
+
dP: float,
|
|
32
|
+
):
|
|
33
|
+
'''
|
|
34
|
+
Calculate permeability with capillary force correction.
|
|
35
|
+
K = μ · φ · L² / (2 · t · (ΔP + p_c))
|
|
36
|
+
:param p_c: capillary pressure (Pa)
|
|
37
|
+
:param L: Sample length/thickness along flow direction (m)
|
|
38
|
+
:param mu: Dynamic viscosity of the fluid (Pa·s)
|
|
39
|
+
:param phi: Porosity of the porous medium (dimensionless, 0 < phi <= 1)
|
|
40
|
+
:param t: Total time for fluid to fully penetrate the sample (s)
|
|
41
|
+
:param dP: Constant pressure difference across the sample (Pa)
|
|
42
|
+
:return: K, Permeability (m^2)
|
|
43
|
+
'''
|
|
44
|
+
if dP <= 0 or t <= 0:
|
|
45
|
+
raise ValueError("dP and t cannot be smaller than 0")
|
|
46
|
+
if mu <= 0:
|
|
47
|
+
raise ValueError("mu cannot be <= 0")
|
|
48
|
+
if phi > 1 or phi < 0:
|
|
49
|
+
raise ValueError("phi must be between 0 and 1")
|
|
50
|
+
if L <= 0:
|
|
51
|
+
raise ValueError("L must be greater than 0")
|
|
52
|
+
if p_c == -dP:
|
|
53
|
+
raise ValueError("p_c + dP cannot be equal to 0")
|
|
54
|
+
return (L * L * mu * phi) / (2 * t * (dP + p_c))
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def calculate_infiltration_time_with_capillary_correction(
|
|
58
|
+
p_c: float,
|
|
59
|
+
L: float,
|
|
60
|
+
mu: float,
|
|
61
|
+
phi: float,
|
|
62
|
+
K: float,
|
|
63
|
+
dP: float
|
|
64
|
+
) -> float:
|
|
65
|
+
'''
|
|
66
|
+
Calculate permeability with capillary force correction.
|
|
67
|
+
t = μ · φ · L² / (2 · K · (ΔP + p_c))
|
|
68
|
+
:param p_c: capillary pressure (Pa)
|
|
69
|
+
:param L: Sample length/thickness along flow direction (m)
|
|
70
|
+
:param mu: Dynamic viscosity of the fluid (Pa·s)
|
|
71
|
+
:param phi: Porosity of the porous medium (dimensionless, 0 < phi <= 1)
|
|
72
|
+
:param K: Permeability (m^2)
|
|
73
|
+
:param dP: Constant pressure difference across the sample (Pa)
|
|
74
|
+
:return: t, Total time for fluid to fully penetrate the sample (s)
|
|
75
|
+
'''
|
|
76
|
+
if K <= 0 or dP <= 0:
|
|
77
|
+
raise ValueError("dP and K cannot be smaller than 0")
|
|
78
|
+
if mu <= 0:
|
|
79
|
+
raise ValueError("mu cannot be <= 0")
|
|
80
|
+
if phi > 1 or phi < 0:
|
|
81
|
+
raise ValueError("phi must be between 0 and 1")
|
|
82
|
+
if L <= 0:
|
|
83
|
+
raise ValueError("L must be greater than 0")
|
|
84
|
+
if p_c == -dP:
|
|
85
|
+
raise ValueError("p_c + dP != 0")
|
|
86
|
+
return (mu * phi * L * L) / (2 * K * (dP+p_c))
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def calculate_infiltration_front_position_with_capillary_correction(
|
|
90
|
+
K: float,
|
|
91
|
+
mu: float,
|
|
92
|
+
phi: float,
|
|
93
|
+
dP: float,
|
|
94
|
+
t: float,
|
|
95
|
+
p_c: float
|
|
96
|
+
) -> float:
|
|
97
|
+
'''
|
|
98
|
+
Calculate infiltration front position with capillary force correction at given time(s).
|
|
99
|
+
z(t) = sqrt(2 · K · (ΔP + p_c) · t / (μ · φ))
|
|
100
|
+
:param K: Permeability (m^2)
|
|
101
|
+
:param p_c: capillary pressure (Pa)
|
|
102
|
+
:param mu: Dynamic viscosity of the fluid (Pa·s)
|
|
103
|
+
:param phi: Porosity of the porous medium (dimensionless, 0 < phi <= 1)
|
|
104
|
+
:param dP: Constant pressure difference across the sample (Pa)
|
|
105
|
+
:param t: Total time recorded for fluid to fully penetrate the sample (s)
|
|
106
|
+
:return: z, the infiltration front position at given time
|
|
107
|
+
'''
|
|
108
|
+
if mu <= 0 or phi <= 0:
|
|
109
|
+
raise ValueError("mu and phi cannot be smaller than 0")
|
|
110
|
+
if phi > 1 or phi < 0:
|
|
111
|
+
raise ValueError("phi must be between 0 and 1")
|
|
112
|
+
if K <= 0:
|
|
113
|
+
raise ValueError("K must be greater than 0")
|
|
114
|
+
if t < 0:
|
|
115
|
+
raise ValueError("t must be greater than 0")
|
|
116
|
+
if dP <= 0:
|
|
117
|
+
raise ValueError("dP must be greater than 0")
|
|
118
|
+
return np.sqrt((2 * K * (dP+p_c) * t) / (mu * phi))
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def calculate_infiltration_front_position_with_multiple_time_with_capillary_correction(
|
|
122
|
+
K: float,
|
|
123
|
+
mu: float,
|
|
124
|
+
phi: float,
|
|
125
|
+
dP: float,
|
|
126
|
+
t: np.ndarray,
|
|
127
|
+
p_c: float
|
|
128
|
+
) -> np.ndarray:
|
|
129
|
+
'''
|
|
130
|
+
Calculate infiltration front position with capillary force correction at multiple times (for graph making).
|
|
131
|
+
z(t) = sqrt(2 · K · (ΔP + p_c) · t / (μ · φ))
|
|
132
|
+
:param p_c: capillary pressure (Pa)
|
|
133
|
+
:param K: Permeability (m^2)
|
|
134
|
+
:param mu: Dynamic viscosity of the fluid (Pa·s)
|
|
135
|
+
:param phi: Porosity of the porous medium (dimensionless, 0 < phi <= 1)
|
|
136
|
+
:param dP: Constant pressure difference across the sample (Pa)
|
|
137
|
+
:param t: Total time recorded for multiple rounds for fluid to fully penetrate the sample (s)
|
|
138
|
+
:return: z, the infiltration front position at given time
|
|
139
|
+
'''
|
|
140
|
+
if mu <= 0 or phi <= 0:
|
|
141
|
+
raise ValueError("mu and phi cannot be smaller than 0")
|
|
142
|
+
if phi > 1 or phi < 0:
|
|
143
|
+
raise ValueError("phi must be between 0 and 1")
|
|
144
|
+
if K <= 0:
|
|
145
|
+
raise ValueError("K must be greater than 0")
|
|
146
|
+
if not np.all(t >= 0):
|
|
147
|
+
raise ValueError("t must be greater than 0")
|
|
148
|
+
if dP <= 0:
|
|
149
|
+
raise ValueError("dP must be greater than 0")
|
|
150
|
+
return np.sqrt((2 * K * (dP+p_c) * t) / (mu * phi))
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def calculate_pressure_difference_with_capillary_correction(
|
|
154
|
+
L: float,
|
|
155
|
+
mu: float,
|
|
156
|
+
phi: float,
|
|
157
|
+
K: float,
|
|
158
|
+
t: float,
|
|
159
|
+
p_c: float
|
|
160
|
+
) -> float:
|
|
161
|
+
'''
|
|
162
|
+
Calculate pressure difference using the seepage distance method with capillary correction.
|
|
163
|
+
ΔP = μ · φ · L² / (2 · K · t) - p_c
|
|
164
|
+
:param L: Sample length/thickness along flow direction (m)
|
|
165
|
+
:param mu: Dynamic viscosity of the fluid (Pa·s)
|
|
166
|
+
:param phi: Porosity of the porous medium (dimensionless, 0 < phi <= 1)
|
|
167
|
+
:param K: Permeability (m^2)
|
|
168
|
+
:param t, Total time for fluid to fully penetrate the sample (s)
|
|
169
|
+
:return: dP, Constant pressure difference across the sample (Pa)
|
|
170
|
+
'''
|
|
171
|
+
if K <= 0 or t <= 0:
|
|
172
|
+
raise ValueError("dP and K cannot be smaller than 0")
|
|
173
|
+
if mu <= 0:
|
|
174
|
+
raise ValueError("mu cannot be <= 0")
|
|
175
|
+
if phi > 1 or phi < 0:
|
|
176
|
+
raise ValueError("phi must be between 0 and 1")
|
|
177
|
+
if L <= 0:
|
|
178
|
+
raise ValueError("L must be greater than 0")
|
|
179
|
+
return (mu * phi * L * L) / (2 * K * t) - p_c
|