@@ -69,14 +69,47 @@ is simply [`locs`](@ref), i.e. the location of the quadrature nodes.
6969""" 
7070centers (B:: BasisOrRestricted ) =  locs (B)
7171
72+ """ 
73+     metric(B) 
74+ 
75+ Returns the metric or mass matrix of the basis `B`, equivalent to 
76+ `S=B'B`. 
77+ """ 
78+ metric (B:: BasisOrRestricted ) =  B' B
79+ 
80+ """ 
81+     metric_shape(B) 
82+ 
83+ Returns the shape of the metric or mass matrix of the basis `B`, 
84+ i.e. `Diagonal`, `BandedMatrix`, etc. 
85+ """ 
86+ metric_shape (B:: BasisOrRestricted ) =  typeof (metric (B))
87+ 
88+ function  matrix_element_metric (B:: BasisOrRestricted )
89+     #  For non-orthogonal bases, we need to apply the metric inverse,
90+     #  after computing the action of a matrix representation of a
91+     #  linear operator on a ket. However, when computing the inner
92+     #  product with the bra afterwards, we again use the metric. Here,
93+     #  we short-circuit this by combining them into them identity
94+     #  operator I, if the operator metric equals the metric. For
95+     #  orthogonal bases, with the integration weights not built into the
96+     #  coefficients, and an identity matrix operator metric, we /do/
97+     #  need to use the metric for the inner product.
98+     S =  metric (B)
99+     oS =  operator_metric (B)
100+     oS ==  S ?  I :  (oS \  S)
101+ end 
102+ 
72103export  AbstractFiniteDifferences,
73104    FiniteDifferences, StaggeredFiniteDifferences, ImplicitFiniteDifferences,
74105    Derivative, dot, QuasiDiagonal, Inclusion, .. , distribution,
75106    FEDVR, Derivative, @elem , dot,
76107    BSpline,
77108    ArbitraryKnotSet, LinearKnotSet, ExpKnotSet,
78109    order, numintervals, numfunctions, nonempty_intervals,
79-     centers, vandermonde, FunctionProduct, Density,
110+     centers, vandermonde,
111+     metric, metric_shape, matrix_element_metric,
112+     FunctionProduct, Density,
80113    LinearOperator, DiagonalOperator, ShiftAndInvert
81114
82115end  #  module
0 commit comments