(defn Hodge-star
"Takes a `metric` and a `spec` and returns the [Hodge star
operator](https://en.wikipedia.org/wiki/Hodge_star_operator) (actually just a
function, but I suspect this should be a proper operator!)
`spec` may be:
- a coordinate system with an orthonormal basis
- an orthonormal basis
- a basis
if the spec is a basis that needs to be orthonormalized, the optional
`:orthonormalize?` keyword argument must be a coordinate system."
[metric spec & {:keys [orthonormalize?]
:or {orthonormalize? false}}]
(let [basis (if (b/basis? spec)
(if orthonormalize?
(orthonormalize spec metric orthonormalize?)
spec)
(if orthonormalize?
(orthonormalize (b/coordinate-system->basis spec)
metric
spec)
(b/coordinate-system->basis spec)))
on-vector-basis (flatten (b/basis->vector-basis basis))
on-oneform-basis (flatten (b/basis->oneform-basis basis))
basis-check (matrix/by-rows*
(map (fn [ei]
(map (fn [ej]
(metric ei ej))
on-vector-basis))
on-vector-basis))
bsigns (matrix/diagonal basis-check)]
(fn the-star [pform-field]
(assert (or (f/function? pform-field)
(ff/form-field? pform-field)))
(let [p (ff/get-rank pform-field)]
(if (zero? p)
(* pform-field (apply ff/wedge on-oneform-basis))
(let [pvect-basis-lists (permute/combinations on-vector-basis p)
coeffs (map (fn [pvect]
(apply pform-field pvect))
pvect-basis-lists)
pform-basis-lists (permute/combinations on-oneform-basis p)
n-p:form-basis-lists (map (fn [onefbl]
(list-difference on-oneform-basis onefbl))
pform-basis-lists)
n-p:basis (map (fn [n-p:basis-list]
(apply ff/wedge n-p:basis-list))
n-p:form-basis-lists)
signs (map (fn [bsign-list p:basis-list n-p:basis-list]
(* (apply * bsign-list)
(permute/permutation-parity
(concat p:basis-list n-p:basis-list)
on-oneform-basis)))
(permute/combinations bsigns p)
pform-basis-lists
n-p:form-basis-lists)]
(apply + (map * signs coeffs n-p:basis))))))))