#2937: TwoPuncturesX largely duplicates TwoPunctures
Reporter: Zach Etienne
Status: new
Milestone:
Version:
Type: bug
Priority: major
Component:
TwoPuncturesX inclusion ticket: #2926
While `TwoPuncturesX` ( is an essential thorn for CarpetX, it currently exists largely as a line-by-line copy of `TwoPunctures`, with more than 90% of the lines of code duplicated.
This approach creates a maintenance burden: any updates to the core logic of either `TwoPunctures` or `TwoPuncturesX` must be manually replicated in the other thorn. This increases the risk that the two implementations will diverge over time, leading to inconsistent behavior, duplicated bugs, or fixes being applied in one thorn but accidentally omitted from the other.
Duplicated code is not acceptable here for several reasons. First, it makes long-term maintenance more error-prone, because developers must remember to update two nearly identical code paths whenever a change is made. Second, it makes review and testing more difficult, since reviewers and maintainers must determine whether differences between the two thorns are intentional, accidental, or simply the result of one copy being out of date. More broadly, this duplication increases the cost of future development and makes it harder to ensure correctness across both `TwoPunctures` and `TwoPuncturesX`.
During the April 30, 2026 ET telecon, several possible approaches were discussed for addressing this issue:
1. **Make `TwoPuncturesX` require `TwoPunctures`.**
This would reduce duplication by allowing `TwoPuncturesX` to reuse functionality from `TwoPunctures`. However, this may be difficult because `TwoPuncturesX` requires `ADMBaseX`, while `TwoPunctures` requires `ADMBase`.
2. **Create symbolic links for files that are identical between the two thorns.**
For files that are exactly the same in both thorns, symbolic links could ensure that updates to one file are automatically reflected in the other. This would reduce the risk of the two copies drifting apart, though care would be needed to ensure this works reliably across development environments and version-control workflows.
3. **Create a shared `TwoPuncturesGuts` thorn.**
A new thorn, tentatively named `TwoPuncturesGuts`, could contain header files or shared source components comprising the core utilities used by both `TwoPunctures` and `TwoPuncturesX`. This would provide a cleaner long-term solution by centralizing the common implementation while allowing the two thorns to retain their separate interfaces and dependencies where necessary.
The goal of this ticket is to identify and implement a maintainable structure that avoids unnecessary code duplication while preserving the functionality required by both `TwoPunctures` and `TwoPuncturesX`.
--
Ticket URL: https://bitbucket.org/einsteintoolkit/tickets/issues/2937/twopuncturesx-lar…
#2916: Include Cottonmouth
Reporter: Beyhan KarakaÅŸ
Status: open
Milestone: ET_2026_05
Version:
Type: enhancement
Priority: major
Component: EinsteinToolkit thorn
Comment (by Lucas Timotheo Sanches):
Hey Zach,
Thanks for the comments! I have addressed all the issues pointed out so far. They are already in the `master` branch of EinsteinEngine. Please recheck and see if the changes are adequate
--
Ticket URL: https://bitbucket.org/einsteintoolkit/tickets/issues/2916/include-cottonmou…
#2931: Claude AI edits to TwoPuncturesX
Reporter: Steven R. Brandt
Status: new
Milestone:
Version:
Type: bug
Priority: major
Component:
Comment (by Steven R. Brandt):
I think all clanker issues are now addressed. While there never was a passing test in this thorn, it still passes the test Lucas added in feature/TwoPuncturesX-tests.
--
Ticket URL: https://bitbucket.org/einsteintoolkit/tickets/issues/2931/claude-ai-edits-t…
#2931: Claude AI edits to TwoPuncturesX
Reporter: Steven R. Brandt
Status: new
Milestone:
Version:
Type: bug
Priority: major
Component:
Comment (by Steven R. Brandt):
I say we leave it as is and wait for the clankers to become smart enough to figure it out.
--
Ticket URL: https://bitbucket.org/einsteintoolkit/tickets/issues/2931/claude-ai-edits-t…
#2929: GRHayLET/IllinoisGRMHD convert_IllinoisGRMHD_to_HydroBase schedule compatibility with VolumeIntegrals_*
Reporter: Maxwell Rizzo
Status: new
Milestone: ET_2026_05
Version: ET_2025_05
Type: bug
Priority: major
Component: EinsteinToolkit thorn
Comment (by Leonardo Rosa Werneck):
[PR #15](https://github.com/GRHayL/GRHayLET/pull/15) was merged. Please close this ticket if in fact issue was resolved.
--
Ticket URL: https://bitbucket.org/einsteintoolkit/tickets/issues/2929/grhaylet-illinois…
#2936: CarpetX tsv output does not append files
Reporter: Maxwell Rizzo
Status: new
Milestone:
Version:
Type: enhancement
Priority: minor
Component: CarpetX
CarpetX’s TSV output, excluding the norms/ files, does not append to a single file per group in the way Carpet’s ASCII output does. Instead, it creates one file per group per iteration: `<group>.it000000.<x/y/z>.tsv` for grid functions and arrays, and `<group>.it000000.tsv` for scalars.
Appending subsequent iterations to the same file would make analysis and post-processing easier, while also reducing the amount of output files.
--
Ticket URL: https://bitbucket.org/einsteintoolkit/tickets/issues/2936/carpetx-tsv-outpu…
#2916: Include Cottonmouth
Reporter: Beyhan KarakaÅŸ
Status: open
Milestone: ET_2026_05
Version:
Type: enhancement
Priority: major
Component: EinsteinToolkit thorn
Comment (by Zach Etienne):
Issues found (sorry for the uneven formatting):
```
Issue 1:
Missing symmetrization in the conformal Ricci tensor inside the constraints/analysis block.
Where the bug is
In `fun_bssn_cons`, the code uses
+ Delta[uc] * Gammat[la, lb, lc]
but in the BSSN Ricci decomposition the corresponding term is the symmetrized object
Delta^c * Gammat_(ab)c
which means
(1/2) * Delta^c * Gammat_abc
+ (1/2) * Delta^c * Gammat_bac.
Minimal fix
Replace
+ Delta[uc] * Gammat[la, lb, lc]
by
+ Rational(1, 2) * Delta[uc] * Gammat[la, lb, lc]
+ Rational(1, 2) * Delta[uc] * Gammat[lb, la, lc]
Note that your own `fun_bssn_rhs` block already contains the correct symmetrized pair and therefore serves as an internal consistency check.
```
2. bssnok.py
```
* Issue 2
- Severity high
- Description of the error
- The momentum-constraint matter source carries an extra factor of `w**2`. With `g_{ij} = (1 / w**2) * gt_{ij}`, one has `gamma^{ij} = w**2 * gt^{ij}`, but the conformal BSSN momentum constraint with free upper index uses `gt^{ij} * S_j`, not `gamma^{ij} * S_j`. The current code therefore overweights the source term by a factor of `w**2`.
- Filename + line number(s)
- Pasted file (filename not provided):638-648
- Original code snippet
- fun_bssn_cons.add_eqn(
MomCons[ua],
+ gt[ua, uc] * gt[ub, ud] * (
D(At[lc, ld], lb)
- Gammat[uk, lc, lb] * At[lk, ld]
- Gammat[uk, ld, lb] * At[lc, lk]
)
+ 6 * At[ua, ub] * cdphi[lb]
- Rational(2, 3) * gt[ua, ub] * D(trK, lb)
# Matter
- 8 * pi * w**2 * gt[ua, ub] * S[lb]
)
- Fixed code snippet.
- fun_bssn_cons.add_eqn(
MomCons[ua],
+ gt[ua, uc] * gt[ub, ud] * (
D(At[lc, ld], lb)
- Gammat[uk, lc, lb] * At[lk, ld]
- Gammat[uk, ld, lb] * At[lc, lk]
)
+ 6 * At[ua, ub] * cdphi[lb]
- Rational(2, 3) * gt[ua, ub] * D(trK, lb)
# Matter
- 8 * pi * gt[ua, ub] * S[lb]
)
- Confidence
- 96%
* Issue 3
- Severity low
- Description of the error
- The comments defining `Delta` are mathematically malformed. They describe the contraction with the wrong index pattern, which can mislead a reader into thinking `Delta^i` is built from `tilde gamma^{i,j} tilde Gamma^a_{ab}` or `tilde gamma^{ij} tilde Gamma^i_{jk}`. The correct definition is `Delta^i = tilde gamma^{jk} tilde Gamma^i_{jk}`. The executable code below the comments is correct; only the comments are wrong.
- Filename + line number(s)
- Pasted file (filename not provided):273-275
- Original code snippet
- # \tilde{\gamma}^{i, j} \tilde{\Gamma}^a_{a b}
# When \tilde{\Gamma}^{i} when it appears and its derivative are not needed,
# the substitution \tilde{\Gamma}^{i} \rightarrow \tilde{gamma}^{ij} \tilde{\Gamma}^{i}_{jk} = \Delta^i
- Fixed code snippet.
- # \Delta^i = \tilde{\gamma}^{jk} \tilde{\Gamma}^i_{jk}
# When \tilde{\Gamma}^{i} appears without derivatives, we replace it by
# \Delta^i = \tilde{\gamma}^{jk} \tilde{\Gamma}^{i}_{jk}
- Confidence
- 99%
```
```
Issue 4:
linear_wave.py:
File sets an unphysical default amplitude for the wave:
amplitude = cottonmouth_linear_wave_id.add_param(
"amplitude",
default=1.0,
desc="Linear wave amplitude"
)
A << 1 for a valid linearized wave.
```
--
Ticket URL: https://bitbucket.org/einsteintoolkit/tickets/issues/2916/include-cottonmou…