MADNESS 0.10.1
operator_diagnostics.h
Go to the documentation of this file.
1// operator_diagnostics.h — unified <ab|op|ij> diagnostic matrix container.
2//
3// Provides a map-based container (DiagnosticMatrix) and projection utilities:
4// project_xy — core primitive: result(a,b) += sum_k <bra[k].g[a](1) bra[k].h[b](2)|ket>
5// signature: project_xy(bra, ket)
6// project_ab — thin wrapper: bra = {CCPairFunction(ao_basis, ao_basis)}
7// project_Gab — thin wrapper: builds nfit Schwinger bra slots, calls project_xy
8//
9// Convention: `ref` = LDIM-D analytic reference, set by the caller.
10// `result` = NDIM-D projection, set by the methods below.
11// `error` = ||ref - result||_F, computed by compute_errors().
12//
13// Template parameters:
14// T — scalar type (default double)
15// NDIM — pair-space dimension (default 6); one-particle space is LDIM = NDIM/2.
16//
17// Bra representation: each element of the bra vector is a decomposed
18// CCPairFunction<T,NDIM> where get_a()[a] is the particle-1 factor for basis
19// index a and get_b()[b] is the particle-2 factor for basis index b. Weights
20// are absorbed into the get_a() functions by the bra builder.
21
22#ifndef MADNESS_CHEM_OPERATOR_DIAGNOSTICS_H
23#define MADNESS_CHEM_OPERATOR_DIAGNOSTICS_H
24
25#include <map>
26#include <string>
27#include <vector>
28
29#include <madness/mra/mra.h>
31// lowrankfunction.h and operator.h are included only in operator_diagnostics.cc
32// to avoid a circular include via lowrankfunction.h -> electronic_correlation_factor.h.
33
34namespace madness {
35
36template<typename T = double>
38 Tensor<T> ref; ///< LDIM-D analytic reference (set by caller)
39 Tensor<T> result; ///< NDIM-D projection result (set by DiagnosticMatrix methods)
40 double error = -1.0;
41
43 if (ref.size() > 0 && result.size() > 0)
44 error = (ref - result).normf();
45 }
46};
47
48/// Container for named <ab|op|ij> diagnostic matrix elements.
49///
50/// Each named entry holds a pair (ref, result) of nbasis×nbasis tensors and
51/// their Frobenius-norm difference. The caller fills `ref` from LDIM-D analytic
52/// formulas; the project_ab / project_Gab methods fill `result` by projecting
53/// NDIM-D functions onto the AO observer basis pairs |ab>.
54///
55/// @tparam T scalar type (default double)
56/// @tparam NDIM pair-space dimension (default 6); LDIM = NDIM/2 is the one-particle space
57template<typename T = double, std::size_t NDIM = 6>
59public:
60 static constexpr std::size_t LDIM = NDIM / 2; ///< one-particle space dimension
61
62 /// element provider: M(x,y) = <p1[x](1) p2[y](2) | X | ij> for arbitrary
63 /// LDIM-D bra lists p1, p2 — the operator-specific unit plugged into
64 /// ref_Gab / ref_GQab. Build via the provider factories of the operator
65 /// classes (CorrelationFactor::ue_*_provider, ExchangeCommutator::*_provider),
66 /// which hoist convolution operators and intermediates into the closure.
67 using ElementProvider = std::function<Tensor<T>(
68 const std::vector<Function<T,LDIM>>&,
69 const std::vector<Function<T,LDIM>>&)>;
70
71 std::map<std::string, DiagnosticEntry<T>> entries;
72 std::vector<Function<T,LDIM>> ao_basis; ///< orthonormalized observer basis
73 double time = 0.0;
74
75 /// Construct with a World reference and an AO basis.
76 /// If the basis is not orthonormal (||S - I||_F > 1e-10) it is
77 /// orthonormalized in-place via symmetric (Löwdin) orthonormalization.
78 /// Pass orthonormalize=false to keep the basis as given (e.g. when matrix
79 /// elements in the raw basis carry physical meaning, like pair energies).
80 DiagnosticMatrix(World& world, std::vector<Function<T,LDIM>> ao_basis_in,
81 bool orthonormalize = true);
82
83 int nbasis() const { return static_cast<int>(ao_basis.size()); }
84
85 /// Allocate zero tensors for a new named quantity.
86 /// Returns the ref tensor by reference so the caller can fill it in-place.
87 Tensor<T>& init(const std::string& name) {
88 auto& e = entries[name];
89 e.ref = Tensor<T>(nbasis(), nbasis());
90 e.result = Tensor<T>(nbasis(), nbasis());
91 e.error = -1.0;
92 return e.ref;
93 }
94
95 // -------------------------------------------------------------------------
96 // Core projection primitive
97 // -------------------------------------------------------------------------
98
99 /// Core primitive: returns T(a,b) = Σ_k inner(bra[k].get_a()[a](1) bra[k].get_b()[b](2), ket_piece)
100 /// summed over all assigned ket pieces and all bra slots k.
101 /// Weight is absorbed into bra[k].get_a() by the bra builder (project_Gab etc.).
102 /// Loop order: ket-pieces outer, (a,b) middle, bra-slots k innermost.
103 /// Caller assigns the returned tensor to entries[name].result.
104 Tensor<T> project_xy(const std::vector<CCPairFunction<T,NDIM>>& bra,
105 const Function<T,NDIM>& ket) const;
106 Tensor<T> project_xy(const std::vector<CCPairFunction<T,NDIM>>& bra,
107 const std::vector<CCPairFunction<T,NDIM>>& ket) const;
108
109 // -------------------------------------------------------------------------
110 // Convenience wrappers
111 // -------------------------------------------------------------------------
112
113 /// Returns T(a,b) = <ao_basis[a] ao_basis[b] | ket>.
114 Tensor<T> project_ab(const Function<T,NDIM>& ket) const;
115 Tensor<T> project_ab(const std::vector<CCPairFunction<T,NDIM>>& ket) const;
116
117 /// Returns T(a,b) ≈ <ao_basis[a] ao_basis[b] | G · ket> via Schwinger BSH quadrature.
118 Tensor<T> project_Gab(const Function<T,NDIM>& ket, double energy, double lo) const;
119 Tensor<T> project_Gab(const std::vector<CCPairFunction<T,NDIM>>& ket,
120 double energy, double lo) const;
121
122 // -------------------------------------------------------------------------
123 // 3D-only reference builders — Schwinger fit of G on the bra
124 // -------------------------------------------------------------------------
125
126 /// ref(a,b) = Σ_n w_n <ã_n b̃_n | X | ij> with ã_n = w_n g_{α_n}⋆a, b̃_n = g_{α_n}⋆b
127 /// (Schwinger/BSH fit of G moved onto the bra; X supplied as an element provider).
128 Tensor<T> ref_Gab(const ElementProvider& elements, double energy, double lo,
129 double eps = -1.0) const;
130
131 /// ref(a,b) = Σ_n w_n <ã_n b̃_n | Q₁₂ X | ij> with Q₁₂ = (1-O₁)(1-O₂),
132 /// O = Σ_k |k_ket><k_bra| (plain sum, matching StrongOrthogonalityProjector).
133 /// Q₁₂ is expanded on the ket side as scalar contractions: per slot
134 /// A − S1·B − C·S2ᵀ + S1·D·S2ᵀ
135 /// with element blocks over p1 = {ã_a} ∪ {occ_bra_k}, p2 = {b̃_b} ∪ {occ_bra_l}
136 /// and overlaps S1(a,k) = <ã_a|occ_ket_k>, S2(b,l) = <b̃_b|occ_ket_l>.
137 /// No nearly-vanishing functions like Q(g_n⋆a) are ever formed — applying Q
138 /// to the bra functions suffers catastrophic cancellation when the convolved
139 /// observers lie nearly in the occupied space (see operator_diagnostics.md).
140 Tensor<T> ref_GQab(const ElementProvider& elements,
141 const std::vector<Function<T,LDIM>>& occ_ket,
142 const std::vector<Function<T,LDIM>>& occ_bra,
143 double energy, double lo, double eps = -1.0) const;
144
145 // -------------------------------------------------------------------------
146 // Post-projection utilities
147 // -------------------------------------------------------------------------
148
149 /// Compute error = ||ref - result||_F for every initialized entry.
150 void compute_errors();
151
152 /// Print a compact report: name, ||ref||, ||result||, error.
153 void print_report(const std::string& tag = "") const;
154
155 // -------------------------------------------------------------------------
156 // Bra builders — return bra vectors for use with project_xy
157 // -------------------------------------------------------------------------
158
159 /// Single-slot bra for plain <ab| projection: {CCPairFunction(ao_basis, ao_basis)}.
160 std::vector<CCPairFunction<T,NDIM>> build_simple_bra() const {
162 }
163
164 /// Multi-slot Schwinger bra for <ab|G| projection (BSH fit for energy).
165 /// bra[n].get_a()[a] = w_n * (g_n * ao_basis[a]) (weight absorbed into particle 1)
166 /// bra[n].get_b()[b] = g_n * ao_basis[b]
167 /// @param[in] eps fit/convolution accuracy for the Schwinger G representation;
168 /// if <=0 falls back to FunctionDefaults<LDIM>::get_thresh().
169 /// (the diagnostics pass tight_thresh_3d to make the 3D
170 /// reference a stable, threshold-decoupled yardstick).
171 std::vector<CCPairFunction<T,NDIM>> build_Gab_bra(double energy, double lo,
172 double eps = -1.0) const;
173
174private:
176};
177
178// Deduction guides: infer NDIM=2*LDIM from the element type of the ao_basis vector.
179template<typename T, std::size_t LDIM>
181template<typename T, std::size_t LDIM>
183
184/// Print the (0,1) elements of the named pieces as "6d / 3d-ref / diff" lines
185/// plus the signed total, via snprintf + print.
186///
187/// Intended for a DiagnosticMatrix built over a raw (non-orthonormalized)
188/// pair-bra basis {bra_i, bra_j}, where entry(0,1) = <bra_i bra_j|G Q₁₂ X|ij>
189/// is the contribution of piece X to the MP2 pair energy.
190///
191/// @param pieces entry names; @param signs per-piece sign in the total
192template<typename T, std::size_t NDIM>
194 const std::vector<std::string>& pieces,
195 const std::vector<double>& signs,
196 const std::string& title);
197
198// forward declaration -- operator.h is included only in operator_diagnostics.cc
199template<typename Q, std::size_t MDIM> class SeparatedConvolution;
200
201/// Strong-orthogonality-projected pair-energy weights over an orthonormal
202/// observer basis {a}:
203/// W^Q(a,b) = 2<phi_i_bra (Q a)|g12|(Q b) phi_j_bra>
204/// - <phi_j_bra (Q a)|g12|(Q b) phi_i_bra>
205/// with Q = 1 - sum_m |occ_ket_m><occ_bra_m| applied to both observer factors
206/// (Q12 = Q⊗Q is separable). Used to contract <ab|G Q12 X|ij> diagnostic
207/// tensors into the MP2 pair-energy contribution
208/// E = factor * sum_ab W^Q(a,b) <ab|G Q12 X|ij>.
209template<typename T, std::size_t NDIM>
211 const std::vector<Function<T,NDIM/2>>& observer,
212 const Function<T,NDIM/2>& phi_i_bra,
213 const Function<T,NDIM/2>& phi_j_bra,
214 const std::vector<Function<T,NDIM/2>>& occ_ket,
215 const std::vector<Function<T,NDIM/2>>& occ_bra,
217
218/// RI pair-energy report: contract the .result (6d-projected ket, "Expr3") and
219/// .ref (3d Schwinger ket, "Expr2") tensors of the named pieces with the
220/// pair-energy weights W and print "Expr2(3d-ket) / Expr3(6d-ket) / diff" per
221/// piece plus the signed total, where the per-term energy is
222/// factor * sum_p sign_p * sum_ab W(a,b) M_p(a,b).
223template<typename T, std::size_t NDIM>
225 const std::vector<std::string>& pieces,
226 const std::vector<double>& signs,
227 const Tensor<T>& W,
228 double factor,
229 const std::string& title);
230
231/// Consolidated constant-part pair-energy summary table.
232///
233/// One row per piece (plus a "sum" row), with columns
234/// energy(6D) energy(6D-RI) energy(3D-RI) Δenergy(RI) err(6D)
235/// where, per piece p with M6d = entries[p].result, M3d = entries[p].ref:
236/// energy(6D) = energy6d[p] (true pair energy, no RI)
237/// energy(6D-RI) = factor * Σ_ab W(a,b) M6d(a,b)
238/// energy(3D-RI) = factor * Σ_ab W(a,b) M3d(a,b)
239/// Δenergy(RI) = energy(6D-RI) − energy(3D-RI)
240/// err(6D) = ‖M3d − M6d‖_F (before W-contraction)
241/// All pieces add with +1 (each Vreg already carries its sign, and energy6d is
242/// already signed). The sum-row err is ‖Σ_p (M3d−M6d)‖_F.
243///
244/// @param pieces entry keys into dm.entries, e.g. {"Ue","KffK"}
245/// @param labels display labels per piece, e.g. {"Ue","[K,f]"}
246/// @param energy6d true per-term 6D pair energy (aligned with pieces)
247template<typename T, std::size_t NDIM>
249 const std::vector<std::string>& pieces,
250 const std::vector<std::string>& labels,
251 const std::vector<double>& energy6d,
252 const Tensor<T>& W,
253 double factor,
254 const std::string& title);
255
256} // namespace madness
257
258#endif // MADNESS_CHEM_OPERATOR_DIAGNOSTICS_H
a 6D function, either in full or low rank form, possibly including an 2-particle function
Definition ccpairfunction.h:373
Definition operator_diagnostics.h:58
double time
Definition operator_diagnostics.h:73
void compute_errors()
Compute error = ||ref - result||_F for every initialized entry.
Definition operator_diagnostics.cc:399
std::vector< CCPairFunction< T, NDIM > > build_simple_bra() const
Single-slot bra for plain.
Definition operator_diagnostics.h:160
std::vector< CCPairFunction< T, NDIM > > build_Gab_bra(double energy, double lo, double eps=-1.0) const
Definition operator_diagnostics.cc:138
Tensor< T > project_ab(const Function< T, NDIM > &ket) const
Returns T(a,b) = <ao_basis[a] ao_basis[b] | ket>.
Definition operator_diagnostics.cc:119
Tensor< T > ref_GQab(const ElementProvider &elements, const std::vector< Function< T, LDIM > > &occ_ket, const std::vector< Function< T, LDIM > > &occ_bra, double energy, double lo, double eps=-1.0) const
Definition operator_diagnostics.cc:212
World & world_
Definition operator_diagnostics.h:175
DiagnosticMatrix(World &world, std::vector< Function< T, LDIM > > ao_basis_in, bool orthonormalize=true)
Definition operator_diagnostics.cc:25
std::vector< Function< T, LDIM > > ao_basis
orthonormalized observer basis
Definition operator_diagnostics.h:72
Tensor< T > project_Gab(const Function< T, NDIM > &ket, double energy, double lo) const
Returns T(a,b) ≈ <ao_basis[a] ao_basis[b] | G · ket> via Schwinger BSH quadrature.
Definition operator_diagnostics.cc:183
Tensor< T > & init(const std::string &name)
Definition operator_diagnostics.h:87
std::map< std::string, DiagnosticEntry< T > > entries
Definition operator_diagnostics.h:71
int nbasis() const
Definition operator_diagnostics.h:83
void print_report(const std::string &tag="") const
Print a compact report: name, ||ref||, ||result||, error.
Definition operator_diagnostics.cc:410
std::function< Tensor< T >( const std::vector< Function< T, LDIM > > &, const std::vector< Function< T, LDIM > > &)> ElementProvider
Definition operator_diagnostics.h:67
Tensor< T > ref_Gab(const ElementProvider &elements, double energy, double lo, double eps=-1.0) const
Definition operator_diagnostics.cc:202
static constexpr std::size_t LDIM
one-particle space dimension
Definition operator_diagnostics.h:60
Tensor< T > project_xy(const std::vector< CCPairFunction< T, NDIM > > &bra, const Function< T, NDIM > &ket) const
Definition operator_diagnostics.cc:59
A multiresolution adaptive numerical function.
Definition mra.h:141
Definition operator.h:158
A tensor is a multidimensional array.
Definition tensor.h:313
A parallel world class.
Definition world.h:134
double(* energy)()
Definition derivatives.cc:58
static double lo
Definition dirac-hatom.cc:23
Main include file for MADNESS and defines Function interface.
Namespace for all elements and tools of MADNESS.
Definition DFConvergence.h:9
void print_pair_energy_report(const DiagnosticMatrix< T, NDIM > &dm, const std::vector< std::string > &pieces, const std::vector< double > &signs, const std::string &title)
Definition operator_diagnostics.cc:248
void print_pair_energy_report_RI(const DiagnosticMatrix< T, NDIM > &dm, const std::vector< std::string > &pieces, const std::vector< double > &signs, const Tensor< T > &W, double factor, const std::string &title)
Definition operator_diagnostics.cc:312
Tensor< T > pair_energy_weights(World &world, const std::vector< Function< T, NDIM/2 > > &observer, const Function< T, NDIM/2 > &phi_i_bra, const Function< T, NDIM/2 > &phi_j_bra, const std::vector< Function< T, NDIM/2 > > &occ_ket, const std::vector< Function< T, NDIM/2 > > &occ_bra, const SeparatedConvolution< T, NDIM/2 > &g12)
Definition operator_diagnostics.cc:279
void print_pair_energy_table_RI(const DiagnosticMatrix< T, NDIM > &dm, const std::vector< std::string > &pieces, const std::vector< std::string > &labels, const std::vector< double > &energy6d, const Tensor< T > &W, double factor, const std::string &title)
Definition operator_diagnostics.cc:350
std::vector< Function< T, NDIM > > orthonormalize(const std::vector< Function< T, NDIM > > &vf_in)
orthonormalize the vectors
Definition vmra.h:466
std::string name(const FuncType &type, const int ex=-1)
Definition ccpairfunction.h:28
DiagnosticMatrix(World &, std::vector< Function< T, LDIM > >) -> DiagnosticMatrix< T, 2 *LDIM >
Definition operator_diagnostics.h:37
Tensor< T > result
NDIM-D projection result (set by DiagnosticMatrix methods).
Definition operator_diagnostics.h:39
void compute_error()
Definition operator_diagnostics.h:42
Tensor< T > ref
LDIM-D analytic reference (set by caller).
Definition operator_diagnostics.h:38
double error
Definition operator_diagnostics.h:40
void e()
Definition test_sig.cc:75
constexpr std::size_t NDIM
Definition testgconv.cc:54