Design of Derivative Property Types
TODO: Motivate need for computing derivatives (i.e., explain why calculus exists).
Derivative Considerations
For simplicity let PT be the property type of the quantity we want the
derivative of and Derivative<PT> be the property type for computing the
derivative of PT.
Common to think about energy with respect to nuclear coordinates, but even that can be chain ruled to for example include derivatives involving molecular orbital coefficients.
PTmay return multiple quantities. In this caseDerivative<PT>should return the derivative of each quantity.Derivative<PT>minimally needs the same inputs asPT.Thinking of the derivative in Leibniz notation (quotient of two differentials), the choice for the numerator is fixed by the return(s) of
PT; there are however an infinite number of choices for the denominator. We thus need a mechanism for specifying the denominator.As a corollary, the choice of practical denominators should be limited by the inputs to
PT, i.e., if you try to take the derivative ofPTwith respect to a quantity thatPTdoes not depend on the value is 0.As a corollary to the corollary, one may conceivably want to take the derivative with respect to a piece of an input, or an internal quantity which stems from an input. An example is the nuclear gradient where the input is a
ChemicalSystem, but we only want the derivative with respect to nuclear coordinates (an object of typePointSet).
Will need to specify the value at which to take the derivative, i.e. need to take as an input an object of the denominator type.
Consistent with general PT philosophy PTs should be for one derivative at a time, e.g., if one wants say the kinetic energy gradient with respect to the nuclear positions and the nuclear gradient of the electron-nuclear attraction this should be two separate PTs.
Can rely on memoization and satisfying multiple PTs to avoid duplicate work.
Ambiguity arises when/if we are taking the derivative with respect to an object of type
TandPTtakes more than oneT.Could decorate
T, e.g.,WithRespectTo<1, T>means take the derivative with respect to the secondTobject (recall C++ is 0-based).Could use strong types. Say the first
Tis the old one and the secondTis the new one, then could make a typeNewTwhich represents the secondTand use that instead ofT.
Derivative Design
Decided on
Derivative<PropertyType, WithRespectTo, ReturnType>.
PropertyTypedefines the quantity (and the API for obtaining the quantity) we are taking the derivative of, i.e., the numerator in Leibniz notation.
WithRespectTodefines the quantity the derivative is with respect to, i.e., the denominator in Leibniz notation.
ReturnTypeis how the derivative is returned. Eventually this Will default to our tensor object, but in the mean time we leave it up to the downstream modules to decide.