paddle 1.1.4__py3-none-any.whl → 1.1.5__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.
paddle/__init__.py CHANGED
@@ -4,4 +4,4 @@ from .find_init_params import find_init_params
4
4
  from .evolve_kinetics import evolve_kinetics
5
5
 
6
6
  __all__ = ["setup_profile", "write_profile", "find_init_params", "evolve_kinetics"]
7
- __version__ = "1.1.4"
7
+ __version__ = "1.1.5"
paddle/nc2pt.py ADDED
@@ -0,0 +1,39 @@
1
+ #! /usr/bin/env python3
2
+
3
+ """
4
+ Read variables in a NetCDF file and write them to jit saved torch tensors.
5
+ Usage: python nc2pt.py input.nc output.pt
6
+ """
7
+
8
+ from netCDF4 import Dataset
9
+ import torch
10
+
11
+
12
+ def save_tensors(tensor_map: dict[str, torch.Tensor], filename: str):
13
+ class TensorModule(torch.nn.Module):
14
+ def __init__(self, tensors):
15
+ super().__init__()
16
+ for name, tensor in tensors.items():
17
+ self.register_buffer(name, tensor)
18
+
19
+ module = TensorModule(tensor_map)
20
+ scripted = torch.jit.script(module) # Needed for LibTorch compatibility
21
+ scripted.save(filename)
22
+
23
+
24
+ fname = "sod.out0.00019.nc"
25
+
26
+ nc = Dataset(fname, "r")
27
+ out_fname = "sod.out0.00019.pt"
28
+
29
+ data = {}
30
+ for varname in nc.variables:
31
+ var = nc.variables[varname][:]
32
+ if var.ndim == 4: # (time, x1, x2, x3) -> (time, x3, x2, x1)
33
+ data[varname] = torch.tensor(var).permute(0, 3, 2, 1).squeeze()
34
+ elif var.ndim == 3: # (x1, x2, x3) -> (x3, x2, x1)
35
+ data[varname] = torch.tensor(var).permute(2, 1, 0).squeeze()
36
+ else:
37
+ data[varname] = torch.tensor(var).squeeze()
38
+
39
+ save_tensors(data, out_fname)
paddle/pt2nc.py ADDED
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Convert a sequence of PyTorch .pt dumps into a CF‐compliant NetCDF4 file
4
+ with dimensions (time, x, y, z) plus a 'species' axis for mole fractions.
5
+ """
6
+
7
+ import os
8
+ import tarfile
9
+ import re
10
+ import torch
11
+ import numpy as np
12
+ from datetime import datetime
13
+ from netCDF4 import Dataset
14
+
15
+ # ──────────────────────────────── CONFIG ────────────────────────────────
16
+ INPUT_DIR = "."
17
+ OUTPUT_FILE = "thermo_x_xfrac_to_conc.nc"
18
+ # ────────────────────────────────────────────────────────────────────────
19
+
20
+ # find all .pt files, skip size==0, sort by timestamp
21
+ pt_files = []
22
+ for fn in os.listdir(INPUT_DIR):
23
+ if not fn.endswith(".pt"):
24
+ continue
25
+ full = os.path.join(INPUT_DIR, fn)
26
+ if os.path.getsize(full) == 0:
27
+ continue
28
+ # expect names like thermo_x_xfrac_to_conc_<epoch>.pt
29
+ m = re.search(r"(\d+)\.pt$", fn)
30
+ if not m:
31
+ continue
32
+ pt_files.append((int(m.group(1)), full))
33
+
34
+ pt_files.sort(key=lambda x: x[0])
35
+ times_epoch = [ts for ts, _ in pt_files]
36
+
37
+ # load the first file to infer shapes
38
+ module = torch.jit.load(pt_files[0][1])
39
+ data = {name: param for name, param in module.named_parameters()}
40
+
41
+ temp0 = data["temp"].numpy()
42
+ pres0 = data["pres"].numpy()
43
+ xfrac0 = data["xfrac"].numpy()
44
+ nx3, nx2, nx1 = temp0.shape
45
+ nspecies = xfrac0.shape[3]
46
+ nt = len(pt_files)
47
+
48
+ # pre‐allocate arrays in (time, x1, x2, x3) order
49
+ temp_arr = np.empty((nt, nx1, nx2, nx3), dtype=temp0.dtype)
50
+ pres_arr = np.empty((nt, nx1, nx2, nx3), dtype=pres0.dtype)
51
+ xfrac_arr = np.empty((nspecies, nt, nx1, nx2, nx3), dtype=xfrac0.dtype)
52
+
53
+ # load all timesteps
54
+ for i, (_, path) in enumerate(pt_files):
55
+ module = torch.jit.load(path)
56
+ data = {name: param for name, param in module.named_parameters()}
57
+ t_np = data["temp"].numpy() # (z, y, x)
58
+ p_np = data["pres"].numpy() # (z, y, x)
59
+ x_np = data["xfrac"].numpy() # (species, z, y, x)
60
+
61
+ # reorder to (x, y, z)
62
+ temp_arr[i] = t_np.transpose(2, 1, 0)
63
+ pres_arr[i] = p_np.transpose(2, 1, 0)
64
+ for j in range(nspecies):
65
+ xfrac_arr[j, i] = x_np[:, :, :, j].transpose(2, 1, 0)
66
+
67
+ # create NetCDF4 file
68
+ ds = Dataset(OUTPUT_FILE, "w", format="NETCDF4")
69
+
70
+ # dimensions
71
+ ds.createDimension("time", nt)
72
+ ds.createDimension("x3", nx3)
73
+ ds.createDimension("x2", nx2)
74
+ ds.createDimension("x1", nx1)
75
+
76
+ # coordinate variables
77
+ tvar = ds.createVariable("time", "f4", ("time",))
78
+ tvar.units = "seconds since 1970-01-01 00:00:00 UTC"
79
+ tvar.calendar = "gregorian"
80
+ tvar[:] = np.array(times_epoch, dtype="f4")
81
+
82
+ zvar = ds.createVariable("x1", "f4", ("x1",))
83
+ yvar = ds.createVariable("x2", "f4", ("x2",))
84
+ xvar = ds.createVariable("x3", "f4", ("x3",))
85
+
86
+ xvar.axis = "X"
87
+ yvar.axis = "Y"
88
+ zvar.axis = "Z"
89
+
90
+ xvar[:] = np.arange(nx3)
91
+ yvar[:] = np.arange(nx2)
92
+ zvar[:] = np.arange(nx1)
93
+
94
+ # data variables
95
+ temp_v = ds.createVariable("temp", "f4", ("time", "x1", "x2", "x3"), zlib=True)
96
+ temp_v.units = "K"
97
+ temp_v.long_name = "temperature"
98
+
99
+ pres_v = ds.createVariable("pres", "f4", ("time", "x1", "x2", "x3"), zlib=True)
100
+ pres_v.units = "Pa"
101
+ pres_v.long_name = "pressure"
102
+
103
+ xfrac_v = []
104
+ for i in range(nspecies):
105
+ xfrac_v.append(
106
+ ds.createVariable(f"xfrac{i}", "f4", ("time", "x1", "x2", "x3"), zlib=True)
107
+ )
108
+ xfrac_v[i].units = "1"
109
+ xfrac_v[i].long_name = "mole fraction of each species"
110
+
111
+ # write the data
112
+ temp_v[:] = temp_arr
113
+ pres_v[:] = pres_arr
114
+ for i in range(nspecies):
115
+ xfrac_v[i][:] = xfrac_arr[i]
116
+
117
+ # global metadata
118
+ ds.title = "Debug fields for thermo_x.xfrac_to_conc"
119
+ ds.institution = "University of Michigan"
120
+ ds.source = "converted from .pt files"
121
+ ds.history = f"Created {datetime.utcnow().isoformat()}Z"
122
+
123
+ ds.close()
124
+ print(f"Converted file: {OUTPUT_FILE}")
paddle/setup_profile.py CHANGED
@@ -140,7 +140,10 @@ def integrate_dry_adiabat(
140
140
 
141
141
 
142
142
  def setup_profile(
143
- block: snapy.MeshBlock, param: dict[str, float] = {}, method: str = "moist-adiabat"
143
+ block: snapy.MeshBlock,
144
+ param: dict[str, float] = {},
145
+ method: str = "moist-adiabat",
146
+ verbose: bool = False,
144
147
  ) -> torch.Tensor:
145
148
  """
146
149
  Set up an adiabatic initial condition for the mesh block.
@@ -227,7 +230,7 @@ def setup_profile(
227
230
  dz = coord.buffer("dx1f")[ifirst]
228
231
 
229
232
  # half a grid to cell center
230
- thermo_x.extrapolate_ad(temp, pres, xfrac, grav, dz / 2.0)
233
+ thermo_x.extrapolate_ad(temp, pres, xfrac, grav, dz / 2.0, verbose=verbose)
231
234
 
232
235
  # adiabatic extrapolation
233
236
  if method == "isothermal":
@@ -257,7 +260,7 @@ def setup_profile(
257
260
  elif method.split("-")[0] == "neutral":
258
261
  temp, pres, xfrac = integrate_neutral(thermo_x, temp, pres, xfrac, grav, dz)
259
262
  else:
260
- thermo_x.extrapolate_ad(temp, pres, xfrac, grav, dz)
263
+ thermo_x.extrapolate_ad(temp, pres, xfrac, grav, dz, verbose=verbose)
261
264
 
262
265
  if torch.any(temp < Tmin):
263
266
  i_isothermal = i + 1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: paddle
3
- Version: 1.1.4
3
+ Version: 1.1.5
4
4
  Summary: Python Atmospheric Dynamics: Discovery and Learning about Exoplanets. An open-source, user-friendly python frontend of canoe
5
5
  Project-URL: Homepage, https://github.com/elijah-mullens/paddle
6
6
  Project-URL: Repository, https://github.com/elijah-mullens/paddle
@@ -22,8 +22,8 @@ Classifier: Topic :: Scientific/Engineering :: Astronomy
22
22
  Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
23
23
  Classifier: Topic :: Scientific/Engineering :: Physics
24
24
  Requires-Python: >=3.9
25
- Requires-Dist: kintera>=1.0.1
26
- Requires-Dist: snapy>=0.7.0
25
+ Requires-Dist: kintera>=1.1.5
26
+ Requires-Dist: snapy>=0.8.2
27
27
  Requires-Dist: torch<=2.7.1,>=2.7.0
28
28
  Provides-Extra: dev
29
29
  Requires-Dist: pytest>=7; extra == 'dev'
@@ -31,3 +31,52 @@ Description-Content-Type: text/markdown
31
31
 
32
32
  # paddle
33
33
  Python Atmospheric Dynamics: Discovering and Learning about Exoplanets. An open-source, user-friendly python version of canoe.
34
+
35
+ ## Install docker and docker-compose plugin
36
+
37
+
38
+ ## Create a python virtual environment
39
+ ```bash
40
+ python -m venv pyenv
41
+ ```
42
+
43
+ # Create a docker container
44
+ ```bash
45
+ make up
46
+ ```
47
+
48
+ # Terminate a docker container
49
+ ```bash
50
+ make down
51
+ ```
52
+
53
+ # Start a docker container
54
+ ```bash
55
+ make start
56
+ ```
57
+
58
+ # Build a new docker image (rarely used)
59
+ ```bash
60
+ make build
61
+ ```
62
+
63
+ ## For Development
64
+ ### Cache your github credential
65
+ ```bash
66
+ git config credential.helper 'cache --timeout=86400'
67
+ ```
68
+
69
+ ### Install paddle package
70
+ ```bash
71
+ pip install paddle
72
+ ```
73
+
74
+ ### Install pre-commit hook
75
+ ```bash
76
+ pip install pre-commit
77
+ ```
78
+
79
+ ### Install pre-commit hook
80
+ ```bash
81
+ pre-commit install
82
+ ```
@@ -0,0 +1,13 @@
1
+ paddle/__init__.py,sha256=McGNGlI-ofIhDsJdizgFYpkgJJwWMwg0oidCOPuXbgA,281
2
+ paddle/crm.py,sha256=HwOLAojR5LBcptqjAC9APEJiWpn8GhxPiAmvvIZ4mTM,1986
3
+ paddle/evolve_kinetics.py,sha256=OWt1-SiLTzaWUCIchwRnBHCjbtcgJIIxrlQ5Lk4iN8c,1541
4
+ paddle/find_init_params.py,sha256=dyRmo-LTwVohbPhSH5LV45jL_XeRmNEcuKPvafBklto,2516
5
+ paddle/nc2pt.py,sha256=LXR0fnUTaOA_uaDsLU4YqdAVFyycB6SvRq12xWhHhLA,1136
6
+ paddle/pt2nc.py,sha256=lLviBm6a2O05RvuPQc8DxV5pGr_VEhlSkrKPV1lQ3yU,3913
7
+ paddle/setup_profile.py,sha256=oJpqPnlq2q1rn_l2flwgbdWwbxbhxx4QOYl4ezWmP-o,8803
8
+ paddle/write_profile.py,sha256=HeBtGaFixGv8DnmJWPiQs-30RsdplSObhMA6ky6eVrg,3908
9
+ paddle-1.1.5.dist-info/METADATA,sha256=e9bgxHKLY-fo1nTgZu2kYrK8toKqXHB4kAmm-Go48II,2197
10
+ paddle-1.1.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
11
+ paddle-1.1.5.dist-info/entry_points.txt,sha256=pDR96GW6ylBZrbFd-tRGthW8qTuYaSLjrEt1LFIEYto,48
12
+ paddle-1.1.5.dist-info/licenses/LICENSE,sha256=e6NthgKABUnLRqjuETcBGgsOuA-aJANpNoeXMe9RBso,1071
13
+ paddle-1.1.5.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- paddle/__init__.py,sha256=_UwSoQUWYoYGzcqdp5ES7q-Z1Dh-7nqkSOOFAl83BIA,281
2
- paddle/crm.py,sha256=HwOLAojR5LBcptqjAC9APEJiWpn8GhxPiAmvvIZ4mTM,1986
3
- paddle/evolve_kinetics.py,sha256=OWt1-SiLTzaWUCIchwRnBHCjbtcgJIIxrlQ5Lk4iN8c,1541
4
- paddle/find_init_params.py,sha256=dyRmo-LTwVohbPhSH5LV45jL_XeRmNEcuKPvafBklto,2516
5
- paddle/setup_profile.py,sha256=MHxRvFyva8CR5_71QSfrLy9ml2rQnW6yy21ZXaVcTGU,8733
6
- paddle/write_profile.py,sha256=HeBtGaFixGv8DnmJWPiQs-30RsdplSObhMA6ky6eVrg,3908
7
- paddle-1.1.4.dist-info/METADATA,sha256=MPjPtUaGGE4X9a6crnB1ktptBQvsD5n28Nz_mjEJfQY,1558
8
- paddle-1.1.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
- paddle-1.1.4.dist-info/entry_points.txt,sha256=pDR96GW6ylBZrbFd-tRGthW8qTuYaSLjrEt1LFIEYto,48
10
- paddle-1.1.4.dist-info/licenses/LICENSE,sha256=e6NthgKABUnLRqjuETcBGgsOuA-aJANpNoeXMe9RBso,1071
11
- paddle-1.1.4.dist-info/RECORD,,
File without changes