Skip to content

Architecture ​

How the source is organized, and why. Files are listed in the order src/TensND.jl includes them, which is also their dependency order.

The include chain ​

Layers ​

Raw arrays. contraction_kernels.jl writes the three shapes every contraction takes — one index changed by a matrix, the last indices of one array against the first of another, two indices traced together — for any order, and array_utils.jl builds every product on them and on broadcasts. It knows nothing about bases, and is therefore generic in the element type by construction. Everything above it inherits that genericity.

Bases and tensors. bases.jl and tens.jl add the basis and the variance; tens_display.jl, tens_components.jl, kelvin_mandel.jl and tens_algebra.jl display tensors, change their basis, write them in Kelvin-Mandel notation and operate on them. The tensor type follows the basis type, which is what makes the cost of a component conversion a property of the data rather than of the call site.

Structured types. tens_isotropic.jl and tens_anisotropic.jl store coefficients instead of components and override the generic operations with closed forms. structured_tens_ops.jl holds the metaprogramming they share — every structured type exposes get_data and a _rebuild, and the shared code generates the scalar arithmetic and the symbolic passes from those two. structured_tens_promotion.jl handles mixed-class operations.

Projection. tens_projection.jl works entirely in the   Kelvin–Mandel picture, at a given orientation. orientation_search.jl searches the axis or the frame when it is free — a screening of fixed orientations, then Newton's method on the angles from the best ones — and symmetry_search.jl tries the classes in turn.

Differential calculus. The symbolic side is written once. ∂ and the five operators are defined in coorsystems.jl over AbstractCoorSystem, and the only thing a submanifold changes is how many directions it differentiates along — the nderiv trait, dim for a chart and dim-1 for a surface. submanifold.jl therefore contains geometry and nothing else; it used to carry a verbatim copy of all six definitions, which is how one bug fix had to be applied twice and one variance bug survived in the copy.

Both types hold the same internal ExactGeometry — position vector, coordinates, the two bases, the natural and dual frames, Lamé coefficients, connection array and simplification settings — and a submanifold adds only the two fundamental forms.

coorsystems_num.jl keeps its own implementation, deliberately: its operators take a field and return a function of the point, a different evaluation model that a shared body would obscure rather than simplify.

Two design decisions worth knowing ​

Geometry and data have independent element types. A TensOrtho carries its material frame as a separate type parameter, so Dual-valued constants can sit on a Float64 frame. Forcing them to agree broke every attempt to differentiate a scheme with respect to a modulus. The same reasoning applies to the symmetry axis of a TensTI and to the frame passed to project, where converting the frame to the field's element type once produced NaN derivatives — see the comment in project(…, ::Val{:ORTHO}, …).

Closed forms only while the result stays in the class. The structured methods return the generic tensor whenever the exact result leaves the class — a product of two orthotropic tensors needs twelve constants, not nine. The fallback is bit-for-bit the generic computation, never an approximation. The full table is on Structured tensors.