Utilities
ClimaCore.Utilities.unionall_type — Function
unionall_type(::Type{T})Extract the type of the input, and strip it of any type parameters.
This is useful when one needs the generic constructor for a given type.
Example
julia> unionall_type(typeof([1, 2, 3]))
Array
julia> struct Foo{A, B}
a::A
b::B
end
julia> unionall_type(typeof(Foo(1,2)))
FooClimaCore.Utilities.replace_type_parameter — Function
replace_type_parameter(T, P, P′)Recursively modifies the parameters of T, replacing every subtype of P with P′. This is like constructing a value of type T and converting subfields of type P to type P′, though no constructors are actually called or compiled.
ClimaCore.Utilities.fieldtype_vals — Function
fieldtype_vals(T)Statically inferrable analogue of Val.(fieldtypes(T)). Functions of Types are specialized upon successful constant propagation, but functions of Vals are always specialized, so fieldtype_vals can be used in place of fieldtypes to ensure that recursive functions over nested types have inferrable outputs.
ClimaCore.Utilities.new — Function
new(T, [fields])Exposes the new pseudo-function that allocates a value of type T, which can otherwise only be explicitly called from inner constructors.
If provided, the second argument is used to initialize fields of the new value (unlike the lowered pseudo-function, this will not automatically convert to the fieldtypes of T). Otherwise, the fields are initialized with arbitrary data, with special handling of DataType fields to avoid errors during compilation.
Examples
julia> new(Int)
4889520192
julia> new(Complex{Int}, (1, 2))
1 + 2im
julia> new(@NamedTuple{a::Type{Int}, b::Int, c::Complex{Int}})
(a = Int64, b = 4889520192, c = 6162822528 + 8036417625im)
julia> new(@NamedTuple{a::DataType, b::Int, c::Complex{Int}}, (Int, 1, 1 + 2im))
(a = Int64, b = 1, c = 1 + 2im)ClimaCore.Utilities.unsafe_eltype — Function
unsafe_eltype(itr)Analogue of eltype with support for un-materialized broadcast expressions, adapted from Base.Broadcast.combine_eltypes. Does not perform any safety checks, and may potentially return non-concrete types (like an empty Union{}).
ClimaCore.Utilities.safe_eltype — Function
safe_eltype(itr)Analogue of eltype with support for un-materialized broadcast expressions, adapted from Base.Broadcast.combine_eltypes. Throws an error when the concrete element type of a broadcast expression cannot be inferred, indicating which part of the expression first encounters a type instability or error during inference.
Utilities.PlusHalf
ClimaCore.Utilities.PlusHalf — Type
PlusHalf(i)Represents i + 1/2, but stored as internally as an integer value. Used for indexing into staggered finite difference meshes: the convention "half" values are indexed at cell faces, whereas centers are indexed at cell centers.
Supports +, - and inequalities.
See also half.
ClimaCore.Utilities.half — Constant
const half = PlusHalf(0)Utilities.AutoBroadcaster
ClimaCore.Utilities.AutoBroadcaster — Type
AutoBroadcaster(itr)Wrapper for an iterator that forces certain functions to be broadcasted over the iterator's elements. This allows different types of broadcasting to be applied simultaneously; e.g., ClimaCore's Fields and similar types use the standard dot syntax to denote parallelized iteration over spatial locations, and they wrap their values in AutoBroadcasters for unrolled iteration over subfields. All statically-sized iterators for which is_auto_broadcastable is true are compatible with AutoBroadcasters.
In the context of AutoBroadcasters, broadcasting a function applies it with unrolled_map, iterating over all arguments for which is_auto_broadcastable is true (including those not wrapped in AutoBroadcasters), while other arguments are passed to the function directly. This behavior is triggered by using AutoBroadcasters, optionally in conjunction with compatible iterators that are not wrapped in AutoBroadcasters, in the following ways:
- passing them to standard math functions or constructors
- passing them to
ifelse(for iterating over conditional values) - applying them as function calls (for iterating over functions)
- explicitly calling
nested_broadcast
Nested AutoBroadcasters constructed with add_auto_broadcasters evaluate broadcasts recursively, mapping across every layer of nested iterators so that broadcasted functions are only applied to non-iterators in the innermost layers. Aside from automatic broadcasting, AutoBroadcasters are essentially identical to their underlying iterators, with support for common operations like iterate, propertynames, getindex, and reduce.
Examples
julia> x = Utilities.AutoBroadcaster((1, 2.0, StaticArrays.SVector(3, 4)))
(1, 2.0, [3, 4])
julia> zero(typeof(x))
(0, 0.0, [0, 0])
julia> 2 * x - (2, 3, [4, 5])
(0, 1.0, [2, 3])
julia> y = Utilities.add_auto_broadcasters((1, 2, (a = 3, b = 4, c = (5, 6, (7, 8)))))
(1, 2, (a = 3, b = 4, c = (5, 6, (7, 8))))
julia> min(y, abs(5 - y))
(1, 2, (a = 2, b = 1, c = (0, 1, (2, 3))))
julia> x' * y * x ÷ 5
(0, 1.0, (a = 15, b = 20, c = (25, 30, (35, 40))))ClimaCore.Utilities.is_auto_broadcastable — Function
is_auto_broadcastable(::Type)
is_auto_broadcastable(itr)Indicates whether an AutoBroadcaster should broadcast over iterators of the given type. By default, this is only true for Tuple and NamedTuple types, but it can be extended to any statically-sized type compatible with UnrolledUtilities.jl.
For convenience, is_auto_broadcastable also supports passing a concrete iterator instead of its type, but this method should not be extended directly.
ClimaCore.Utilities.add_auto_broadcasters — Function
add_auto_broadcasters(itr)
add_auto_broadcasters(::Type)Recursively applies the AutoBroadcaster constructor to iterators for which is_auto_broadcastable is true, as well as their elements for which it is true, while leaving values for which it is false unmodified. Can also be passed an iterator's type to infer the result type for such an iterator.
ClimaCore.Utilities.drop_auto_broadcasters — Function
drop_auto_broadcasters(itr)
drop_auto_broadcasters(::Type)Recursively unwraps constructors applied by add_auto_broadcasters, extracting the iterator from every AutoBroadcaster in itr. Can also be passed an iterator's type to infer the result type for such an iterator.
ClimaCore.Utilities.auto_broadcasted — Function
auto_broadcasted([style], f, args, [axes])Analogue of Base.Broadcast.Broadcasted(style, f, args, axes) that can pass the arguments of f through either add_auto_broadcasters or drop_auto_broadcasters if doing so will help avoid an inferred error.
When the unsafe_eltype of Broadcasted(style, f, args, axes) indicates that f will throw an error, a new Broadcasted wrapper is constructed with add_auto_broadcasters applied to every argument, and then another is constructed with drop_auto_broadcasters applied to every argument. If one of the new wrappers no longer corresponds to a guaranteed error, it is returned instead of the original wrapper. Otherwise, the default result of Broadcasted(style, f, args, axes) is returned without modifications.
Examples
julia> x = (im, (1, 2.0), [3, 4])
(im, (1, 2.0), [3, 4])
julia> y = [x, x, x, x];
julia> bc = Base.Broadcast.Broadcasted(*, (Base.Broadcast.Broadcasted(adjoint, (y,)), y));
julia> sum(Base.materialize(bc))
ERROR: MethodError: no method matching adjoint(::Tuple{...})
[...]
julia> bc = Utilities.auto_broadcasted(*, (Utilities.auto_broadcasted(adjoint, (y,)), y));
julia> sum(Base.materialize(bc))
(4 + 0im, (4, 16.0), 100)ClimaCore.Utilities.nested_broadcast — Function
nested_broadcast(f, args...)Analogue of broadcast that is applied recursively over nested iterators, as long as at least one argument is an AutoBroadcaster. All loops over iterator elements are unrolled and inlined to optimize performance.
This function is automatically called when an AutoBroadcaster is passed to any standard math function or constructor, but for generic operations it must be called explicitly.
Examples
julia> x = Utilities.add_auto_broadcasters(((:a, :b, :c), (:d, :e, :f), :g))
((:a, :b, :c), (:d, :e, :f), :g)
julia> Utilities.nested_broadcast(string, x)
(("a", "b", "c"), ("d", "e", "f"), "g")
julia> y = Utilities.add_auto_broadcasters((1, 11, (111, 1111, 11111)))
(1, 11, (111, 1111, 11111))
julia> Utilities.nested_broadcast(Symbol, x, y * y)
((:a1, :b1, :c1), (:d121, :e121, :f121), (:g12321, :g1234321, :g123454321))Utilities.Cache
ClimaCore.Utilities.Cache — Module
Utilities.Cache
ClimaCore maintains an internal cache of topology and grid objects: this ensures that if the constructor with the same arguments is invoked again (e.g. by reading from a file), the cached object will be returned (also known as memoization). This has two main advantages:
topology and metric information can be reused, reducing memory usage.
it is easy to check if two fields live on the same grid: we can just check if the underlying grid objects are the same (
===), rather than checking all the fields are equal (via==).
However this means that objects in the cache will not be removed from the garbage collector, so we provide an interface to remove these.
ClimaCore.Utilities.Cache.cached_objects — Function
Utilities.Cache.cached_objects()List all currently cached objects.
ClimaCore.Utilities.Cache.clean_cache! — Function
Utilities.Cache.clean_cache!(object)Remove object from the cache of created objects.
In most cases, this function should not need to be called, unless you are constructing many grid objects, for example when doing a sweep over grid paramaters.
Utilities.Cache.clean_cache!()Remove all objects from the cache of created objects.
In most cases, this function should not need to be called, unless you are constructing many grid objects, for example when doing a sweep over grid paramaters.