@@ -164,6 +164,8 @@ struct RightBoundaryWindow{name} <: BoundaryWindow end
164
164
165
165
An abstract type for finite difference operators. Instances of this should define:
166
166
167
+ - [`getidx_return_type`](@ref)
168
+ - [`stencil_return_type`](@ref)
167
169
- [`return_eltype`](@ref)
168
170
- [`return_space`](@ref)
169
171
- [`stencil_interior_width`](@ref)
@@ -175,6 +177,18 @@ abstract type FiniteDifferenceOperator <: AbstractOperator end
175
177
176
178
return_eltype (:: FiniteDifferenceOperator , arg) = eltype (arg)
177
179
180
+ """
181
+ getidx_return_type(::Base.Broadcasted)
182
+ getidx_return_type(::StencilBroadcasted)
183
+ getidx_return_type(::Field)
184
+ getidx_return_type(::Any)
185
+ ...
186
+
187
+ The return type of `getidx` on the arguemnt.
188
+ Defaults to the type of the argument.
189
+ """
190
+ function getidx_return_type end
191
+
178
192
# boundary width error fallback
179
193
@noinline invalid_boundary_condition_error (op_type:: Type , bc_type:: Type ) =
180
194
error (" Boundary `$bc_type ` is not supported for operator `$op_type `" )
@@ -327,6 +341,13 @@ Defines the stencil of the operator `Op` in the interior of the domain at `idx`;
327
341
"""
328
342
function stencil_interior end
329
343
344
+ """
345
+ stencil_return_type(::Op, args...)
346
+
347
+ The return type of the given stencil and arguments.
348
+ """
349
+ function stencil_return_type end
350
+
330
351
331
352
"""
332
353
boundary_width(::Op, ::BC, args...)
@@ -355,6 +376,14 @@ function stencil_right_boundary end
355
376
356
377
abstract type InterpolationOperator <: FiniteDifferenceOperator end
357
378
379
+ # single argument interpolation must be the return type of getidx on the
380
+ # argument, which should be cheaper / simpler than return_eltype(op, args...)
381
+ @inline stencil_return_type (:: InterpolationOperator , arg) =
382
+ getidx_return_type (arg)
383
+
384
+ @inline stencil_return_type (op:: FiniteDifferenceOperator , args... ) =
385
+ return_eltype (op, args... )
386
+
358
387
function assert_no_bcs (op, kwargs)
359
388
length (kwargs) == 0 && return nothing
360
389
error (" InterpolateF2C does not accept boundary conditions." )
@@ -3812,6 +3841,20 @@ Base.@propagate_inbounds function getidx(
3812
3841
end
3813
3842
end
3814
3843
3844
+ @inline getidx_return_type (scalar:: Tuple{<:Any} ) = eltype (scalar)
3845
+ @inline getidx_return_type (scalar:: Ref ) = eltype (scalar)
3846
+ @inline getidx_return_type (x:: T ) where {T} = T
3847
+ @inline getidx_return_type (f:: Fields.Field ) = eltype (f)
3848
+
3849
+ @inline getidx_return_type (bc:: Base.Broadcast.Broadcasted ) =
3850
+ Base. promote_op (bc. f, map (getidx_return_type, bc. args)... )
3851
+
3852
+ @inline getidx_return_type (op:: AbstractOperator , args... ) =
3853
+ stencil_return_type (bc. op, bc. args... )
3854
+
3855
+ @inline getidx_return_type (bc:: StencilBroadcasted ) =
3856
+ stencil_return_type (bc. op, bc. args... )
3857
+
3815
3858
# broadcasting a ColumnStencilStyle gives the StencilBroadcasted's style
3816
3859
Base. Broadcast. BroadcastStyle (
3817
3860
:: Type{<:StencilBroadcasted{Style}} ,
@@ -4104,6 +4147,7 @@ Base.@propagate_inbounds function apply_stencil!(
4104
4147
hidx,
4105
4148
(li, lw, rw, ri) = window_bounds (space, bc),
4106
4149
)
4150
+ T = getidx_return_type (bc)
4107
4151
if ! Topologies. isperiodic (Spaces. vertical_topology (space))
4108
4152
# left window
4109
4153
lbw = LeftBoundaryWindow {Spaces.left_boundary_name(space)} ()
@@ -4114,7 +4158,7 @@ Base.@propagate_inbounds function apply_stencil!(
4114
4158
end
4115
4159
# interior
4116
4160
@inbounds for idx in lw: rw
4117
- val = getidx (space, bc, Interior (), idx, hidx)
4161
+ val = getidx (space, bc, Interior (), idx, hidx):: T
4118
4162
setidx! (space, field_out, idx, hidx, val)
4119
4163
end
4120
4164
if ! Topologies. isperiodic (Spaces. vertical_topology (space))
0 commit comments