[pull] develop from lammps:develop#156
Merged
Merged
Conversation
Implement the Yeh-Berkowitz EW3DC slab correction (kspace_modify slab <volfactor>) for triclinic simulation cells in the ewald, ewald/disp, pppm, and pppm/cg styles (addresses #410). The slab z-extension (slab_volfactor) was missing from the triclinic reciprocal-space sum: the reciprocal lattice vectors built via KSpace::x2lamdaT() used the real box z dimension, not the slab-extended one. Since z is non-periodic for slab geometries (xz == yz == 0), the extended-box transform reduces to scaling the z component of the transformed reciprocal vector by 1/slab_volfactor, which centralizes the fix for both Ewald and PPPM. It is a no-op for all non-slab runs. For PPPM the lamda grid z spacing (delzinv) is extended to match Grid3d::set_zfactor(), slabcorr() is reordered after the lamda->box coordinate conversion so it operates on Cartesian z, and the Green's-function alias-sum bound in z accounts for the extended cell. Validated: ewald and ewald/disp reproduce the orthogonal slab result to machine precision for a zero-tilt triclinic cell; pppm and pppm/cg match the exact Ewald slab result to PPPM accuracy for both zero and finite xy tilt; results are identical on 1, 2, and 4 MPI ranks. Adds four regression tests under unittest/force-styles/tests. The pppm/tip4p, pppm/gpu, pppm/intel, and pppm/kk styles are kept blocked for triclinic cells, as are the slab nozforce and ew2d options. esp and pppm/stagger have pre-existing triclinic limitations unrelated to the slab correction and remain unsupported. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The slab z-extension is applied in KSpace::x2lamdaT() by scaling the transformed reciprocal vector's z component by 1/slab_volfactor. This is exactly the extended-cell transform c' = (xz, yz, zz*volfactor): for xz == yz == 0 the images stack perpendicular to the xy plane, matching the Yeh-Berkowitz analytic correction in slabcorr() (which uses only the Cartesian z coordinates and L_z). With a non-zero xz or yz tilt the reciprocal-space sum would use tilted image stacking while slabcorr() still assumes perpendicular stacking, silently producing an inconsistent result. A Yeh-Berkowitz slab is premised on the slab normal being the Cartesian z axis, so such boxes are now rejected with a clear error in the init() of ewald, ewald/disp, and pppm (covering pppm/cg and the OpenMP variants by inheritance) rather than computed incorrectly. An xy tilt remains fully supported and exact. Nothing in domain.cpp forbade a non-zero xz/yz tilt with a non-periodic z dimension (boundary p p f), so this path was reachable. Update the x2lamdaT() comment to state the requirement is now enforced and document the restriction in kspace_modify.rst. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stage 1 of modernizing P. in 't Veld's long-range dispersion styles.
Structural changes only; the force/energy kernel math is preserved
verbatim (deeper kernel rewrite deferred to a later stage).
- replace the magic ewald_order/ewald_off bit literals ((1<<1), (1<<6),
0x42, 64, 2) with a named enum {EWALD_COUL, EWALD_DISP} and use it
consistently; spell (ewald_off^-1) as ~ewald_off
- options() now takes an explicit flag mask and dispatches on the
keyword with strcmp instead of a parallel-array linear search + switch
- extract() rewritten as an explicit if-chain instead of parallel
id/pointer arrays with index magic for the dim value
- compute(), compute_inner/middle/outer(): replace manual pointer
arithmetic (x0+(i+(i<<1)), f0+3*i, memcpy) and sentinel-pointer
neighbor loops with standard indexed ilist/jlist loops and x[i]/f[i]
indexing; split assignment-in-condition; drop the shadowing scratch
'f' in the force update
pair lj/long/tip4p/long shares the base options(), so its settings()
is updated to the new flag enum in lockstep (its compute kernels are
refactored in a later stage).
No behavior change; force-style YAML regression tests for
lj_long_coul_long(+dielectric/off/cut) and lj_long(+cut)_tip4p_long pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stage 2 of modernizing P. in 't Veld's long-range dispersion styles.
Same structural-only transformation as for lj/long/coul/long; the
Buckingham force/energy kernel math is preserved verbatim.
- named enum {EWALD_COUL, EWALD_DISP} replaces the magic ewald_order
bit literals; ~ewald_off replaces (ewald_off^-1)
- options() takes a flag mask and dispatches with strcmp
- extract() rewritten as an explicit if-chain
- compute(), compute_inner/middle/outer(): standard indexed
ilist/jlist neighbor loops and x[i]/f[i] indexing instead of pointer
arithmetic, memcpy and sentinel-pointer loops; assignment-in-condition
split out; shadowing scratch in the force update removed; stray
comma operator in the per-i setup fixed to a statement separator
No behavior change; force-style YAML regression tests for
buck_long_coul_long(+off/cut) and buck_table_coul_* pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stage 3 of modernizing P. in 't Veld's long-range dispersion styles.
Unlike its lj/long/coul/long base class, this derived style was already
written with conventional indexed ilist/jlist neighbor loops and
x[i]/f[i] indexing, so no loop restructuring is needed. Replace the
remaining magic ewald_order bit literals ((1<<1), (1<<6)) in the
compute/compute_inner/compute_middle/compute_outer kernels with the
named {EWALD_COUL, EWALD_DISP} enum introduced for the family (the
settings() function was already converted alongside Stage 1).
No behavior change; tip4p force-style and kspace regression tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stage 4 of modernizing P. in 't Veld's long-range dispersion styles.
Structural changes only; the dipole/charge/LJ force, energy and torque
kernel math is preserved verbatim.
- named enum {EWALD_COUL, EWALD_DIPOLE, EWALD_DISP} replaces the magic
ewald_order bit literals ((1<<1), (1<<3), (1<<6), 0x4a)
- options() takes a flag mask and dispatches with strcmp
- extract() rewritten as an explicit if-chain
- compute(): standard indexed ilist/jlist neighbor loop with x[i]/f[i]/
mu[i]/torque[i] indexing instead of manual pointer arithmetic
(x0+(i+(i<<1)), mu0+(i<<2), f0+3*i, memcpy) and sentinel-pointer
loops; the per-pair torque-on-i update (identical in both newton
branches) is hoisted so only the j-side update stays newton-guarded;
fx/fy/fz are still captured for ev_tally_xyz
This style has no respa or single() support (single is commented out and
left as-is), so compute() is the only kernel.
No behavior change; lj_long_dipole_long and lj_long_cut_dipole_long
force-style regression tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stage 5 of modernizing P. in 't Veld's long-range dispersion styles.
Structural changes only; all k-space math is preserved verbatim.
- convert the C_RMULT/C_CRMULT/C_SET/C_CONJ/C_ANGLE function-like macros
(complex multiply, conjugate-multiply, set, conjugate, e^i*angle) into
type-safe static inline functions c_rmult/c_crmult/c_set/c_conj/
c_angle on the local complex struct; the multiplies copy their input
first so the destination may still alias an argument, as before
- replace the COMPLEX_NULL brace-macro with a plain {0, 0} aggregate
initializer and the EWALD_NSUMS brace-macro with its {1, 1, 7, 1}
literal at the single use site (drops the macro from the header)
- remove the dead "//#define DEBUG" toggle
The intricate k-vector structure-factor loops are left intact; deeper
expression-level cleanup is deferred to the later kernel-rewrite stage.
No behavior change; ewald_disp and ewald_disp_dipole kspace regression
tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stage 6 of modernizing P. in 't Veld's long-range dispersion styles.
Brings the /omp variants in line with their refactored base classes;
structural changes only, kernel math preserved verbatim.
pair lj/long/coul/long/omp and buck/long/coul/long/omp:
- named enum {EWALD_COUL, EWALD_DISP} for the compute() dispatcher flags
and the eval_inner/eval_middle order tests; ~ewald_off for (ewald_off^-1)
- eval()/eval_inner/eval_middle/eval_outer: drop the manual pointer
arithmetic (x0+(i+(i<<1)), f0+3*i, memcpy) and pointer-walked inner
neighbor loops for standard jlist/jnum loops with x[i]/f[j] indexing;
the per-thread force array from thr->get_f() is indexed directly;
split assignment-in-condition and the shadowing force-update scratch;
fixed the stray comma operator in buck's per-i setup
pair lj/long/tip4p/long/omp: already used conventional indexed loops, so
only the ewald_order bit literals are replaced with the enum.
No behavior change; the force-style tests run each style with -sf omp
-pk omp 4, and lj_long*, buck_long*, buck_table* and tip4p* all pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stage 7 of modernizing P. in 't Veld's long-range dispersion styles.
Brings the /opt variant in line with its refactored base class;
structural changes only, kernel math preserved verbatim.
- named enum {EWALD_COUL, EWALD_DISP} for the compute()/compute_outer()
dispatcher flags
- eval() and eval_outer(): standard indexed ilist/jlist neighbor loops
with x[i]/f[i] indexing instead of manual pointer arithmetic
(x0+(i+(i<<1)), f0+3*i, memcpy) and sentinel-pointer loops; split the
assignment-in-condition and the shadowing force-update scratch
No behavior change; the force-style tests run the style with -sf opt and
lj_long_coul_long(+dielectric/off) pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The long-range dispersion pair styles exposed their vdW/LJ cutoff through the Pair::extract() key "cut_LJ", while lj/long/dipole/long already used "cut_vdwl". Standardize on "cut_vdwl" across the family: - lj/long/coul/long, buck/long/coul/long and lj/long/tip4p/long now return the cutoff for "cut_vdwl" and keep "cut_LJ" as a backward-compatibility alias (commented for future removal). tip4p's extract() parallel-array lookup is converted to the same explicit if-chain as the others. - the only in-tree consumer, pppm/disp (and pppm/disp/tip4p via inheritance), now requests "cut_vdwl". No behavior change; lj_long*, buck_long*, tip4p* and pppm_disp* regression tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Kernel-math readability pass (follow-up to the structural refactor on branch refactor-dispersion-styles). Behavior is preserved: every floating-point operation keeps its original grouping and order, so results stay bit-for-bit identical; only names and statement structure change. Covers compute(), compute_inner/middle/outer() and single(). - rename single-letter scratch to convey meaning: x->grij (Ewald scaled distance), s->pre (qqrd2e*qi*qj), rn->r6inv/r12inv, x2->gr2/expterm, f->fraction (table interpolation weight) / factor (special-bond scale) - name the erfc series polynomial (erfc_poly), the reciprocal-space dispersion terms (g6term/g8term, expterm), and precompute the dispersion-table interpolants (ftable_disp/etable_disp) once instead of inlining them in each branch - unpack the "force_coul = (t *= ...) + ..." assignment-in-expression and the in-place "(rn *= rn)" squaring into explicit r6inv/r12inv so the power used by each force/energy term is visible; the special-bond subtraction is named "adjust" - rename the union scratch t->rsq_lookup in the table branches No behavior change; lj_long_coul_long(+dielectric/off/cut) force-style tests pass (verlet, rRESPA, and single()). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Kernel-math readability pass, same conventions as for lj/long/coul/long. Behavior preserved: every floating-point operation keeps its original grouping and order (bit-for-bit identical results); only names and statement structure change. Covers compute(), compute_inner/middle/ outer() and single(). - Coulomb real-space term: x->grij, s->pre, named erfc_poly, the special-bond subtraction named adjust, the (t *= ...) compound unpacked - Buckingham dispersion: rn->r6inv, x2->gr2/expterm, named the reciprocal-space g6term/g8term and the dispersion-table interpolants ftable_disp/etable_disp, f->factor for the special-bond scale; the redundant inner re-derivation of r6inv in the table branch is dropped - table branches: union scratch t->rsq_lookup, weight f->fraction - single(): the function-scope coulomb scratch f is replaced by a local adjust No behavior change; buck_long_coul_long(+off/cut) and buck_table_coul_* force-style tests pass (verlet, rRESPA, single()). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Kernel-math readability pass, same conventions as for lj/long/coul/long. The Coulomb / M-site path was already written in the conventional expanded form, so only the Lennard-Jones blocks are touched, in compute(), compute_inner/middle() and compute_outer(). Behavior is preserved bit-for-bit (operation grouping unchanged); this style has no single() (single_enable = 0). - rn->r6inv/r12inv (unpacking the in-place (rn *= rn) squaring), x2->gr2/expterm, named reciprocal-space terms g6term/g8term, named the dispersion-table interpolants ftable_disp/etable_disp, f->factor, union scratch disp_t->rsq_lookup No behavior change; tip4p force-style and kspace regression tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Kernel-math readability pass, same conventions as for the rest of the family. Behavior preserved bit-for-bit (operation grouping unchanged). Only compute() exists (single() is commented out and untouched). - Lennard-Jones block: rn->r6inv/r12inv (unpacking the in-place (rn *= rn)), x2->gr2/expterm, named reciprocal-space g6term/g8term, f->factor; the existing "ni < 0" special-bond test is preserved as-is - dipole real-space header: x->grij for consistency with the family The dipole Smith-Ewald recursion (B0..B3, G0..G2) is already written with named intermediates and is left as-is. No behavior change; lj_long_dipole_long and lj_long_cut_dipole_long force-style tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Same kernel-math readability pass as the base class, applied to the threaded eval()/eval_inner/eval_middle/eval_outer() kernels. Behavior preserved bit-for-bit (operation grouping unchanged). - Coulomb: x->grij, s->pre, named erfc_poly, special-bond term adjust, (t *= ...) unpacked; LJ: rn->r6inv/r12inv, x2->gr2/expterm, g6term/g8term, dispersion-table interpolants ftable_disp/etable_disp, f->factor; table union scratch t/disp_t->rsq_lookup, weight f->fraction - the table-branch "double f" scratch also previously shadowed the thread-local force array f; renaming it to fraction/factor removes the shadow No behavior change; the force-style tests run the style with -sf omp -pk omp 4 and lj_long_coul_long(+dielectric/off/cut) pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Same kernel-math readability pass as the base class, applied to the threaded eval()/eval_inner/eval_middle/eval_outer() kernels; behavior preserved bit-for-bit (operation grouping unchanged). - Coulomb: x->grij, s->pre, named erfc_poly, special-bond term adjust (the old 'ri'/'f' names), (t *= ...) unpacked - Buckingham: rn->r6inv, x2->gr2/expterm, named g6term/g8term and the dispersion-table interpolants ftable_disp/etable_disp, f->factor; the redundant inner r6inv re-derivation in the table branch is dropped - table union scratch t/disp_t->rsq_lookup, weight f->fraction No behavior change; buck_long_coul_long(+off/cut) and buck_table_coul_* pass under -sf omp -pk omp 4. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Same kernel-math readability pass as the base class; only the Lennard-Jones blocks of the threaded eval()/eval_inner/eval_middle/ eval_outer() kernels are touched (Coulomb / M-site path was already in expanded form). Behavior preserved bit-for-bit. - rn->r6inv/r12inv, x2->gr2/expterm, named g6term/g8term and the dispersion-table interpolants ftable_disp/etable_disp, f->factor, union scratch disp_t->rsq_lookup No behavior change; tip4p force-style and kspace tests pass under -sf omp -pk omp 4. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Same kernel-math readability pass as the base class, applied to the templated eval()/eval_outer() kernels; behavior preserved bit-for-bit. - Coulomb: x->grij, s->pre, named erfc_poly, special-bond term adjust, (t *= ...) unpacked; LJ: rn->r6inv/r12inv, x2->gr2/expterm, g6term/g8term, dispersion-table interpolants ftable_disp/etable_disp, f->factor; table union scratch t/disp_t->rsq_lookup, weight f->fraction No behavior change; lj_long_coul_long(+dielectric/off) pass under -sf opt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The dispersion-capable k-space solvers stored which interaction terms are enabled in an int array named 'function' indexed by magic numbers 0..3. Rename it to termflag[] and replace the magic indices with named constants (TERM_COUL, TERM_DISP_GEOM, TERM_DISP_ARITH, TERM_DIPOLE/TERM_DISP_NONE) shared via ewald_const.h, which now also hosts the previously per-header EWALD_MAXORDER and EWALD_NTERMS counts. Applied to pppm/disp and its OPENMP, INTEL, and DIELECTRIC variants. No behavior change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Statement-level rewrite of the ewald/disp k-space solver while keeping every numeric expression and its evaluation order intact: - all pointer-sentinel atom loops (while (x<xn) with *(x++)) replaced by indexed for-loops over nlocal using x[i]/f[i]/q[i]/type[i]/mu[i] - running output pointers (*(ke++), (cek++)->im, (--bi)[0]) replaced by explicit running indices into kenergy/kvirial/sfac_all - the zx/zy/zz pointer dance building the e^(ikr) table replaced by an indexed recursion built directly into the per-atom table (this also removes a scratch allocation and memcpy per atom per step) - assignment-in-expression and multi-statement lines split up - raw new[]/delete[] with a hand-maintained byte counter replaced by memory->create()/destroy() and a memory_usage() computed from the current allocation sizes - the kvec x-major ordering invariant that the kx/ky caching in all k-loops relies on is now documented at the point where it is created - skip-increment blocks in compute_virial_dipole() replaced by computed channel offsets - members and methods renamed to match ewald.cpp and ewald_dipole.cpp vocabulary: compute_ek() -> eik_dot_r(), coefficients() -> coeffs(), compute_slabcorr() -> slabcorr(), nbox -> kmax, nkvec -> kcount, unit -> unitk, cek_local/cek_global -> sfac/sfac_all, ekr_local -> ekr, function[] -> termflag[] with named TERM_* indices, sum -> coeff_sum - dead code removed: the never-called compute_surface(), commented-out code blocks, and stale questions in comments; the unused-member shadowing in reallocate() is resolved by a true high-water mark Verified bit-for-bit against the previous code: forces, torques, energies, pressure, per-atom energy/stress identical to the last bit over 4-step runs of geometric, arithmetic, and dipole mixing, triclinic, slab correction, per-atom output, and a 4-rank MPI run. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The seven-channel arithmetic-mixing code path of ewald/disp had no test coverage; the existing kspace-ewald_disp.yaml exercises geometric mixing only. Reference data generated with the (bit-identical) refactored code. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MSM is a true non-periodic method and handles non-periodic boundaries natively via the boundary command, so the Yeh-Berkowitz EW3DC slab correction is meaningless for it. Previously MSM only printed a "slab correction not needed" warning on rank 0 but left slabflag/slab_volfactor untouched. After extending EW3DC to triclinic boxes, KSpace::x2lamdaT() now scales the z component of the transposed reciprocal transform by slab_volfactor whenever slabflag == 1. MSM also supports triclinic boxes and calls x2lamdaT() on its triclinic grid/force paths, so "kspace_modify slab N" silently divided the MSM z-force by N (e.g. fz 2.5236 -> 1.4879 for N=3). Fix: in MSM::init(), if slabflag == 1, warn on rank 0 and reset slabflag and slab_volfactor on ALL ranks (a rank-0-only reset would diverge the parallel reciprocal-space transform). This also covers msm/dielectric, which calls MSM::init(). With the fix, an MSM run with "slab" is once again bit-identical to one without it at every MPI rank count. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The force-style YAML tests (kspace-*_tri_slab.yaml) exercise the pair+kspace force in a triclinic slab box, but they never invoke "compute group/group", whose own slab correction (KSpace::slabcorr_groups) was separately enabled for triclinic cells when EW3DC was generalized to non-orthogonal boxes. This adds unittest/commands/test_kspace_group_group_slab.cpp, a GoogleTest that builds the two-charged-sheet reproducer from #411 (charges +/-1 in a box periodic in x,y and non-periodic in z, Lx=1 Ly=2) and checks the group A <-> group B interaction for ewald and pppm: - the orthogonal reference matches the analytic infinite-sheet result, z force = 2*pi*q^2/(Lx*Ly) = pi and energy = 2*pi*q^2*d/(Lx*Ly) = 5*pi; - the triclinic xy-tilted box reproduces the orthogonal result (Ewald to ~1e-13, PPPM within mesh tolerance), confirming the triclinic group/group slab path. Verified passing on 1, 2, and 4 MPI ranks. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ic box Locks in the fix that makes MSM reset slabflag/slab_volfactor: builds a triclinic (xy-tilted) charged system and checks that the MSM forces are bit-for-bit identical with and without "kspace_modify slab". Without the fix the shared KSpace::x2lamdaT() slab_volfactor scaling corrupts the MSM z-force. Verified identical (max diff 0) on 1, 2, and 4 MPI ranks. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Addresses review comments on PR #5002: - Extend the triclinic slab (EW3DC) correction to the Kokkos PPPM style (pppm/kk). The change mirrors the already-tested CPU pppm.cpp path: * relax the init() guard to allow slabflag==1 with xz==yz==0 and reject nozforce/ew2d (slabflag 2/3) and xz/yz-tilted triclinic slab boxes; * extend the lamda z grid by slab_volfactor in setup_triclinic() (delzinv, delvolinv); * scale the z alias-sum bound by slab_volfactor in compute_gf_ik_triclinic(); * scale the transformed reciprocal z vector by 1/slab_volfactor in x2lamdaT_kokkos(); * run slabcorr() after lamda2x() so it sees Cartesian z (DomainKokkos lamda2x updates the device x view, so this is correct on device). - Clarify the kspace_modify docs: the point-dipole slab correction (ewald/disp, ewald/dipole, pppm/dipole) is independent of the triclinic support and remains limited to orthogonal cells; add pppm/kk to the list of styles supporting the triclinic EW3DC correction. Compiles cleanly with the Kokkos Serial backend. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VXCmsqrGjFZh99YynfDg4M Co-authored-by: stanmoore1 <stanmoore1@gmail.com>
Now that pppm/kk supports the EW3DC triclinic slab correction, drop kokkos_omp from the skip list of kspace-pppm_tri_slab.yaml so the existing reference forces are checked against pppm/kk run with '-sf kk' on a triclinic xy-tilted slab box. gpu and intel remain skipped since pppm/gpu and pppm/intel still reject triclinic slab boxes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VXCmsqrGjFZh99YynfDg4M Co-authored-by: stanmoore1 <stanmoore1@gmail.com>
Support kspace slab correction (EW3DC) for triclinic boxes
Refactor long-range dispersion styles to idiomatic LAMMPS (structural, no behavior change)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )