xslope 0.1.11__py3-none-any.whl → 0.1.12__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/plot_fem.py CHANGED
@@ -22,7 +22,7 @@ from matplotlib.colors import LinearSegmentedColormap
22
22
  from matplotlib.patches import Polygon
23
23
 
24
24
 
25
- def plot_fem_data(fem_data, figsize=(14, 6), show_nodes=False, show_bc=True, material_table=False,
25
+ def plot_fem_data(fem_data, figsize=(14, 6), show_nodes=False, show_bc=True,
26
26
  label_elements=False, label_nodes=False, alpha=0.4, bc_symbol_size=0.03, save_png=False, dpi=300):
27
27
  """
28
28
  Plots a FEM mesh colored by material zone with boundary conditions displayed.
@@ -32,7 +32,6 @@ def plot_fem_data(fem_data, figsize=(14, 6), show_nodes=False, show_bc=True, mat
32
32
  figsize: Figure size
33
33
  show_nodes: If True, plot node points
34
34
  show_bc: If True, plot boundary condition symbols
35
- material_table: If True, show material table
36
35
  label_elements: If True, label each element with its number at its centroid
37
36
  label_nodes: If True, label each node with its number just above and to the right
38
37
  alpha: Transparency for element faces
@@ -245,10 +244,6 @@ def plot_fem_data(fem_data, figsize=(14, 6), show_nodes=False, show_bc=True, mat
245
244
  else:
246
245
  title = f"FEM Mesh with Material Zones ({num_triangles} triangles)"
247
246
 
248
- # Place the table in the upper left
249
- if material_table:
250
- _plot_fem_material_table(ax, fem_data, xloc=0.3, yloc=1.1) # upper left
251
-
252
247
  ax.set_title(title)
253
248
  plt.tight_layout()
254
249
 
@@ -366,69 +361,6 @@ def _plot_boundary_conditions(ax, nodes, bc_type, bc_values, legend_handles, bc_
366
361
  markersize=8, label='Applied Force (bc_type=4)')
367
362
  )
368
363
 
369
-
370
- def _plot_fem_material_table(ax, fem_data, xloc=0.6, yloc=0.7):
371
- """
372
- Adds a FEM material properties table to the plot.
373
-
374
- Parameters:
375
- ax: matplotlib Axes object
376
- fem_data: Dictionary containing FEM data with material properties
377
- xloc: x-location of table (0-1)
378
- yloc: y-location of table (0-1)
379
-
380
- Returns:
381
- None
382
- """
383
- # Extract material properties from fem_data
384
- c_by_mat = fem_data.get("c_by_mat")
385
- phi_by_mat = fem_data.get("phi_by_mat")
386
- E_by_mat = fem_data.get("E_by_mat")
387
- nu_by_mat = fem_data.get("nu_by_mat")
388
- gamma_by_mat = fem_data.get("gamma_by_mat")
389
- material_names = fem_data.get("material_names", [])
390
-
391
- if c_by_mat is None or len(c_by_mat) == 0:
392
- return
393
-
394
- # Column headers for FEM properties
395
- col_labels = ["Mat", "Name", "γ", "c", "φ", "E", "ν"]
396
-
397
- # Build table rows
398
- table_data = []
399
- for idx in range(len(c_by_mat)):
400
- c = c_by_mat[idx]
401
- phi = phi_by_mat[idx] if phi_by_mat is not None else 0.0
402
- E = E_by_mat[idx] if E_by_mat is not None else 0.0
403
- nu = nu_by_mat[idx] if nu_by_mat is not None else 0.0
404
- gamma = gamma_by_mat[idx] if gamma_by_mat is not None else 0.0
405
-
406
- # Get material name, use default if not available
407
- material_name = material_names[idx] if idx < len(material_names) else f"Material {idx+1}"
408
-
409
- # Format values with appropriate precision
410
- row = [
411
- idx + 1, # Material number (1-based)
412
- material_name, # Material name
413
- f"{gamma:.1f}", # unit weight
414
- f"{c:.1f}", # cohesion
415
- f"{phi:.1f}", # friction angle
416
- f"{E:.0f}", # Young's modulus
417
- f"{nu:.2f}" # Poisson's ratio
418
- ]
419
- table_data.append(row)
420
-
421
- # Add the table
422
- table = ax.table(cellText=table_data,
423
- colLabels=col_labels,
424
- loc='upper right',
425
- colLoc='center',
426
- cellLoc='center',
427
- bbox=[xloc, yloc, 0.45, 0.25]) # Increased width to accommodate name column
428
- table.auto_set_font_size(False)
429
- table.set_fontsize(8)
430
-
431
-
432
364
  def plot_fem_results(fem_data, solution, plot_type='displacement', deform_scale=None,
433
365
  show_mesh=True, show_reinforcement=True, figsize=(12, 8), label_elements=False,
434
366
  plot_nodes=False, plot_elements=False, plot_boundary=True, displacement_tolerance=0.5,
xslope/plot_seep.py CHANGED
@@ -4,7 +4,7 @@ from matplotlib.ticker import MaxNLocator
4
4
  import numpy as np
5
5
 
6
6
 
7
- def plot_seep_data(seep_data, figsize=(14, 6), show_nodes=False, show_bc=False, material_table=False, label_elements=False, label_nodes=False, alpha=0.4, save_png=False, dpi=300):
7
+ def plot_seep_data(seep_data, figsize=(14, 6), show_nodes=False, show_bc=False, label_elements=False, label_nodes=False, alpha=0.4, save_png=False, dpi=300):
8
8
  """
9
9
  Plots a mesh colored by material zone.
10
10
  Supports both triangular and quadrilateral elements.
@@ -13,7 +13,6 @@ def plot_seep_data(seep_data, figsize=(14, 6), show_nodes=False, show_bc=False,
13
13
  seep_data: Dictionary containing seepage data from import_seep2d
14
14
  show_nodes: If True, plot node points
15
15
  show_bc: If True, plot boundary condition nodes
16
- material_table: If True, show material table
17
16
  label_elements: If True, label each element with its number at its centroid
18
17
  label_nodes: If True, label each node with its number just above and to the right
19
18
  """
@@ -181,10 +180,10 @@ def plot_seep_data(seep_data, figsize=(14, 6), show_nodes=False, show_bc=False,
181
180
  bc1 = nodes[bc_type == 1]
182
181
  bc2 = nodes[bc_type == 2]
183
182
  if len(bc1) > 0:
184
- h1, = ax.plot(bc1[:, 0], bc1[:, 1], 'ro', label="Fixed Head (bc_type=1)")
183
+ h1, = ax.plot(bc1[:, 0], bc1[:, 1], 'bs', label="Fixed Head (bc_type=1)")
185
184
  legend_handles.append(h1)
186
185
  if len(bc2) > 0:
187
- h2, = ax.plot(bc2[:, 0], bc2[:, 1], 'bs', label="Exit Face (bc_type=2)")
186
+ h2, = ax.plot(bc2[:, 0], bc2[:, 1], 'ro', label="Exit Face (bc_type=2)")
188
187
  legend_handles.append(h2)
189
188
 
190
189
  # Single combined legend outside the plot
@@ -196,6 +195,12 @@ def plot_seep_data(seep_data, figsize=(14, 6), show_nodes=False, show_bc=False,
196
195
  frameon=False
197
196
  )
198
197
  ax.set_aspect("equal")
198
+
199
+ # Add a bit of headroom so the mesh/BC markers don't touch the top border
200
+ y0, y1 = ax.get_ylim()
201
+ if y1 > y0:
202
+ pad = 0.05 * (y1 - y0)
203
+ ax.set_ylim(y0, y1 + pad)
199
204
 
200
205
  # Count element types for title
201
206
  num_triangles = np.sum(element_types == 3)
@@ -207,10 +212,6 @@ def plot_seep_data(seep_data, figsize=(14, 6), show_nodes=False, show_bc=False,
207
212
  else:
208
213
  title = f"SEEP2D Mesh with Material Zones ({num_triangles} triangles)"
209
214
 
210
- # Place the table in the upper left
211
- if material_table:
212
- plot_seep_material_table(ax, seep_data, xloc=0.3, yloc=1.1) # upper left
213
-
214
215
  ax.set_title(title)
215
216
  # plt.subplots_adjust(bottom=0.2) # Add vertical cushion
216
217
  plt.tight_layout()
@@ -592,66 +593,7 @@ def plot_seep_solution(seep_data, solution, figsize=(14, 6), levels=20, base_mat
592
593
  plt.show()
593
594
 
594
595
 
595
- def plot_seep_material_table(ax, seep_data, xloc=0.6, yloc=0.7):
596
- """
597
- Adds a seepage material properties table to the plot.
598
-
599
- Parameters:
600
- ax: matplotlib Axes object
601
- seep_data: Dictionary containing seepage data with material properties
602
- xloc: x-location of table (0-1)
603
- yloc: y-location of table (0-1)
604
-
605
- Returns:
606
- None
607
- """
608
- # Extract material properties from seep_data
609
- k1_by_mat = seep_data.get("k1_by_mat")
610
- k2_by_mat = seep_data.get("k2_by_mat")
611
- angle_by_mat = seep_data.get("angle_by_mat")
612
- kr0_by_mat = seep_data.get("kr0_by_mat")
613
- h0_by_mat = seep_data.get("h0_by_mat")
614
- material_names = seep_data.get("material_names", [])
615
-
616
- if k1_by_mat is None or len(k1_by_mat) == 0:
617
- return
618
-
619
- # Column headers for seepage properties
620
- col_labels = ["Mat", "Name", "k₁", "k₂", "Angle", "kr₀", "h₀"]
621
-
622
- # Build table rows
623
- table_data = []
624
- for idx in range(len(k1_by_mat)):
625
- k1 = k1_by_mat[idx]
626
- k2 = k2_by_mat[idx] if k2_by_mat is not None else 0.0
627
- angle = angle_by_mat[idx] if angle_by_mat is not None else 0.0
628
- kr0 = kr0_by_mat[idx] if kr0_by_mat is not None else 0.0
629
- h0 = h0_by_mat[idx] if h0_by_mat is not None else 0.0
630
-
631
- # Get material name, use default if not available
632
- material_name = material_names[idx] if idx < len(material_names) else f"Material {idx+1}"
633
-
634
- # Format values with appropriate precision
635
- row = [
636
- idx + 1, # Material number (1-based)
637
- material_name, # Material name
638
- f"{k1:.3f}", # k1 in scientific notation
639
- f"{k2:.3f}", # k2 in scientific notation
640
- f"{angle:.1f}", # angle in degrees
641
- f"{kr0:.4f}", # kr0
642
- f"{h0:.2f}" # h0
643
- ]
644
- table_data.append(row)
645
-
646
- # Add the table
647
- table = ax.table(cellText=table_data,
648
- colLabels=col_labels,
649
- loc='upper right',
650
- colLoc='center',
651
- cellLoc='center',
652
- bbox=[xloc, yloc, 0.45, 0.25]) # Increased width to accommodate name column
653
- table.auto_set_font_size(False)
654
- table.set_fontsize(8)
596
+ # plot_seep_material_table has been moved to xslope/plot.py
655
597
 
656
598
 
657
599
  def get_ordered_mesh_boundary(nodes, elements, element_types=None):
xslope/seep.py CHANGED
@@ -404,7 +404,7 @@ def solve_confined(nodes, elements, bc_type, dirichlet_bcs, k1_vals, k2_vals, an
404
404
 
405
405
  def solve_unsaturated(nodes, elements, bc_type, bc_values, kr0=0.001, h0=-1.0,
406
406
  k1_vals=1.0, k2_vals=1.0, angles=0.0,
407
- max_iter=200, tol=1e-4, element_types=None):
407
+ max_iter=200, tol=1e-6, element_types=None):
408
408
  """
409
409
  Iterative FEM solver for unconfined flow using linear kr frontal function.
410
410
  Supports triangular and quadrilateral elements with both linear and quadratic shape functions.
@@ -716,7 +716,7 @@ def solve_unsaturated(nodes, elements, bc_type, bc_values, kr0=0.001, h0=-1.0,
716
716
  print(" - Non-conservative flow field")
717
717
  print(" - Incorrect boundary identification")
718
718
  print(" - Numerical issues in the flow solution")
719
-
719
+ print(f"Try reducing the tolerance (tol) parameter. Current value: {tol:.6e}")
720
720
 
721
721
  return h, A, q_final, total_inflow
722
722
 
@@ -969,10 +969,14 @@ def create_flow_potential_bc(nodes, elements, q, debug=False, element_types=None
969
969
  starting_phi = phi[ordered_nodes[start_idx]]
970
970
  closure_error = phi_val - starting_phi
971
971
 
972
- if debug or abs(closure_error) > 1e-3:
972
+ # Use a relative threshold based on total positive boundary flow
973
+ rel_tol = 1e-2 # 1%
974
+ scale = max(total_q, 1e-12)
975
+
976
+ if debug or abs(closure_error) > rel_tol * scale:
973
977
  print(f"Flow potential closure check: error = {closure_error:.6e}")
974
978
 
975
- if abs(closure_error) > 1e-3:
979
+ if abs(closure_error) > rel_tol * scale:
976
980
  print(f"Warning: Large flow potential closure error = {closure_error:.6e}")
977
981
  print("This may indicate:")
978
982
  print(" - Non-conservative flow field")
@@ -1983,7 +1987,7 @@ def quad4_stiffness_matrix(nodes_elem, Kmat):
1983
1987
 
1984
1988
  return ke
1985
1989
 
1986
- def run_seepage_analysis(seep_data):
1990
+ def run_seepage_analysis(seep_data, tol=1e-6):
1987
1991
  """
1988
1992
  Standalone function to run seepage analysis.
1989
1993
 
@@ -2048,7 +2052,8 @@ def run_seepage_analysis(seep_data):
2048
2052
  k1_vals=k1,
2049
2053
  k2_vals=k2,
2050
2054
  angles=angle,
2051
- element_types=element_types
2055
+ element_types=element_types,
2056
+ tol=tol
2052
2057
  )
2053
2058
  # Solve for potential function φ for flow lines
2054
2059
  dirichlet_phi_bcs = create_flow_potential_bc(nodes, elements, q, element_types=element_types)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: xslope
3
- Version: 0.1.11
3
+ Version: 0.1.12
4
4
  Summary: Slope stability analysis (limit equilibrium and FEM) in Python.
5
5
  Author: Norman L. Jones
6
6
  Project-URL: Homepage, https://github.com/njones61/xslope
@@ -0,0 +1,21 @@
1
+ xslope/__init__.py,sha256=ZygAIkX6Nbjag1czWdQa-yP-GM1mBE_9ss21Xh__JFc,34
2
+ xslope/_version.py,sha256=q5MF9vedBklo3vj52_gwvihlwfAGwilLmjxYlgKI-zM,51
3
+ xslope/advanced.py,sha256=35k_ekQJ-mQJ1wHnoIHMc5TVfYn-2EPCJyHz827Cpbc,18281
4
+ xslope/fem.py,sha256=K4_Pq06HFBpRkN3JwtXF2zw_AMnCkXvj0ggrlRFMQQw,115731
5
+ xslope/fileio.py,sha256=nxpD5dnkWjSVnby9jsQgHrxikfAsL3KOUehiw8sMb-Q,31783
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=dY_G7ctgOroUSv2oUuM-ZQOnKAEJ1dIq6FTU_JLWEqs,136816
9
+ xslope/plot.py,sha256=SuwC6quvkdQ66sVzSam3USRoEUC99s-iS1_0j-V7k8A,81401
10
+ xslope/plot_fem.py,sha256=z2FLPbIx6yNIKYcgC-LcZz2jfx0WLYFL3xJgNvQ1t-c,69488
11
+ xslope/plot_seep.py,sha256=wEmK3FCYjkqtnNqy1nhFLe72GBVrdhcR0CkgxlLaAjc,32948
12
+ xslope/search.py,sha256=dvgKn8JCobuvyD7fClF5lcbeHESCvV8gZ_U_lQnYRok,16867
13
+ xslope/seep.py,sha256=Xc3C3HcAOXBdsVStJTPo2AxY4QjQKjMcfTuJGYCazMY,93300
14
+ xslope/slice.py,sha256=QHawTk7XPLziHoN_ZS0jrEPYKlhPT62caUc_q-_EGjs,45236
15
+ xslope/solve.py,sha256=u_sBjtsj1EeZtgSEmo80tEWoRrrMgvRjmi6P0ODO1lU,48645
16
+ xslope-0.1.12.dist-info/LICENSE,sha256=NU5J88FUai_4Ixu5DqOQukA-gcXAyX8pXLhIg8OB3AM,10969
17
+ xslope-0.1.12.dist-info/METADATA,sha256=BPz97uzKVuFiS9_RqS5r6iYd4O0W4IacO-CyZEsUaHY,2028
18
+ xslope-0.1.12.dist-info/NOTICE,sha256=E-sbN0MWwvJC27Z-2_G4VUHIx4IsfvLDTmOstvY4-OQ,530
19
+ xslope-0.1.12.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
20
+ xslope-0.1.12.dist-info/top_level.txt,sha256=5qHbWJ1R2pdTNIainFyrVtFk8R1tRcwIn0kzTuwuV1Q,7
21
+ xslope-0.1.12.dist-info/RECORD,,
@@ -1,21 +0,0 @@
1
- xslope/__init__.py,sha256=ZygAIkX6Nbjag1czWdQa-yP-GM1mBE_9ss21Xh__JFc,34
2
- xslope/_version.py,sha256=EuS8ourwvf_O1n08GOG1eXlKDKt7dguYQ663MaapOxQ,51
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=MexmrZJ1CVSnG0ZN3lNz67DyQdDTdO6hLlbTTBYz4Zw,56016
10
- xslope/plot_fem.py,sha256=WiFFt9cUIRwX1uCiJrPaMtmhz5LfhZnzNVJwhp0fMP8,71902
11
- xslope/plot_seep.py,sha256=ep9spY2DiMvOJELccBAj77p9HTnBRgoyqQ_brQphWHw,35166
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=u_sBjtsj1EeZtgSEmo80tEWoRrrMgvRjmi6P0ODO1lU,48645
16
- xslope-0.1.11.dist-info/LICENSE,sha256=NU5J88FUai_4Ixu5DqOQukA-gcXAyX8pXLhIg8OB3AM,10969
17
- xslope-0.1.11.dist-info/METADATA,sha256=ZbDxeZ2g25EwvsZDdbQIhwRB5eOu-LSpeFYmcFn0nUk,2028
18
- xslope-0.1.11.dist-info/NOTICE,sha256=E-sbN0MWwvJC27Z-2_G4VUHIx4IsfvLDTmOstvY4-OQ,530
19
- xslope-0.1.11.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
20
- xslope-0.1.11.dist-info/top_level.txt,sha256=5qHbWJ1R2pdTNIainFyrVtFk8R1tRcwIn0kzTuwuV1Q,7
21
- xslope-0.1.11.dist-info/RECORD,,