cfs-python 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.
- app_panel.py +1058 -0
- cfs_lib/__init__.py +0 -0
- cfs_lib/coulomb_math.py +142 -0
- cfs_lib/io_parser.py +165 -0
- cfs_lib/main.py +173 -0
- cfs_lib/okada_math.py +652 -0
- cfs_lib/okada_wrapper.py +148 -0
- cfs_python-0.1.0.dist-info/METADATA +51 -0
- cfs_python-0.1.0.dist-info/RECORD +11 -0
- cfs_python-0.1.0.dist-info/WHEEL +5 -0
- cfs_python-0.1.0.dist-info/top_level.txt +2 -0
cfs_lib/okada_wrapper.py
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from .okada_math import coord_conversion, tensor_trans, okada_dc3d, okada_dc3d0
|
|
3
|
+
|
|
4
|
+
def okada_elastic_halfspace(xgrid, ygrid, element, young, pois, calcdepth, kode):
|
|
5
|
+
"""
|
|
6
|
+
Python equivalent of okada_elastic_halfspace.m
|
|
7
|
+
xgrid, ygrid: 1D numpy arrays of grid coordinates
|
|
8
|
+
element: 2D numpy array of fault elements. Shape (num_faults, M)
|
|
9
|
+
(el: xs, ys, xf, yf, latslip, dipslip, dip, top, bottom)
|
|
10
|
+
young: Young's modulus
|
|
11
|
+
pois: Poisson's ratio
|
|
12
|
+
calcdepth: Calculation depth (km, positive)
|
|
13
|
+
kode: array/list of calculation types (e.g., 100 for rectangular)
|
|
14
|
+
"""
|
|
15
|
+
alpha = 1.0 / (2.0 * (1.0 - pois))
|
|
16
|
+
|
|
17
|
+
if np.isscalar(xgrid) or xgrid.size == 1:
|
|
18
|
+
ncell = 1
|
|
19
|
+
xgrid = np.array([xgrid]).flatten()
|
|
20
|
+
ygrid = np.array([ygrid]).flatten()
|
|
21
|
+
else:
|
|
22
|
+
# Check if xgrid and ygrid are 1D arrays creating a meshgrid,
|
|
23
|
+
# or if they are already parallel arrays (from batch)?
|
|
24
|
+
# Let's assume if they are exactly the same size, they could be a meshgrid OR a 1D parallel list.
|
|
25
|
+
# Wait, if it's a batch file, xgrid, ygrid, calcdepth are parallel 1D lists.
|
|
26
|
+
# But for deformation mesh grids, xv, yv = np.meshgrid(xgrid, ygrid) creates len(x)*len(y).
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
# Better logic: if calcdepth is an array of same size as xgrid, we use parallel 1D computation.
|
|
30
|
+
is_parallel_1d = False
|
|
31
|
+
if isinstance(calcdepth, np.ndarray) and calcdepth.shape == xgrid.shape and xgrid.ndim == 1:
|
|
32
|
+
is_parallel_1d = True
|
|
33
|
+
|
|
34
|
+
if is_parallel_1d:
|
|
35
|
+
ncell = len(xgrid)
|
|
36
|
+
xycoord = np.zeros((ncell, 2), dtype=np.float64)
|
|
37
|
+
xycoord[:, 0] = xgrid
|
|
38
|
+
xycoord[:, 1] = ygrid
|
|
39
|
+
zd = calcdepth * (-1.0)
|
|
40
|
+
else:
|
|
41
|
+
ncell = len(xgrid) * len(ygrid) if not (np.isscalar(xgrid) or xgrid.size == 1) else 1
|
|
42
|
+
xycoord = np.zeros((ncell, 2), dtype=np.float64)
|
|
43
|
+
xv, yv = np.meshgrid(xgrid, ygrid, indexing='ij') if ncell > 1 else (xgrid, ygrid)
|
|
44
|
+
if ncell > 1:
|
|
45
|
+
xycoord[:, 0] = xv.flatten()
|
|
46
|
+
xycoord[:, 1] = yv.flatten()
|
|
47
|
+
else:
|
|
48
|
+
xycoord[:, 0] = xgrid
|
|
49
|
+
xycoord[:, 1] = ygrid
|
|
50
|
+
zd = np.full(ncell, calcdepth * (-1.0), dtype=np.float64)
|
|
51
|
+
|
|
52
|
+
dc3d_out = np.zeros((ncell, 14), dtype=np.float64)
|
|
53
|
+
|
|
54
|
+
for i in range(element.shape[0]):
|
|
55
|
+
depth = (element[i, 7] + element[i, 8]) / 2.0 # depth is positive (top+bottom)/2
|
|
56
|
+
c1, c2, c3, c4 = coord_conversion(
|
|
57
|
+
xycoord[:, 0], xycoord[:, 1],
|
|
58
|
+
element[i, 0], element[i, 1],
|
|
59
|
+
element[i, 2], element[i, 3],
|
|
60
|
+
element[i, 7], element[i, 8],
|
|
61
|
+
element[i, 6]
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
aa = np.full(ncell, alpha, dtype=np.float64)
|
|
65
|
+
zz = zd # already array of length ncell
|
|
66
|
+
dp = np.full(ncell, depth, dtype=np.float64)
|
|
67
|
+
e7 = np.full(ncell, element[i, 6], dtype=np.float64)
|
|
68
|
+
x = c1.astype(np.float64)
|
|
69
|
+
y = c2.astype(np.float64)
|
|
70
|
+
al = c3.astype(np.float64)
|
|
71
|
+
|
|
72
|
+
# Determine kode for this element
|
|
73
|
+
kd = kode[i] if isinstance(kode, (list, np.ndarray)) else kode
|
|
74
|
+
|
|
75
|
+
if kd == 400:
|
|
76
|
+
aw = np.full(ncell, -element[i, 4], dtype=np.float64)
|
|
77
|
+
e5 = np.full(ncell, element[i, 5], dtype=np.float64)
|
|
78
|
+
e6 = np.zeros(ncell, dtype=np.float64)
|
|
79
|
+
zr = np.zeros(ncell, dtype=np.float64)
|
|
80
|
+
|
|
81
|
+
ux, uy, uz, uxx, uyx, uzx, uxy, uyy, uzy, uxz, uyz, uzz, iret = okada_dc3d0(
|
|
82
|
+
aa[0], x, y, zz, dp, e7, aw, e5, e6, zr
|
|
83
|
+
)
|
|
84
|
+
elif kd == 100:
|
|
85
|
+
aw = c4.astype(np.float64)
|
|
86
|
+
e5 = np.full(ncell, -element[i, 4], dtype=np.float64) # left-lat positive in Okada
|
|
87
|
+
e6 = np.full(ncell, element[i, 5], dtype=np.float64)
|
|
88
|
+
zr = np.zeros(ncell, dtype=np.float64)
|
|
89
|
+
|
|
90
|
+
ux, uy, uz, uxx, uyx, uzx, uxy, uyy, uzy, uxz, uyz, uzz, iret = okada_dc3d(
|
|
91
|
+
aa[0], x, y, zz, dp, e7, al, al, aw, aw, e5, e6, zr
|
|
92
|
+
)
|
|
93
|
+
else:
|
|
94
|
+
continue
|
|
95
|
+
|
|
96
|
+
# Displacement Conversion
|
|
97
|
+
sw = np.sqrt((element[i, 3] - element[i, 1])**2 + (element[i, 2] - element[i, 0])**2)
|
|
98
|
+
sina = (element[i, 3] - element[i, 1]) / float(sw)
|
|
99
|
+
cosa = (element[i, 2] - element[i, 0]) / float(sw)
|
|
100
|
+
|
|
101
|
+
uxg = ux * cosa - uy * sina
|
|
102
|
+
uyg = ux * sina + uy * cosa
|
|
103
|
+
uzg = uz
|
|
104
|
+
|
|
105
|
+
# Strain to stress
|
|
106
|
+
sk = young / (1.0 + pois)
|
|
107
|
+
gk = pois / (1.0 - 2.0 * pois)
|
|
108
|
+
vol = uxx + uyy + uzz
|
|
109
|
+
|
|
110
|
+
# Strain dimension is / 1000
|
|
111
|
+
sxx = sk * (gk * vol + uxx) * 0.001
|
|
112
|
+
syy = sk * (gk * vol + uyy) * 0.001
|
|
113
|
+
szz = sk * (gk * vol + uzz) * 0.001
|
|
114
|
+
sxy = (young / (2.0 * (1.0 + pois))) * (uxy + uyx) * 0.001
|
|
115
|
+
sxz = (young / (2.0 * (1.0 + pois))) * (uxz + uzx) * 0.001
|
|
116
|
+
syz = (young / (2.0 * (1.0 + pois))) * (uyz + uzy) * 0.001
|
|
117
|
+
|
|
118
|
+
s0 = np.array([sxx, syy, szz, syz, sxz, sxy]) # shape (6, ncell)
|
|
119
|
+
|
|
120
|
+
# Strain Conversion
|
|
121
|
+
s1 = tensor_trans(sina, cosa, s0)
|
|
122
|
+
|
|
123
|
+
sxx_n = s1[0, :]
|
|
124
|
+
syy_n = s1[1, :]
|
|
125
|
+
szz_n = s1[2, :]
|
|
126
|
+
syz_n = s1[3, :]
|
|
127
|
+
sxz_n = s1[4, :]
|
|
128
|
+
sxy_n = s1[5, :]
|
|
129
|
+
|
|
130
|
+
dc3d0_arr = np.column_stack([
|
|
131
|
+
xycoord[:, 0], xycoord[:, 1], x, y, zz,
|
|
132
|
+
uxg, uyg, uzg, sxx_n, syy_n, szz_n, syz_n, sxz_n, sxy_n
|
|
133
|
+
])
|
|
134
|
+
|
|
135
|
+
if i == 0:
|
|
136
|
+
dc3d0_final = np.column_stack([
|
|
137
|
+
xycoord[:, 0], xycoord[:, 1], x, y, zz,
|
|
138
|
+
uxg, uyg, uzg, sxx_n, syy_n, szz_n, syz_n, sxz_n, sxy_n
|
|
139
|
+
])
|
|
140
|
+
else:
|
|
141
|
+
dc3d0_final = np.column_stack([
|
|
142
|
+
np.zeros(ncell), np.zeros(ncell), np.zeros(ncell), np.zeros(ncell), np.zeros(ncell),
|
|
143
|
+
uxg, uyg, uzg, sxx_n, syy_n, szz_n, syz_n, sxz_n, sxy_n
|
|
144
|
+
])
|
|
145
|
+
|
|
146
|
+
dc3d_out += dc3d0_final
|
|
147
|
+
|
|
148
|
+
return dc3d_out
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cfs-python
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python-based Coulomb Stress Change UI and API
|
|
5
|
+
Home-page: https://github.com/yudhastyawan/cfs-python
|
|
6
|
+
Author: Yudha Styawan
|
|
7
|
+
Author-email: yudhastyawan97@gmail.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
12
|
+
Requires-Python: >=3.8
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: numpy
|
|
15
|
+
Requires-Dist: pandas
|
|
16
|
+
Requires-Dist: panel
|
|
17
|
+
Requires-Dist: plotly
|
|
18
|
+
Requires-Dist: param
|
|
19
|
+
Requires-Dist: geopandas
|
|
20
|
+
Requires-Dist: rasterio
|
|
21
|
+
Requires-Dist: shapely
|
|
22
|
+
Dynamic: author
|
|
23
|
+
Dynamic: author-email
|
|
24
|
+
Dynamic: classifier
|
|
25
|
+
Dynamic: description
|
|
26
|
+
Dynamic: description-content-type
|
|
27
|
+
Dynamic: home-page
|
|
28
|
+
Dynamic: requires-dist
|
|
29
|
+
Dynamic: requires-python
|
|
30
|
+
Dynamic: summary
|
|
31
|
+
|
|
32
|
+
# PyCFS Dashboard
|
|
33
|
+
|
|
34
|
+
An interactive dashboard for visualizing and computing Coulomb Stress Changes.
|
|
35
|
+
Powered by Python (`numpy`), `Panel`, and `Plotly`.
|
|
36
|
+
|
|
37
|
+
## Features
|
|
38
|
+
- Interactive 2D and 3D map views of fault sources and computed stress variables.
|
|
39
|
+
- Dynamically extract Cross-Sectional geometries over user-defined paths.
|
|
40
|
+
- Support for Single Point (Lat/Lon or Km), Grid Box mapping, and Custom Receivers matching algorithms.
|
|
41
|
+
- Custom Scientific Colormaps configurations (`Viridis`, `Jet`, `balance`, etc.) with manual boundary values (`vmin`/`vmax`).
|
|
42
|
+
- High-fidelity exporting: Results available in `.csv` (coordinates included), Georeferenced TIF, and Esri `.shp`.
|
|
43
|
+
|
|
44
|
+
## Interface Snapshot
|
|
45
|
+
This toolkit renders directly in the browser via native WebSockets using the pure Python `Panel` framework.
|
|
46
|
+
|
|
47
|
+
## Usage
|
|
48
|
+
Simply start the dashboard interface locally with:
|
|
49
|
+
```bash
|
|
50
|
+
panel serve app_panel.py --show
|
|
51
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
app_panel.py,sha256=S2Zp4FtIUtJ0yQqIn-VZWviaa-Yxn56UDzVU5UG5iXk,39958
|
|
2
|
+
cfs_lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
cfs_lib/coulomb_math.py,sha256=R8sH1EOs-7R-u3d5mahYba5QsG92rI4MlltbRLyWBDU,3961
|
|
4
|
+
cfs_lib/io_parser.py,sha256=TIhzKnvKj8pG3ztscx_xhh6vevEOV-iCnBt8E8D0i-c,5910
|
|
5
|
+
cfs_lib/main.py,sha256=ZpmG5CIp4-0QCg2zW6df6Jve6jLdVKhyNN6gbO66pmE,7084
|
|
6
|
+
cfs_lib/okada_math.py,sha256=9lhVBLCotw-L9tihPJQ2G1z8KA-ObYRgkSmkitBrLvM,27286
|
|
7
|
+
cfs_lib/okada_wrapper.py,sha256=ujL_2F3jyWCE3lwBvmjf4aPaFxqy_d7753QFNyRYPNw,5931
|
|
8
|
+
cfs_python-0.1.0.dist-info/METADATA,sha256=AXb8zj2zuunn6wxVAJcbT9Hle4tkykonFt_3-qAY4BE,1765
|
|
9
|
+
cfs_python-0.1.0.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
|
|
10
|
+
cfs_python-0.1.0.dist-info/top_level.txt,sha256=hWJkKJsmaKZ_8J8tBskSYHxGpCIoNdrkET9c195c5-o,18
|
|
11
|
+
cfs_python-0.1.0.dist-info/RECORD,,
|