@@ -3088,6 +3088,107 @@ Base.@propagate_inbounds function stencil_right_boundary(
3088
3088
)
3089
3089
end
3090
3090
3091
+ """
3092
+ UG = UpwindBiasedGradient()
3093
+ UG.(v, θ)
3094
+
3095
+ Compute the vertical gradient of the field `θ` by upwinding it according to the
3096
+ direction of a vector field `v` on the same space.
3097
+
3098
+ More precisely, the gradient is computed based on the sign of the 3rd
3099
+ contravariant component of `v`:
3100
+ ```math
3101
+ UG(\\ boldsymbol{v}, θ)[i] = \\ begin{cases}
3102
+ G(LB(θ))[i] \\ textrm{, if } v^3[i] > 0 \\\\
3103
+ G(RB(θ))[i] \\ textrm{, if } v^3[i] < 0
3104
+ \\ end{cases}
3105
+ ```
3106
+ where `G` is a gradient operator and `LB`/`RB` are left/right-bias operators.
3107
+ When `θ` and `v` are located on centers, `G = GradientF2C()`,
3108
+ `LB = LeftBiasedC2F()`, and `RB = RightBiasedC2F()`. When they are located on
3109
+ faces, `G = GradientC2F()`, `LB = LeftBiasedF2C()`, and `RB = RightBiasedF2C()`.
3110
+
3111
+ No boundary conditions are currently supported. The default behavior on the left
3112
+ boundary is
3113
+ ```math
3114
+ UG(\\ boldsymbol{v}, θ)[i_min] = G(RB(θ))[i_min]
3115
+ ```
3116
+ and the default behavior on the right boundary is
3117
+ ```math
3118
+ UG(\\ boldsymbol{v}, θ)[i_max] = G(LB(θ))[i_max]
3119
+ ```
3120
+ """
3121
+ struct UpwindBiasedGradient{BCS} <: FiniteDifferenceOperator
3122
+ bcs:: BCS
3123
+ end
3124
+ function UpwindBiasedGradient (; kwargs... )
3125
+ assert_no_bcs (" UpwindBiasedGradient" , kwargs)
3126
+ return UpwindBiasedGradient (NamedTuple ())
3127
+ end
3128
+
3129
+ return_eltype (:: UpwindBiasedGradient , velocity, arg) =
3130
+ Geometry. gradient_result_type (Val ((3 ,)), eltype (arg))
3131
+
3132
+ return_space (
3133
+ :: UpwindBiasedGradient ,
3134
+ velocity_space:: AllCenterFiniteDifferenceSpace ,
3135
+ arg_space:: AllCenterFiniteDifferenceSpace ,
3136
+ ) = arg_space
3137
+ return_space (
3138
+ :: UpwindBiasedGradient ,
3139
+ velocity_space:: AllFaceFiniteDifferenceSpace ,
3140
+ arg_space:: AllFaceFiniteDifferenceSpace ,
3141
+ ) = arg_space
3142
+
3143
+ stencil_interior_width (:: UpwindBiasedGradient , velocity, arg) =
3144
+ ((0 , 0 ), (- 1 , 1 ))
3145
+ Base. @propagate_inbounds function stencil_interior (
3146
+ :: UpwindBiasedGradient ,
3147
+ space,
3148
+ idx,
3149
+ hidx,
3150
+ velocity,
3151
+ arg,
3152
+ )
3153
+ FT = Spaces. undertype (space)
3154
+ a⁺ = getidx (space, arg, idx + 1 , hidx)
3155
+ a = getidx (space, arg, idx, hidx)
3156
+ a⁻ = getidx (space, arg, idx - 1 , hidx)
3157
+ v = Geometry. contravariant3 (
3158
+ getidx (space, velocity, idx, hidx),
3159
+ Geometry. LocalGeometry (space, idx, hidx),
3160
+ )
3161
+ ∂a∂ξ₃_times_2 = (1 - sign (v)) ⊠ a⁺ + 2 * sign (v) ⊠ a - (1 + sign (v)) ⊠ a⁻
3162
+ return Geometry. Covariant3Vector (FT (1 ) / 2 ) ⊗ ∂a∂ξ₃_times_2
3163
+ end
3164
+ boundary_width (:: UpwindBiasedGradient , :: AbstractBoundaryCondition ) = 1
3165
+
3166
+ Base. @propagate_inbounds function stencil_left_boundary (
3167
+ :: UpwindBiasedGradient ,
3168
+ :: NullBoundaryCondition ,
3169
+ space,
3170
+ idx,
3171
+ hidx,
3172
+ arg,
3173
+ )
3174
+ @assert idx == left_face_boundary_idx (space)
3175
+ a⁺ = getidx (space, arg, idx + 1 , hidx)
3176
+ a = getidx (space, arg, idx, hidx)
3177
+ return Geometry. Covariant3Vector (1 ) ⊗ (a⁺ ⊟ a)
3178
+ end
3179
+ Base. @propagate_inbounds function stencil_right_boundary (
3180
+ :: UpwindBiasedGradient ,
3181
+ :: NullBoundaryCondition ,
3182
+ space,
3183
+ idx,
3184
+ hidx,
3185
+ arg,
3186
+ )
3187
+ @assert idx == right_face_boundary_idx (space)
3188
+ a = getidx (space, arg, idx, hidx)
3189
+ a⁻ = getidx (space, arg, idx - 1 , hidx)
3190
+ return Geometry. Covariant3Vector (1 ) ⊗ (a ⊟ a⁻)
3191
+ end
3091
3192
3092
3193
abstract type DivergenceOperator <: FiniteDifferenceOperator end
3093
3194
return_eltype (:: DivergenceOperator , arg) =
0 commit comments