Quantcast
Channel: First steps - JuliaLang
Viewing all articles
Browse latest Browse all 2795

What is a Julian approach to data structures for a simulation package?

$
0
0

I’m working on my first major Julia project which is a physics simulation package. The overall goal is to develop this package to be as neat, efficient, and extensible as possible using good Julian code conventions so people can easily add to it in the future.

The user will be able to specify the calculation parameters and physical system in an input file, then ask for various properties to be calculated. As these properties are expensive to compute, I’m aiming for the package to calculate them in an intelligent way.

As an analogy, if the physical system was a circle then we should calculate and store the area only if this field is accessed, not when the object is created and not every time the field is accessed. I have come up with one way to do this by overloading Base.getproperty (see MWE below).

A further complication (that may need a separate post later) is that several properties (a, b, c) can be calculated from the same mathematical object M. Getting M is the expensive part of the calculation so I’d like to set things up such that when the user asks for a or b or c, the package calculates all three.

The current data structure looks like the following where all capitalised fields are structs with their own fields:

Output  # mutable, highest level struct
    Calculation  # immutable, defined from input file
        Parameters
        Options
        System
    Parameter1  # calculated when requested with output.parameter1 or similar
        anintegervalue
        SubParam1  # calculated when SubParam1 or SubParam2 is requested
        SubParam2  # calculated when SubParam1 or SubParam2 is requested
        ...

My questions are:

  1. What is an appropriate layout for the various structs here? Putting everything in one big nested object seems like a clunky way to operate but I haven’t yet worked out anything better.
  2. Should the user get data with circle.area (as in the MWE) or area(circle)? The latter seems more in line with what I’ve seen of Julia so far.
  3. Is there a better way to calculate properties on demand without repeating the same calculations twice?

MWE:

mutable struct Circle
    radius::Number
    area::Union{Number, Missing}
    Circle(radius::Number) = new(radius, missing)
end

""" Extends Base.getproperty such that missing data is filled in when accessed """
function Base.getproperty(object::Circle, field::Symbol)
    if ismissing(getfield(object, field))
        setfield!(object, field, getfieldondemand(object, field))
    end
    return getfield(object, field)
end

function getfieldondemand(C::Circle, field::Symbol)
    if field === :area
        return areaofcircle(C)
    end
end

function areaofcircle(C::Circle)
    return pi * C.radius^2    # some long and complicated calculation
end

circle = Circle(1.0)
@info("circle.area = $(getfield(circle, :area))")
circle.area
@info("circle.area = $(getfield(circle, :area))")

2 posts - 2 participants

Read full topic


Viewing all articles
Browse latest Browse all 2795

Latest Images

Trending Articles



Latest Images