From 806fea2487c907f05c0784ba540bad37bba28c38 Mon Sep 17 00:00:00 2001 From: "njzjz-bot (driven by OpenClaw (model: GLM-5))[bot]" <48687836+njzjz-bot@users.noreply.github.com> Date: Mon, 23 Feb 2026 01:22:31 +0000 Subject: [PATCH 1/4] docs: add formulas to fitting classes Add mathematical formulas to fitting class docstrings: - DipoleFitting: dipole computation from rotation matrix - PolarFitting: polarizability tensor with diagonal/full fitting Follow numpydoc convention: parameters in class docstring. --- deepmd/dpmodel/fitting/dipole_fitting.py | 18 +++++++++++++- .../dpmodel/fitting/polarizability_fitting.py | 24 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/deepmd/dpmodel/fitting/dipole_fitting.py b/deepmd/dpmodel/fitting/dipole_fitting.py index 2f10d7b487..54526ba3bc 100644 --- a/deepmd/dpmodel/fitting/dipole_fitting.py +++ b/deepmd/dpmodel/fitting/dipole_fitting.py @@ -34,7 +34,23 @@ @BaseFitting.register("dipole") @fitting_check_output class DipoleFitting(GeneralFitting): - r"""Fitting rotationally equivariant diploe of the system. + r"""Fitting rotationally equivariant dipole of the system. + + The dipole :math:`\boldsymbol{\mu}` is computed from the fitting network output + and the rotation matrix: + + .. math:: + \boldsymbol{\mu}^i = \mathbf{M}^i \cdot \mathbf{R}^i, + + where :math:`\mathbf{M}^i \in \mathbb{R}^{1 \times m_1}` is the output of the fitting + network for atom :math:`i`, and :math:`\mathbf{R}^i \in \mathbb{R}^{m_1 \times 3}` is + the rotation matrix from the descriptor. The fitting network is: + + .. math:: + \mathbf{M}^i = \mathcal{L}^{(n)} \circ \mathcal{L}^{(n-1)} \circ \cdots \circ \mathcal{L}^{(0)}(\mathcal{D}^i), + + where :math:`\mathcal{D}^i` is the descriptor and each layer :math:`\mathcal{L}^{(k)}` + is a fully connected layer with activation function. Parameters ---------- diff --git a/deepmd/dpmodel/fitting/polarizability_fitting.py b/deepmd/dpmodel/fitting/polarizability_fitting.py index dff86f04cb..4ae7090867 100644 --- a/deepmd/dpmodel/fitting/polarizability_fitting.py +++ b/deepmd/dpmodel/fitting/polarizability_fitting.py @@ -44,6 +44,30 @@ class PolarFitting(GeneralFitting): r"""Fitting rotationally equivariant polarizability of the system. + The polarizability tensor :math:`\boldsymbol{\alpha} \in \mathbb{R}^{3 \times 3}` is + computed from the fitting network output and the rotation matrix: + + **Diagonal fitting** (when `fit_diag=True`): + + .. math:: + \boldsymbol{\alpha}^i = \mathbf{R}^{i,T} \cdot \mathrm{diag}(\mathbf{p}^i) \cdot \mathbf{R}^i, + + where :math:`\mathbf{p}^i \in \mathbb{R}^{m_1}` is the diagonal elements predicted by + the fitting network. + + **Full matrix fitting** (when `fit_diag=False`): + + .. math:: + \boldsymbol{\alpha}^i = \mathbf{R}^{i,T} \cdot \mathbf{P}^i \cdot \mathbf{R}^i, + + where :math:`\mathbf{P}^i \in \mathbb{R}^{m_1 \times m_1}` is the full matrix predicted + by the fitting network. + + The fitting network is: + + .. math:: + \mathbf{p}^i \text{ (or } \mathbf{P}^i) = \mathcal{L}^{(n)} \circ \cdots \circ \mathcal{L}^{(0)}(\mathcal{D}^i). + Parameters ---------- ntypes From d181a887d1a77c5d071e028130a31930a89ff704 Mon Sep 17 00:00:00 2001 From: "njzjz-bot (driven by OpenClaw (model: GLM-5))[bot]" <48687836+njzjz-bot@users.noreply.github.com> Date: Mon, 23 Feb 2026 02:48:11 +0000 Subject: [PATCH 2/4] docs: add symmetrization step to polarizability formula The full matrix fitting symmetrizes the network output before use: P = (P_raw + P_raw^T) / 2, ensuring a symmetric polarizability tensor. --- deepmd/dpmodel/fitting/polarizability_fitting.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/deepmd/dpmodel/fitting/polarizability_fitting.py b/deepmd/dpmodel/fitting/polarizability_fitting.py index 4ae7090867..b32da6f6b9 100644 --- a/deepmd/dpmodel/fitting/polarizability_fitting.py +++ b/deepmd/dpmodel/fitting/polarizability_fitting.py @@ -60,8 +60,9 @@ class PolarFitting(GeneralFitting): .. math:: \boldsymbol{\alpha}^i = \mathbf{R}^{i,T} \cdot \mathbf{P}^i \cdot \mathbf{R}^i, - where :math:`\mathbf{P}^i \in \mathbb{R}^{m_1 \times m_1}` is the full matrix predicted - by the fitting network. + where :math:`\mathbf{P}^i = \frac{1}{2}(\hat{\mathbf{P}}^i + \hat{\mathbf{P}}^{i,T}) \in \mathbb{R}^{m_1 \times m_1}` + is the symmetrized output of the fitting network (:math:`\hat{\mathbf{P}}^i` being the raw output), + ensuring :math:`\boldsymbol{\alpha}^i` is a symmetric tensor. The fitting network is: From c735ce9af183c3dd044009f92413287894ecbeae Mon Sep 17 00:00:00 2001 From: "njzjz-bot (driven by OpenClaw (model: GLM-5))[bot]" <48687836+njzjz-bot@users.noreply.github.com> Date: Mon, 23 Feb 2026 04:47:27 +0000 Subject: [PATCH 3/4] docs: improve formula documentation based on review - dipole_fitting: add 'an' before 'activation function' - polarizability_fitting: add R^i shape, clarify local-frame tensor, explain symmetry preservation in A^T S A form --- deepmd/dpmodel/fitting/dipole_fitting.py | 2 +- deepmd/dpmodel/fitting/polarizability_fitting.py | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/deepmd/dpmodel/fitting/dipole_fitting.py b/deepmd/dpmodel/fitting/dipole_fitting.py index 54526ba3bc..12a7c759c3 100644 --- a/deepmd/dpmodel/fitting/dipole_fitting.py +++ b/deepmd/dpmodel/fitting/dipole_fitting.py @@ -50,7 +50,7 @@ class DipoleFitting(GeneralFitting): \mathbf{M}^i = \mathcal{L}^{(n)} \circ \mathcal{L}^{(n-1)} \circ \cdots \circ \mathcal{L}^{(0)}(\mathcal{D}^i), where :math:`\mathcal{D}^i` is the descriptor and each layer :math:`\mathcal{L}^{(k)}` - is a fully connected layer with activation function. + is a fully connected layer with an activation function. Parameters ---------- diff --git a/deepmd/dpmodel/fitting/polarizability_fitting.py b/deepmd/dpmodel/fitting/polarizability_fitting.py index b32da6f6b9..361b2acfe6 100644 --- a/deepmd/dpmodel/fitting/polarizability_fitting.py +++ b/deepmd/dpmodel/fitting/polarizability_fitting.py @@ -45,24 +45,27 @@ class PolarFitting(GeneralFitting): r"""Fitting rotationally equivariant polarizability of the system. The polarizability tensor :math:`\boldsymbol{\alpha} \in \mathbb{R}^{3 \times 3}` is - computed from the fitting network output and the rotation matrix: + computed from the fitting network output and the rotation matrix + :math:`\mathbf{R}^i \in \mathbb{R}^{m_1 \times 3}` from the descriptor: **Diagonal fitting** (when `fit_diag=True`): .. math:: \boldsymbol{\alpha}^i = \mathbf{R}^{i,T} \cdot \mathrm{diag}(\mathbf{p}^i) \cdot \mathbf{R}^i, - where :math:`\mathbf{p}^i \in \mathbb{R}^{m_1}` is the diagonal elements predicted by - the fitting network. + where :math:`\mathbf{p}^i \in \mathbb{R}^{m_1}` is the diagonal elements of the + local-frame polarizability predicted by the fitting network. **Full matrix fitting** (when `fit_diag=False`): .. math:: \boldsymbol{\alpha}^i = \mathbf{R}^{i,T} \cdot \mathbf{P}^i \cdot \mathbf{R}^i, - where :math:`\mathbf{P}^i = \frac{1}{2}(\hat{\mathbf{P}}^i + \hat{\mathbf{P}}^{i,T}) \in \mathbb{R}^{m_1 \times m_1}` - is the symmetrized output of the fitting network (:math:`\hat{\mathbf{P}}^i` being the raw output), - ensuring :math:`\boldsymbol{\alpha}^i` is a symmetric tensor. + where :math:`\hat{\mathbf{P}}^i \in \mathbb{R}^{m_1 \times m_1}` is the raw output of + the fitting network, and :math:`\mathbf{P}^i = \frac{1}{2}(\hat{\mathbf{P}}^i + \hat{\mathbf{P}}^{i,T})` + is the symmetrized version. Since :math:`\mathbf{P}^i` is symmetric, the resulting + :math:`\boldsymbol{\alpha}^i` is guaranteed to be a symmetric tensor (matrix products + of the form :math:`A^T S A` preserve symmetry). The fitting network is: From 9b165eb155e42a6afd65e6217b9ab568f5cb561f Mon Sep 17 00:00:00 2001 From: "njzjz-bot (driven by OpenClaw (model: GLM-5))[bot]" <48687836+njzjz-bot@users.noreply.github.com> Date: Mon, 23 Feb 2026 17:18:13 +0000 Subject: [PATCH 4/4] docs: define m_1 (embedding width) in fitting formulas Add explicit definition of m_1 as the embedding width in both dipole_fitting and polarizability_fitting docstrings. --- deepmd/dpmodel/fitting/dipole_fitting.py | 5 +++-- deepmd/dpmodel/fitting/polarizability_fitting.py | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/deepmd/dpmodel/fitting/dipole_fitting.py b/deepmd/dpmodel/fitting/dipole_fitting.py index 12a7c759c3..0fc3a1fefa 100644 --- a/deepmd/dpmodel/fitting/dipole_fitting.py +++ b/deepmd/dpmodel/fitting/dipole_fitting.py @@ -43,8 +43,9 @@ class DipoleFitting(GeneralFitting): \boldsymbol{\mu}^i = \mathbf{M}^i \cdot \mathbf{R}^i, where :math:`\mathbf{M}^i \in \mathbb{R}^{1 \times m_1}` is the output of the fitting - network for atom :math:`i`, and :math:`\mathbf{R}^i \in \mathbb{R}^{m_1 \times 3}` is - the rotation matrix from the descriptor. The fitting network is: + network for atom :math:`i`, :math:`\mathbf{R}^i \in \mathbb{R}^{m_1 \times 3}` is + the rotation matrix from the descriptor, and :math:`m_1` is the embedding width + (the dimension of the rotation matrix). The fitting network is: .. math:: \mathbf{M}^i = \mathcal{L}^{(n)} \circ \mathcal{L}^{(n-1)} \circ \cdots \circ \mathcal{L}^{(0)}(\mathcal{D}^i), diff --git a/deepmd/dpmodel/fitting/polarizability_fitting.py b/deepmd/dpmodel/fitting/polarizability_fitting.py index 361b2acfe6..b7868a9502 100644 --- a/deepmd/dpmodel/fitting/polarizability_fitting.py +++ b/deepmd/dpmodel/fitting/polarizability_fitting.py @@ -46,7 +46,8 @@ class PolarFitting(GeneralFitting): The polarizability tensor :math:`\boldsymbol{\alpha} \in \mathbb{R}^{3 \times 3}` is computed from the fitting network output and the rotation matrix - :math:`\mathbf{R}^i \in \mathbb{R}^{m_1 \times 3}` from the descriptor: + :math:`\mathbf{R}^i \in \mathbb{R}^{m_1 \times 3}` from the descriptor, + where :math:`m_1` is the embedding width (the dimension of the rotation matrix): **Diagonal fitting** (when `fit_diag=True`):