Compare commits
18
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21fe71d332 | ||
|
|
2b3c2a7529 | ||
|
|
dbcdb87081 | ||
|
|
0d62c3cfb8 | ||
|
|
96c5decf69 | ||
|
|
e4049a6183 | ||
|
|
733e4d1fe7 | ||
|
|
0f8fdbc30e | ||
|
|
e4538219b2 | ||
|
|
888c80381c | ||
|
|
bf5088f84c | ||
|
|
af406b44bf | ||
|
|
78c0f1811b | ||
|
|
0ddc6c3d62 | ||
|
|
43e226c59a | ||
|
|
93e692a40f | ||
|
|
33837697da | ||
|
|
b47af12c9d |
@@ -0,0 +1,393 @@
|
||||
# Evidence index (draft, R0)
|
||||
|
||||
Active-tree evidence at candidate 0f8fdbc30ea640c764b38ee598d8f4d135c81c85, classified for the release cleanup
|
||||
(thread C0C78UFKGRM 1793021833.593279). Draft for review: nothing is removed by this file.
|
||||
Recovery of any listed file: `git show 0f8fdbc3:<path>` (blob id given; an immutable tag is requested as anchor).
|
||||
|
||||
Classes: K = conclusion kept in the active tree; K-code = tested research code kept; D-snapshot = pre-Gitea
|
||||
patch/diff transport (code landed in git from ed1a6ee on; not yet verified hunk by hunk); P-pin = generated hash inventories, git-status dumps and manifests;
|
||||
R-raw = run outputs, logs, signals, frames, one-shot run scripts and handoff notes. D, P, R leave the active tree in R1.
|
||||
No file under src/ or a test reads any of these paths (git grep at 0f8fdbc3); runners under tests/validation
|
||||
that read research/j* are handled in R2.
|
||||
|
||||
| Class | Files | Bytes |
|
||||
|---|---:|---:|
|
||||
| K | 31 | 196,506 |
|
||||
| K-code | 3 | 24,324 |
|
||||
| D-snapshot | 18 | 338,948 |
|
||||
| P-pin | 50 | 979,177 |
|
||||
| R-raw | 142 | 3,790,554 |
|
||||
|
||||
## (root)
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| BASELINE_JET_AMR.txt | R-raw | 5,244 | 62aa2a66dc05 |
|
||||
|
||||
## output
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| round3_compatibility_summary.md | R-raw | 4,366 | f243318f5591 |
|
||||
|
||||
## research/fine_surface_20261014
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| baseline.json | P-pin | 54,507 | 71a4543ead37 |
|
||||
| cpu_device_guard_cmd.txt | R-raw | 241 | 06e0f35d92b3 |
|
||||
| cpu_device_guard_exit.txt | R-raw | 2 | 573541ac9702 |
|
||||
| cpu_device_guard_stdout.txt | R-raw | 98 | 424d584a031c |
|
||||
| cpu_existing_runs.json | R-raw | 650 | 3179536407b7 |
|
||||
| cpu_final_run.json | R-raw | 386 | 523fadb3fec9 |
|
||||
| cpu_final_stdout.txt | R-raw | 99 | 9cfe73da3858 |
|
||||
| cpu_lifecycle_run.json | R-raw | 387 | 5b403b9e2f30 |
|
||||
| cpu_lifecycle_stdout.txt | R-raw | 112 | 3c5c49b285fa |
|
||||
| cpu_maps_stdout.txt | R-raw | 95 | 71dd87f9faf9 |
|
||||
| cpu_preallocation_run.json | R-raw | 337 | fa6e96d98cdd |
|
||||
| cpu_preallocation_stdout.txt | R-raw | 98 | 5d643576f251 |
|
||||
| cpu_shared_kernel_stdout.txt | R-raw | 98 | 8a0c046bb9b1 |
|
||||
| cpu_surface_command.txt | R-raw | 113 | 2a5ff31e8d06 |
|
||||
| cpu_surface_exit.txt | R-raw | 2 | 573541ac9702 |
|
||||
| cpu_surface_projection_command.txt | R-raw | 171 | 70b7f5c62c1a |
|
||||
| cpu_surface_projection_exit.txt | R-raw | 2 | 573541ac9702 |
|
||||
| cpu_surface_projection_stdout.txt | R-raw | 113 | efd37a149cc1 |
|
||||
| cpu_surface_stdout.txt | R-raw | 99 | 9cfe73da3858 |
|
||||
| gpu_preparation_run1.py | R-raw | 14,043 | ee586d035b7a |
|
||||
| gpu_run.json | R-raw | 2,943 | 15b8ba70d528 |
|
||||
| gpu_stdout.txt | R-raw | 5,424 | c5216e0267f3 |
|
||||
| gpu_test_run1.py | R-raw | 15,479 | f30376abc97f |
|
||||
| incremental.diff | D-snapshot | 53,853 | 318d92e7d177 |
|
||||
| manifest.json | P-pin | 8,411 | 8281338416af |
|
||||
| report.txt | K | 8,373 | 6b9e5123e414 |
|
||||
|
||||
## research/fine_surface_joint_20261014
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| baseline_00.json | P-pin | 21,302 | 4ae101ebd02b |
|
||||
| baseline_01.json | P-pin | 26,191 | 548cf7b3b494 |
|
||||
| baseline_02.json | P-pin | 22,440 | e0421e7a4052 |
|
||||
| baseline_03.json | P-pin | 8,584 | da99b45f32a4 |
|
||||
| blow_boundary.csv | R-raw | 12,536 | e13363b69457 |
|
||||
| blow_collisions.csv | R-raw | 19,145 | 5d5b395486bb |
|
||||
| blow_ledger.csv | R-raw | 15,977 | b43bbfd0b8d2 |
|
||||
| blow_propagation.csv | R-raw | 9,714 | f06d80d296ca |
|
||||
| blow_signals.npz | R-raw | 221,114 | 528adf75baa2 |
|
||||
| blow_summary.json | R-raw | 4,113 | 32285ac15be3 |
|
||||
| command.txt | R-raw | 232 | 510ecb2925dd |
|
||||
| criteria.txt | K | 7,480 | dd36e76a3be1 |
|
||||
| frozen.json | R-raw | 11,972 | b5a3324e8686 |
|
||||
| gpu_run.json | R-raw | 1,955 | 67ac4785f7e4 |
|
||||
| incremental.diff | D-snapshot | 625 | e03c132d22df |
|
||||
| integrity.json | P-pin | 826 | a8b6e4be88d2 |
|
||||
| manifest.json | P-pin | 4,388 | d2af50260c39 |
|
||||
| regions.json | R-raw | 27,525 | 7bba26904221 |
|
||||
| report.txt | K | 8,207 | d7571e068ad3 |
|
||||
| result.json | R-raw | 11,442 | 9580c2686e70 |
|
||||
| review.txt | K | 2,117 | bbe1d8a83d47 |
|
||||
| runner.py | R-raw | 5,847 | 812973acc000 |
|
||||
| stdout.txt | R-raw | 19,940 | c9218e2e48fc |
|
||||
| suction_boundary.csv | R-raw | 12,505 | b870be05e6c0 |
|
||||
| suction_collisions.csv | R-raw | 19,173 | 2de48c0a84ab |
|
||||
| suction_ledger.csv | R-raw | 16,208 | 92cf1f44911e |
|
||||
| suction_propagation.csv | R-raw | 9,720 | f017bcc3ca6f |
|
||||
| suction_signals.npz | R-raw | 220,058 | 66d06cf2d909 |
|
||||
| suction_summary.json | R-raw | 4,126 | d70a1d371950 |
|
||||
| validate.py | R-raw | 19,576 | 37441febd168 |
|
||||
| zero_boundary.csv | R-raw | 11,491 | 65c92e48c974 |
|
||||
| zero_collisions.csv | R-raw | 18,915 | 027cb8ff6b23 |
|
||||
| zero_ledger.csv | R-raw | 16,051 | 34a99bb89dd7 |
|
||||
| zero_signals.npz | R-raw | 127,958 | a966f093a9cd |
|
||||
| zero_summary.json | R-raw | 1,508 | 6e033f991438 |
|
||||
|
||||
## research/fixed_patch_jet_20261013
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| baseline.json | P-pin | 69,721 | 91ad9c4d1e88 |
|
||||
| before.json | R-raw | 690 | 06e1b6278a29 |
|
||||
| fixed_patch_jet.py | R-raw | 9,646 | 6fbdcd9a076b |
|
||||
| incremental.patch | D-snapshot | 9,891 | b43129d82c69 |
|
||||
| manifest.json | P-pin | 1,967 | 08daa0248f60 |
|
||||
| notes.txt | K | 2,214 | 50070fe54efb |
|
||||
| results.json | R-raw | 1,100 | d959a6a1cc2c |
|
||||
| stdout.txt | R-raw | 1,272 | eccdc0f6b16a |
|
||||
|
||||
## research/fixed_patch_jet_closure_20261013
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| baseline.json | P-pin | 72,692 | 8a157af82ecf |
|
||||
| cpu_results.json | R-raw | 628 | 8e4a1c090c93 |
|
||||
| cpu_stdout.txt | R-raw | 590 | d800b783fe47 |
|
||||
| incremental.patch | D-snapshot | 3,490 | a9a486c68afd |
|
||||
| layout_uncropped.png | R-raw | 51,785 | 0cf1cfa5e99d |
|
||||
| manifest.json | P-pin | 1,849 | 31cf0c739241 |
|
||||
| notes.txt | K | 3,023 | 0f7e7bdfd0e6 |
|
||||
|
||||
## research/fixed_patch_jet_records_20261013
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| baseline.json | P-pin | 71,228 | a8e967f76e08 |
|
||||
| before.json | R-raw | 690 | ebd6f4251fc2 |
|
||||
| fixed_patch_jet.py | R-raw | 10,650 | f6b299885da0 |
|
||||
| incremental.patch | D-snapshot | 5,539 | c7f4d0c02ccc |
|
||||
| manifest.json | P-pin | 2,057 | 1d616c2541df |
|
||||
| notes.txt | K | 2,449 | b58cec14d359 |
|
||||
| results.json | R-raw | 1,136 | 788af64a6ebd |
|
||||
| stdout.txt | R-raw | 20,750 | a765b06deefa |
|
||||
|
||||
## research/j1-2026-10-12
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| REVIEW.md | K | 7,667 | 8f469daef054 |
|
||||
| baseline-status.txt | P-pin | 2,601 | 64ca05ab952e |
|
||||
| baseline.json | P-pin | 23,052 | ab5852bcb0ef |
|
||||
| incremental.diff | D-snapshot | 29,912 | dd9c4e688888 |
|
||||
| results.json | R-raw | 68,294 | 56547aa8a678 |
|
||||
|
||||
## research/j2-slot-2026-10-12
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| REVIEW.md | K | 12,930 | 69fa4d3bccd3 |
|
||||
| baseline-status.txt | P-pin | 2,825 | e711afb0016c |
|
||||
| baseline.json | P-pin | 24,660 | 286e023da94f |
|
||||
| incremental.diff | D-snapshot | 25,231 | 649f3b5d168d |
|
||||
| results.json | R-raw | 477,249 | b4272e25179d |
|
||||
|
||||
## research/j3-coverage-2026-10-12
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| REVIEW.md | K | 11,409 | 5887cf73dce2 |
|
||||
| baseline-status.txt | P-pin | 3,055 | 78e88356caa3 |
|
||||
| baseline.json | P-pin | 30,407 | 095972547a7f |
|
||||
| incremental.diff | D-snapshot | 20,114 | f0d502dc5c5b |
|
||||
| negative-budget-20744.h5 | R-raw | 88,017 | 693b133be84d |
|
||||
| negative-end-20760.h5 | R-raw | 88,174 | 429270d263d4 |
|
||||
| restart-21280.h5 | R-raw | 88,062 | 74900affae38 |
|
||||
| restart-reference-21296.h5 | R-raw | 88,154 | 7510ee97885b |
|
||||
| results.json | R-raw | 296,314 | 7806b10e65cb |
|
||||
| verification.json | K | 1,468 | 78a07c47aea4 |
|
||||
|
||||
## research/j3-lag-2026-10-12
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| REVIEW.md | K | 11,732 | 34fe5dbb2cae |
|
||||
| baseline-status.txt | P-pin | 2,968 | 6ae6094ea9d7 |
|
||||
| baseline.json | P-pin | 26,505 | 5c289d14ff30 |
|
||||
| end-21280.h5 | R-raw | 92,366 | f30b209179ab |
|
||||
| incremental.diff | D-snapshot | 15,790 | 5c6c485e1f75 |
|
||||
| results.json | R-raw | 21,718 | 2bf58939129c |
|
||||
| start-20760.h5 | R-raw | 92,247 | ae0abd05190c |
|
||||
|
||||
## research/j3-offline-2026-10-12
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| REVIEW.md | K | 6,271 | a76e1b486bd2 |
|
||||
| lags.csv | R-raw | 1,104 | dd3136dd2dc2 |
|
||||
| localization.png | R-raw | 136,013 | 74b56f3e814c |
|
||||
| regions.csv | R-raw | 2,126 | 5d361e6872af |
|
||||
| results.json | R-raw | 8,852 | bf77b0f534d4 |
|
||||
|
||||
## research/j3-reservoir-2026-10-12
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| REVIEW.md | K | 13,563 | a74b67a64e0d |
|
||||
| baseline-status.txt | P-pin | 2,896 | a318e077dfae |
|
||||
| baseline.json | P-pin | 25,571 | 060502ea7dd8 |
|
||||
| incremental.diff | D-snapshot | 22,898 | 8e2c79a86c98 |
|
||||
| results.json | R-raw | 182,747 | 7fd5e51a1785 |
|
||||
|
||||
## research/refinement_example_20261013
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| baseline.json | P-pin | 8,286 | 591478100da8 |
|
||||
| before.json | R-raw | 818 | 7ab0962775b1 |
|
||||
| incremental.patch | D-snapshot | 8,682 | 7ad8719d0167 |
|
||||
| manifest.json | P-pin | 1,798 | bf1eee8a7cf8 |
|
||||
| notes.txt | K | 1,185 | 7ff019ad023d |
|
||||
| results.json | R-raw | 1,118 | 94697b0988b9 |
|
||||
| stdout.txt | R-raw | 325 | 501446f557f4 |
|
||||
|
||||
## research/refinement_followup_20261013
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| README.txt | K | 4,887 | af65e889f20e |
|
||||
| baseline.json | P-pin | 5,343 | 7c60ad8ad692 |
|
||||
| cleanup.json | R-raw | 1,253 | 15cf342fba2e |
|
||||
| cpu_results.json | R-raw | 1,056 | 1166dffd2a09 |
|
||||
| cpu_results_attempt1.json | R-raw | 642 | d139d5508105 |
|
||||
| cpu_stdout.txt | R-raw | 499 | d1b33ea20563 |
|
||||
| cpu_stdout_attempt1.txt | R-raw | 879 | 6a9fe7fce39a |
|
||||
| gpu_before.json | R-raw | 589 | 46762a0ab207 |
|
||||
| gpu_before_no_launch.json | R-raw | 589 | 074982d1b2d4 |
|
||||
| gpu_rectangle_before.json | R-raw | 589 | 831e3793339f |
|
||||
| gpu_rectangle_before_no_launch_1791886104981638567.json | R-raw | 589 | c33885d50bfd |
|
||||
| gpu_rectangle_results.json | R-raw | 1,003 | 9c6da219ac6c |
|
||||
| gpu_rectangle_stdout.txt | R-raw | 332 | 9185bf303954 |
|
||||
| gpu_results.json | R-raw | 1,189 | 53e4f1c44de1 |
|
||||
| gpu_seed1_before.json | R-raw | 589 | c77ea3485f84 |
|
||||
| gpu_seed1_results.json | R-raw | 996 | b718e8af84e4 |
|
||||
| gpu_seed1_stdout.txt | R-raw | 306 | 4d7de0897137 |
|
||||
| gpu_stdout.txt | R-raw | 68 | b0956fe3cdb0 |
|
||||
| incremental.patch | D-snapshot | 16,836 | 9df25d8c177a |
|
||||
| manifest.json | P-pin | 4,410 | 177704d6f1ae |
|
||||
| run_gpu.py | R-raw | 5,237 | b5af3f0d4f79 |
|
||||
|
||||
## research/refinement_prepare_20261013
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| README.txt | K | 8,939 | 8e210c28c7c5 |
|
||||
| baseline.json | P-pin | 46,348 | d5f257216b8d |
|
||||
| incremental.patch | D-snapshot | 15,751 | 0ddb32550584 |
|
||||
| manifest.json | P-pin | 2,113 | 9fd94ccf2c3e |
|
||||
| validation.json | R-raw | 3,567 | f057e7cbcd35 |
|
||||
| validation.txt | R-raw | 873 | 594daa45c58c |
|
||||
|
||||
## research/refinement_slot_20261013
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| baseline.json | P-pin | 67,717 | d498081e7c50 |
|
||||
| before.json | R-raw | 690 | 430e76b3aa8a |
|
||||
| cpu_results.json | R-raw | 1,421 | 4f6bc4d9428f |
|
||||
| incremental.patch | D-snapshot | 18,676 | 67a3e8cc9e68 |
|
||||
| manifest.json | P-pin | 2,270 | 6515458290f4 |
|
||||
| notes.txt | K | 2,612 | 08a713ba4b37 |
|
||||
| results.json | R-raw | 1,160 | 03e683027ba8 |
|
||||
| stdout.txt | R-raw | 643 | d57b91769826 |
|
||||
|
||||
## research/refinement_slot_followup_20261013
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| baseline.json | P-pin | 68,536 | 89a26ce79438 |
|
||||
| before.json | R-raw | 690 | e707df192ff2 |
|
||||
| incremental.patch | D-snapshot | 495 | c6f6fa11237d |
|
||||
| manifest.json | P-pin | 1,920 | 4840243a33aa |
|
||||
| notes.txt | K | 1,549 | 4b77583ca116 |
|
||||
| planar_velocity.cuh | R-raw | 1,911 | 87db7466c843 |
|
||||
| planar_velocity.sha256 | P-pin | 251 | 6694c4a1c1f0 |
|
||||
| results.json | R-raw | 1,050 | 6ef6eda854c6 |
|
||||
| stdout.txt | R-raw | 1,160 | 461860351c0c |
|
||||
|
||||
## research/refinement_step_20261013
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| README.txt | K | 10,671 | 88d6f24743f5 |
|
||||
| baseline.json | P-pin | 40,620 | 20f61559dd38 |
|
||||
| cpu_validation.json | R-raw | 1,231 | 7999fd30018c |
|
||||
| gpu_failure_validation.json | R-raw | 868 | 5f6db65ee4f9 |
|
||||
| gpu_failure_validation.txt | R-raw | 248 | d9a570a1e9e9 |
|
||||
| gpu_validation.json | R-raw | 672 | 2028f59e1055 |
|
||||
| gpu_validation.txt | R-raw | 632 | 9699918ee127 |
|
||||
| incremental.patch | D-snapshot | 26,516 | d95f9347633d |
|
||||
| manifest.json | P-pin | 2,075 | 32a7f1a7309e |
|
||||
|
||||
## research/repair-2026-10-10
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| TRON_HANDOFF.md | R-raw | 25,208 | a339786c7944 |
|
||||
| baseline-hashes.json | P-pin | 16,020 | 9b4e24cb1d10 |
|
||||
| baseline-status.txt | P-pin | 429 | 515be249b638 |
|
||||
| checkpoint-domain-2026-10-12.diff | D-snapshot | 14,443 | 035ed630dda1 |
|
||||
| classic-results.json | R-raw | 244,729 | 7297aa0d5bca |
|
||||
| classic-signals.npz | R-raw | 630,332 | 8cf6d1218aa0 |
|
||||
| final-gpu.log | R-raw | 191 | a0eec1a8ea31 |
|
||||
| final-unit.log | R-raw | 188 | 94efba2f1d42 |
|
||||
| provenance.json | P-pin | 1,020 | 25e22b4f0696 |
|
||||
| repair-architecture.md | K | 9,498 | 12051c3e8571 |
|
||||
| repair-numerical.md | K | 10,769 | 0c5757fe5f36 |
|
||||
| repair-state.md | K | 8,481 | 3c7f2d5b687a |
|
||||
| simplification-checks.log | R-raw | 1,045 | fa9d464be740 |
|
||||
|
||||
## research/shear_refinement
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| README.md | K-code | 4,142 | 67bdd8ed622b |
|
||||
| boundary_shear_tagging.py | K-code | 13,859 | b5415a1c4ea1 |
|
||||
| example.py | K-code | 6,323 | 66295d3f0273 |
|
||||
|
||||
## research/surface_actuation_20261014
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| baseline.json | P-pin | 54,139 | 0ad06888dbeb |
|
||||
| cpu_checkpoint_run.json | R-raw | 400 | 39681b60ff15 |
|
||||
| cpu_checkpoint_stdout.txt | R-raw | 114 | 929e4b8d4f46 |
|
||||
| cpu_initial.txt | R-raw | 620 | 29213c58a679 |
|
||||
| cpu_surface_command.txt | R-raw | 118 | 6d8c615a6e03 |
|
||||
| cpu_surface_exit.txt | R-raw | 2 | 573541ac9702 |
|
||||
| cpu_surface_stdout.txt | R-raw | 99 | ee9237fc26e5 |
|
||||
| gpu_run.json | R-raw | 1,698 | dc8f87eafaa9 |
|
||||
| gpu_stdout.txt | R-raw | 159 | b262891e52c3 |
|
||||
| incremental.diff | D-snapshot | 50,206 | 43090a1a8b11 |
|
||||
| manifest.json | P-pin | 7,527 | 35daa01271cb |
|
||||
| report.txt | K | 5,078 | 1162a6479f9f |
|
||||
|
||||
## research/wall_seam_pulse_20261014
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| analyze.py | R-raw | 10,343 | ed7cf6999a49 |
|
||||
| interpretation.txt | K | 3,514 | 90935db2aa99 |
|
||||
| results.json | R-raw | 15,137 | 678a0759871a |
|
||||
| run.json | R-raw | 1,170 | 53e303fd0d5d |
|
||||
| sources.csv | R-raw | 2,313 | 40d3736b8ef1 |
|
||||
| stdout.txt | R-raw | 1,179 | 756d8c38e213 |
|
||||
|
||||
## tests/validation/multigrid/cpuref_0_3_evidence
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| README.txt | K | 4,133 | 62897bfd9812 |
|
||||
| README_grok.md | K | 1,751 | 2d36e05661a8 |
|
||||
| baseline.json | P-pin | 39,291 | 188491096547 |
|
||||
| manifest.json | P-pin | 3,495 | 10c19f5fe5ca |
|
||||
| results_horsea.json | R-raw | 2,281 | 3b163384e376 |
|
||||
| stdout_grok.txt | R-raw | 7,143 | 5a0c270ea4ae |
|
||||
| stdout_horsea.txt | R-raw | 9,013 | adff8bb8d295 |
|
||||
|
||||
## tests/validation/multigrid/local_stress_v1_evidence
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| README.txt | K | 8,239 | 3513fd294223 |
|
||||
| TABLE_local_stress_observable_v1.md | K | 2,967 | 6115dcde0f46 |
|
||||
| baseline.json | P-pin | 43,991 | ab631ea4f2ad |
|
||||
| comparison.json | R-raw | 13,248 | d7d1b36eb247 |
|
||||
| manifest.json | P-pin | 4,132 | c6c44d8125cd |
|
||||
| results_horsea.json | R-raw | 2,671 | 79bdf001f948 |
|
||||
| run_once.py | R-raw | 4,313 | fa9c5239e993 |
|
||||
| source_manifest.json | P-pin | 622 | 0516f1860407 |
|
||||
| stdout_horsea.txt | R-raw | 17,091 | a20c554693df |
|
||||
| stdout_local_stress_observable_v1.txt | R-raw | 12,238 | 692ffe1a05da |
|
||||
|
||||
## tests/validation/multigrid/shear_v0_2_evidence
|
||||
|
||||
| File | Class | Bytes | Blob |
|
||||
|---|---|---:|---|
|
||||
| README.txt | K | 7,220 | 772f74ad40ff |
|
||||
| baseline.json | P-pin | 41,751 | 70d9c9fa71c0 |
|
||||
| comparison.json | R-raw | 7,679 | 0af8736f9a01 |
|
||||
| joint_report.md | K | 6,110 | eed871221298 |
|
||||
| manifest.json | P-pin | 3,796 | b22d03a1ba9e |
|
||||
| results_horsea.json | R-raw | 1,957 | b2cd48a07a08 |
|
||||
| run_once.py | R-raw | 3,245 | 0b8d5e21f326 |
|
||||
| source_manifest.json | P-pin | 574 | 4d1c742690c7 |
|
||||
| stdout_grok.txt | R-raw | 7,950 | 0e80b1aba7f6 |
|
||||
| stdout_horsea.txt | R-raw | 11,421 | 3c867cdac197 |
|
||||
@@ -0,0 +1,25 @@
|
||||
# Device state lifecycle (uniform Simulation, PeriodicBlockStepper, FixedPatchStepper)
|
||||
|
||||
State is grouped by what a change invalidates. This file describes the code as
|
||||
it is; it adds no framework. Line references are to candidate 0f8fdbc3.
|
||||
|
||||
| Class | Contents | How it changes | Owner rule |
|
||||
|---|---|---|---|
|
||||
| 1. Module and its globals | Compile-time (visible to the compiler, fixed per module): `config.h` macros incl. `NX`/`NY`, `COLLISION_MODEL`, `BLOCK_ROOT_BC`, `WALL_*`. Runtime per-module globals (not visible to the compiler; written by host code): `__constant__` `d_params`, `d_w`, `d_cx`, `d_cy`, `d_block_channel`, `d_block_wall`; plus bound kernel handles | Globals are written once by the owner right after `load_module`. Uniform grid: `Simulation._recompile` (construction, body-topology sync) loads a new module and re-uploads; `update_runtime_params` rewrites `d_params` (omega, force, n_objects) between runs. Steppers: never rewritten after construction, so they are immutable for the instance's lifetime although they are runtime values. The same quantity can be a macro in one route and a global in another (dense slot root: `WALL_SLOT_WIDTH`/`WALL_NORMAL_VELOCITY` macros; blocked slot root: `d_block_wall`), which can change generated arithmetic. | Every owner loads its own module (`compiler_v2.load_module` = `module_from_file`, no cache). A loaded module is never shared between live owners: globals are per module, so sharing would share mutable `d_params`. |
|
||||
| 2. Geometry, layout, tables | flags, curved-link tables, block layouts and halo pairs, transfer (explode/coalesce) tables, block kinds | Immutable for the life of an instance. Uniform grid: rebuilt by body sync. `FixedPatchStepper`: a geometry change is a new instance (`remap_child`), committed only after a successful transfer. | No in-place table edits. |
|
||||
| 3. Controls and dependent boundary columns | Jet amplitude -> per-link `surface_velocity`; body actions (uniform grid) | Between steps, without a table or module rebuild (`set_jet_amplitude`). | Host copy commits only after the device upload succeeded; a device error fails the instance. |
|
||||
| 4. Per-step state | population double buffers and their parity, raw-exchange ledgers, observations | Device-only during `step(n)` / `run(n)`; buffer swaps are host-handle swaps. | Valid on the host only after the single wait at the end of the call. |
|
||||
|
||||
Storage routes are separate concerns:
|
||||
|
||||
- Original uniform grid (`uniform.cu`, `Simulation`): whole-domain `NX`/`NY`.
|
||||
- Blocked levels (`blocked.cu`; `PeriodicBlockStepper` and every blocked
|
||||
`FixedPatchStepper` level): `NX`/`NY` are one block window including halo.
|
||||
- Dense refinement levels (`refinement.cu`, `level_blocks[l] is None`).
|
||||
|
||||
A single-rectangle refinement (`FixedPatch2D`) is stored in its own fine
|
||||
window frame in both dense and blocked form (`refinement_stepper.py:222-224`,
|
||||
`BlockLayout2D.build(*pair.fine_shape, ...)`). Only a rectangle set
|
||||
(`FixedPatchSet2D`) uses the level-wide frame `(2*ny, 2*nx)`, whose
|
||||
`fine_layout` requires that full grid to be divisible by the tile
|
||||
(`refinement.py:240-252`).
|
||||
+27
-26
@@ -1,6 +1,7 @@
|
||||
# Supported settings: 2D Jet + fixed multilevel refinement (candidate c95a7ba)
|
||||
# Supported settings: 2D Jet + fixed multilevel refinement (candidate 888c8038)
|
||||
|
||||
Every entry names the guard that enforces it (file:line at c95a7ba) and, where one
|
||||
Every entry names the guard that enforces it (file and function or kernel guard,
|
||||
at source revision 888c80381c006e976be2af8a452288729fc17c1b) and, where one
|
||||
exists, an existing test that exercises it. A setting not listed here is not
|
||||
claimed. Observations at the end are tied to the exact case in which they were
|
||||
measured; they are not general bounds.
|
||||
@@ -9,12 +10,12 @@ measured; they are not general bounds.
|
||||
|
||||
| Setting | Supported | Guard |
|
||||
|---|---|---|
|
||||
| Dimension / lattice | 2D D2Q9 only (3D refinement is future work) | `lbm/refinement.py:65`, `lbm/kernels/blocks.cu:25`, `lbm/kernels/refinement.cu:26` |
|
||||
| Dimension / lattice | 2D D2Q9 only (3D refinement is future work) | `lbm/refinement.py` `FixedPatch2D.from_config`; `#error` guards in `lbm/kernels/blocks.cu` and `lbm/kernels/refinement.cu` |
|
||||
| Precision / streaming | FP32 storage, double buffer | same guards |
|
||||
| Collision on refinement levels | SRT or MRT; TRT and LES rejected | `lbm/refinement.py:65` (re-checked for fine boundaries at `lbm/refinement.py:457`) |
|
||||
| Shifted (ddf_shifting) storage | only when every level is blocked; dense or mixed rejected | `lbm/refinement_stepper.py:198`, `:469`; `lbm/kernels/refinement.cu:26` (dense patch kernel unshifted only) |
|
||||
| Fine relaxation | 1/tau_fine must lie inside the configured omega guards | `lbm/refinement.py:80` |
|
||||
| Uniform blocked backend `PeriodicBlockStepper` | doubly periodic, SRT only, stationary passive circles | `lbm/block_stepper.py:84`, `:91`, `:45`-`:67` |
|
||||
| Collision on refinement levels | SRT or MRT; TRT and LES rejected | `lbm/refinement.py` `FixedPatch2D.from_config` (re-checked for fine boundaries in `prepare_fine_boundary`) |
|
||||
| Shifted (ddf_shifting) storage | only when every level is blocked; dense or mixed rejected | `lbm/refinement_stepper.py` `FixedPatchStepper.__init__`, `FixedPatchStepper._check_storage`; `#error` guard in `lbm/kernels/refinement.cu` (dense patch kernel unshifted only) |
|
||||
| Fine relaxation | 1/tau_fine must lie inside the configured omega guards | `lbm/refinement.py` `FixedPatch2D.from_config` |
|
||||
| Uniform blocked backend `PeriodicBlockStepper` | doubly periodic, SRT only, stationary passive circles | `lbm/block_stepper.py` `PeriodicBlockStepper.__init__`, `_static_circles` |
|
||||
|
||||
Tests: `tests/unit/test_refinement_mrt.py`, `tests/validation/multigrid/test_refinement_mrt_gpu.py`,
|
||||
`tests/unit/test_shifted_storage.py`, `tests/unit/test_shifted_block_operators.py`.
|
||||
@@ -23,17 +24,17 @@ Tests: `tests/unit/test_refinement_mrt.py`, `tests/validation/multigrid/test_ref
|
||||
|
||||
| Setting | Supported | Guard |
|
||||
|---|---|---|
|
||||
| Depth | at least one refinement level; one entry per level in `level_blocks`/`level_objects`/`level_jets` | `lbm/refinement_stepper.py:72`, `:75` |
|
||||
| Single L1 rectangle | two-coarse-cell margin to the domain edge | `lbm/refinement.py:73` |
|
||||
| Several L1 rectangles (union) | require `level_blocks[0]` and `level_blocks[1]`; transfers must close (dependency checks, no fixed gap rule) | `lbm/refinement_stepper.py:84`; `lbm/refinement.py:283`-`:295` |
|
||||
| Nested levels | depth >= 3 must be all blocked; a blocked level requires blocked levels below; a scalar child needs a scalar parent | `lbm/refinement_stepper.py:82`, `:87`; `lbm/hierarchy.py:54` |
|
||||
| Nested transfer support | child only over inherited ACTIVE cells, donors/receivers uncovered ACTIVE, no child over the parent restriction footprint | `lbm/refinement.py:391`-`:407` |
|
||||
| Tile shape | positive `(by, bx)`; the level allocation must be divisible by the tile (no partial tiles yet) | `lbm/refinement_stepper.py:78`, `lbm/refinement.py:246` (shape); `lbm/blocks.py:134` (divisibility) |
|
||||
| Coarse boundary | `periodic`, `slot_reservoir` or `channel` | `lbm/refinement_stepper.py:177` |
|
||||
| `slot_reservoir` | on-site velocity bottom slot, reservoir top, velocity 0, 2 <= slot width < nx, patch rows 4..ny-4 | `lbm/refinement_stepper.py:205`, `:212`; `lbm/refinement.py:546` |
|
||||
| `channel` | all levels blocked; Zou-He inlet, pressure-NEQ outlet, stationary bounce-back walls; transfers away from the closure | `lbm/channel.py:22`, `:26`, `:43`, `:54` |
|
||||
| Explosion | `constant` (default); `projected_linear` only periodic, all-blocked SRT, no bodies/Jets, no LES (experimental) | `lbm/refinement_stepper.py:188`, `:193` |
|
||||
| L2 runtime remap (`remap_child`) | periodic three-level L2 sets only, no L0/L1 bodies, identical pinned boundary | `lbm/refinement_stepper.py:557`, `:567`-`:581` |
|
||||
| Depth | at least one refinement level; one entry per level in `level_blocks`/`level_objects`/`level_jets` | `lbm/refinement_stepper.py` `_check_levels` |
|
||||
| Single L1 rectangle | two-coarse-cell margin to the domain edge | `lbm/refinement.py` `FixedPatch2D.from_config` |
|
||||
| Several L1 rectangles (union) | require `level_blocks[0]` and `level_blocks[1]`; transfers must close (dependency checks, no fixed gap rule) | `lbm/refinement_stepper.py` `_check_levels`; `lbm/refinement.py` `_check_parent_pull_closure` |
|
||||
| Nested levels | depth >= 3 must be all blocked; a blocked level requires blocked levels below; a scalar child needs a scalar parent | `lbm/refinement_stepper.py` `_check_levels`; `lbm/hierarchy.py` `build_hierarchy` |
|
||||
| Nested transfer support | child only over inherited ACTIVE cells, donors/receivers uncovered ACTIVE, no child over the parent restriction footprint | `lbm/refinement.py` `_nested_kind` |
|
||||
| Tile shape | positive `(by, bx)`; the level allocation must be divisible by the tile (no partial tiles yet) | `lbm/refinement_stepper.py` `_check_levels`, `lbm/refinement.py` `FixedPatchSet2D.fine_layout` (shape); `lbm/blocks.py` `BlockLayout2D.build` (divisibility) |
|
||||
| Coarse boundary | `periodic`, `slot_reservoir` or `channel` | `lbm/refinement_stepper.py` `FixedPatchStepper.__init__` |
|
||||
| `slot_reservoir` | on-site velocity bottom slot, reservoir top, velocity 0, 2 <= slot width < nx, patch rows 4..ny-4 | `lbm/refinement_stepper.py` `FixedPatchStepper.__init__`; `lbm/refinement.py` `prepare_fine_boundary` |
|
||||
| `channel` | all levels blocked; Zou-He inlet, pressure-NEQ outlet, stationary bounce-back walls; transfers away from the closure | `lbm/channel.py` `validate_channel_config`, `validate_channel_transfers` |
|
||||
| Explosion | `constant` (default); `projected_linear` only periodic, all-blocked SRT, no bodies/Jets, no LES (experimental) | `lbm/refinement_stepper.py` `FixedPatchStepper.__init__` |
|
||||
| L2 runtime remap (`remap_child`) | periodic three-level L2 sets only, no L0/L1 bodies, identical pinned boundary | `lbm/refinement_stepper.py` `FixedPatchStepper.remap_child` |
|
||||
|
||||
Tests: `tests/unit/test_refinement_three_level_multipatch.py`, `tests/validation/multigrid/test_refinement_multipatch.py`,
|
||||
`test_refinement_three_level.py`, `test_refinement_three_level_multipatch_gpu.py`, `test_refinement_blocked_base.py`,
|
||||
@@ -44,14 +45,14 @@ Tests: `tests/unit/test_refinement_three_level_multipatch.py`, `tests/validation
|
||||
|
||||
| Setting | Supported | Guard |
|
||||
|---|---|---|
|
||||
| Bodies | stationary circles without sensor/force-region roles, entirely inside the patch union, fully resolved, disjoint, stencil away from the two-hop transfer footprint | `lbm/refinement.py:474`-`:542` |
|
||||
| Level | not on L0; only on the finest level of a nested hierarchy | `lbm/refinement_stepper.py:80`, `:89` |
|
||||
| Jet condition | velocity only; `pressure` is reserved and raises NotImplementedError | `body/jets.py:148`, `:150` |
|
||||
| Jet geometry | each Jet selects resolved links of exactly one stationary body; no Jet/Jet or Jet/SurfaceActuation overlap; abs(amplitude) < 1 lattice | `body/jets.py:155`, `:175`, `:177`, `:255`, `:261`, `:263` |
|
||||
| Jets with shifted storage | only in the all-blocked stepper with SRT and no LES | `body/jets.py:249` |
|
||||
| SurfaceActuation | unshifted storage only | `body/objects.py:155` |
|
||||
| Raw boundary exchange (force) | blocked body levels only; the window ledger requires `observe_raw_exchange` | `lbm/refinement_stepper.py:264`, `:269` |
|
||||
| Checkpoint with Jets | refused | `simulation.py:687` |
|
||||
| Bodies | stationary circles without sensor/force-region roles, entirely inside the patch union, fully resolved, disjoint, stencil away from the two-hop transfer footprint | `lbm/refinement.py` `prepare_fine_boundary` |
|
||||
| Level | not on L0; only on the finest level of a nested hierarchy | `lbm/refinement_stepper.py` `_check_levels` |
|
||||
| Jet condition | velocity only; `pressure` is reserved and raises NotImplementedError | `body/jets.py` `Jet.__post_init__` |
|
||||
| Jet geometry | each Jet selects resolved links of exactly one stationary body; no Jet/Jet or Jet/SurfaceActuation overlap; abs(amplitude) < 1 lattice | `body/jets.py` `Jet.__post_init__`, `jet_link_shapes`, `_surface_links` |
|
||||
| Jets with shifted storage | only in the all-blocked stepper with SRT and no LES | `body/jets.py` `_surface_links` |
|
||||
| SurfaceActuation | unshifted storage only | `body/objects.py` `SimObject.validate_surface_actuation` |
|
||||
| Raw boundary exchange (force) | blocked body levels only; the window ledger requires `observe_raw_exchange` | `lbm/refinement_stepper.py` `FixedPatchStepper.__init__` |
|
||||
| Checkpoint with Jets | refused | `simulation.py` `Simulation.save_checkpoint` |
|
||||
|
||||
Raw exchange is the cut-link momentum reaction (wall + aperture), not a validated
|
||||
nozzle thrust or stress load. Jet amplitude is a lattice velocity, not a flow rate.
|
||||
|
||||
@@ -60,7 +60,7 @@ Python `config.py` 只负责读取和校验,不是配置位置。显式配置
|
||||
|
||||
**`lbm/kernels/config/*.h` 由编译器根据 `LBMConfig` 自动生成,请勿手改。**
|
||||
|
||||
仓库中检入的 `config/*.h` 可能是历史版本。`compiler_v2.generate_config` 会复制 kernel 源码到独立临时构建目录,并在副本中生成配置;不会改写包内头文件或 PTX。返回目录须显式传给 `compile_kernel(build_dir=...)`,编译结果与配置摘要均保存在该目录。`Simulation` 负责目录清理;直接使用编译器的调用者须调用 `cleanup_build_dir()`。跳过生成配置直接编译仓库中的 `kernel_v2.cu` 属不受支持用法。
|
||||
仓库中检入的 `config/*.h` 可能是历史版本。`compiler_v2.generate_config` 会复制 kernel 源码到独立临时构建目录,并在副本中生成配置;不会改写包内头文件或 PTX。返回目录须显式传给 `compile_kernel(build_dir=...)`,编译结果与配置摘要均保存在该目录。`Simulation` 负责目录清理;直接使用编译器的调用者须调用 `cleanup_build_dir()`。跳过生成配置直接编译仓库中的 `uniform.cu` 属不受支持用法。
|
||||
|
||||
```
|
||||
config_lbm.json
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
"""
|
||||
Kernel configuration, compilation, and module loading.
|
||||
|
||||
Workflow:
|
||||
Owners call build_module(cfg, entry, arch=...), then set_params(module, omega, ...).
|
||||
build_module runs, in a private directory it removes afterwards:
|
||||
1. build_dir = generate_config(lbm_cfg, n_objects) — isolated source snapshot
|
||||
2. compile_kernel(arch, build_dir=build_dir) — nvcc -ptx kernel_v2.cu
|
||||
2. compile_kernel(arch, source=entry, build_dir=build_dir) — nvcc -ptx
|
||||
3. load_module(ptx_path) — PyCUDA module from PTX
|
||||
Entries: uniform.cu (uniform grid), blocked.cu (blocked level), refinement.cu
|
||||
(dense refinement level).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -16,7 +19,6 @@ import shutil
|
||||
import tempfile
|
||||
import hashlib
|
||||
import json
|
||||
from contextvars import ContextVar
|
||||
from dataclasses import asdict
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
@@ -33,9 +35,6 @@ _KERNEL_DIR = os.path.join(
|
||||
)
|
||||
|
||||
|
||||
_last_build_dir = ContextVar("celeris_last_build_dir", default=None)
|
||||
_last_ptx_path = ContextVar("celeris_last_ptx_path", default=None)
|
||||
|
||||
|
||||
def kernel_path(filename: str) -> str:
|
||||
return os.path.join(_KERNEL_DIR, filename)
|
||||
@@ -57,9 +56,7 @@ def generate_config(cfg: LBMConfig, n_objects: int = 0,
|
||||
*, build_root: Optional[str] = None, block_root_bc: int = 0) -> str:
|
||||
"""Snapshot kernels and render headers in a fresh private directory.
|
||||
|
||||
Returns its path. Pass it explicitly to compile_kernel for interleaved
|
||||
builds. Legacy generate_config(); compile_kernel() remains context-local.
|
||||
The caller owns cleanup_build_dir() once the loaded module is no longer
|
||||
Returns its path; pass it to compile_kernel(build_dir=...). The caller owns cleanup_build_dir() once the loaded module is no longer
|
||||
needed for recompilation/debugging. No package files are changed.
|
||||
block_root_bc specializes a blocked root module; fine/dense builds use 0.
|
||||
"""
|
||||
@@ -88,8 +85,6 @@ def generate_config(cfg: LBMConfig, n_objects: int = 0,
|
||||
except BaseException:
|
||||
shutil.rmtree(build_dir)
|
||||
raise
|
||||
_last_build_dir.set(build_dir)
|
||||
_last_ptx_path.set(None)
|
||||
return build_dir
|
||||
|
||||
|
||||
@@ -101,9 +96,6 @@ def cleanup_build_dir(build_dir: Optional[str]) -> None:
|
||||
if path == Path(_KERNEL_DIR).resolve() or not (path / ".celeris-build").is_file():
|
||||
raise ValueError("Refusing to remove a directory not owned by the compiler")
|
||||
shutil.rmtree(path)
|
||||
if _last_build_dir.get() == str(build_dir):
|
||||
_last_build_dir.set(None)
|
||||
_last_ptx_path.set(None)
|
||||
|
||||
|
||||
def _render_config(m: dict, n_objects: int, cdir: str, *, block_root_bc: int = 0):
|
||||
@@ -249,13 +241,9 @@ def _render_config(m: dict, n_objects: int, cdir: str, *, block_root_bc: int = 0
|
||||
# ---------------------------------------------------------------------------
|
||||
# Compilation
|
||||
# ---------------------------------------------------------------------------
|
||||
def compile_kernel(arch: str = "sm_70", source: str = "kernel_v2.cu",
|
||||
output: Optional[str] = None, *,
|
||||
build_dir: Optional[str] = None) -> str:
|
||||
"""Compile a generated private source snapshot; never use package headers."""
|
||||
# A failed attempt must not make implicit load_module() reuse older code.
|
||||
_last_ptx_path.set(None)
|
||||
build_dir = build_dir or _last_build_dir.get()
|
||||
def compile_kernel(arch: str = "sm_70", source: str = "uniform.cu",
|
||||
output: Optional[str] = None, *, build_dir: str) -> str:
|
||||
"""Compile the snapshot in build_dir (from generate_config); never package headers."""
|
||||
if not build_dir or not (Path(build_dir) / ".celeris-build").is_file():
|
||||
raise RuntimeError("Call generate_config() and pass its build_dir before compiling")
|
||||
root = Path(build_dir).resolve()
|
||||
@@ -280,23 +268,36 @@ def compile_kernel(arch: str = "sm_70", source: str = "kernel_v2.cu",
|
||||
finally:
|
||||
if os.path.exists(tmp):
|
||||
os.unlink(tmp)
|
||||
_last_ptx_path.set(str(dst))
|
||||
return str(dst)
|
||||
|
||||
|
||||
def load_module(ptx_path: Optional[str] = None):
|
||||
"""Load explicit PTX or the last PTX compiled in this Python context."""
|
||||
ptx_path = ptx_path or _last_ptx_path.get()
|
||||
if not ptx_path:
|
||||
raise RuntimeError("No compiled PTX; call compile_kernel() first")
|
||||
def load_module(ptx_path: str):
|
||||
"""Load one compiled PTX file as a new PyCUDA module."""
|
||||
import pycuda.driver as cuda
|
||||
return cuda.module_from_file(ptx_path)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Back-compat helpers (used by test scripts)
|
||||
# ---------------------------------------------------------------------------
|
||||
def build_module(cfg: LBMConfig, source: str, *, arch: str, n_objects: int = 0,
|
||||
block_root_bc: int = 0):
|
||||
"""Generate, compile and load one private module; the build directory is removed.
|
||||
|
||||
def compile_kernel_v2(arch: str = "sm_70") -> str:
|
||||
"""Alias for compile_kernel() kept for test-script compatibility."""
|
||||
return compile_kernel(arch=arch)
|
||||
The single build path of every owner (Simulation, PeriodicBlockStepper,
|
||||
FixedPatchStepper levels). Each call returns a NEW module: callers must not
|
||||
share it, because its globals (d_params, ...) are mutable per module.
|
||||
"""
|
||||
build_dir = generate_config(cfg, n_objects=n_objects, block_root_bc=block_root_bc)
|
||||
try:
|
||||
return load_module(compile_kernel(arch, source=source, build_dir=build_dir))
|
||||
finally:
|
||||
cleanup_build_dir(build_dir)
|
||||
|
||||
|
||||
def set_params(module, omega: float, fx: float = 0.0, fy: float = 0.0, fz: float = 0.0,
|
||||
n_objects: int = 0) -> None:
|
||||
"""Write the module's __constant__ LBMParams (core/params.cuh layout)."""
|
||||
import struct
|
||||
import pycuda.driver as cuda
|
||||
ptr, size = module.get_global("d_params")
|
||||
if size != struct.calcsize("=ffffI"):
|
||||
raise RuntimeError("LBMParams host/device layout mismatch")
|
||||
cuda.memcpy_htod(ptr, struct.pack("=ffffI", omega, fx, fy, fz, n_objects))
|
||||
|
||||
@@ -12,7 +12,6 @@ parameter mutation; wall/slot/inlet fields in cfg are ignored.
|
||||
"""
|
||||
from dataclasses import replace
|
||||
from numbers import Integral
|
||||
import struct
|
||||
from threading import RLock
|
||||
|
||||
import numpy as np
|
||||
@@ -129,16 +128,8 @@ class PeriodicBlockStepper:
|
||||
config.validate()
|
||||
if not np.isclose(config.omega, 1 / (3 * checked.viscosity + .5), rtol=1e-14, atol=0):
|
||||
raise RuntimeError("block omega/tau mismatch")
|
||||
build = compiler.generate_config(config)
|
||||
try:
|
||||
ptx = compiler.compile_kernel(self.ctx.sm_arch, source="blocks.cu", build_dir=build)
|
||||
module = compiler.load_module(ptx)
|
||||
finally:
|
||||
compiler.cleanup_build_dir(build)
|
||||
ptr, size = module.get_global("d_params")
|
||||
if size != struct.calcsize("=ffffI"):
|
||||
raise RuntimeError("LBMParams host/device layout mismatch")
|
||||
cuda.memcpy_htod(ptr, struct.pack("=ffffI", config.omega, 0, 0, 0, 0))
|
||||
module = compiler.build_module(config, "blocked.cu", arch=self.ctx.sm_arch)
|
||||
compiler.set_params(module, config.omega)
|
||||
self._module = module
|
||||
self._current = self._allocate(self._bytes)
|
||||
self._spare = self._allocate(self._bytes)
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// CelerisLab/lbm/kernels/blocked.cu
|
||||
// One fixed-size blocked level (lbm/blocks.py layout), specialized at compile
|
||||
// time for periodic/fine, slot/reservoir or channel stepping. Separate
|
||||
// compilation entry: NX, NY are the block window including halo, so index_f
|
||||
// and linear_index address one block; blockIdx.z selects the block, whose
|
||||
// populations start at b*NQ*TOTAL_CELLS (block-contiguous, Q-major inside).
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include "config.h"
|
||||
#include "core/precision.cuh"
|
||||
#include "core/descriptors.cuh"
|
||||
#include "core/layout.cuh"
|
||||
#include "core/params.cuh"
|
||||
#include "core/flags.cuh"
|
||||
#include "core/obs.cuh"
|
||||
#include "core/cell_kind.cuh"
|
||||
#include "operators/macro.cuh"
|
||||
#include "operators/collision_srt.cuh"
|
||||
#if COLLISION_MODEL == 2
|
||||
#include "operators/collision_mrt.cuh"
|
||||
#endif
|
||||
#include "streaming/pull_double_buffer.cuh"
|
||||
#include "boundary/curved_boundary.cuh"
|
||||
|
||||
#if DIM != 2 || NQ != 9 || (COLLISION_MODEL != 0 && COLLISION_MODEL != 2) || STORE_PRECISION != 0 || USE_LES || STREAMING_MODEL != 0
|
||||
#error "Blocks require FP32 D2Q9 SRT or MRT double buffers without LES"
|
||||
#endif
|
||||
#ifndef BLOCK_ROOT_BC
|
||||
#error "Blocks require a generated BLOCK_ROOT_BC mode"
|
||||
#elif BLOCK_ROOT_BC < 0 || BLOCK_ROOT_BC > 2
|
||||
#error "BLOCK_ROOT_BC must be 0, 1 or 2"
|
||||
#endif
|
||||
|
||||
#if BLOCK_ROOT_BC == 1
|
||||
#include "boundary/block_wall.cuh"
|
||||
#endif
|
||||
#if BLOCK_ROOT_BC != 2
|
||||
#include "operators/block_collision.cuh"
|
||||
#endif
|
||||
|
||||
// Kernels, in definition order: transfers, boundary staging, then the one full
|
||||
// step selected for this module (BlockStep, or BlockChannelStep for a channel root).
|
||||
#include "step/block_transfer.cu"
|
||||
#include "step/block_boundary.cu"
|
||||
#if BLOCK_ROOT_BC != 2
|
||||
#include "step/block_step.cu"
|
||||
#else
|
||||
#include "step/block_channel.cu"
|
||||
#endif
|
||||
@@ -1,190 +0,0 @@
|
||||
// CelerisLab/lbm/kernels/blocks.cu
|
||||
// One fixed-size blocked level (lbm/blocks.py layout), specialized at compile
|
||||
// time for periodic/fine, slot/reservoir or channel stepping. Separate
|
||||
// compilation entry: NX, NY are the block window including halo, so index_f
|
||||
// and linear_index address one block; blockIdx.z selects the block, whose
|
||||
// populations start at b*NQ*TOTAL_CELLS (block-contiguous, Q-major inside).
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include "config.h"
|
||||
#include "core/precision.cuh"
|
||||
#include "core/descriptors.cuh"
|
||||
#include "core/layout.cuh"
|
||||
#include "core/params.cuh"
|
||||
#include "core/flags.cuh"
|
||||
#include "core/obs.cuh"
|
||||
#include "core/cell_kind.cuh"
|
||||
#include "operators/macro.cuh"
|
||||
#include "operators/collision_srt.cuh"
|
||||
#if COLLISION_MODEL == 2
|
||||
#include "operators/collision_mrt.cuh"
|
||||
#endif
|
||||
#include "streaming/pull_double_buffer.cuh"
|
||||
#include "boundary/curved_boundary.cuh"
|
||||
|
||||
#if DIM != 2 || NQ != 9 || (COLLISION_MODEL != 0 && COLLISION_MODEL != 2) || STORE_PRECISION != 0 || USE_LES || STREAMING_MODEL != 0
|
||||
#error "Blocks require FP32 D2Q9 SRT or MRT double buffers without LES"
|
||||
#endif
|
||||
#ifndef BLOCK_ROOT_BC
|
||||
#error "Blocks require a generated BLOCK_ROOT_BC mode"
|
||||
#elif BLOCK_ROOT_BC < 0 || BLOCK_ROOT_BC > 2
|
||||
#error "BLOCK_ROOT_BC must be 0, 1 or 2"
|
||||
#endif
|
||||
|
||||
#if BLOCK_ROOT_BC == 1
|
||||
#include "boundary/block_wall.cuh"
|
||||
#endif
|
||||
#if BLOCK_ROOT_BC != 2
|
||||
#include "operators/block_collision.cuh"
|
||||
#endif
|
||||
|
||||
// Halo refresh: block cell ids b*TOTAL_CELLS+c, sources are always core cells.
|
||||
extern "C" __global__ void BlockHaloCopy(
|
||||
fpxx* f, const uint64_t* dst, const uint64_t* src, unsigned int count)
|
||||
{
|
||||
unsigned int row = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (row >= count) return;
|
||||
const uint64_t d = dst[row], s = src[row];
|
||||
fpxx* to = f + (d / TOTAL_CELLS) * NQ * TOTAL_CELLS;
|
||||
const fpxx* from = f + (s / TOTAL_CELLS) * NQ * TOTAL_CELLS;
|
||||
for (unsigned int q = 0; q < NQ; ++q)
|
||||
to[index_f(d % TOTAL_CELLS, q)] = from[index_f(s % TOTAL_CELLS, q)];
|
||||
}
|
||||
|
||||
// Fixed-patch explosion into blocked fine storage: target = owner block cell
|
||||
// id of a patch-ghost cell; donors are parent block cell ids. Dense parent
|
||||
// storage is the one-window case with coarse_cells = full domain size.
|
||||
extern "C" __global__ void BlockExplode(
|
||||
const fpxx* coarse, fpxx* fine, const uint64_t* target, const uint64_t* donor,
|
||||
unsigned int count, unsigned long coarse_cells)
|
||||
{
|
||||
unsigned int row = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (row >= count) return;
|
||||
const uint64_t t = target[row];
|
||||
fpxx* to = fine + (t / TOTAL_CELLS) * NQ * TOTAL_CELLS;
|
||||
const uint64_t d = donor[row];
|
||||
const fpxx* from = coarse + (d / coarse_cells) * NQ * coarse_cells;
|
||||
for (unsigned int q = 0; q < NQ; ++q)
|
||||
to[index_f(t % TOTAL_CELLS, q)] = from[q * coarse_cells + d % coarse_cells];
|
||||
}
|
||||
|
||||
// Experimental Schornbaum--Ruede (arXiv:1508.07982, Algorithm 2)
|
||||
// and Chen et al. (doi:10.1016/j.physa.2005.09.036) population interpolation.
|
||||
// Independent implementation of the mathematical stencil; no upstream source copied.
|
||||
// Stencil cells are owner cores; a disabled axis repeats its center twice.
|
||||
extern "C" __global__ void BlockExplodeProjected(
|
||||
const fpxx* coarse, fpxx* fine, const uint64_t* target, const uint64_t* donor,
|
||||
unsigned int count, unsigned long coarse_cells,
|
||||
const uint64_t* neighbors, const float* offsets)
|
||||
{
|
||||
unsigned int row = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (row >= count) return;
|
||||
const uint64_t t = target[row], d = donor[row];
|
||||
fpxx* to = fine + (t / TOTAL_CELLS) * NQ * TOTAL_CELLS;
|
||||
for (unsigned int q = 0; q < NQ; ++q) {
|
||||
float v[4];
|
||||
for (unsigned int a = 0; a < 4; ++a) {
|
||||
const uint64_t n = neighbors[4ul * row + a];
|
||||
v[a] = coarse[(n / coarse_cells) * NQ * coarse_cells
|
||||
+ q * coarse_cells + n % coarse_cells];
|
||||
}
|
||||
float gx = .5f * (v[1] - v[0]), gy = .5f * (v[3] - v[2]);
|
||||
const float ex = d_cx[q], ey = d_cy[q];
|
||||
if (q != 0) {
|
||||
const float along = (ex * gx + ey * gy) / (ex * ex + ey * ey);
|
||||
gx -= ex * along;
|
||||
gy -= ey * along;
|
||||
}
|
||||
to[index_f(t % TOTAL_CELLS, q)] =
|
||||
coarse[(d / coarse_cells) * NQ * coarse_cells + q * coarse_cells + d % coarse_cells]
|
||||
+ offsets[2ul * row] * gx + offsets[2ul * row + 1] * gy;
|
||||
}
|
||||
}
|
||||
|
||||
// Targets are receiver-local SOURCE slots for the immediately following pull.
|
||||
// Keep child summation order identical to PatchCoarseStep; no collision here.
|
||||
extern "C" __global__ void BlockCoalesce(
|
||||
const fpxx* fine, fpxx* coarse, const uint64_t* target, const uint64_t* children,
|
||||
unsigned int count)
|
||||
{
|
||||
unsigned int row = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (row >= count) return;
|
||||
const uint64_t* s = children + 4ul * row;
|
||||
coarse[target[row]] = 0.25f * (fine[s[0]] + fine[s[1]] + fine[s[2]] + fine[s[3]]);
|
||||
}
|
||||
|
||||
// Static cut links, receiver-local staging: cell is the receiver's local core
|
||||
// cell, so the existing BFL writes the solid-source window image that this
|
||||
// block's next pull reads (no halo copy between this kernel and BlockStep).
|
||||
// surface_velocity (nullable, 2 floats per link): prescribed fluid velocity on
|
||||
// fixed geometry, same convention as CurvedBoundaryKernel. Optional raw rows
|
||||
// (jx,jy,torque,dm) are unique physical links, never body-observation slots.
|
||||
extern "C" __global__ void BlockCurvedBoundary(
|
||||
fpxx* f, const uint32_t* block, const uint32_t* cell, const unsigned char* dir,
|
||||
const float* q, const unsigned char* fallback, unsigned int count,
|
||||
const float* surface_velocity, const float* rx, const float* ry, float* raw)
|
||||
{
|
||||
unsigned int row = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (row >= count) return;
|
||||
float Uw = 0.0f, Vw = 0.0f;
|
||||
if (surface_velocity != nullptr) {
|
||||
const float u = surface_velocity[2 * row], v = surface_velocity[2 * row + 1];
|
||||
if (u != 0.0f || v != 0.0f) { Uw = u; Vw = v; }
|
||||
}
|
||||
apply_bouzidi_link(dir[row], q[row], cell[row], f + (unsigned long)block[row] * NQ * TOTAL_CELLS,
|
||||
Uw, Vw, rx ? rx[row] : 0.0f, ry ? ry[row] : 0.0f,
|
||||
fallback[row], nullptr, -1, raw ? raw + 4ul * row : nullptr,
|
||||
raw ? raw + 4ul * row + 3 : nullptr);
|
||||
}
|
||||
|
||||
// Same-stream BFL -> this row-owned accumulation -> pull step. No atomics,
|
||||
// no cross-row reduction and no history allocation proportional to substeps.
|
||||
extern "C" __global__ void BlockAccumulateExchange(
|
||||
const float* raw, double* integral, unsigned int count, double h, double dt)
|
||||
{
|
||||
unsigned int row = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (row >= count) return;
|
||||
const unsigned long k = 4ul * row;
|
||||
const double impulse = h * dt;
|
||||
integral[k] += impulse * (double)raw[k];
|
||||
integral[k + 1] += impulse * (double)raw[k + 1];
|
||||
integral[k + 2] += h * impulse * (double)raw[k + 2];
|
||||
integral[k + 3] += h * h * (double)raw[k + 3];
|
||||
}
|
||||
|
||||
#if BLOCK_ROOT_BC != 2
|
||||
// Pull/collide/store core cells only; halo cells of out are left untouched.
|
||||
// flags (block cell ids, nullable): solid cores store NaN and never collide.
|
||||
// kind (block cell ids, nullable = all ACTIVE): OUTER skips the pull and
|
||||
// stores NaN, INNER pulls without collision, ACTIVE pulls and collides.
|
||||
extern "C" __global__ void BlockStep(const fpxx* in, fpxx* out, unsigned int halo,
|
||||
const uint16_t* flags, const unsigned char* kind) {
|
||||
unsigned int x, y; unsigned long k;
|
||||
index_from_thread(x, y, k);
|
||||
if (x < halo || y < halo || x >= NX - halo || y >= NY - halo) return;
|
||||
const unsigned long base = (unsigned long)blockIdx.z * NQ * TOTAL_CELLS;
|
||||
const unsigned long cell = (unsigned long)blockIdx.z * TOTAL_CELLS + k;
|
||||
const unsigned char cell_kind = kind != nullptr ? kind[cell] : KIND_ACTIVE;
|
||||
float f[NQ];
|
||||
if (cell_kind == KIND_OUTER || (flags != nullptr && is_solid(flags[cell]))) {
|
||||
for (int q = 0; q < NQ; ++q) f[q] = NAN;
|
||||
} else {
|
||||
unsigned long j[NQ];
|
||||
compute_neighbors(x, y, j); // Core neighbors stay inside the window: no wrap.
|
||||
stream_pull_load(k, f, in + base, j);
|
||||
if (cell_kind == KIND_ACTIVE) {
|
||||
#if BLOCK_ROOT_BC == 1
|
||||
block_wall(f, x, y, halo);
|
||||
#endif
|
||||
block_collide(f);
|
||||
}
|
||||
}
|
||||
stream_pull_store(k, f, out + base);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Root channel is a replacement full step, selected once by the host.
|
||||
#if BLOCK_ROOT_BC == 2
|
||||
#include "step/block_channel.cu"
|
||||
#endif
|
||||
@@ -15,10 +15,13 @@
|
||||
// D2Q9 y-wall half-way bounce-back for pull double-buffer streaming.
|
||||
// ---------------------------------------------------------------------------
|
||||
#if LATTICE_MODEL == LATTICE_D2Q9
|
||||
__device__ inline void apply_wall_bb_d2q9_y_pull(unsigned int y,
|
||||
float* __restrict__ f,
|
||||
const fpxx* __restrict__ fi_in,
|
||||
unsigned long k)
|
||||
// Rows 1 and top_row (= physical ny - 2) next to walls at rows 0 and ny - 1.
|
||||
// y is the physical row; k addresses the node in fi_in (a block window may
|
||||
// have NX/NY strides different from the physical extent).
|
||||
__device__ inline void apply_wall_bb_d2q9_rows(unsigned int y, unsigned int top_row,
|
||||
float* __restrict__ f,
|
||||
const fpxx* __restrict__ fi_in,
|
||||
unsigned long k)
|
||||
{
|
||||
if (y == 1) {
|
||||
// Directions sourced from y=0 wall in pull step: +y, +x+y, -x+y.
|
||||
@@ -26,14 +29,22 @@ __device__ inline void apply_wall_bb_d2q9_y_pull(unsigned int y,
|
||||
f[5] = load_ddf(fi_in, index_f(k, 6u));
|
||||
f[8] = load_ddf(fi_in, index_f(k, 7u));
|
||||
}
|
||||
else if (y == (unsigned int)(NY - 2)) {
|
||||
// Directions sourced from y=NY-1 wall in pull step: -y, -x-y, +x-y.
|
||||
else if (y == top_row) {
|
||||
// Directions sourced from the y = ny - 1 wall in pull step: -y, -x-y, +x-y.
|
||||
f[4] = load_ddf(fi_in, index_f(k, 3u));
|
||||
f[6] = load_ddf(fi_in, index_f(k, 5u));
|
||||
f[7] = load_ddf(fi_in, index_f(k, 8u));
|
||||
}
|
||||
}
|
||||
|
||||
__device__ inline void apply_wall_bb_d2q9_y_pull(unsigned int y,
|
||||
float* __restrict__ f,
|
||||
const fpxx* __restrict__ fi_in,
|
||||
unsigned long k)
|
||||
{
|
||||
apply_wall_bb_d2q9_rows(y, (unsigned int)(NY - 2), f, fi_in, k);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// D2Q9 y-wall free-slip (specular reflection) for pull double-buffer streaming.
|
||||
//
|
||||
|
||||
@@ -7,4 +7,10 @@
|
||||
|
||||
constexpr unsigned char KIND_ACTIVE = 0u, KIND_INNER = 1u, KIND_OUTER = 2u;
|
||||
|
||||
// NaN populations mark a cell without valid state (OUTER ghost or solid core).
|
||||
__device__ __forceinline__ void fill_invalid(float* f)
|
||||
{
|
||||
for (int q = 0; q < NQ; ++q) f[q] = NAN;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// CelerisLab – operators/bounce_back_swap.cuh
|
||||
// Full-way bounce-back at a wall node: swap every opposite pair (paired
|
||||
// order q, q+1). Needs only NQ; shared by the uniform and blocked steps.
|
||||
#ifndef CELERIS_OPERATORS_BOUNCE_BACK_SWAP_CUH
|
||||
#define CELERIS_OPERATORS_BOUNCE_BACK_SWAP_CUH
|
||||
|
||||
__device__ __forceinline__ void bounce_back_swap(float* f) {
|
||||
#pragma unroll
|
||||
for (int i = 1; i < NQ; i += 2) {
|
||||
float t = f[i]; f[i] = f[i+1]; f[i+1] = t;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -5,12 +5,7 @@
|
||||
#ifndef CELERIS_OPERATORS_HELPERS_CUH
|
||||
#define CELERIS_OPERATORS_HELPERS_CUH
|
||||
|
||||
__device__ __forceinline__ void bounce_back_swap(float* f) {
|
||||
#pragma unroll
|
||||
for (int i = 1; i < NQ; i += 2) {
|
||||
float t = f[i]; f[i] = f[i+1]; f[i+1] = t;
|
||||
}
|
||||
}
|
||||
#include "bounce_back_swap.cuh"
|
||||
|
||||
__device__ __forceinline__ void collide_dispatch(
|
||||
float* f, float rho_n,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "core/params.cuh"
|
||||
#include "core/flags.cuh"
|
||||
#include "core/obs.cuh"
|
||||
#include "core/cell_kind.cuh"
|
||||
#include "operators/macro.cuh"
|
||||
#include "operators/collision_srt.cuh"
|
||||
#if COLLISION_MODEL == 2
|
||||
@@ -35,93 +36,5 @@ __device__ unsigned int incoming_counts[NQ * TOTAL_CELLS];
|
||||
}
|
||||
#endif
|
||||
|
||||
__device__ __forceinline__ void patch_collide(float* f, unsigned long k) {
|
||||
#if COLLISION_MODEL == 2
|
||||
collide_mrt_unforced(f);
|
||||
#else
|
||||
float rho, ux, uy, feq[NQ];
|
||||
compute_rho_u(f, rho, ux, uy);
|
||||
compute_feq(rho, ux, uy, feq);
|
||||
collide_srt_no_force(f, feq, d_params.omega);
|
||||
#endif
|
||||
#ifdef CELERIS_REFINEMENT_AUDIT
|
||||
++collision_counts[k];
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" __global__ void PatchExplode(
|
||||
const float* coarse, float* fine, const uint32_t* targets,
|
||||
const uint32_t* donors, unsigned int count, unsigned long coarse_cells)
|
||||
{
|
||||
unsigned int row = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (row >= count) return;
|
||||
for (unsigned int q = 0; q < NQ; ++q)
|
||||
fine[index_f(targets[row], q)] = coarse[q * coarse_cells + donors[row]];
|
||||
#ifdef CELERIS_REFINEMENT_AUDIT
|
||||
++explosion_counts[targets[row]];
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" __global__ void PatchFineStep(const float* in, float* out, const uint16_t* flags) {
|
||||
unsigned int x, y; unsigned long k;
|
||||
index_from_thread(x, y, k);
|
||||
if (x >= NX || y >= NY) return;
|
||||
float f[NQ];
|
||||
// Outer halo is invalid after EACH hop, including when reusing the buffer
|
||||
// that held explosion data. Inner halo only streams; it never collides.
|
||||
if (x < 2 || y < 2 || x >= NX - 2 || y >= NY - 2
|
||||
|| (flags != nullptr && is_solid(flags[k]))) {
|
||||
for (int q = 0; q < NQ; ++q) f[q] = NAN;
|
||||
} else {
|
||||
unsigned long j[NQ];
|
||||
compute_neighbors(x, y, j); // These interior targets never wrap.
|
||||
stream_pull_load(k, f, in, j);
|
||||
if (x >= 4 && y >= 4 && x < NX - 4 && y < NY - 4)
|
||||
patch_collide(f, k);
|
||||
}
|
||||
stream_pull_store(k, f, out);
|
||||
}
|
||||
|
||||
extern "C" __global__ void PatchCoarseStep(
|
||||
const float* in, float* out, const float* fine,
|
||||
const uint64_t* targets, const uint64_t* children, unsigned int count,
|
||||
unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1,
|
||||
unsigned int wall_aware)
|
||||
{
|
||||
unsigned int x, y; unsigned long k;
|
||||
index_from_thread(x, y, k);
|
||||
if (x >= NX || y >= NY) return;
|
||||
// Both buffers were poisoned at initialization; covered cells stay invalid.
|
||||
if (x >= x0 && x < x1 && y >= y0 && y < y1) return;
|
||||
if (wall_aware && (y == 0 || y == NY - 1)) return;
|
||||
unsigned long j[NQ];
|
||||
compute_neighbors(x, y, j);
|
||||
float f[NQ];
|
||||
stream_pull_load(k, f, in, j);
|
||||
if (x >= x0 - 1 && x <= x1 && y >= y0 - 1 && y <= y1) {
|
||||
for (unsigned int q = 1; q < NQ; ++q) {
|
||||
uint64_t slot = index_f(k, q);
|
||||
unsigned int lo = 0, hi = count;
|
||||
while (lo < hi) {
|
||||
unsigned int mid = lo + (hi - lo) / 2;
|
||||
if (targets[mid] < slot) lo = mid + 1;
|
||||
else hi = mid;
|
||||
}
|
||||
if (lo < count && targets[lo] == slot) {
|
||||
const uint64_t* s = children + 4ul * lo;
|
||||
f[q] = 0.25f * (fine[s[0]] + fine[s[1]] + fine[s[2]] + fine[s[3]]);
|
||||
#ifdef CELERIS_REFINEMENT_AUDIT
|
||||
++incoming_counts[slot];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
// Includes the eight grazing-corner links with UNCOVERED coarse donors.
|
||||
// All replacement arrivals must be in place before computing rho/u.
|
||||
if (wall_aware) {
|
||||
if (y == 1) reconstruct_bottom_velocity(f, 0.0f, bottom_wall_normal_velocity(x));
|
||||
else if (y == NY - 2) reconstruct_top_reservoir(f, RHO);
|
||||
}
|
||||
patch_collide(f, k);
|
||||
stream_pull_store(k, f, out);
|
||||
}
|
||||
// Kernels: patch collision helper, PatchExplode, PatchFineStep, PatchCoarseStep.
|
||||
#include "step/patch_step.cu"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// ApplyEsoPullCurvedKernel, SensorKernel, ForceRegionKernel.
|
||||
//
|
||||
// Launched on compact lists (n_curved / n_sensor / n_cells threads).
|
||||
// Included by kernel_v2.cu. No standalone compilation.
|
||||
// Included by uniform.cu. No standalone compilation.
|
||||
//
|
||||
// Double-buffer mode:
|
||||
// CurvedBoundaryKernel runs BEFORE OneStep.
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// CelerisLab/lbm/kernels/step/block_boundary.cu
|
||||
// Receiver-local curved-boundary staging and its raw-exchange accumulation.
|
||||
// Part of the blocked.cu compilation entry; relies on its includes and guards.
|
||||
|
||||
// Static cut links, receiver-local staging: cell is the receiver's local core
|
||||
// cell, so the existing BFL writes the solid-source window image that this
|
||||
// block's next pull reads (no halo copy between this kernel and BlockStep).
|
||||
// surface_velocity (nullable, 2 floats per link): prescribed fluid velocity on
|
||||
// fixed geometry, same convention as CurvedBoundaryKernel. Optional raw rows
|
||||
// (jx,jy,torque,dm) are unique physical links, never body-observation slots.
|
||||
extern "C" __global__ void BlockCurvedBoundary(
|
||||
fpxx* f, const uint32_t* block, const uint32_t* cell, const unsigned char* dir,
|
||||
const float* q, const unsigned char* fallback, unsigned int count,
|
||||
const float* surface_velocity, const float* rx, const float* ry, float* raw)
|
||||
{
|
||||
unsigned int row = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (row >= count) return;
|
||||
float Uw = 0.0f, Vw = 0.0f;
|
||||
if (surface_velocity != nullptr) {
|
||||
const float u = surface_velocity[2 * row], v = surface_velocity[2 * row + 1];
|
||||
if (u != 0.0f || v != 0.0f) { Uw = u; Vw = v; }
|
||||
}
|
||||
apply_bouzidi_link(dir[row], q[row], cell[row], f + (unsigned long)block[row] * NQ * TOTAL_CELLS,
|
||||
Uw, Vw, rx ? rx[row] : 0.0f, ry ? ry[row] : 0.0f,
|
||||
fallback[row], nullptr, -1, raw ? raw + 4ul * row : nullptr,
|
||||
raw ? raw + 4ul * row + 3 : nullptr);
|
||||
}
|
||||
|
||||
// Same-stream BFL -> this row-owned accumulation -> pull step. No atomics,
|
||||
// no cross-row reduction and no history allocation proportional to substeps.
|
||||
extern "C" __global__ void BlockAccumulateExchange(
|
||||
const float* raw, double* integral, unsigned int count, double h, double dt)
|
||||
{
|
||||
unsigned int row = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (row >= count) return;
|
||||
const unsigned long k = 4ul * row;
|
||||
const double impulse = h * dt;
|
||||
integral[k] += impulse * (double)raw[k];
|
||||
integral[k + 1] += impulse * (double)raw[k + 1];
|
||||
integral[k + 2] += h * impulse * (double)raw[k + 2];
|
||||
integral[k + 3] += h * h * (double)raw[k + 3];
|
||||
}
|
||||
@@ -5,6 +5,8 @@
|
||||
// Root-only blocked counterpart of OneStep's D2Q9/SRT channel closure.
|
||||
// NX/NY are LOCAL strides; all physical boundary decisions use global coordinates.
|
||||
#include "../core/cell_kind.cuh"
|
||||
#include "../operators/bounce_back_swap.cuh"
|
||||
#include "../boundary/bounce_back.cuh"
|
||||
#include "../boundary/inlet/common.cuh"
|
||||
#include "../boundary/inlet/zou_he_local.cuh"
|
||||
#include "../boundary/outlet/pressure_neq.cuh"
|
||||
@@ -26,7 +28,7 @@ extern "C" __global__ void BlockChannelStep(
|
||||
const unsigned long cell = (unsigned long)blockIdx.z * TOTAL_CELLS + k;
|
||||
float f[NQ];
|
||||
if (kind != nullptr && kind[cell] == KIND_OUTER) {
|
||||
for (int q = 0; q < NQ; ++q) f[q] = NAN;
|
||||
fill_invalid(f);
|
||||
} else {
|
||||
unsigned long j[NQ];
|
||||
compute_neighbors(x, y, j);
|
||||
@@ -34,27 +36,17 @@ extern "C" __global__ void BlockChannelStep(
|
||||
const bool wall = gy == 0 || gy == d_block_channel.ny - 1;
|
||||
const bool outlet = gx == d_block_channel.nx - 1;
|
||||
if (wall) {
|
||||
// Wall owns all four corners. Ghosts pull and swap, never collide.
|
||||
for (int q = 1; q < NQ; q += 2) {
|
||||
const float t = f[q]; f[q] = f[q + 1]; f[q + 1] = t;
|
||||
}
|
||||
bounce_back_swap(f); // Wall owns all four corners; ghosts never collide.
|
||||
} else if (gx == 0) {
|
||||
apply_zou_he_left_velocity_inlet_d2q9(
|
||||
f, inlet_target_u((float)gy, d_block_channel.ny, d_block_channel.velocity), 0.0f);
|
||||
} else if (outlet) {
|
||||
// Immutable input donor, receiver-local (also valid across a block seam).
|
||||
float donor[NQ];
|
||||
for (int q = 0; q < NQ; ++q)
|
||||
donor[q] = load_ddf(in + base, index_f(k - 1, q));
|
||||
load_node(in + base, k - 1, donor);
|
||||
apply_pressure_outlet_d2q9(f, donor);
|
||||
} else if (gy == 1) {
|
||||
f[3] = load_ddf(in + base, index_f(k, 4));
|
||||
f[5] = load_ddf(in + base, index_f(k, 6));
|
||||
f[8] = load_ddf(in + base, index_f(k, 7));
|
||||
} else if (gy == d_block_channel.ny - 2) {
|
||||
f[4] = load_ddf(in + base, index_f(k, 3));
|
||||
f[6] = load_ddf(in + base, index_f(k, 5));
|
||||
f[7] = load_ddf(in + base, index_f(k, 8));
|
||||
} else {
|
||||
apply_wall_bb_d2q9_rows(gy, d_block_channel.ny - 2, f, in + base, k);
|
||||
}
|
||||
if (!wall && !outlet) {
|
||||
#if COLLISION_MODEL == 2
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// CelerisLab/lbm/kernels/step/block_step.cu
|
||||
// Generic blocked pull/collide/store for periodic/fine and slot/reservoir levels.
|
||||
// Part of the blocked.cu compilation entry; relies on its includes and guards.
|
||||
#if BLOCK_ROOT_BC == 2
|
||||
#error "BlockStep is not built for the channel root (BLOCK_ROOT_BC == 2)"
|
||||
#endif
|
||||
|
||||
// Pull/collide/store core cells only; halo cells of out are left untouched.
|
||||
// flags (block cell ids, nullable): solid cores store NaN and never collide.
|
||||
// kind (block cell ids, nullable = all ACTIVE): OUTER skips the pull and
|
||||
// stores NaN, INNER pulls without collision, ACTIVE pulls and collides.
|
||||
extern "C" __global__ void BlockStep(const fpxx* in, fpxx* out, unsigned int halo,
|
||||
const uint16_t* flags, const unsigned char* kind) {
|
||||
unsigned int x, y; unsigned long k;
|
||||
index_from_thread(x, y, k);
|
||||
if (x < halo || y < halo || x >= NX - halo || y >= NY - halo) return;
|
||||
const unsigned long base = (unsigned long)blockIdx.z * NQ * TOTAL_CELLS;
|
||||
const unsigned long cell = (unsigned long)blockIdx.z * TOTAL_CELLS + k;
|
||||
const unsigned char cell_kind = kind != nullptr ? kind[cell] : KIND_ACTIVE;
|
||||
float f[NQ];
|
||||
if (cell_kind == KIND_OUTER || (flags != nullptr && is_solid(flags[cell]))) {
|
||||
fill_invalid(f);
|
||||
} else {
|
||||
unsigned long j[NQ];
|
||||
compute_neighbors(x, y, j); // Core neighbors stay inside the window: no wrap.
|
||||
stream_pull_load(k, f, in + base, j);
|
||||
if (cell_kind == KIND_ACTIVE) {
|
||||
#if BLOCK_ROOT_BC == 1
|
||||
block_wall(f, x, y, halo);
|
||||
#endif
|
||||
block_collide(f);
|
||||
}
|
||||
}
|
||||
stream_pull_store(k, f, out + base);
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// CelerisLab/lbm/kernels/step/block_transfer.cu
|
||||
// Same-level halo refresh and 2:1 explosion/coalescence between blocked levels.
|
||||
// Part of the blocked.cu compilation entry; relies on its includes and guards.
|
||||
|
||||
// Halo refresh: block cell ids b*TOTAL_CELLS+c, sources are always core cells.
|
||||
extern "C" __global__ void BlockHaloCopy(
|
||||
fpxx* f, const uint64_t* dst, const uint64_t* src, unsigned int count)
|
||||
{
|
||||
unsigned int row = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (row >= count) return;
|
||||
const uint64_t d = dst[row], s = src[row];
|
||||
fpxx* to = f + (d / TOTAL_CELLS) * NQ * TOTAL_CELLS;
|
||||
const fpxx* from = f + (s / TOTAL_CELLS) * NQ * TOTAL_CELLS;
|
||||
for (unsigned int q = 0; q < NQ; ++q)
|
||||
to[index_f(d % TOTAL_CELLS, q)] = from[index_f(s % TOTAL_CELLS, q)];
|
||||
}
|
||||
|
||||
// Fixed-patch explosion into blocked fine storage: target = owner block cell
|
||||
// id of a patch-ghost cell; donors are parent block cell ids. Dense parent
|
||||
// storage is the one-window case with coarse_cells = full domain size.
|
||||
extern "C" __global__ void BlockExplode(
|
||||
const fpxx* coarse, fpxx* fine, const uint64_t* target, const uint64_t* donor,
|
||||
unsigned int count, unsigned long coarse_cells)
|
||||
{
|
||||
unsigned int row = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (row >= count) return;
|
||||
const uint64_t t = target[row];
|
||||
fpxx* to = fine + (t / TOTAL_CELLS) * NQ * TOTAL_CELLS;
|
||||
const uint64_t d = donor[row];
|
||||
const fpxx* from = coarse + (d / coarse_cells) * NQ * coarse_cells;
|
||||
for (unsigned int q = 0; q < NQ; ++q)
|
||||
to[index_f(t % TOTAL_CELLS, q)] = from[q * coarse_cells + d % coarse_cells];
|
||||
}
|
||||
|
||||
// Experimental Schornbaum--Ruede (arXiv:1508.07982, Algorithm 2)
|
||||
// and Chen et al. (doi:10.1016/j.physa.2005.09.036) population interpolation.
|
||||
// Independent implementation of the mathematical stencil; no upstream source copied.
|
||||
// Stencil cells are owner cores; a disabled axis repeats its center twice.
|
||||
extern "C" __global__ void BlockExplodeProjected(
|
||||
const fpxx* coarse, fpxx* fine, const uint64_t* target, const uint64_t* donor,
|
||||
unsigned int count, unsigned long coarse_cells,
|
||||
const uint64_t* neighbors, const float* offsets)
|
||||
{
|
||||
unsigned int row = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (row >= count) return;
|
||||
const uint64_t t = target[row], d = donor[row];
|
||||
fpxx* to = fine + (t / TOTAL_CELLS) * NQ * TOTAL_CELLS;
|
||||
for (unsigned int q = 0; q < NQ; ++q) {
|
||||
float v[4];
|
||||
for (unsigned int a = 0; a < 4; ++a) {
|
||||
const uint64_t n = neighbors[4ul * row + a];
|
||||
v[a] = coarse[(n / coarse_cells) * NQ * coarse_cells
|
||||
+ q * coarse_cells + n % coarse_cells];
|
||||
}
|
||||
float gx = .5f * (v[1] - v[0]), gy = .5f * (v[3] - v[2]);
|
||||
const float ex = d_cx[q], ey = d_cy[q];
|
||||
if (q != 0) {
|
||||
const float along = (ex * gx + ey * gy) / (ex * ex + ey * ey);
|
||||
gx -= ex * along;
|
||||
gy -= ey * along;
|
||||
}
|
||||
to[index_f(t % TOTAL_CELLS, q)] =
|
||||
coarse[(d / coarse_cells) * NQ * coarse_cells + q * coarse_cells + d % coarse_cells]
|
||||
+ offsets[2ul * row] * gx + offsets[2ul * row + 1] * gy;
|
||||
}
|
||||
}
|
||||
|
||||
// Targets are receiver-local SOURCE slots for the immediately following pull.
|
||||
// Keep child summation order identical to PatchCoarseStep; no collision here.
|
||||
extern "C" __global__ void BlockCoalesce(
|
||||
const fpxx* fine, fpxx* coarse, const uint64_t* target, const uint64_t* children,
|
||||
unsigned int count)
|
||||
{
|
||||
unsigned int row = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (row >= count) return;
|
||||
const uint64_t* s = children + 4ul * row;
|
||||
coarse[target[row]] = 0.25f * (fine[s[0]] + fine[s[1]] + fine[s[2]] + fine[s[3]]);
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Decodes the EsoPull backing layout into physical distributions, then
|
||||
// computes rho/ux/uy. Output is SoA: rho_out[N], ux_out[N], uy_out[N].
|
||||
// Included by kernel_v2.cu. No standalone compilation.
|
||||
// Included by uniform.cu. No standalone compilation.
|
||||
//
|
||||
// This kernel is the sole path for macroscopic diagnostics in EsoPull mode.
|
||||
// It uses the shared semantic helper layer (esopull_semantic_helpers.cuh).
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// or encodes physical DDF back to EsoPull backing layout.
|
||||
// Each thread handles one cell from a compact index list.
|
||||
//
|
||||
// Included by kernel_v2.cu. No standalone compilation.
|
||||
// Included by uniform.cu. No standalone compilation.
|
||||
// ============================================================================
|
||||
|
||||
#ifndef CELERIS_STEP_ESOPULL_SYNC_CU
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// CelerisLab – step/init_flow.cu
|
||||
// Channel-flow initialization kernels (double-buffer and EsoPull).
|
||||
// Included by kernel_v2.cu after all headers. No standalone compilation.
|
||||
// Included by uniform.cu after all headers. No standalone compilation.
|
||||
// ============================================================================
|
||||
|
||||
#ifndef CELERIS_STEP_INIT_FLOW_CU
|
||||
@@ -73,9 +73,9 @@ __device__ __forceinline__ uint16_t finalize_domain_flag(
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// InitTubeFlow_v2 — double-buffer channel initialization
|
||||
// InitTubeFlow — double-buffer channel initialization
|
||||
// ============================================================================
|
||||
__global__ void InitTubeFlow_v2(uint16_t* flag, fpxx* fi)
|
||||
__global__ void InitTubeFlow(uint16_t* flag, fpxx* fi)
|
||||
{
|
||||
#if DIM == 2
|
||||
unsigned int x, y; unsigned long k;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// CelerisLab – step/one_step_double.cu
|
||||
// Double-buffer PULL streaming step kernel.
|
||||
// Included by kernel_v2.cu. No standalone compilation.
|
||||
// Included by uniform.cu. No standalone compilation.
|
||||
// ============================================================================
|
||||
|
||||
#ifndef CELERIS_STEP_ONE_STEP_DOUBLE_CU
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// CelerisLab – step/one_step_esopull.cu
|
||||
// Esoteric-Pull single-buffer step kernel.
|
||||
// Included by kernel_v2.cu. No standalone compilation.
|
||||
// Included by uniform.cu. No standalone compilation.
|
||||
//
|
||||
// CURVED BC: supported via PrepareEsoPullCurvedKernel + ApplyEsoPullCurvedKernel
|
||||
// in aux_kernels.cu, launched by stepper.py before EsoPullStep.
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
// CelerisLab/lbm/kernels/step/patch_step.cu
|
||||
// Dense fixed-patch collision, explosion and the fine/coarse steps.
|
||||
// Part of the refinement.cu compilation entry; relies on its includes, guards
|
||||
// and the optional CELERIS_REFINEMENT_AUDIT counters declared there.
|
||||
|
||||
__device__ __forceinline__ void patch_collide(float* f, unsigned long k) {
|
||||
#if COLLISION_MODEL == 2
|
||||
collide_mrt_unforced(f);
|
||||
#else
|
||||
float rho, ux, uy, feq[NQ];
|
||||
compute_rho_u(f, rho, ux, uy);
|
||||
compute_feq(rho, ux, uy, feq);
|
||||
collide_srt_no_force(f, feq, d_params.omega);
|
||||
#endif
|
||||
#ifdef CELERIS_REFINEMENT_AUDIT
|
||||
++collision_counts[k];
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" __global__ void PatchExplode(
|
||||
const float* coarse, float* fine, const uint32_t* targets,
|
||||
const uint32_t* donors, unsigned int count, unsigned long coarse_cells)
|
||||
{
|
||||
unsigned int row = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (row >= count) return;
|
||||
for (unsigned int q = 0; q < NQ; ++q)
|
||||
fine[index_f(targets[row], q)] = coarse[q * coarse_cells + donors[row]];
|
||||
#ifdef CELERIS_REFINEMENT_AUDIT
|
||||
++explosion_counts[targets[row]];
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" __global__ void PatchFineStep(const float* in, float* out, const uint16_t* flags) {
|
||||
unsigned int x, y; unsigned long k;
|
||||
index_from_thread(x, y, k);
|
||||
if (x >= NX || y >= NY) return;
|
||||
float f[NQ];
|
||||
// Outer halo is invalid after EACH hop, including when reusing the buffer
|
||||
// that held explosion data. Inner halo only streams; it never collides.
|
||||
if (x < 2 || y < 2 || x >= NX - 2 || y >= NY - 2
|
||||
|| (flags != nullptr && is_solid(flags[k]))) {
|
||||
fill_invalid(f);
|
||||
} else {
|
||||
unsigned long j[NQ];
|
||||
compute_neighbors(x, y, j); // These interior targets never wrap.
|
||||
stream_pull_load(k, f, in, j);
|
||||
if (x >= 4 && y >= 4 && x < NX - 4 && y < NY - 4)
|
||||
patch_collide(f, k);
|
||||
}
|
||||
stream_pull_store(k, f, out);
|
||||
}
|
||||
|
||||
extern "C" __global__ void PatchCoarseStep(
|
||||
const float* in, float* out, const float* fine,
|
||||
const uint64_t* targets, const uint64_t* children, unsigned int count,
|
||||
unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1,
|
||||
unsigned int wall_aware)
|
||||
{
|
||||
unsigned int x, y; unsigned long k;
|
||||
index_from_thread(x, y, k);
|
||||
if (x >= NX || y >= NY) return;
|
||||
// Both buffers were poisoned at initialization; covered cells stay invalid.
|
||||
if (x >= x0 && x < x1 && y >= y0 && y < y1) return;
|
||||
if (wall_aware && (y == 0 || y == NY - 1)) return;
|
||||
unsigned long j[NQ];
|
||||
compute_neighbors(x, y, j);
|
||||
float f[NQ];
|
||||
stream_pull_load(k, f, in, j);
|
||||
if (x >= x0 - 1 && x <= x1 && y >= y0 - 1 && y <= y1) {
|
||||
for (unsigned int q = 1; q < NQ; ++q) {
|
||||
uint64_t slot = index_f(k, q);
|
||||
unsigned int lo = 0, hi = count;
|
||||
while (lo < hi) {
|
||||
unsigned int mid = lo + (hi - lo) / 2;
|
||||
if (targets[mid] < slot) lo = mid + 1;
|
||||
else hi = mid;
|
||||
}
|
||||
if (lo < count && targets[lo] == slot) {
|
||||
const uint64_t* s = children + 4ul * lo;
|
||||
f[q] = 0.25f * (fine[s[0]] + fine[s[1]] + fine[s[2]] + fine[s[3]]);
|
||||
#ifdef CELERIS_REFINEMENT_AUDIT
|
||||
++incoming_counts[slot];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
// Includes the eight grazing-corner links with UNCOVERED coarse donors.
|
||||
// All replacement arrivals must be in place before computing rho/u.
|
||||
if (wall_aware) {
|
||||
if (y == 1) reconstruct_bottom_velocity(f, 0.0f, bottom_wall_normal_velocity(x));
|
||||
else if (y == NY - 2) reconstruct_top_reservoir(f, RHO);
|
||||
}
|
||||
patch_collide(f, k);
|
||||
stream_pull_store(k, f, out);
|
||||
}
|
||||
@@ -21,6 +21,14 @@
|
||||
// i.e. the population traveling in direction i at node n
|
||||
// arrived from the node at n - c_i = neighbor in direction opp(i)
|
||||
// ---------------------------------------------------------------------------
|
||||
// load_node: all NQ populations of node n as stored (no streaming).
|
||||
__device__ __forceinline__ void load_node(const fpxx* __restrict__ fi, unsigned long n,
|
||||
float* __restrict__ f)
|
||||
{
|
||||
for (int q = 0; q < NQ; ++q)
|
||||
f[q] = load_ddf(fi, index_f(n, q));
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void stream_pull_load(unsigned long n,
|
||||
float* __restrict__ f,
|
||||
const fpxx* __restrict__ fi,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// CelerisLab – kernel_v2.cu
|
||||
// CelerisLab – uniform.cu
|
||||
// ============================================================================
|
||||
// Compilation entry point (Stage 2 Architecture).
|
||||
//
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
// File layout (each <300 lines):
|
||||
// operators/helpers.cuh — bounce_back_swap, collide_dispatch
|
||||
// step/init_flow.cu — InitTubeFlow_v2, InitEsoPull
|
||||
// step/init_flow.cu — InitTubeFlow, InitEsoPull
|
||||
// step/one_step_double.cu — OneStep (pull double-buffer)
|
||||
// step/one_step_esopull.cu — EsoPullStep (single-buffer)
|
||||
// step/aux_kernels.cu — CurvedBoundaryKernel, SensorKernel
|
||||
@@ -124,7 +124,7 @@ class FixedPatchStepper:
|
||||
stream. On a device/launch failure the instance becomes unusable: close and
|
||||
recreate it, rather than pretending a partially advanced buffer rolled back.
|
||||
|
||||
A ``level_blocks`` entry (by, bx) stores that level in blocks.cu storage:
|
||||
A ``level_blocks`` entry (by, bx) stores that level in blocked.cu storage:
|
||||
the ENTIRE level shape, including the four-cell patch ghost band, is
|
||||
partitioned by a non-periodic BlockLayout2D with one-cell same-level halos.
|
||||
Patch kinds stay per cell (OUTER invalid, INNER stream only, ACTIVE
|
||||
@@ -356,7 +356,7 @@ class FixedPatchStepper:
|
||||
config = replace(config, nx=layout.local_shape[1], ny=layout.local_shape[0],
|
||||
y_wall_bc="bounce_back", top_wall_bc="velocity",
|
||||
wall_slot_width=0, wall_normal_velocity=0.0, velocity=0.0)
|
||||
name, source = ("BlockChannelStep" if index == 0 and self._channel else "BlockStep"), "blocks.cu"
|
||||
name, source = ("BlockChannelStep" if index == 0 and self._channel else "BlockStep"), "blocked.cu"
|
||||
config.validate()
|
||||
if not np.isclose(config.omega, 1 / tau, rtol=1e-14, atol=0):
|
||||
raise RuntimeError("level omega/tau mismatch")
|
||||
@@ -365,16 +365,9 @@ class FixedPatchStepper:
|
||||
block_root_bc = 0
|
||||
if index == 0 and layout is not None:
|
||||
block_root_bc = 2 if self._channel else 1 if self._wall_aware else 0
|
||||
build = compiler.generate_config(config, n_objects=n_objects, block_root_bc=block_root_bc)
|
||||
try:
|
||||
ptx = compiler.compile_kernel(self.ctx.sm_arch, source=source, build_dir=build)
|
||||
module = compiler.load_module(ptx)
|
||||
finally:
|
||||
compiler.cleanup_build_dir(build)
|
||||
ptr, size = module.get_global("d_params")
|
||||
if size != struct.calcsize("=ffffI"):
|
||||
raise RuntimeError("LBMParams host/device layout mismatch")
|
||||
cuda.memcpy_htod(ptr, struct.pack("=ffffI", config.omega, 0, 0, 0, n_objects))
|
||||
module = compiler.build_module(config, source, arch=self.ctx.sm_arch, n_objects=n_objects,
|
||||
block_root_bc=block_root_bc)
|
||||
compiler.set_params(module, config.omega, n_objects=n_objects)
|
||||
shape = (9, *self.hierarchy.kinds[index].shape)
|
||||
size = int(np.prod(shape if layout is None else layout.blocked_shape)) * 4
|
||||
grid = ((config.nx + self._block[0] - 1) // self._block[0], config.ny,
|
||||
@@ -949,8 +942,8 @@ class FixedPatchStepper:
|
||||
if exc[0] is None:
|
||||
raise
|
||||
|
||||
# Read-only compatibility views over the level lists. Internal code must not use them;
|
||||
# REMOVE AFTER the existing tests/docs migrate to hierarchy/_layouts/_level_* lists.
|
||||
# Read-only compatibility views over the level lists, kept on purpose for the existing
|
||||
# tests and docs. Internal code must not use them; it reads hierarchy/_layouts/_level_*.
|
||||
patch = property(lambda self: self.hierarchy.pairs[0])
|
||||
child_patch = property(lambda self: self.hierarchy.pairs[1] if self.hierarchy.depth > 2 else None)
|
||||
base_layout = property(lambda self: self._layouts[0])
|
||||
|
||||
@@ -28,7 +28,7 @@ class LBMStepper:
|
||||
self.boundary_values_gpu = cuda.mem_alloc((6 * cfg.nx + 2 * cfg.ny * cfg.nq) * 4)
|
||||
else:
|
||||
self.step_fn = module.get_function("OneStep")
|
||||
self.init_fn = module.get_function("InitTubeFlow_v2")
|
||||
self.init_fn = module.get_function("InitTubeFlow")
|
||||
|
||||
self.curved_fn = module.get_function("CurvedBoundaryKernel")
|
||||
self.prepare_esopull_curved_fn = module.get_function("PrepareEsoPullCurvedKernel")
|
||||
|
||||
@@ -46,7 +46,6 @@ class Simulation:
|
||||
device_id: int = 0):
|
||||
# Internal stream for async DTOH coordination
|
||||
self._stream: Optional[cuda.Stream] = None
|
||||
self._build_dir = None
|
||||
self._closed = False
|
||||
|
||||
# Load configs
|
||||
@@ -59,9 +58,7 @@ class Simulation:
|
||||
try:
|
||||
with self.ctx.activate():
|
||||
arch = self._resolve_compile_arch()
|
||||
self._build_dir = compiler.generate_config(self.lbm_cfg, n_objects=0)
|
||||
self._ptx_path = compiler.compile_kernel(arch=arch, build_dir=self._build_dir)
|
||||
self._module = compiler.load_module(self._ptx_path)
|
||||
self._module = compiler.build_module(self.lbm_cfg, "uniform.cu", arch=arch)
|
||||
self._compiled_n_objects = 0
|
||||
self._allocation_signature = self.lbm_cfg.allocation_signature()
|
||||
self._compiled_viscosity = self.lbm_cfg.viscosity
|
||||
@@ -412,15 +409,8 @@ class Simulation:
|
||||
self.lbm_cfg.validate_runtime()
|
||||
self._assert_allocation_contract()
|
||||
arch = self._resolve_compile_arch()
|
||||
next_dir = compiler.generate_config(self.lbm_cfg, n_objects=expected_n_objects)
|
||||
try:
|
||||
next_ptx = compiler.compile_kernel(arch=arch, build_dir=next_dir)
|
||||
next_module = compiler.load_module(next_ptx)
|
||||
except Exception:
|
||||
compiler.cleanup_build_dir(next_dir)
|
||||
raise
|
||||
old_dir = self._build_dir
|
||||
self._build_dir, self._ptx_path, self._module = next_dir, next_ptx, next_module
|
||||
self._module = compiler.build_module(self.lbm_cfg, "uniform.cu", arch=arch,
|
||||
n_objects=expected_n_objects)
|
||||
self._compiled_n_objects = int(expected_n_objects)
|
||||
|
||||
# Reconnect field and stepper to new module
|
||||
@@ -438,7 +428,6 @@ class Simulation:
|
||||
self.stepper._step_count = _prev_step_count
|
||||
|
||||
self._assert_object_count_contract(expected_count=expected_n_objects)
|
||||
compiler.cleanup_build_dir(old_dir)
|
||||
|
||||
def recompile(self):
|
||||
"""Re-generate config headers and recompile kernel.
|
||||
@@ -715,8 +704,6 @@ class Simulation:
|
||||
self._module = None
|
||||
self._stream = None
|
||||
ctx.close()
|
||||
compiler.cleanup_build_dir(getattr(self, "_build_dir", None))
|
||||
self._build_dir = None
|
||||
self._closed = True
|
||||
|
||||
def __enter__(self):
|
||||
|
||||
@@ -13,7 +13,7 @@ from ._cases import make_sim
|
||||
def test_source_provenance():
|
||||
root = Path(__file__).resolve().parents[2] / "src/CelerisLab"
|
||||
assert Path(CelerisLab.__file__).resolve().parent == root
|
||||
assert Path(compiler_v2.kernel_path("kernel_v2.cu")).resolve() == root / "lbm/kernels/kernel_v2.cu"
|
||||
assert Path(compiler_v2.kernel_path("uniform.cu")).resolve() == root / "lbm/kernels/uniform.cu"
|
||||
|
||||
|
||||
def test_two_contexts_interleaved_and_non_lifo_close():
|
||||
@@ -21,7 +21,7 @@ def test_two_contexts_interleaved_and_non_lifo_close():
|
||||
first = make_sim(nx=32, ny=16)
|
||||
second = make_sim(nx=48, ny=24, streaming="esopull", shifted=True)
|
||||
try:
|
||||
assert first._build_dir != second._build_dir
|
||||
assert first._module is not second._module
|
||||
assert cuda.Context.get_current() == before
|
||||
first.initialize()
|
||||
second.initialize()
|
||||
|
||||
@@ -37,7 +37,7 @@ def backend():
|
||||
module.get_global.return_value = (Mock(), 20)
|
||||
module.get_function.side_effect = lambda name: Mock(
|
||||
side_effect=lambda *a, **k: log.append((name, a[:2])))
|
||||
host.compiler.load_module.return_value = module
|
||||
host.compiler.build_module.return_value = module
|
||||
cfg = LBMConfig(nx=16, ny=16, viscosity=.1)
|
||||
run = host.PeriodicBlockStepper(cfg, BlockLayout2D.build(16, 16, 8, 8),
|
||||
context=Mock(activate=nullcontext, sm_arch="sm_70"))
|
||||
|
||||
@@ -126,8 +126,7 @@ class BuildContracts(unittest.TestCase):
|
||||
def work(nx, count):
|
||||
build = compiler.generate_config(LBMConfig(nx=nx), count, build_root=root)
|
||||
barrier.wait()
|
||||
# Compatibility form is context-local even without explicit path.
|
||||
output = compiler.compile_kernel()
|
||||
output = compiler.compile_kernel(build_dir=build)
|
||||
data = json.loads(Path(output).read_text())
|
||||
self.assertEqual(data, {"nx": nx, "objects": count})
|
||||
metadata = json.loads(Path(output + ".json").read_text())
|
||||
@@ -156,7 +155,7 @@ class BuildContracts(unittest.TestCase):
|
||||
compiler.cleanup_build_dir(a)
|
||||
compiler.cleanup_build_dir(b)
|
||||
with self.assertRaises(RuntimeError):
|
||||
compiler.compile_kernel()
|
||||
compiler.compile_kernel(build_dir=a) # removed snapshot is never compiled
|
||||
|
||||
def test_failed_compile_cannot_implicitly_load_previous_artifact(self):
|
||||
with tempfile.TemporaryDirectory() as root:
|
||||
@@ -169,8 +168,7 @@ class BuildContracts(unittest.TestCase):
|
||||
with self.assertRaises(subprocess.CalledProcessError):
|
||||
compiler.compile_kernel(build_dir=build)
|
||||
self.assertEqual(Path(previous).read_bytes(), old_bytes)
|
||||
with self.assertRaisesRegex(RuntimeError, "No compiled PTX"):
|
||||
compiler.load_module()
|
||||
self.assertEqual(sorted(Path(build).glob("uniform-*.ptx")), []) # no partial output
|
||||
compiler.cleanup_build_dir(build)
|
||||
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ def test_evolved_ghost_snapshot_and_physical_download():
|
||||
from .test_refinement_three_level_multipatch import host_module
|
||||
host = host_module()
|
||||
storage = {}
|
||||
host.compiler.load_module.return_value.get_global.side_effect = lambda name: (name, 12 if name == "d_block_channel" else 20)
|
||||
host.compiler.build_module.return_value.get_global.side_effect = lambda name: (name, 12 if name == "d_block_channel" else 20)
|
||||
host.cuda.mem_alloc.side_effect = lambda size: Mock()
|
||||
host.cuda.memcpy_htod.side_effect = lambda ptr, a: storage.__setitem__(id(ptr), np.array(a, copy=True))
|
||||
host.cuda.memcpy_dtoh.side_effect = lambda a, ptr: np.copyto(a, storage[id(ptr)])
|
||||
@@ -96,7 +96,7 @@ def test_evolved_ghost_snapshot_and_physical_download():
|
||||
arrays[0][0, 0, 0] = np.nan
|
||||
with pytest.raises(ValueError, match="finite"):
|
||||
backend.initialize(*arrays)
|
||||
assert backend._levels[0].kernel == host.compiler.load_module.return_value.get_function("BlockChannelStep")
|
||||
assert [call.kwargs["block_root_bc"] for call in host.compiler.generate_config.call_args_list] == [2, 0]
|
||||
assert backend._levels[0].kernel == host.compiler.build_module.return_value.get_function("BlockChannelStep")
|
||||
assert [call.kwargs["block_root_bc"] for call in host.compiler.build_module.call_args_list] == [2, 0]
|
||||
finally:
|
||||
backend.close()
|
||||
|
||||
@@ -135,6 +135,6 @@ def test_d2_entrypoint_compiles_in_isolation(tmp_path, model, shift, storage):
|
||||
source=re.sub(r"(#define\s+"+key+r"\s+)\S+",lambda match: match[1]+str(value),source)
|
||||
path.write_text(source)
|
||||
result=subprocess.run([nvcc,"-ptx","-arch=sm_70","-std=c++17",
|
||||
str(copy/"kernel_v2.cu"),"-o",str(tmp_path/"kernel.ptx")],
|
||||
str(copy/"uniform.cu"),"-o",str(tmp_path/"kernel.ptx")],
|
||||
capture_output=True,text=True)
|
||||
assert result.returncode == 0, result.stderr
|
||||
|
||||
@@ -18,7 +18,7 @@ from .test_state_regressions import device, make_field, manager
|
||||
def test_planar_helper_moments_and_known_populations(tmp_path):
|
||||
root = Path(__file__).resolve().parents[2]
|
||||
assert Path(CelerisLab.__file__).resolve() == root/'src/CelerisLab/__init__.py'
|
||||
assert Path(compiler.kernel_path('kernel_v2.cu')).resolve() == root/'src/CelerisLab/lbm/kernels/kernel_v2.cu'
|
||||
assert Path(compiler.kernel_path('uniform.cu')).resolve() == root/'src/CelerisLab/lbm/kernels/uniform.cu'
|
||||
lines = compile_run(tmp_path, 'planar_velocity.cpp', dict(WALL_NORMAL_VELOCITY='0.0f'))
|
||||
cx = np.array([0,1,-1,0,0,1,-1,1,-1])
|
||||
cy = np.array([0,0,0,1,-1,1,-1,-1,1])
|
||||
|
||||
@@ -162,7 +162,7 @@ class ProjectedKernelTests(unittest.TestCase):
|
||||
targets = child.owner.ravel()[p.ghost_fine]
|
||||
donors = parent.owner.ravel()[p.ghost_coarse]
|
||||
source = (Path(__file__).resolve().parents[2] /
|
||||
"src/CelerisLab/lbm/kernels/blocks.cu").read_text()
|
||||
"src/CelerisLab/lbm/kernels/step/block_transfer.cu").read_text()
|
||||
kernel = source.split('extern "C" __global__ void BlockExplodeProjected(',1)[1]
|
||||
kernel = 'void BlockExplodeProjected(' + kernel.split('// Targets are receiver-local SOURCE slots',1)[0]
|
||||
def array(name, values, kind):
|
||||
|
||||
@@ -29,7 +29,7 @@ def backend(**options):
|
||||
name=name, side_effect=lambda *a, **kw: calls.append((name, a, kw)))
|
||||
return module
|
||||
|
||||
host.compiler.load_module.side_effect = load
|
||||
host.compiler.build_module.side_effect = lambda *a, **k: load(None)
|
||||
host.cuda.memcpy_htod.side_effect = lambda ptr, a: storage.__setitem__(id(ptr), np.array(a, copy=True))
|
||||
host.cuda.memcpy_dtoh.side_effect = lambda a, ptr: np.copyto(a, storage[id(ptr)])
|
||||
cfg = options.pop('cfg', CFG)
|
||||
|
||||
@@ -25,7 +25,7 @@ def backend(observe=True, obj=None):
|
||||
module = Mock()
|
||||
module.get_global.return_value = (Mock(), 20)
|
||||
module.get_function.side_effect = lambda name: Mock(side_effect=lambda *a, **k: calls.append((name, a, k)))
|
||||
host.compiler.load_module.return_value = module
|
||||
host.compiler.build_module.return_value = module
|
||||
host.cuda.mem_alloc.side_effect = lambda n: Mock(size=n)
|
||||
host.cuda.memcpy_dtoh.side_effect = lambda array, pointer: array.fill(0)
|
||||
ctx = Mock(activate=nullcontext, sm_arch='sm_70')
|
||||
|
||||
@@ -22,12 +22,12 @@ class RefinementMRTHost(unittest.TestCase):
|
||||
|
||||
def test_srt_statements_and_guards_preserved(self):
|
||||
"""MRT is an additive compile-time branch; SRT statements and other guards remain."""
|
||||
blocks = (KERNELS / "blocks.cu").read_text()
|
||||
blocks = (KERNELS / "blocked.cu").read_text() + (KERNELS / "step/block_step.cu").read_text()
|
||||
channel = (KERNELS / "step/block_channel.cu").read_text()
|
||||
block_collision = (KERNELS / "operators/block_collision.cuh").read_text()
|
||||
self.assertIn('#include "operators/block_collision.cuh"', blocks)
|
||||
self.assertEqual(blocks.count("block_collide(f);"), 1)
|
||||
refinement = (KERNELS / "refinement.cu").read_text()
|
||||
refinement = (KERNELS / "refinement.cu").read_text() + (KERNELS / "step/patch_step.cu").read_text()
|
||||
for text in ("compute_feq_from_momentum(drho, jx, jy, ux, uy, feq);",
|
||||
"compute_feq(rho, ux, uy, feq);",
|
||||
"collide_srt_no_force(f, feq, d_params.omega);"):
|
||||
|
||||
@@ -193,9 +193,9 @@ def mock_backend(*, children=CHILDREN, bodies=False, fail_compile=False, fail_up
|
||||
gpu.get_function.side_effect=lambda name: Mock(name=name)
|
||||
gpu.get_global.side_effect=lambda name: (Mock(),20 if name=='d_params' else 16)
|
||||
return gpu
|
||||
module.compiler.load_module.side_effect=load
|
||||
module.compiler.build_module.side_effect=lambda *a,**k: load(None)
|
||||
if fail_compile:
|
||||
module.compiler.compile_kernel.side_effect=['first','second',RuntimeError('L2 compile failed')]
|
||||
module.compiler.build_module.side_effect=[load(None),load(None),RuntimeError('L2 compile failed')]
|
||||
if fail_upload:
|
||||
def upload(*args):
|
||||
if len(allocations)>20:
|
||||
|
||||
@@ -86,7 +86,7 @@ class RuntimeChildRemap(unittest.TestCase):
|
||||
before = run.download()
|
||||
old_allocations = list(allocations)
|
||||
if failure == 'construction':
|
||||
operation = patch.object(module.compiler, 'compile_kernel', side_effect=RuntimeError('candidate compile'))
|
||||
operation = patch.object(module.compiler, 'build_module', side_effect=RuntimeError('candidate compile'))
|
||||
else:
|
||||
initialize = type(run).initialize
|
||||
def fail(candidate, *arrays):
|
||||
|
||||
@@ -62,7 +62,7 @@ class ShiftedJets(unittest.TestCase):
|
||||
level_blocks=list(blocks),level_objects=[(),(),(body(),)],
|
||||
level_jets=[(),(),(jet(),)])
|
||||
module.cuda.mem_alloc.assert_not_called()
|
||||
module.compiler.compile_kernel.assert_not_called()
|
||||
module.compiler.build_module.assert_not_called()
|
||||
|
||||
def test_switch_upload_only_then_raw_remap_keeps_live_velocity(self):
|
||||
run,module,allocations,storage,objects=ready();clone=None
|
||||
|
||||
@@ -135,7 +135,7 @@ class ShiftedStorage(unittest.TestCase):
|
||||
with self.assertRaisesRegex(ValueError,'all-blocked|blocked refined levels below'):
|
||||
module.FixedPatchStepper(cfg,context=None,refinements=[(4,4,20,28)],
|
||||
level_blocks=blocks)
|
||||
module.compiler.compile_kernel.assert_not_called()
|
||||
module.compiler.build_module.assert_not_called()
|
||||
|
||||
def test_uniform_block_codec_and_raw_snapshot(self):
|
||||
path = Path(backend.r.__file__).with_name('block_stepper.py')
|
||||
@@ -151,7 +151,7 @@ class ShiftedStorage(unittest.TestCase):
|
||||
cuda.mem_get_info.return_value=(10**9,10**9)
|
||||
cuda.mem_alloc.side_effect=lambda size: Mock()
|
||||
gpu=Mock();gpu.get_global.return_value=(Mock(),20)
|
||||
compiler.load_module.return_value=gpu
|
||||
compiler.build_module.return_value=gpu
|
||||
context=Mock(activate=nullcontext,sm_arch='sm_70')
|
||||
layout=module.BlockLayout2D.build(16,16,4,4)
|
||||
cfg=replace(backend.CFG,nx=16,ny=16,ddf_shifting=True)
|
||||
|
||||
@@ -36,12 +36,10 @@ def make_simulation(monkeypatch):
|
||||
sim = module.Simulation.__new__(module.Simulation)
|
||||
sim.ctx = Owner()
|
||||
sim._closed = False
|
||||
sim._build_dir = "private-build"
|
||||
for name in ("stepper", "bodies", "field", "_module", "_stream"):
|
||||
setattr(sim, name, object())
|
||||
monkeypatch.setattr(module, "cuda", SimpleNamespace(
|
||||
Context=SimpleNamespace(synchronize=lambda: None)))
|
||||
monkeypatch.setattr(module.compiler, "cleanup_build_dir", lambda path: None)
|
||||
return sim
|
||||
|
||||
|
||||
@@ -57,7 +55,7 @@ def test_close_inside_activation_preserves_resources(monkeypatch):
|
||||
assert sim._closed and sim.ctx.is_closed
|
||||
|
||||
|
||||
@pytest.mark.parametrize("failure", ["synchronize", "detach", "directory"])
|
||||
@pytest.mark.parametrize("failure", ["synchronize", "detach"])
|
||||
def test_close_failure_is_retryable(monkeypatch, failure):
|
||||
sim = make_simulation(monkeypatch)
|
||||
if failure == "detach":
|
||||
@@ -68,17 +66,12 @@ def test_close_failure_is_retryable(monkeypatch, failure):
|
||||
calls.append(args)
|
||||
if len(calls) == 1:
|
||||
raise RuntimeError(failure + " failed")
|
||||
if failure == "synchronize":
|
||||
monkeypatch.setattr(module.cuda.Context, "synchronize", fail_once)
|
||||
else:
|
||||
monkeypatch.setattr(module.compiler, "cleanup_build_dir", fail_once)
|
||||
monkeypatch.setattr(module.cuda.Context, "synchronize", fail_once)
|
||||
with pytest.raises(RuntimeError, match="failed"):
|
||||
sim.close()
|
||||
assert not sim._closed
|
||||
assert sim._build_dir == "private-build"
|
||||
sim.close()
|
||||
assert sim._closed and sim.ctx.is_closed
|
||||
assert sim._build_dir is None
|
||||
sim.close()
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ def backend(window=False):
|
||||
module.get_global.return_value = (Mock(), 20)
|
||||
module.get_function.side_effect = lambda name: Mock(
|
||||
side_effect=lambda *a, **k: log.append((name, a, k)))
|
||||
host.compiler.load_module.return_value = module
|
||||
host.compiler.build_module.return_value = module
|
||||
host.cuda.mem_alloc.side_effect = allocate
|
||||
host.cuda.memcpy_dtoh.side_effect = lambda array, pointer: array.fill(0)
|
||||
host.cuda.memset_d8_async.side_effect = lambda *a: log.append(("memset", a, {}))
|
||||
|
||||
@@ -30,7 +30,7 @@ original_module = gate.compile_module
|
||||
cache = {}
|
||||
def retain_compile(*args, **kwargs):
|
||||
result = original_compile(*args, **kwargs)
|
||||
source = kwargs.get('source', 'kernel_v2.cu')
|
||||
source = kwargs.get('source', 'uniform.cu')
|
||||
shutil.copyfile(result, a.output / (Path(source).stem + '.ptx'))
|
||||
metadata = Path(result + '.json')
|
||||
if metadata.exists(): shutil.copyfile(metadata, a.output / (Path(source).stem + '.ptx.json'))
|
||||
|
||||
@@ -171,7 +171,7 @@ class CpuContracts(unittest.TestCase):
|
||||
patch.object(cuda, "mem_alloc") as alloc, patch.object(cuda, "memcpy_htod") as upload:
|
||||
with self.assertRaisesRegex(RuntimeError, "layout mismatch"):
|
||||
PeriodicBlockStepper(config(), layout, context=context)
|
||||
self.assertEqual(compile_kernel.call_args.kwargs["source"], "blocks.cu")
|
||||
self.assertEqual(compile_kernel.call_args.kwargs["source"], "blocked.cu")
|
||||
alloc.assert_not_called()
|
||||
upload.assert_not_called()
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ def state(ny, nx):
|
||||
|
||||
def compile_module(cfg, context, source):
|
||||
cfg.validate()
|
||||
build = compiler.generate_config(cfg, block_root_bc=2 if source == "blocks.cu" else 0)
|
||||
build = compiler.generate_config(cfg, block_root_bc=2 if source == "blocked.cu" else 0)
|
||||
try:
|
||||
module = compiler.load_module(compiler.compile_kernel(context.sm_arch, source=source, build_dir=build))
|
||||
finally:
|
||||
@@ -46,7 +46,7 @@ def run_root(cfg, context, initial, block=None, steps=8):
|
||||
try:
|
||||
layout = None if block is None else BlockLayout2D.build(cfg.ny, cfg.nx, *block)
|
||||
local = cfg if layout is None else replace(cfg, nx=layout.local_shape[1], ny=layout.local_shape[0])
|
||||
module = compile_module(local, context, "kernel_v2.cu" if layout is None else "blocks.cu")
|
||||
module = compile_module(local, context, "uniform.cu" if layout is None else "blocked.cu")
|
||||
data = initial if layout is None else layout.to_blocked(initial)
|
||||
current, spare = upload(data), upload(np.full_like(data, np.nan))
|
||||
tpb = cfg.threads_per_block
|
||||
|
||||
Reference in New Issue
Block a user