Utilities

ClimaCore.Utilities.unionall_typeFunction
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)))
Foo
source
ClimaCore.Utilities.replace_type_parameterFunction
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.

source
ClimaCore.Utilities.fieldtype_valsFunction
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.

source
ClimaCore.Utilities.newFunction
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)
source
ClimaCore.Utilities.unsafe_eltypeFunction
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{}).

source
ClimaCore.Utilities.safe_eltypeFunction
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.

source

Utilities.PlusHalf

ClimaCore.Utilities.PlusHalfType
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.

source

Utilities.AutoBroadcaster

ClimaCore.Utilities.AutoBroadcasterType
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))))
source
ClimaCore.Utilities.is_auto_broadcastableFunction
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.

source
ClimaCore.Utilities.auto_broadcastedFunction
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)
source
ClimaCore.Utilities.nested_broadcastFunction
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))
source

Utilities.Cache

ClimaCore.Utilities.CacheModule

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:

  1. topology and metric information can be reused, reducing memory usage.

  2. 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.

source
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.

source
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.

source