# How to define input from users for a 2D heteregenous model

**URL:** <https://discourse.julialang.org/t/how-to-define-input-from-users-for-a-2d-heteregenous-model/79624>\
**Category:** General Usage\
**Tags:** input-output, code-organization\
**Created:** [April 18, 2022, 9:22am UTC](https://discourse.julialang.org/t/how-to-define-input-from-users-for-a-2d-heteregenous-model/79624 "2022-04-18T09:22:29Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Iddingsite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iddingsite/32/31840_2.png) [@Iddingsite](https://discourse.julialang.org/u/Iddingsite)\
**Post date:** [April 18, 2022, 9:22am UTC](https://discourse.julialang.org/t/how-to-define-input-from-users-for-a-2d-heteregenous-model/79624/1 "2022-04-18T09:22:29Z")

</div>

Hi everyone,

I am working on a small modeling project. Let’s say I want to do 2D diffusion modeling in different units. All the units are homogeneous but they can have different geometries and physical properties.

I was wondering what would be the most Julia way to ask the user for that?

My first idea is to ask the user to give a raster image with each pixel color beeing a different units or to draw on a GUI his model. He would then need to give names to each units and tell me their physical properties.

From that, I can build boolean matrices for the position of each units and define matrices for each physical properties for the whole model.

What would be your idea for this situation?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 18, 2022, 12:33pm UTC](https://discourse.julialang.org/t/how-to-define-input-from-users-for-a-2d-heteregenous-model/79624/2 "2022-04-18T12:33:04Z")

</div>

The most flexible thing is probably to have the caller pass in functions `f(x,y)` rather than images. (This is called a [higher-order function](https://sodocumentation.net/julia-lang/topic/6955/higher-order-functions).)

e.g. suppose you are solving the diffusion equation du/dt = \nabla \cdot (D \nabla u) + f with some initial conditions u(x,y,0) = u\_0(x,y) and some boundary conditions on a box domain [0,L\_x] \times [0,L\_y], say with finite differences. Then you ask the user to specify the size L\_x \times L\_y of the domain, and pass in functions f(x,y) and u\_0(x,y) and D(x,y), along with some information about the desired discretization and the simulation time.

Note that your program doesn’t need to care about the units of L and f etcetera, as long as the caller was consistent in their units.

---

<div class="post-metadata">

**Author:** ![Iddingsite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iddingsite/32/31840_2.png) [@Iddingsite](https://discourse.julialang.org/u/Iddingsite)\
**Post date:** [April 18, 2022, 2:56pm UTC](https://discourse.julialang.org/t/how-to-define-input-from-users-for-a-2d-heteregenous-model/79624/3 "2022-04-18T14:56:38Z")

</div>

Mmh, I am a bit confused. Let’s say the user wants to have a geometry like this for his model:

![test](https://global.discourse-cdn.com/julialang/original/3X/b/9/b9b35bf096fe9933eb91d62ad43fd2e759e3ae69.png)

with the three colors having different values of D, f and u0

How can he build that easily as a function?

The other thing is that my project is not targeting people who knows programming. So I can’t expect them to write any complicated functions.

EDIT

Alright, after thinking a bit, I guess your idea would be for the user, for example, to write something like that for D(x,y)

```julia
function D_calc(nx,ny)

    D = zeros(nx,ny)

    D[1:Int(ny/10), :] .= 1
    D[Int(ny/10)+1:end, :] .= 2

    return D
end

```

to obtain:  
 ![plot_2](https://global.discourse-cdn.com/julialang/original/3X/7/0/708e108a6b4c015c11622f08e117cf6ffbd1824a.png)

and to use that function as an input for my model (correct me if I am wrong). But that is still a bit to complicated for the people I am targetting… And it should be a bit more tricky for more fancy geometries.

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [April 18, 2022, 6:49pm UTC](https://discourse.julialang.org/t/how-to-define-input-from-users-for-a-2d-heteregenous-model/79624/4 "2022-04-18T18:49:22Z")

</div>

There’s really no good way to initialize simulations without any programming knowledge unless you’re willing to build a GUI, which can be quite expensive and time-consuming. Higher-order functions may work well enough if you provide example scripts and a few geometric primitives (box, circle, line, ellipsoid, …). I’d recommend Unitful.jl to handle different input units on the frontend, with everything converted internally to a consistent unit system on the backend.

As for specification of higher-order functions, the user should provide a function `f(x, y)` that’s _independent of the grid_. If all material interfaces are initially sharp (_i.e._ materials start unmixed), you could do something like this:

```julia
using Unitful

@derived_dimension MassDiffusivity Unitful.𝐋^2/Unitful.𝐓

struct DiffusiveMaterial
    D::Float64 # Mass diffusivity
    ρ::Float64 # Density
    function DiffusiveMaterial(D, ρ)
        D < 0 && error("Diffusivity must be positive")
        ρ < 0 && error("Density must be positive")
        new(D, ρ)
    end
end

# Convert to uniform internal units
function DiffusiveMaterial(D::MassDiffusivity, ρ::Unitful.Density)
    DiffusiveMaterial(ustrip(u"m^2/s", D), ustrip(u"kg/m^3", ρ))
end

struct Domain{T <: AbstractRange}
    x::T
    y::T
    D::Array{Float64, 2}
    ρ::Array{Float64, 2}
    materials::Dict{Symbol, DiffusiveMaterial}
    function Domain(x::T, y::T, materials) where {T}
        return new{T}(x, y, 
                      Array{Float64}(undef, length(x), length(y)), 
                      Array{Float64}(undef, length(x), length(y)), 
                      materials)
    end
end

function initialize!(material, d::Domain)
    for (j, y) in enumerate(d.y), (i, x) in enumerate(d.x)
        m = material(x, y)
        d.D[i, j] = d.materials[m].D
        d.ρ[i, j] = d.materials[m].ρ
    end
end

incircle(x₀, y₀, R) = (x, y) -> hypot(x - x₀, y - y₀) <= R
inrectangle(x₀, y₀, x₁, y₁) = (x, y) -> x₀ <= x <= x₁ && y₀ <= y <= y₁

```

which would allow the user to initialize a model like this

```julia
materials = Dict(:Mud => DiffusiveMaterial(1.0e-7u"cm^2/s", 2.65e3u"kg/m^3"),
                 :Water => DiffusiveMaterial(1.0e-6u"cm^2/s", 1000u"kg/m^3"),
                 :Ethanol => DiffusiveMaterial(8.0e-6u"cm^2/s", 800u"kg/m^3"),)

d = Domain(LinRange(0, 100, 512), LinRange(0, 200, 1024), materials)

initialize!(d) do x, y
    if incircle(50, 50, 20)(x, y)
        :Ethanol
    elseif inrectangle(0, 0, 200, 30)(x, y)
        :Mud
    else
        :Water
    end
end

```

---

<div class="post-metadata">

**Author:** ![Iddingsite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iddingsite/32/31840_2.png) [@Iddingsite](https://discourse.julialang.org/u/Iddingsite)\
**Post date:** [April 18, 2022, 8:54pm UTC](https://discourse.julialang.org/t/how-to-define-input-from-users-for-a-2d-heteregenous-model/79624/5 "2022-04-18T20:54:01Z")

</div>

Thank you very much for taking the time to write that! I’ve learned a lot about structures and how I could make use of that by playing with your code. Very elegant!
