raystrack 1.0.1__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.
- raystrack/__init__.py +30 -0
- raystrack/api.py +198 -0
- raystrack/io.py +238 -0
- raystrack/main.py +2194 -0
- raystrack/params.py +129 -0
- raystrack/utils/__init__.py +23 -0
- raystrack/utils/bvh.py +74 -0
- raystrack/utils/cpu_trace.py +811 -0
- raystrack/utils/cuda_trace.py +1285 -0
- raystrack/utils/geometry.py +66 -0
- raystrack/utils/halton.py +61 -0
- raystrack/utils/helpers.py +284 -0
- raystrack/utils/prepared.py +442 -0
- raystrack/utils/ray_builder.py +97 -0
- raystrack-1.0.1.dist-info/METADATA +125 -0
- raystrack-1.0.1.dist-info/RECORD +19 -0
- raystrack-1.0.1.dist-info/WHEEL +5 -0
- raystrack-1.0.1.dist-info/licenses/LICENSE +674 -0
- raystrack-1.0.1.dist-info/top_level.txt +1 -0
raystrack/params.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import asdict, dataclass
|
|
4
|
+
from typing import Any, Dict
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class MatrixParams:
|
|
9
|
+
"""Configuration for scene-to-scene view-factor solves.
|
|
10
|
+
|
|
11
|
+
Parameters
|
|
12
|
+
----------
|
|
13
|
+
samples : int
|
|
14
|
+
Quasi-Monte Carlo grid per side used for emission per emitter.
|
|
15
|
+
rays : int
|
|
16
|
+
Rays per grid cell.
|
|
17
|
+
seed : int
|
|
18
|
+
Base RNG seed. Each emitter/iteration derives its own sub-seed.
|
|
19
|
+
bvh : {"auto","off","builtin"}
|
|
20
|
+
Toggle a built-in BVH for faster visibility.
|
|
21
|
+
device : {"auto","gpu","cpu"}
|
|
22
|
+
Visibility device. GPU uses CUDA hitmask kernels. CPU uses numba njit.
|
|
23
|
+
cuda_async : bool
|
|
24
|
+
Use pinned memory + streams for overlap on CUDA.
|
|
25
|
+
gpu_raygen : bool
|
|
26
|
+
Generate rays on GPU to avoid H2D copies of rays.
|
|
27
|
+
max_iters : int
|
|
28
|
+
Maximum number of Monte-Carlo iterations.
|
|
29
|
+
tol : float
|
|
30
|
+
Convergence tolerance. Interpretation depends on ``tol_mode``.
|
|
31
|
+
tol_mode : {"delta", "stderr"}
|
|
32
|
+
- "delta": stop when successive cumulative estimates change by < tol.
|
|
33
|
+
- "stderr": stop when per-iteration replicate standard error is <= tol.
|
|
34
|
+
min_iters : int
|
|
35
|
+
Minimum number of Monte-Carlo iterations before a convergence check.
|
|
36
|
+
convergence_interval : int
|
|
37
|
+
Check convergence every N iterations. Values > 1 mainly help the CUDA
|
|
38
|
+
path by reducing host-side convergence work.
|
|
39
|
+
reciprocity : bool
|
|
40
|
+
Also compute inverse view factors via reciprocity.
|
|
41
|
+
enforce_reciprocity_rowsum : bool
|
|
42
|
+
After computation, enforce reciprocity and make each row sum to 1 using
|
|
43
|
+
symmetric diagonal scaling.
|
|
44
|
+
flip_faces : bool
|
|
45
|
+
If True, flip emitter triangle winding during emission sampling.
|
|
46
|
+
"""
|
|
47
|
+
samples: int = 16
|
|
48
|
+
rays: int = 128
|
|
49
|
+
seed: int = 1
|
|
50
|
+
bvh: str = "auto"
|
|
51
|
+
device: str = "auto"
|
|
52
|
+
cuda_async: bool = True
|
|
53
|
+
gpu_raygen: bool = True
|
|
54
|
+
max_iters: int = 100
|
|
55
|
+
tol: float = 1e-4
|
|
56
|
+
tol_mode: str = "stderr"
|
|
57
|
+
min_iters: int = 5
|
|
58
|
+
convergence_interval: int = 1
|
|
59
|
+
reciprocity: bool = True
|
|
60
|
+
enforce_reciprocity_rowsum: bool = False
|
|
61
|
+
flip_faces: bool = False
|
|
62
|
+
|
|
63
|
+
def as_dict(self) -> Dict[str, Any]:
|
|
64
|
+
return asdict(self)
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def from_dict(cls, data: Dict[str, Any]) -> "MatrixParams":
|
|
68
|
+
return cls(**data)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass
|
|
72
|
+
class SkyParams:
|
|
73
|
+
"""Configuration for merged sky view-factor solves.
|
|
74
|
+
|
|
75
|
+
Parameters
|
|
76
|
+
----------
|
|
77
|
+
samples : int
|
|
78
|
+
Quasi-Monte Carlo grid per side used for emission per emitter.
|
|
79
|
+
rays : int
|
|
80
|
+
Rays per grid cell.
|
|
81
|
+
seed : int
|
|
82
|
+
Base RNG seed. Each emitter/iteration derives its own sub-seed.
|
|
83
|
+
bvh : {"auto","off","builtin"}
|
|
84
|
+
Toggle a built-in BVH for faster visibility.
|
|
85
|
+
device : {"auto","gpu","cpu"}
|
|
86
|
+
Visibility device. GPU uses CUDA hitmask kernels. CPU uses numba njit.
|
|
87
|
+
cuda_async : bool
|
|
88
|
+
Use pinned memory + streams for overlap on CUDA.
|
|
89
|
+
gpu_raygen : bool
|
|
90
|
+
Generate rays on GPU to avoid H2D copies of rays.
|
|
91
|
+
max_iters : int
|
|
92
|
+
Maximum number of Monte-Carlo iterations.
|
|
93
|
+
tol : float
|
|
94
|
+
Convergence tolerance. Interpretation depends on ``tol_mode``.
|
|
95
|
+
tol_mode : {"delta", "stderr"}
|
|
96
|
+
- "delta": stop when successive cumulative estimates change by < tol.
|
|
97
|
+
- "stderr": stop when per-iteration replicate standard error is <= tol.
|
|
98
|
+
min_iters : int
|
|
99
|
+
Minimum number of Monte-Carlo iterations before a convergence check.
|
|
100
|
+
convergence_interval : int
|
|
101
|
+
Check convergence every N iterations. Values > 1 mainly help the CUDA
|
|
102
|
+
path by reducing host-side convergence work.
|
|
103
|
+
discrete : bool
|
|
104
|
+
If True, return 145 directional patches. If False, return a single
|
|
105
|
+
merged "Sky" entry.
|
|
106
|
+
"""
|
|
107
|
+
samples: int = 16
|
|
108
|
+
rays: int = 128
|
|
109
|
+
seed: int = 1
|
|
110
|
+
bvh: str = "auto"
|
|
111
|
+
device: str = "auto"
|
|
112
|
+
cuda_async: bool = True
|
|
113
|
+
gpu_raygen: bool = True
|
|
114
|
+
max_iters: int = 100
|
|
115
|
+
tol: float = 1e-4
|
|
116
|
+
tol_mode: str = "stderr"
|
|
117
|
+
min_iters: int = 5
|
|
118
|
+
convergence_interval: int = 1
|
|
119
|
+
discrete: bool = False
|
|
120
|
+
|
|
121
|
+
def as_dict(self) -> Dict[str, Any]:
|
|
122
|
+
return asdict(self)
|
|
123
|
+
|
|
124
|
+
@classmethod
|
|
125
|
+
def from_dict(cls, data: Dict[str, Any]) -> "SkyParams":
|
|
126
|
+
return cls(**data)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
__all__ = ["MatrixParams", "SkyParams"]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""Utility subpackage exports.
|
|
4
|
+
|
|
5
|
+
This module re-exports commonly used helpers so callers can do:
|
|
6
|
+
from raystrack.utils import cached_halton, flatten_receivers, build_rays
|
|
7
|
+
|
|
8
|
+
Keeping imports light: avoid importing CUDA-specific modules here so that the
|
|
9
|
+
package imports cleanly on systems without CUDA. Heavy modules are loaded on
|
|
10
|
+
first use by their direct importers.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
# Lightweight, CPU-safe helpers
|
|
14
|
+
from .halton import cached_halton # noqa: F401
|
|
15
|
+
from .geometry import flatten_receivers, flip_meshes # noqa: F401
|
|
16
|
+
from .ray_builder import build_rays # noqa: F401
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"cached_halton",
|
|
20
|
+
"flatten_receivers",
|
|
21
|
+
"flip_meshes",
|
|
22
|
+
"build_rays",
|
|
23
|
+
]
|
raystrack/utils/bvh.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
LEAF_SIZE = 8 # triangles per leaf
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _tri_bounds(p0: np.ndarray, p1: np.ndarray, p2: np.ndarray):
|
|
8
|
+
bmin = np.minimum(np.minimum(p0, p1), p2)
|
|
9
|
+
bmax = np.maximum(np.maximum(p0, p1), p2)
|
|
10
|
+
centroid = (p0 + p1 + p2) / 3.0
|
|
11
|
+
return bmin.astype(np.float32), bmax.astype(np.float32), centroid.astype(np.float32)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def build_bvh(v0: np.ndarray, e1: np.ndarray, e2: np.ndarray,
|
|
15
|
+
leaf_size: int = LEAF_SIZE):
|
|
16
|
+
"""Return BVH arrays and triangle permutation."""
|
|
17
|
+
m = v0.shape[0]
|
|
18
|
+
tmin = np.empty((m, 3), np.float32)
|
|
19
|
+
tmax = np.empty((m, 3), np.float32)
|
|
20
|
+
cent = np.empty((m, 3), np.float32)
|
|
21
|
+
for i in range(m):
|
|
22
|
+
p0 = v0[i]
|
|
23
|
+
p1 = v0[i] + e1[i]
|
|
24
|
+
p2 = v0[i] + e2[i]
|
|
25
|
+
bmin, bmax, c = _tri_bounds(p0, p1, p2)
|
|
26
|
+
tmin[i] = bmin
|
|
27
|
+
tmax[i] = bmax
|
|
28
|
+
cent[i] = c
|
|
29
|
+
|
|
30
|
+
bb_min, bb_max = [], []
|
|
31
|
+
left, right = [], []
|
|
32
|
+
start, count = [], []
|
|
33
|
+
order: list[int] = []
|
|
34
|
+
|
|
35
|
+
def add_node(idxs: np.ndarray) -> int:
|
|
36
|
+
node = len(bb_min)
|
|
37
|
+
bb_min.append(np.zeros(3, np.float32))
|
|
38
|
+
bb_max.append(np.zeros(3, np.float32))
|
|
39
|
+
left.append(-1)
|
|
40
|
+
right.append(-1)
|
|
41
|
+
start.append(0)
|
|
42
|
+
count.append(0)
|
|
43
|
+
|
|
44
|
+
bmin = tmin[idxs].min(axis=0)
|
|
45
|
+
bmax = tmax[idxs].max(axis=0)
|
|
46
|
+
bb_min[node][:] = bmin
|
|
47
|
+
bb_max[node][:] = bmax
|
|
48
|
+
|
|
49
|
+
if len(idxs) <= leaf_size:
|
|
50
|
+
start[node] = len(order)
|
|
51
|
+
count[node] = len(idxs)
|
|
52
|
+
order.extend(idxs.tolist())
|
|
53
|
+
else:
|
|
54
|
+
ext = bmax - bmin
|
|
55
|
+
axis = int(np.argmax(ext))
|
|
56
|
+
idxs_sorted = idxs[np.argsort(cent[idxs, axis])]
|
|
57
|
+
mid = idxs_sorted.size // 2
|
|
58
|
+
l = add_node(idxs_sorted[:mid])
|
|
59
|
+
r = add_node(idxs_sorted[mid:])
|
|
60
|
+
left[node] = l
|
|
61
|
+
right[node] = r
|
|
62
|
+
return node
|
|
63
|
+
|
|
64
|
+
add_node(np.arange(m, dtype=np.int32))
|
|
65
|
+
perm = np.array(order, dtype=np.int32)
|
|
66
|
+
return (np.asarray(bb_min, np.float32),
|
|
67
|
+
np.asarray(bb_max, np.float32),
|
|
68
|
+
np.asarray(left, np.int32),
|
|
69
|
+
np.asarray(right, np.int32),
|
|
70
|
+
np.asarray(start, np.int32),
|
|
71
|
+
np.asarray(count, np.int32),
|
|
72
|
+
perm)
|
|
73
|
+
|
|
74
|
+
__all__ = ["build_bvh", "LEAF_SIZE"]
|