ClimaCore.jl
ClimaCore.jl copied to clipboard
Manipulating `AxisTensor`s
I'm unsure of the support or best way to manipulate AxisTensor
objects like U
V
and WVector
s, such as taking a norm or inner product. One way is of course to manipulate the array with parent, but then I'd have to repackage the result in a Field.
Motivation: In #325 we add the ability to specify boundary conditions as fields, so that we can have a location-varying flux applied at the boundaries. I want to easily be able to compute the wind stress at every point on a boundary field and have this represented as a scalar valued Field.
A current workaround can be seen in ClimaAtmos or ClimaCoupler in which single elements of vectors are used to calculate this stress which is then uniform on the boundary.
@akshaysridhar please chime in, I think we have different understandings of the issue here.
Options:
- We define a function
normal_field(space, boundaryname)
which would return a vector field on the boundary space (see #325), that contains the unit-length vector field normal to the boundary
- at the top and bottom this would be a
Contravariant3Vector(1/sqrt(g_{33}))
- you would then multiply your scalar field by this
- for wind stress you want the normal gradient of the tangential component, which would be a 2-tensor, with
Covariant12Axis
and aContravariant3Axis
.- define a covariant12 vector field, then multiply it by the
normal_field
- define a covariant12 vector field, then multiply it by the
- Define some notion of a
NormalAxis
/NormalVector
, which can only be defined on boundary fields, and can be converted to the other vector/tensor types
- this gets more complicated, and we would need to store the direction of the normal in the boundary space for this to work.
I would lean toward 1 for now.
https://github.com/CliMA/ClimaCoupler.jl/blob/4f6534f511055ea1e47a955c2ea4c131df2998ec/experiments/ClimaCore/sea_breeze/coupledbc.jl#L22
I think you can just do
norm.(uₕ_nearwall)
to get the tangential wind speed, will need to double check though
Actually we may need to reconstruct the vector at the boundary?
From discussion on Slack: a Covariant3Vector
is orthogonal to the surface, since
$$\boldsymbol{u}_v = u_3 \boldsymbol{e}^3$$.
To get the unit normal, we can normalize this, i.e. we choose $u_3$ such that $$u_3 u_3 g^{33} = 1$$
In other words, Covariant3Vector(1.0) / norm(Covariant3Vector(1.0))
, or equivalently Covariant3Vector(1/sqrt(g^{33}))
I think we should provide a Normal3Vector
to handle this.