trnsolver 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. trnsolver-0.3.0/.github/ISSUE_TEMPLATE/bug_report.md +31 -0
  2. trnsolver-0.3.0/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
  3. trnsolver-0.3.0/.github/pull_request_template.md +9 -0
  4. trnsolver-0.3.0/.github/workflows/ci.yml +20 -0
  5. trnsolver-0.3.0/.github/workflows/neuron.yml +63 -0
  6. trnsolver-0.3.0/.github/workflows/notify-umbrella.yml +36 -0
  7. trnsolver-0.3.0/.github/workflows/publish.yml +56 -0
  8. trnsolver-0.3.0/.gitignore +26 -0
  9. trnsolver-0.3.0/CHANGELOG.md +87 -0
  10. trnsolver-0.3.0/CLAUDE.md +105 -0
  11. trnsolver-0.3.0/CODE_OF_CONDUCT.md +25 -0
  12. trnsolver-0.3.0/CONTRIBUTING.md +69 -0
  13. trnsolver-0.3.0/LICENSE +201 -0
  14. trnsolver-0.3.0/PKG-INFO +127 -0
  15. trnsolver-0.3.0/README.md +98 -0
  16. trnsolver-0.3.0/benchmarks/bench_cuda.py +94 -0
  17. trnsolver-0.3.0/benchmarks/bench_solver.py +144 -0
  18. trnsolver-0.3.0/benchmarks/conftest.py +35 -0
  19. trnsolver-0.3.0/docs/api/eigen.md +30 -0
  20. trnsolver-0.3.0/docs/api/factor.md +53 -0
  21. trnsolver-0.3.0/docs/api/iterative.md +26 -0
  22. trnsolver-0.3.0/docs/api/nki.md +36 -0
  23. trnsolver-0.3.0/docs/architecture.md +54 -0
  24. trnsolver-0.3.0/docs/aws_setup.md +110 -0
  25. trnsolver-0.3.0/docs/benchmarks.md +71 -0
  26. trnsolver-0.3.0/docs/index.md +32 -0
  27. trnsolver-0.3.0/docs/installation.md +41 -0
  28. trnsolver-0.3.0/docs/quickstart.md +65 -0
  29. trnsolver-0.3.0/examples/scf_eigen.py +135 -0
  30. trnsolver-0.3.0/infra/terraform/README.md +58 -0
  31. trnsolver-0.3.0/infra/terraform/gpu.tf +84 -0
  32. trnsolver-0.3.0/infra/terraform/main.tf +150 -0
  33. trnsolver-0.3.0/mkdocs.yml +38 -0
  34. trnsolver-0.3.0/pyproject.toml +54 -0
  35. trnsolver-0.3.0/scripts/run_cuda_tests.sh +126 -0
  36. trnsolver-0.3.0/scripts/run_neuron_tests.sh +143 -0
  37. trnsolver-0.3.0/setup.cfg +4 -0
  38. trnsolver-0.3.0/tests/conftest.py +38 -0
  39. trnsolver-0.3.0/tests/test_eigen.py +72 -0
  40. trnsolver-0.3.0/tests/test_factor.py +140 -0
  41. trnsolver-0.3.0/tests/test_iterative.py +87 -0
  42. trnsolver-0.3.0/trnsolver/__init__.py +33 -0
  43. trnsolver-0.3.0/trnsolver/eigen.py +170 -0
  44. trnsolver-0.3.0/trnsolver/factor.py +157 -0
  45. trnsolver-0.3.0/trnsolver/iterative.py +179 -0
  46. trnsolver-0.3.0/trnsolver/nki/__init__.py +5 -0
  47. trnsolver-0.3.0/trnsolver/nki/dispatch.py +91 -0
  48. trnsolver-0.3.0/trnsolver.egg-info/PKG-INFO +127 -0
  49. trnsolver-0.3.0/trnsolver.egg-info/SOURCES.txt +50 -0
  50. trnsolver-0.3.0/trnsolver.egg-info/dependency_links.txt +1 -0
  51. trnsolver-0.3.0/trnsolver.egg-info/requires.txt +11 -0
  52. trnsolver-0.3.0/trnsolver.egg-info/top_level.txt +1 -0
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: Bug report
3
+ about: Report a bug in trnsolver
4
+ labels: bug
5
+ ---
6
+
7
+ ## Environment
8
+
9
+ - trnsolver version:
10
+ - Python version:
11
+ - PyTorch version:
12
+ - Hardware: CPU / trn1 / trn2 / inf2
13
+ - OS:
14
+
15
+ ## Description
16
+
17
+ What happened?
18
+
19
+ ## Steps to reproduce
20
+
21
+ ```python
22
+ # Minimal code to reproduce
23
+ ```
24
+
25
+ ## Expected behavior
26
+
27
+ What should have happened?
28
+
29
+ ## Actual behavior
30
+
31
+ What happened instead? Include error messages/tracebacks if applicable.
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest a new feature or enhancement
4
+ labels: enhancement
5
+ ---
6
+
7
+ ## Description
8
+
9
+ What feature would you like?
10
+
11
+ ## Motivation
12
+
13
+ Why is this needed? What problem does it solve?
14
+
15
+ ## Alternatives considered
16
+
17
+ Any other approaches you've thought about?
@@ -0,0 +1,9 @@
1
+ ## Summary
2
+
3
+ What does this PR do?
4
+
5
+ ## Test plan
6
+
7
+ - [ ] Tests pass (`pytest tests/ -v`)
8
+ - [ ] New tests added for new functionality
9
+ - [ ] CHANGELOG.md updated (if user-facing change)
@@ -0,0 +1,20 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python-version: ["3.10", "3.11", "3.12"]
14
+ steps:
15
+ - uses: actions/checkout@v6
16
+ - uses: actions/setup-python@v6
17
+ with:
18
+ python-version: ${{ matrix.python-version }}
19
+ - run: pip install -e ".[dev]"
20
+ - run: pytest tests/ -v -x --tb=short -m "not neuron"
@@ -0,0 +1,63 @@
1
+ name: Neuron hardware tests
2
+
3
+ # Manually triggered workflow that runs the `@pytest.mark.neuron`-marked suite
4
+ # on a Trainium instance via SSM. The instance is provisioned separately with
5
+ # `infra/terraform/`. This workflow wraps `scripts/run_neuron_tests.sh`.
6
+ #
7
+ # Prerequisites (one-time, manual):
8
+ # 1. Provision the CI instance: `cd infra/terraform && terraform apply`.
9
+ # 2. Register an AWS IAM role that trusts the GitHub OIDC provider for this
10
+ # repo. The role needs ec2:{Start,Stop,Describe}Instances and
11
+ # ssm:{SendCommand,GetCommandInvocation,DescribeInstanceInformation}.
12
+ # 3. Add the role ARN to repo secrets as `AWS_ROLE_ARN`.
13
+ #
14
+ # Until step 3 is done, the workflow will fail at the OIDC assume-role step.
15
+
16
+ on:
17
+ workflow_dispatch:
18
+ inputs:
19
+ instance_type:
20
+ description: "Instance family tag suffix (trn1, trn2, inf2)"
21
+ required: false
22
+ default: "trn1"
23
+ aws_region:
24
+ description: "AWS region"
25
+ required: false
26
+ default: "us-east-1"
27
+ warm:
28
+ description: "Run suite twice (warm NEFF cache pass)"
29
+ type: boolean
30
+ required: false
31
+ default: false
32
+
33
+ concurrency:
34
+ # Only one hardware run at a time — the EC2 instance is shared.
35
+ group: neuron-hardware
36
+ cancel-in-progress: false
37
+
38
+ jobs:
39
+ neuron:
40
+ runs-on: ubuntu-latest
41
+ timeout-minutes: 45
42
+ permissions:
43
+ id-token: write
44
+ contents: read
45
+ steps:
46
+ - uses: actions/checkout@v6
47
+
48
+ - name: Configure AWS credentials (OIDC)
49
+ uses: aws-actions/configure-aws-credentials@v4
50
+ with:
51
+ role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
52
+ aws-region: ${{ inputs.aws_region }}
53
+
54
+ - name: Run neuron-marked tests via SSM
55
+ env:
56
+ AWS_REGION: ${{ inputs.aws_region }}
57
+ run: |
58
+ chmod +x scripts/run_neuron_tests.sh
59
+ if [[ "${{ inputs.warm }}" == "true" ]]; then
60
+ ./scripts/run_neuron_tests.sh --warm "${{ inputs.instance_type }}"
61
+ else
62
+ ./scripts/run_neuron_tests.sh "${{ inputs.instance_type }}"
63
+ fi
@@ -0,0 +1,36 @@
1
+ name: Notify trnsci umbrella of docs change
2
+
3
+ # Fires a repository_dispatch at trnsci/trnsci whenever this repo's docs or
4
+ # mkdocs.yml change on main, so the combined site at trnsci.dev rebuilds
5
+ # immediately rather than waiting for the daily cron.
6
+ #
7
+ # Requires repo/org secret TRNSCI_DISPATCH_TOKEN — a fine-grained PAT scoped
8
+ # to the trnsci/trnsci repo with "Contents: Read and write" (which covers
9
+ # repository_dispatch). See README for setup.
10
+
11
+ on:
12
+ push:
13
+ branches: [main]
14
+ paths:
15
+ - "docs/**"
16
+ - "mkdocs.yml"
17
+ - "README.md"
18
+ - "CHANGELOG.md"
19
+ workflow_dispatch:
20
+
21
+ jobs:
22
+ dispatch:
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - name: Trigger umbrella rebuild
26
+ env:
27
+ GH_TOKEN: ${{ secrets.TRNSCI_DISPATCH_TOKEN }}
28
+ run: |
29
+ if [ -z "${GH_TOKEN:-}" ]; then
30
+ echo "::notice::TRNSCI_DISPATCH_TOKEN not set; umbrella will pick up this change on next daily cron or manual dispatch."
31
+ exit 0
32
+ fi
33
+ gh api --method POST repos/trnsci/trnsci/dispatches \
34
+ -f event_type=subproject-updated \
35
+ -f "client_payload[repo]=${GITHUB_REPOSITORY}" \
36
+ -f "client_payload[sha]=${GITHUB_SHA}"
@@ -0,0 +1,56 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v6
12
+ - uses: actions/setup-python@v6
13
+ with:
14
+ python-version: "3.12"
15
+ - run: pip install build
16
+ - run: python -m build
17
+ - uses: actions/upload-artifact@v4
18
+ with:
19
+ name: dist
20
+ path: dist/
21
+
22
+ publish-pypi:
23
+ needs: build
24
+ runs-on: ubuntu-latest
25
+ # Only publish stable releases (v1.2.3), not pre-releases (v1.2.3-rc1)
26
+ if: ${{ !contains(github.event.release.tag_name, '-') }}
27
+ environment:
28
+ name: pypi
29
+ url: https://pypi.org/project/trnsolver/
30
+ permissions:
31
+ id-token: write
32
+ steps:
33
+ - uses: actions/download-artifact@v4
34
+ with:
35
+ name: dist
36
+ path: dist/
37
+ - uses: pypa/gh-action-pypi-publish@release/v1
38
+
39
+ publish-testpypi:
40
+ needs: build
41
+ runs-on: ubuntu-latest
42
+ # Only publish pre-releases to TestPyPI
43
+ if: ${{ contains(github.event.release.tag_name, '-') }}
44
+ environment:
45
+ name: testpypi
46
+ url: https://test.pypi.org/project/trnsolver/
47
+ permissions:
48
+ id-token: write
49
+ steps:
50
+ - uses: actions/download-artifact@v4
51
+ with:
52
+ name: dist
53
+ path: dist/
54
+ - uses: pypa/gh-action-pypi-publish@release/v1
55
+ with:
56
+ repository-url: https://test.pypi.org/legacy/
@@ -0,0 +1,26 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .eggs/
8
+ *.egg
9
+ .pytest_cache/
10
+ .tox/
11
+ .venv/
12
+ venv/
13
+ *.so
14
+ .idea/
15
+ .vscode/
16
+ *.swp
17
+ *.swo
18
+ *~
19
+ site/
20
+ .benchmarks/
21
+ .terraform/
22
+ *.tfstate
23
+ *.tfstate.backup
24
+ .terraform.lock.hcl
25
+ .claude/
26
+ .DS_Store
@@ -0,0 +1,87 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.3.0] — 2026-04-12
11
+
12
+ ### Added
13
+
14
+ - `inv_sqrt_spd_ns(A)` — Newton-Schulz iteration for `A^{-1/2}`. All-GEMM,
15
+ returns `(X, iters, residual)`. Progress on #14 (NKI-GEMM backend swap
16
+ lands when trnblas GEMM validates on hardware).
17
+ - scipy.linalg baselines (eigh, cholesky, cho_solve) in
18
+ `benchmarks/bench_solver.py` for LAPACK comparison. Progress on #13.
19
+ - `benchmarks/bench_cuda.py` — CUDA / cuSOLVER benchmarks, auto-skipped
20
+ when no GPU is available. Vintage-matched methodology (trn1 ↔ A10G,
21
+ trn2 ↔ H100). Progress on #13.
22
+ - `infra/terraform/gpu.tf` — opt-in GPU CI instance (default `g5.xlarge`
23
+ A10G, vintage peer of trn1; `p5.4xlarge` for trn2 via override).
24
+ Disabled by default via `enable_gpu_ci = false`.
25
+ - `scripts/run_cuda_tests.sh` — SSM-based runner mirroring
26
+ `run_neuron_tests.sh` for the GPU box.
27
+
28
+ ### Changed
29
+
30
+ - `docs/benchmarks.md` rewritten with vintage-matching methodology and
31
+ real CPU numbers; `docs/aws_setup.md` documents the GPU instance and
32
+ H100 opt-in.
33
+ - CI: bumped to `actions/checkout@v6` and `actions/setup-python@v6`
34
+ (Node.js 24 runtime); standalone Deploy Docs workflow removed — docs
35
+ are served from trnsci.dev.
36
+ - `pyproject.toml` normalized across the trnsci suite; added
37
+ `Documentation` URL pointing to `trnsci.dev/trnsolver/`.
38
+
39
+ ## [0.2.0] — 2026-04-12
40
+
41
+ ### Added
42
+
43
+ - `jacobi_preconditioner(A)` in `trnsolver.iterative` — diagonal preconditioner
44
+ callable for `cg`. Partial progress on #16.
45
+ - Benchmark suite `benchmarks/bench_solver.py` covering eigh, factorizations,
46
+ solve, CG (with/without Jacobi preconditioner), and GMRES. Closes #8.
47
+ - Status badges in README (CI, PyPI, Python versions, license, docs). Closes #4.
48
+ - Manual Neuron hardware CI workflow (`.github/workflows/neuron.yml`) —
49
+ `workflow_dispatch`-only, OIDC-based, wraps `scripts/run_neuron_tests.sh`.
50
+ Closes #5.
51
+
52
+ ### Changed
53
+
54
+ - `cg(A, b, M=...)` tensor preconditioner is now applied as `M @ r` (already-
55
+ inverted operator), not `inv(M) @ r` recomputed every iteration.
56
+ - Repository transferred from `scttfrdmn/trnsolver` to `trnsci/trnsolver`.
57
+ Hardcoded URLs updated across docs, pyproject, terraform, and CI.
58
+
59
+ ## [0.1.1] — 2026-04-12
60
+
61
+ ### Changed
62
+
63
+ - Bumped `neuronxcc` floor from `>=2.15` to `>=2.24` to unify with the
64
+ rest of the trnsci suite. `torch-neuronx` floor bumped to `>=2.9`.
65
+
66
+ ## [0.1.0] - 2026-04-11
67
+
68
+ ### Added
69
+
70
+ - Initial scaffold of `trnsolver` — linear solvers and eigendecomposition
71
+ for AWS Trainium via NKI. Third sibling in the `trn-*` suite alongside
72
+ `trnblas` and `trnfft`.
73
+ - Eigenvalue API: `eigh` (symmetric), `eigh_generalized` (Cholesky reduction
74
+ for `Ax = λBx`).
75
+ - Factorizations: `cholesky`, `lu`, `qr`, `solve`, `solve_spd`, `inv_spd`,
76
+ `inv_sqrt_spd`.
77
+ - Iterative solvers: `cg`, `gmres`.
78
+ - NKI Jacobi rotation kernel scaffold in `trnsolver/nki/dispatch.py` with
79
+ auto/pytorch/nki backend selection. PyTorch fallback active until
80
+ on-hardware validation lands.
81
+ - SCF demo (`examples/scf_eigen.py`) for the quantum-chemistry use case:
82
+ build Fock → solve `FC = SCε` → density → convergence loop.
83
+ - pytest test suite covering eigen, factorization, and iterative solvers
84
+ on CPU.
85
+ - mkdocs-material site, GitHub Actions CI/docs/publish workflows, Terraform
86
+ module for the Neuron CI instance, and `scripts/run_neuron_tests.sh`
87
+ SSM-driven hardware test runner — all mirroring the trnblas/trnfft layout.
@@ -0,0 +1,105 @@
1
+ # trnsolver
2
+
3
+ Linear solvers and eigendecomposition for AWS Trainium via NKI.
4
+ Part of the trnsci scientific computing suite.
5
+
6
+ ## What This Is
7
+
8
+ Eigenvalue problems, matrix factorizations, and iterative solvers targeting
9
+ Trainium's Tensor Engine. Complements trnblas (BLAS) and trnfft (FFT).
10
+
11
+ **Primary use case:** SCF eigenvalue problem for quantum chemistry. The SCF
12
+ iteration solves FC = SCε at each step — a generalized symmetric eigenvalue
13
+ problem reduced to standard form via Cholesky of the overlap matrix S. This
14
+ feeds into DF-MP2 (trnblas) for the correlation energy.
15
+
16
+ ## Architecture
17
+
18
+ ```
19
+ trnsolver/
20
+ ├── trnsolver/
21
+ │ ├── __init__.py # Re-exports all solver operations
22
+ │ ├── eigen.py # eigh, eigh_generalized (Jacobi + torch fallback)
23
+ │ ├── factor.py # cholesky, lu, qr, solve, solve_spd, inv_sqrt_spd
24
+ │ ├── iterative.py # cg, gmres
25
+ │ └── nki/
26
+ │ ├── __init__.py
27
+ │ └── dispatch.py # auto/pytorch/nki dispatch + Jacobi rotation kernel
28
+ ├── tests/
29
+ │ ├── conftest.py # Fixtures: symmetric, SPD, random matrices
30
+ │ ├── test_eigen.py # Eigenvalue tests (reconstruction, orthogonality)
31
+ │ ├── test_factor.py # Cholesky, LU, QR, solve tests
32
+ │ └── test_iterative.py # CG, GMRES convergence tests
33
+ ├── examples/
34
+ │ └── scf_eigen.py # SCF iteration demo (quantum chemistry)
35
+ ├── pyproject.toml
36
+ ├── README.md
37
+ ├── LICENSE # Apache 2.0
38
+ └── CLAUDE.md # This file
39
+ ```
40
+
41
+ ## SCF → Solver Mapping
42
+
43
+ | SCF Step | Math | trnsolver Call |
44
+ |----------|------|---------------|
45
+ | Overlap Cholesky | S = L L^T | `cholesky(S)` |
46
+ | Reduce to standard | A' = L^{-1} F L^{-T} | `eigh_generalized(F, S)` |
47
+ | Eigensolve | A' V = V Λ | `eigh(A')` (Jacobi on NKI) |
48
+ | Back-transform | C = L^{-T} V | `trsm` (in trnblas) |
49
+ | Density | P = C_occ @ C_occ^T | `syrk` (in trnblas) |
50
+ | Metric inverse | J^{-1/2} | `inv_sqrt_spd(J)` |
51
+
52
+ ## NKI Jacobi Strategy
53
+
54
+ The Jacobi eigensolver maps to Trainium hardware:
55
+
56
+ - **Each Givens rotation** is a 2-row/col update — rank-2 matmul on Tensor Engine
57
+ - **Off-diagonal max finding** maps to Vector Engine reduction
58
+ - **Sweep convergence check** is a scalar reduction on Scalar Engine
59
+ - **Eigenvector accumulation** V' = V @ G is a batched column update
60
+
61
+ The Jacobi method is preferred over Householder tridiagonalization on
62
+ Trainium because each rotation is a fixed-size operation that maps cleanly
63
+ to the 128×128 tile, vs Householder which requires growing reflector chains.
64
+
65
+ ## Known Gaps & Design Notes
66
+
67
+ - **NKI Jacobi kernel is a stub.** Falls back to torch.linalg.eigh until
68
+ validated on hardware. The rotation kernel scaffold is in nki/dispatch.py.
69
+
70
+ - **Jacobi is O(n³) per sweep with O(n) sweeps** — cubic overall but with
71
+ a large constant. For n > ~500, Householder + QR iteration would be faster.
72
+ The Jacobi method is chosen because it's embarrassingly parallel (rotations
73
+ on disjoint pairs can run concurrently) and maps cleanly to NKI tiles.
74
+
75
+ - **CG/GMRES are pure PyTorch.** The inner products and matvecs would
76
+ benefit from NKI Level 1/2 kernels in trnblas, but the iteration logic
77
+ stays on the host.
78
+
79
+ - **inv_sqrt_spd uses eigendecomposition**, not the Newton-Schulz iteration.
80
+ Newton-Schulz (X_{k+1} = 0.5 X_k (3I - A X_k²)) is all GEMMs and would
81
+ map better to trnblas, but needs good initial scaling.
82
+
83
+ ## Dependencies
84
+
85
+ - `torch>=2.1` — tensor operations and CPU fallback
86
+ - `numpy>=1.24` — test reference
87
+ - `neuronxcc` — NKI kernels (optional, only on Neuron hardware)
88
+
89
+ ## Development
90
+
91
+ ```bash
92
+ pip install -e ".[dev]"
93
+ pytest tests/ -v
94
+ python examples/scf_eigen.py --demo
95
+ ```
96
+
97
+ ## Naming Convention
98
+
99
+ Sibling repos in the trn-* suite:
100
+ - `trnfft` — FFT + complex ops (https://github.com/trnsci/trnfft)
101
+ - `trnblas` — BLAS operations (https://github.com/trnsci/trnblas)
102
+ - `trnsolver` — Linear solvers, eigendecomposition (this repo)
103
+ - `trnrand` — Random number generation (planned)
104
+
105
+ All repos: Python/NKI, Apache 2.0.
@@ -0,0 +1,25 @@
1
+ # Code of Conduct
2
+
3
+ This project adopts the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1, as its code of conduct. The full text is available at:
4
+
5
+ https://www.contributor-covenant.org/version/2/1/code_of_conduct/
6
+
7
+ ## Scope
8
+
9
+ This Code applies within all project spaces — the GitHub repositories under the [trnsci](https://github.com/trnsci) organization, issue trackers, pull request discussions, and any public forums where an individual is representing the project or its community.
10
+
11
+ ## Reporting
12
+
13
+ Concerns about behaviour in project spaces may be reported confidentially to:
14
+
15
+ **scttfrdmn@gmail.com**
16
+
17
+ All reports will be reviewed and investigated promptly and fairly. The project maintainers are obligated to respect the privacy and security of the reporter.
18
+
19
+ ## Enforcement
20
+
21
+ Maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
22
+
23
+ ## Attribution
24
+
25
+ This Code of Conduct is adapted from the Contributor Covenant, version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html. It is licensed under CC BY 4.0.
@@ -0,0 +1,69 @@
1
+ # Contributing to trnsolver
2
+
3
+ Thanks for your interest in contributing. This document covers the whole suite — the same guidelines apply to the umbrella and to each of the six sub-projects (`trnfft`, `trnblas`, `trnrand`, `trnsolver`, `trnsparse`, `trntensor`).
4
+
5
+ ## Where does my change belong?
6
+
7
+ - **Scoped to a single library** — bug fix, new feature, added kernel in one sub-project → open a PR in that sub-project's repo.
8
+ - **Cross-cutting** — integration examples, umbrella docs, CUDA-rosetta content, coordinated version bumps, shared tooling → open a PR against [trnsci/trnsci](https://github.com/trnsci/trnsci).
9
+
10
+ If you aren't sure, open the PR where it's easiest and we'll move it.
11
+
12
+ ## Development setup
13
+
14
+ ```bash
15
+ git clone git@github.com:trnsci/trnsci.git
16
+ cd trnsci
17
+ # Clone sibling sub-projects if you don't already have them:
18
+ for p in trnfft trnblas trnrand trnsolver trnsparse trntensor; do
19
+ [ -d "$p" ] || git clone "git@github.com:trnsci/$p.git"
20
+ done
21
+ make install-dev
22
+ make test-all
23
+ ```
24
+
25
+ A single sub-project in isolation:
26
+
27
+ ```bash
28
+ cd trnfft # or any other
29
+ pip install -e ".[dev]"
30
+ pytest tests/ -v -m "not neuron"
31
+ ```
32
+
33
+ ## Tests
34
+
35
+ - `pytest tests/ -v -m "not neuron"` — the CPU-only suite. Must pass on every PR.
36
+ - `pytest tests/ -v -m neuron` — on-hardware suite, run from a machine with AWS credentials via `scripts/run_neuron_tests.sh`. Not part of standard CI.
37
+
38
+ ## Conventions
39
+
40
+ - **License header** — new files get the Apache 2.0 notice and `Copyright 2026 Scott Friedman` where a notice is customary (long source files, not one-line configs).
41
+ - **Python** — ≥ 3.10; `torch` ≥ 2.1; `numpy` ≥ 1.24.
42
+ - **No emoji** in source, commits, or docs unless the feature is literally about emoji.
43
+ - **Docstrings** only where they help a reader who doesn't have the context you had when writing. Don't restate the signature.
44
+ - **No throwaway files** in the repo root — work-in-progress notes belong in PR descriptions or `docs/`.
45
+
46
+ ## Commit style
47
+
48
+ Conventional-ish prefixes: `fix:`, `feat:`, `docs:`, `test:`, `bench:`, `chore:`, `refactor:`. Keep the subject line ≤ 72 characters. Longer context goes in the body.
49
+
50
+ ## Pull requests
51
+
52
+ Before opening a PR:
53
+
54
+ - [ ] `pytest tests/ -v -m "not neuron"` passes
55
+ - [ ] If you changed public API or behaviour, `CHANGELOG.md` has an `[Unreleased]` entry
56
+ - [ ] If you added a public symbol, the project's `docs/api.md` lists it
57
+ - [ ] PR description says *what* changed and *why*, not just *what*
58
+
59
+ ## Issues
60
+
61
+ Label each issue one of: `bug`, `feature`, `question`, `docs`, `infra`. Bugs include repro steps and expected-vs-actual output. Features describe the use case.
62
+
63
+ ## Code of conduct
64
+
65
+ By participating, you agree to abide by the [Contributor Covenant v2.1](CODE_OF_CONDUCT.md). Report concerns to the contact listed there.
66
+
67
+ ## License
68
+
69
+ Contributions are Apache 2.0, per the repository's [LICENSE](LICENSE). You attest you have the right to submit the code.