Repository navigation
Conversation
…separately - Restore tests/01_PW/scf_sccs_pcc_0d to its Step 2 input and reference, so the default PCC0D path keeps its integration coverage. The lowpass run moves to a new case, scf_sccs_pcc_0d_lowpass (same input as before plus sccs_lowpass_p1 10 / sccs_lowpass_p2 5, same reference values). - Restore PotSccsTest.IonicForceAddsRydbergDerivativeOnce and PotSccsTest.InputMapsOntoSccsConfig; the full-cavity force check and the new key mapping move to FullCavityForceMatchesTheEnergyDerivative and InputMapsCavityModelKeys. - Restore CellTools.ExtractsPositionsMassesAndValenceChargesInAtomOrder; the atomic-number check moves to AtomDataCarriesPseudopotentialAtomicNumber. - SccsCavityDerivativesTest.OpenBoundaryCoefficientUsesSwitchingFunctionFft keeps only the adaptation to the CavityDerivatives interface; the lowpass check moves to OpenBoundaryLowpassFiltersSwitchingFunctionDerivatives. No change to source code or to reference values.
ABACUS-PR-BOT
left a comment
There was a problem hiding this comment.
Static review of 5f305c8f7feda99e5eecb03f739658a7362c68dc: one correctness issue and two non-blocking follow-ups below. No builds, runtime tests, MPI runs or CI diagnostics were executed.
INPUT metadata is updated; the YAML/Markdown references are intentionally untracked and regenerated by the existing documentation build, so no tracked generated-file update is expected. Documentation generation was not run.
…vity-density derivative only for the full cavity - A list of nat values for sccs_corespread can give symmetry-equivalent atoms different core Gaussians, which the symmetry analysis does not see. The symmetry reset now lowers symmetry 1 to 0 for imp_sol 2 with sccs_solvent_mode full and more than one width, as it already does for efield. A single width is chosen per element and stays compatible with symmetry. The sccs_corespread help states this. - eval_functional copies and accumulates the cavity-density derivative only when the cavity has core Gaussians; its only reader is the core-Gaussian force of the full cavity. The electronic mode no longer keeps this grid. - Tests: InputTest.PerAtomSccsCavityWidthsDisableSpatialSymmetry and SccsFunctionalTest.CavityDensityDerivativeOnlyForTheFullCavity.
Critsium-xy
left a comment
There was a problem hiding this comment.
Static review (no build/run).
INPUT docs: docs/parameters.yaml and input-main.md are generated from the Input_Item descriptions, so no manual update is needed. Please state this in the PR body to resolve the governance checker's INPUT-doc warning.
finish_response chose lowpass_cav_pot from uses_lowpass(cavity) alone, but make_cav_derivs keeps the filtered gradient that it reads only when the boundary is open as well. Use open_boundary && uses_lowpass(cavity) in both. Input validation already rejects lowpass without PCC, so results do not change; the path no longer depends on that check to stay in bounds. Test: SccsLowpassTest.PeriodicResponseIgnoresTheLowpass sets the lowpass parameters on a periodic cavity in code and checks that the response is unchanged; without the fix it reads the empty filtered gradient and crashes.
Critsium-xy
left a comment
There was a problem hiding this comment.
Thanks a lot for your contribution!
Linked Issue
Fourth part of #8052. It follows #8075 (PCC), #8162 (SCCS Step 1: periodic SCCS) and #8194 (SCCS Step 2: SCCS with PCC 0D/2D).
Remaining follow-up PRs, each stacked on the previous one:
out_sol).This PR also answers the open review thread on #8194 about the accuracy of SCCS + PCC forces (see D1 and the force table below).
Summary
This PR adds two optional cavity models from QE-Environ, both off by default:
fullcavity. It adds core Gaussians to the cavity density, which removes the dielectric pockets that some pseudopotentials produce inside atoms. (How to find: when using APNS PP, some cases cannot converge)Both follow Environ's definitions, so the energies agree with QE-Environ: to within 0.6 meV with the filter, and to 0.01 meV in
fullmode. Where ABACUS deliberately differs, the forces become derivatives of the energy, and the atom selection becomes robust. The differences and their advantages are listed in D1–D2.What's changed?
sccs_lowpass_p1/sccs_lowpass_p2.deriv_lowpass_p1/p2, and is available withassume_isolated pcc_0d/pcc_2donly.core_fft_lowpass.f90.sccs_solvent_mode fullwithsccs_corespread.solvent_mode='full'.sccs_corespread, default 0.5 bohr) is added to the density that defines the cavity, and only to that density. Electrostatics are unchanged.Differences from QE-Environ
D1. With the lowpass, the cavity potential is the derivative of the energy
What Environ does.
deriv_lowpass_p1/p2 > 0,setup.f90replaces the whole FFT derivative core withcore_fft_lowpass. Every gradient, Laplacian and Hessian is filtered, including the gradient of the potential and the ionic force (force_fft_lowpass).calc_dedielectric_dboundarystays the continuum formula, applied to the filtered ∇̃φ.calc_eelectrostatic).What we do. It filters only the derivatives of s, which define the discrete operator, and differentiates that energy exactly.
Advantages.
Forces are the derivative of the energy. That's what relaxation, NEB and MD need. The table shows the solvation part of analytic − FD, in eV/Å:
full)An analytic gradient of the solved potential, ∇v = (∇w − w∇ln ε/2)/√ε, avoids the FFT ringing at the PCC cell boundary, but it is not the gradient the discrete FFT energy implies: the SCF potential is then not variational (energy ~2 meV too high, H₃O⁺ FD slope off by 0.045 eV/Å from QE, analytic − FD 2.3–2.6e-2 eV/Å), so we keep Environ’s FFT gradient and obtain consistent forces from the exact derivative of the lowpass-filtered energy instead.
D2. The lowpass is accepted only with
pcc_0d/pcc_2dderiv_method chain). It takes no FFT derivative of s, so the filter would act on nothing.Validation
Codes. ABACUS: this layer's code, measured in the stacked SCCS build. The cases use no feature of the later PRs. QE 7.6 + Environ 3.1.1. Both with the same pseudopotentials and geometries, 100/400 Ry, PCC0D unless stated otherwise.
FD protocol. A zero-sum displacement (two atoms moved ±0.01 Å in opposite directions along y) cancels the net-force subtraction that both codes apply to printed forces.
Force consistency (eV/Å). The numbers are the solvation part of analytic minus finite difference: (analytic − FD) of the solvent run minus that of vacuum + PCC.
Lowpass energies against QE-Environ.
The ABACUS value is the lower one in every case (D1). The filter changes the model energy itself, by 14–16 meV for H₃O⁺ and 6 meV for OH⁻. It therefore stays off by default, because the water presets were fitted without it.
How the comparison was run.
INPUT/STRU/KPTand a QEpw.in+environ.in, both written by one generator script.OMP_NUM_THREADS=1:mpirun -np 8 abacus_std_parampirun -np 8 pw.x -environ -in pw.in!FINAL_ETOT_IS(ABACUS) and! total energy(QE). Forces come fromTOTAL-FORCEand "Forces acting on atoms".D3. The lowpass is accepted only with
pcc_0d/pcc_2dderiv_method chain). It takes no FFT derivative of s, so the filter would act on nothing.The discretization error of chain at the cavity edge is proportional to the potential there. This is why it works well for neutral periodic systems (it converges faster in neutral systems without PCC) and fails for charged systems with PCC.
Our choice
D4. Which atoms get a core Gaussian in
fullmodeWhat Environ does.
iontype.f90compares the species label with'H'and sets the width to 1e-10 for that species. Every other species gets the given width, or 0.5 if the given value is ≤ 0.What we do.
sccs_corespreadvalue, atoms whose atomic number equals their pseudopotential valence charge are skipped. Those atoms have no core electrons.natvalues gives per-atom widths, and a value ≤ 0 disables that atom.Governance Notes
sccs_lowpass_p1,sccs_lowpass_p2: both positive or both non-positive; PCC only.sccs_solvent_mode:electronicorfull.sccs_corespread: one value ornatvalues. A per-atom list lowerssymmetry 1to0(reset hook ofsymmetryinread_inp_sys.cpp).docs/parameters.yamlandinput-main.mdare generated in CI from the C++ help, so they are not edited here.source_cell:unitcell::AtomDatagainsatomic_number, filled by the newpseudo_atom_z(const Atom&)(0 if the element is not recognized).PotSccsgainscheck_sccs_cell. It stops the run if thesccs_corespreadcount is neither 1 nornat. It warns when an unknown element prevents the automatic core exclusion.read_inp_sccs.cppis split: the parse and validation helpers move tosccs_inp_check.cpp.vector3.hinsccs_cav_deriv.h, and<vector>insccs_lowpass.h,sccs_parameters.handread_inp_sccs.h. Each declares a member or parameter of that type.