Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ and this project follows [Semantic Versioning](https://semver.org/).

## [Unreleased]

- Long weighted Gram diagonals and cross-table cells use compensated accumulation, avoiding roundoff-driven Laplacian validation failures and loss of signed cell contributions.
- Long weighted Gram diagonals use compensated accumulation.

### Changed

- **BREAKING:** `schwarz_precond::PartitionWeights::Uniform` is a unit variant; `PartitionWeights::len` and `is_empty` are removed. Uniform weights take their shape from `SubdomainCore::n_local`; only explicit weights carry a length. The serialized uniform variant no longer carries a count; the wire-format fixture moves v20 → v21; v20, v19 and v12 remain rejected-payload controls. The fixture number is not a runtime serialization envelope (#425).

- Schwarz subdomains are factored by approx-chol 0.7 from each channel pair's factor-width-2 Gram factor `V`, one column per observation: sign folding, dominance scaling, floating detection and the Schur complement move into approx-chol, and each irreducible block is a subdomain (#481).
- **BREAKING:** `ApproxSchurConfig::seed` (Python `seed=`) is removed; the Schur sampler draws from `ApproxCholConfig::seed`.
- **BREAKING:** `ScalingConfig::tolerance` must lie in `[0, 1)`, else `BuildError::InvalidScalingTolerance`.
- Levels with no cross-factor entries in a channel pair are batched into diagonal Schwarz subdomains per side instead of one subdomain each, cutting per-subdomain build and apply overhead without changing the preconditioner.
- **BREAKING:** `ReductionStrategy` is removed: the `reduction` field of `PreconditionerConfig::Additive` and `::Adaptive`, Python's `reduction=` argument and `within.config.ReductionStrategy`, and the strategy argument of `SchwarzPreconditioner::new`/`with_n_dofs` with its `reduction_strategy()` getter. Overlapping subdomain outputs always sum in subdomain order (#472).
- **BREAKING:** `schwarz_precond::LocalSolver::solve_local(x, workspace, allow_inner_parallelism)` solves in place, and the required `workspace_len()` replaces `scratch_size()`. `SubdomainEntry::{core, is_empty, scratch_size, apply_weighted_into_with_scratch, apply_weighted_into_atomic}`, `SubdomainCore::{restrict_weighted, prolongate_weighted_add, prolongate_weighted_add_atomic}`, `BuildError::ScratchSizeTooSmall` and `SolveError::Synchronization` are removed.
Expand Down
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ as `.build_duration_seconds`; both are preserved across pickling and reuse.
| `LocalSolverConfig(approx_chol?, schur?, dense_threshold=24, scaling?)` | Schur reduction + approximate Cholesky. Omit `schur` for the library-default approximate variant; pass `schur=Schur.exact()` to request an exact Schur (slower, used for validation). |
| `Schur.approximate(config?)` / `Schur.exact()` | Schur-reduction mode passed as `LocalSolverConfig(schur=...)`. |
| `ApproxCholConfig(seed=0, split_merge=None)` | Approximate Cholesky parameters. |
| `ApproxSchurConfig(seed=0, split=1)` | Approximate Schur complement sampling parameters. |
| `ApproxSchurConfig(split=1)` | Approximate Schur complement sampling parameters; draws from `ApproxCholConfig.seed`. |

### Result types

Expand Down Expand Up @@ -284,7 +284,7 @@ across solves like any other.
|---|---|---|
| `within::config` | public | `LsmrOptions`, `PreconditionerConfig`, `LocalSolverConfig`, `SchurMode`, `ApproxCholConfig`, `ApproxSchurConfig`, `ScalingConfig` |
| `within::error` | public | `WithinError`, `BuildError`, `SolveError` |
| `block_elim` / `channel` / `csr_block` / `domain` / `linalg` / `operator` / `solver` | `pub(crate)` | implementation layers — public items are re-exported at the crate root |
| `block_solver` / `channel` / `domain` / `linalg` / `operator` / `solver` | `pub(crate)` | implementation layers — public items are re-exported at the crate root |

## Project structure

Expand Down
4 changes: 2 additions & 2 deletions benchmarks/_framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,13 +207,13 @@ def standard_solver_configs(
"""
schur = LocalSolverConfig(
approx_chol=ApproxCholConfig(seed=opts.seed),
schur=Schur.approximate(ApproxSchurConfig(seed=opts.seed)),
schur=Schur.approximate(ApproxSchurConfig()),
)
# "2-2": both densification knobs on — split_merge=2 (AC2 reduced-system
# factorization) and split=2 (denser Schur clique-tree sampling).
schur_2_2 = LocalSolverConfig(
approx_chol=ApproxCholConfig(seed=opts.seed, split_merge=2),
schur=Schur.approximate(ApproxSchurConfig(seed=opts.seed, split=2)),
schur=Schur.approximate(ApproxSchurConfig(split=2)),
)
return [
SolverConfig(
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/suites/ac_comparison.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
def _schur(seed: int, split_merge: int | None) -> LocalSolverConfig:
return LocalSolverConfig(
approx_chol=ApproxCholConfig(seed=seed, split_merge=split_merge),
schur=Schur.approximate(ApproxSchurConfig(seed=seed)),
schur=Schur.approximate(ApproxSchurConfig()),
)


Expand Down
4 changes: 2 additions & 2 deletions benchmarks/suites/fixest_comparison.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,13 @@ def run_fixest_comparison(opts: SuiteOptions) -> list[BenchmarkResult]:
)
approx_schur = LocalSolverConfig(
approx_chol=ApproxCholConfig(seed=0, split_merge=8),
schur=Schur.approximate(ApproxSchurConfig(seed=0)),
schur=Schur.approximate(ApproxSchurConfig()),
)
# "2-2": both densification knobs on — split_merge=2 (AC2 factorization)
# and split=2 (denser Schur clique-tree sampling).
schur_2_2 = LocalSolverConfig(
approx_chol=ApproxCholConfig(seed=0, split_merge=2),
schur=Schur.approximate(ApproxSchurConfig(seed=0, split=2)),
schur=Schur.approximate(ApproxSchurConfig(split=2)),
)

solver_configs = [
Expand Down
15 changes: 5 additions & 10 deletions crates/within-py/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,32 +55,27 @@ impl PyApproxCholConfig {
#[pyclass(frozen, module = "within._within")]
#[pyo3(name = "ApproxSchurConfig")]
pub struct PyApproxSchurConfig {
#[pyo3(get)]
pub seed: u64,
#[pyo3(get)]
pub split: u32,
}

#[pymethods]
impl PyApproxSchurConfig {
#[new]
#[pyo3(signature = (seed=0, split=1))]
fn new(seed: u64, split: u32) -> PyResult<Self> {
#[pyo3(signature = (split=1))]
fn new(split: u32) -> PyResult<Self> {
if split == 0 {
return Err(pyo3::exceptions::PyValueError::new_err(
"split must be >= 1",
));
}
Ok(Self { seed, split })
Ok(Self { split })
}
}

impl PyApproxSchurConfig {
pub(crate) fn to_native(&self) -> ApproxSchurConfig {
ApproxSchurConfig {
seed: self.seed,
split: self.split,
}
ApproxSchurConfig { split: self.split }
}
}

Expand Down Expand Up @@ -117,7 +112,7 @@ impl PySchur {
fn __repr__(&self) -> String {
match &self.inner {
SchurMode::Approximate(cfg) => {
format!("Schur.approximate(seed={}, split={})", cfg.seed, cfg.split)
format!("Schur.approximate(split={})", cfg.split)
}
SchurMode::Exact => "Schur.exact()".to_string(),
}
Expand Down
2 changes: 1 addition & 1 deletion crates/within/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ categories.workspace = true

[dependencies]
schwarz-precond = { workspace = true, features = ["serde"] }
approx-chol = { version = "0.6.0", features = ["serde"] }
approx-chol = { version = "0.7.0", features = ["serde"] }
serde = { workspace = true, features = ["rc"] }
postcard.workspace = true
ndarray = "0.17"
Expand Down
17 changes: 0 additions & 17 deletions crates/within/src/block_elim.rs

This file was deleted.

82 changes: 0 additions & 82 deletions crates/within/src/block_elim/csr_matrix.rs

This file was deleted.

Loading
Loading