xslope 0.1.6__py3-none-any.whl → 0.1.8__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.
- xslope/_version.py +1 -1
- xslope/mesh copy.py +2962 -0
- xslope/mesh.py +156 -9
- xslope/plot.py +4 -2
- xslope/plot_seep.py +157 -37
- xslope/seep.py +172 -3
- {xslope-0.1.6.dist-info → xslope-0.1.8.dist-info}/METADATA +1 -1
- xslope-0.1.8.dist-info/RECORD +21 -0
- xslope-0.1.6.dist-info/RECORD +0 -20
- {xslope-0.1.6.dist-info → xslope-0.1.8.dist-info}/LICENSE +0 -0
- {xslope-0.1.6.dist-info → xslope-0.1.8.dist-info}/NOTICE +0 -0
- {xslope-0.1.6.dist-info → xslope-0.1.8.dist-info}/WHEEL +0 -0
- {xslope-0.1.6.dist-info → xslope-0.1.8.dist-info}/top_level.txt +0 -0
xslope/seep.py
CHANGED
|
@@ -1515,6 +1515,142 @@ def compute_velocity(nodes, elements, head, k1_vals, k2_vals, angles, kr0=None,
|
|
|
1515
1515
|
velocity /= count[:, None]
|
|
1516
1516
|
return velocity
|
|
1517
1517
|
|
|
1518
|
+
def compute_gradient(nodes, elements, head, element_types=None):
|
|
1519
|
+
"""
|
|
1520
|
+
Compute nodal hydraulic gradient by averaging element-wise head gradients.
|
|
1521
|
+
The hydraulic gradient i = -grad(h), where grad(h) is the gradient of head.
|
|
1522
|
+
Supports both triangular and quadrilateral elements.
|
|
1523
|
+
|
|
1524
|
+
Parameters:
|
|
1525
|
+
nodes : (n_nodes, 2) array of node coordinates
|
|
1526
|
+
elements : (n_elements, 3 or 4) triangle or quad node indices
|
|
1527
|
+
head : (n_nodes,) nodal head solution
|
|
1528
|
+
element_types : (n_elements,) array indicating 3 for triangles, 4 for quads
|
|
1529
|
+
|
|
1530
|
+
Returns:
|
|
1531
|
+
gradient : (n_nodes, 2) array of nodal hydraulic gradient vectors [ix, iy]
|
|
1532
|
+
"""
|
|
1533
|
+
# If element_types is not provided, assume all triangles (backward compatibility)
|
|
1534
|
+
if element_types is None:
|
|
1535
|
+
element_types = np.full(len(elements), 3)
|
|
1536
|
+
|
|
1537
|
+
n_nodes = nodes.shape[0]
|
|
1538
|
+
gradient = np.zeros((n_nodes, 2))
|
|
1539
|
+
count = np.zeros(n_nodes)
|
|
1540
|
+
|
|
1541
|
+
for idx, element_nodes in enumerate(elements):
|
|
1542
|
+
element_type = element_types[idx]
|
|
1543
|
+
|
|
1544
|
+
if element_type == 3:
|
|
1545
|
+
# Triangle: use first 3 nodes
|
|
1546
|
+
i, j, k = element_nodes[:3]
|
|
1547
|
+
xi, yi = nodes[i]
|
|
1548
|
+
xj, yj = nodes[j]
|
|
1549
|
+
xk, yk = nodes[k]
|
|
1550
|
+
|
|
1551
|
+
area = 0.5 * np.linalg.det([[1, xi, yi], [1, xj, yj], [1, xk, yk]])
|
|
1552
|
+
if area <= 0:
|
|
1553
|
+
continue
|
|
1554
|
+
|
|
1555
|
+
beta = np.array([yj - yk, yk - yi, yi - yj])
|
|
1556
|
+
gamma = np.array([xk - xj, xi - xk, xj - xi])
|
|
1557
|
+
grad = np.array([beta, gamma]) / (2 * area)
|
|
1558
|
+
|
|
1559
|
+
h_vals = head[[i, j, k]]
|
|
1560
|
+
grad_h = grad @ h_vals
|
|
1561
|
+
# Hydraulic gradient i = -grad(h)
|
|
1562
|
+
i_elem = -grad_h
|
|
1563
|
+
|
|
1564
|
+
for node in element_nodes[:3]:
|
|
1565
|
+
gradient[node] += i_elem
|
|
1566
|
+
count[node] += 1
|
|
1567
|
+
elif element_type == 4:
|
|
1568
|
+
# Quadrilateral: use first 4 nodes
|
|
1569
|
+
i, j, k, l = element_nodes[:4]
|
|
1570
|
+
nodes_elem = nodes[[i, j, k, l], :]
|
|
1571
|
+
h_elem = head[[i, j, k, l]]
|
|
1572
|
+
|
|
1573
|
+
# 2x2 Gauss points and weights
|
|
1574
|
+
gauss_pts = [(-1/np.sqrt(3), -1/np.sqrt(3)),
|
|
1575
|
+
(1/np.sqrt(3), -1/np.sqrt(3)),
|
|
1576
|
+
(1/np.sqrt(3), 1/np.sqrt(3)),
|
|
1577
|
+
(-1/np.sqrt(3), 1/np.sqrt(3))]
|
|
1578
|
+
|
|
1579
|
+
for (xi, eta) in gauss_pts:
|
|
1580
|
+
# Shape function derivatives w.r.t. natural coords
|
|
1581
|
+
dN_dxi = np.array([-(1-eta), (1-eta), (1+eta), -(1+eta)]) * 0.25
|
|
1582
|
+
dN_deta = np.array([-(1-xi), -(1+xi), (1+xi), (1-xi)]) * 0.25
|
|
1583
|
+
# Jacobian
|
|
1584
|
+
J = np.zeros((2,2))
|
|
1585
|
+
for a in range(4):
|
|
1586
|
+
J[0,0] += dN_dxi[a] * nodes_elem[a,0]
|
|
1587
|
+
J[0,1] += dN_dxi[a] * nodes_elem[a,1]
|
|
1588
|
+
J[1,0] += dN_deta[a] * nodes_elem[a,0]
|
|
1589
|
+
J[1,1] += dN_deta[a] * nodes_elem[a,1]
|
|
1590
|
+
detJ = np.linalg.det(J)
|
|
1591
|
+
if detJ <= 0:
|
|
1592
|
+
continue
|
|
1593
|
+
Jinv = np.linalg.inv(J)
|
|
1594
|
+
# Shape function derivatives w.r.t. x,y
|
|
1595
|
+
dN_dx = Jinv[0,0]*dN_dxi + Jinv[0,1]*dN_deta
|
|
1596
|
+
dN_dy = Jinv[1,0]*dN_dxi + Jinv[1,1]*dN_deta
|
|
1597
|
+
gradN = np.vstack((dN_dx, dN_dy)) # shape (2,4)
|
|
1598
|
+
# Compute grad(h) at this Gauss point
|
|
1599
|
+
grad_h = gradN @ h_elem
|
|
1600
|
+
# Hydraulic gradient i = -grad(h)
|
|
1601
|
+
i_gp = -grad_h
|
|
1602
|
+
# Distribute/average to nodes
|
|
1603
|
+
for node in element_nodes[:4]:
|
|
1604
|
+
gradient[node] += i_gp
|
|
1605
|
+
count[node] += 1
|
|
1606
|
+
elif element_type == 6:
|
|
1607
|
+
# 6-node triangle (quadratic): compute gradient using 3-point Gauss quadrature
|
|
1608
|
+
nodes_elem = nodes[element_nodes[:6], :]
|
|
1609
|
+
h_elem = head[element_nodes[:6]]
|
|
1610
|
+
|
|
1611
|
+
# 3-point Gauss quadrature for triangles
|
|
1612
|
+
gauss_pts = [(1/6, 1/6, 2/3), (1/6, 2/3, 1/6), (2/3, 1/6, 1/6)]
|
|
1613
|
+
weights = [1/3, 1/3, 1/3]
|
|
1614
|
+
|
|
1615
|
+
for (L1, L2, L3), w in zip(gauss_pts, weights):
|
|
1616
|
+
# Shape function derivatives w.r.t. area coordinates
|
|
1617
|
+
dN_dL1 = np.array([4*L1-1, 0, 0, 4*L2, 0, 4*L3])
|
|
1618
|
+
dN_dL2 = np.array([0, 4*L2-1, 0, 4*L1, 4*L3, 0])
|
|
1619
|
+
dN_dL3 = np.array([0, 0, 4*L3-1, 0, 4*L2, 4*L1])
|
|
1620
|
+
|
|
1621
|
+
# Jacobian transformation
|
|
1622
|
+
x0, y0 = nodes_elem[0]
|
|
1623
|
+
x1, y1 = nodes_elem[1]
|
|
1624
|
+
x2, y2 = nodes_elem[2]
|
|
1625
|
+
|
|
1626
|
+
J = np.array([[x0 - x2, x1 - x2],
|
|
1627
|
+
[y0 - y2, y1 - y2]])
|
|
1628
|
+
|
|
1629
|
+
detJ = np.linalg.det(J)
|
|
1630
|
+
if abs(detJ) < 1e-10:
|
|
1631
|
+
continue
|
|
1632
|
+
|
|
1633
|
+
Jinv = np.linalg.inv(J)
|
|
1634
|
+
|
|
1635
|
+
# Transform derivatives to global coordinates
|
|
1636
|
+
dN_dx = Jinv[0,0] * (dN_dL1 - dN_dL3) + Jinv[0,1] * (dN_dL2 - dN_dL3)
|
|
1637
|
+
dN_dy = Jinv[1,0] * (dN_dL1 - dN_dL3) + Jinv[1,1] * (dN_dL2 - dN_dL3)
|
|
1638
|
+
gradN = np.vstack((dN_dx, dN_dy)) # shape (2,6)
|
|
1639
|
+
|
|
1640
|
+
# Compute grad(h) at this Gauss point
|
|
1641
|
+
grad_h = gradN @ h_elem
|
|
1642
|
+
# Hydraulic gradient i = -grad(h)
|
|
1643
|
+
i_gp = -grad_h
|
|
1644
|
+
|
|
1645
|
+
# Distribute gradient to all 6 nodes of tri6 element
|
|
1646
|
+
for node in element_nodes[:6]:
|
|
1647
|
+
gradient[node] += i_gp * w # Weight by Gauss weight
|
|
1648
|
+
count[node] += w
|
|
1649
|
+
|
|
1650
|
+
count[count == 0] = 1 # Avoid division by zero
|
|
1651
|
+
gradient /= count[:, None]
|
|
1652
|
+
return gradient
|
|
1653
|
+
|
|
1518
1654
|
def tri3_stiffness_matrix(nodes_elem, Kmat):
|
|
1519
1655
|
"""
|
|
1520
1656
|
Compute the 3x3 local stiffness matrix for a 3-node triangular element.
|
|
@@ -1855,7 +1991,16 @@ def run_seepage_analysis(seep_data):
|
|
|
1855
1991
|
seep_data: Dictionary containing all the seepage data
|
|
1856
1992
|
|
|
1857
1993
|
Returns:
|
|
1858
|
-
Dictionary containing solution results
|
|
1994
|
+
Dictionary containing solution results with the following keys:
|
|
1995
|
+
- 'head': numpy array of hydraulic head values at each node
|
|
1996
|
+
- 'u': numpy array of pore pressure values at each node
|
|
1997
|
+
- 'velocity': numpy array of shape (n_nodes, 2) containing velocity vectors [vx, vy] at each node
|
|
1998
|
+
- 'gradient': numpy array of shape (n_nodes, 2) containing hydraulic gradient vectors [ix, iy] at each node
|
|
1999
|
+
- 'v_mag': numpy array of velocity magnitude at each node
|
|
2000
|
+
- 'i_mag': numpy array of hydraulic gradient magnitude at each node
|
|
2001
|
+
- 'q': numpy array of nodal flow vector
|
|
2002
|
+
- 'phi': numpy array of stream function/flow potential values at each node
|
|
2003
|
+
- 'flowrate': scalar total flow rate
|
|
1859
2004
|
"""
|
|
1860
2005
|
# Extract data from seep_data
|
|
1861
2006
|
nodes = seep_data["nodes"]
|
|
@@ -1920,6 +2065,13 @@ def run_seepage_analysis(seep_data):
|
|
|
1920
2065
|
# Compute velocity, don't pass kr0 and h0
|
|
1921
2066
|
velocity = compute_velocity(nodes, elements, head, k1, k2, angle, element_types=element_types)
|
|
1922
2067
|
|
|
2068
|
+
# Compute hydraulic gradient i = -grad(h)
|
|
2069
|
+
gradient = compute_gradient(nodes, elements, head, element_types)
|
|
2070
|
+
|
|
2071
|
+
# Compute velocity and gradient magnitudes
|
|
2072
|
+
v_mag = np.linalg.norm(velocity, axis=1)
|
|
2073
|
+
i_mag = np.linalg.norm(gradient, axis=1)
|
|
2074
|
+
|
|
1923
2075
|
gamma_w = unit_weight
|
|
1924
2076
|
u = gamma_w * (head - nodes[:, 1])
|
|
1925
2077
|
|
|
@@ -1927,6 +2079,9 @@ def run_seepage_analysis(seep_data):
|
|
|
1927
2079
|
"head": head,
|
|
1928
2080
|
"u": u,
|
|
1929
2081
|
"velocity": velocity,
|
|
2082
|
+
"gradient": gradient,
|
|
2083
|
+
"v_mag": v_mag,
|
|
2084
|
+
"i_mag": i_mag,
|
|
1930
2085
|
"q": q,
|
|
1931
2086
|
"phi": phi,
|
|
1932
2087
|
"flowrate": total_flow
|
|
@@ -1937,10 +2092,21 @@ def run_seepage_analysis(seep_data):
|
|
|
1937
2092
|
def export_seep_solution(seep_data, solution, filename):
|
|
1938
2093
|
"""Exports nodal results to a CSV file.
|
|
1939
2094
|
|
|
2095
|
+
The exported CSV file contains the following columns:
|
|
2096
|
+
- node_id: Node identifier (1-based)
|
|
2097
|
+
- head: Hydraulic head at each node
|
|
2098
|
+
- u: Pore pressure at each node
|
|
2099
|
+
- v_x, v_y: Velocity vector components
|
|
2100
|
+
- v_mag: Velocity magnitude
|
|
2101
|
+
- i_x, i_y: Hydraulic gradient vector components
|
|
2102
|
+
- i_mag: Hydraulic gradient magnitude
|
|
2103
|
+
- q: Nodal flow vector
|
|
2104
|
+
- phi: Stream function/flow potential
|
|
2105
|
+
|
|
1940
2106
|
Args:
|
|
1941
2107
|
filename: Path to the output CSV file
|
|
1942
2108
|
seep_data: Dictionary containing seepage data
|
|
1943
|
-
solution: Dictionary containing solution results from
|
|
2109
|
+
solution: Dictionary containing solution results from run_seepage_analysis
|
|
1944
2110
|
"""
|
|
1945
2111
|
import pandas as pd
|
|
1946
2112
|
n_nodes = len(seep_data["nodes"])
|
|
@@ -1950,7 +2116,10 @@ def export_seep_solution(seep_data, solution, filename):
|
|
|
1950
2116
|
"u": solution["u"],
|
|
1951
2117
|
"v_x": solution["velocity"][:, 0],
|
|
1952
2118
|
"v_y": solution["velocity"][:, 1],
|
|
1953
|
-
"v_mag":
|
|
2119
|
+
"v_mag": solution["v_mag"],
|
|
2120
|
+
"i_x": solution["gradient"][:, 0],
|
|
2121
|
+
"i_y": solution["gradient"][:, 1],
|
|
2122
|
+
"i_mag": solution["i_mag"],
|
|
1954
2123
|
"q": solution["q"],
|
|
1955
2124
|
"phi": solution["phi"]
|
|
1956
2125
|
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
xslope/__init__.py,sha256=ZygAIkX6Nbjag1czWdQa-yP-GM1mBE_9ss21Xh__JFc,34
|
|
2
|
+
xslope/_version.py,sha256=NdJ0AO0Uqe8qXyVhnXjyePxheMvSfPnlWIjEyON0wio,50
|
|
3
|
+
xslope/advanced.py,sha256=35k_ekQJ-mQJ1wHnoIHMc5TVfYn-2EPCJyHz827Cpbc,18281
|
|
4
|
+
xslope/fem.py,sha256=K4_Pq06HFBpRkN3JwtXF2zw_AMnCkXvj0ggrlRFMQQw,115731
|
|
5
|
+
xslope/fileio.py,sha256=DnFUYmJedjKXOuVPZUfTRxGfTjiIz8KyHkRDK7ddQg0,28840
|
|
6
|
+
xslope/global_config.py,sha256=Cj8mbPidIuj5Ty-5cZM-c8H12kNvyHsk5_ofNGez-3M,2253
|
|
7
|
+
xslope/mesh copy.py,sha256=qtMH1yKFgHM4kNuIrxco7tKV86R3Dbf7Nok5j6MtlLY,131013
|
|
8
|
+
xslope/mesh.py,sha256=qtMH1yKFgHM4kNuIrxco7tKV86R3Dbf7Nok5j6MtlLY,131013
|
|
9
|
+
xslope/plot.py,sha256=OW2eZyrT5h3Y95qjNFgGMnC_Am7TurUB2S7b_BgnO6E,54641
|
|
10
|
+
xslope/plot_fem.py,sha256=al9zjqjxWKooLl4SAds77Zz-j9cjD4TJGygyU9QK5vo,71111
|
|
11
|
+
xslope/plot_seep.py,sha256=lPMaKbm4VURWDb1lwtLT7UhuEwuXi5cKRQw3mKt4HkM,34657
|
|
12
|
+
xslope/search.py,sha256=dvgKn8JCobuvyD7fClF5lcbeHESCvV8gZ_U_lQnYRok,16867
|
|
13
|
+
xslope/seep.py,sha256=tLvme-eL0R5SGGTH2Y6z4Rrfe36UuSWWLlL_1kglee8,93030
|
|
14
|
+
xslope/slice.py,sha256=QHawTk7XPLziHoN_ZS0jrEPYKlhPT62caUc_q-_EGjs,45236
|
|
15
|
+
xslope/solve.py,sha256=j7N66QBjBpDAo-aizTiP8auwd5Ey1SiYAYeySaMVzkw,48554
|
|
16
|
+
xslope-0.1.8.dist-info/LICENSE,sha256=NU5J88FUai_4Ixu5DqOQukA-gcXAyX8pXLhIg8OB3AM,10969
|
|
17
|
+
xslope-0.1.8.dist-info/METADATA,sha256=Pf0XtMc9nlYRojBMzwsvKv4izxJh32ydwOQwCUmUhzA,2027
|
|
18
|
+
xslope-0.1.8.dist-info/NOTICE,sha256=E-sbN0MWwvJC27Z-2_G4VUHIx4IsfvLDTmOstvY4-OQ,530
|
|
19
|
+
xslope-0.1.8.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
|
|
20
|
+
xslope-0.1.8.dist-info/top_level.txt,sha256=5qHbWJ1R2pdTNIainFyrVtFk8R1tRcwIn0kzTuwuV1Q,7
|
|
21
|
+
xslope-0.1.8.dist-info/RECORD,,
|
xslope-0.1.6.dist-info/RECORD
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
xslope/__init__.py,sha256=ZygAIkX6Nbjag1czWdQa-yP-GM1mBE_9ss21Xh__JFc,34
|
|
2
|
-
xslope/_version.py,sha256=El5otyOm5tn7_NTNUcawnWQ_lZMwfYOTw_-GGhANHSI,50
|
|
3
|
-
xslope/advanced.py,sha256=35k_ekQJ-mQJ1wHnoIHMc5TVfYn-2EPCJyHz827Cpbc,18281
|
|
4
|
-
xslope/fem.py,sha256=K4_Pq06HFBpRkN3JwtXF2zw_AMnCkXvj0ggrlRFMQQw,115731
|
|
5
|
-
xslope/fileio.py,sha256=DnFUYmJedjKXOuVPZUfTRxGfTjiIz8KyHkRDK7ddQg0,28840
|
|
6
|
-
xslope/global_config.py,sha256=Cj8mbPidIuj5Ty-5cZM-c8H12kNvyHsk5_ofNGez-3M,2253
|
|
7
|
-
xslope/mesh.py,sha256=OhaAMlunbO86Sx4iF5sRsk4eEN7-AG-_TYPUvYVTGA4,122513
|
|
8
|
-
xslope/plot.py,sha256=rr1D-6KzYyJtq51o4yLyaFkowBa1LtygIk9rtA3GxgQ,54592
|
|
9
|
-
xslope/plot_fem.py,sha256=al9zjqjxWKooLl4SAds77Zz-j9cjD4TJGygyU9QK5vo,71111
|
|
10
|
-
xslope/plot_seep.py,sha256=3wbKp85cmK_6EniFnK9x-FaZtYBZ3KZbRn9U1GsInmk,28775
|
|
11
|
-
xslope/search.py,sha256=dvgKn8JCobuvyD7fClF5lcbeHESCvV8gZ_U_lQnYRok,16867
|
|
12
|
-
xslope/seep.py,sha256=zVX8NJOp8e6VJ6y99YLkmOh_RPQFly9Z9UI3tka6yQQ,85765
|
|
13
|
-
xslope/slice.py,sha256=QHawTk7XPLziHoN_ZS0jrEPYKlhPT62caUc_q-_EGjs,45236
|
|
14
|
-
xslope/solve.py,sha256=j7N66QBjBpDAo-aizTiP8auwd5Ey1SiYAYeySaMVzkw,48554
|
|
15
|
-
xslope-0.1.6.dist-info/LICENSE,sha256=NU5J88FUai_4Ixu5DqOQukA-gcXAyX8pXLhIg8OB3AM,10969
|
|
16
|
-
xslope-0.1.6.dist-info/METADATA,sha256=8eM1VvzchbN-xSlSrTzbRMX86Vy2L3WDUVrdt3_BJq4,2027
|
|
17
|
-
xslope-0.1.6.dist-info/NOTICE,sha256=E-sbN0MWwvJC27Z-2_G4VUHIx4IsfvLDTmOstvY4-OQ,530
|
|
18
|
-
xslope-0.1.6.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
|
|
19
|
-
xslope-0.1.6.dist-info/top_level.txt,sha256=5qHbWJ1R2pdTNIainFyrVtFk8R1tRcwIn0kzTuwuV1Q,7
|
|
20
|
-
xslope-0.1.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|