ProCreations's picture
Publish validated GP-FVM reproduction
c711202 verified
Raw
History Blame Contribute Delete
4.71 kB
"""
Problem definition for source identification experiments.
Defines the physics, sources, and observations for advection-diffusion
source identification. Both GP-FVM and PINN baselines read from the same
problem files for fair comparison.
"""
using TOML
"""
GaussianSource
A Gaussian source term: s(x,y) = strength * exp(-((x-x₀)² + (y-y₀)²) / (2σ²))
"""
struct GaussianSource
x::Float64
y::Float64
strength::Float64
width::Float64 # σ
end
"""
Observation
A point observation of concentration.
"""
struct Observation
x::Float64
y::Float64
end
"""
SourceIdentificationProblem
Complete problem specification for source identification.
"""
struct SourceIdentificationProblem
# Physics
vx::Float64
vy::Float64
D::Float64
domain::NTuple{4, Float64} # (x_min, x_max, y_min, y_max)
c_inflow::Float64
# Sources (can be multiple)
sources::Vector{GaussianSource}
# Observations
observations::Vector{Observation}
noise_std::Float64
noise_seed::Int
end
"""
evaluate_source(prob, x, y)
Evaluate the total source field at point (x, y).
"""
function evaluate_source(prob::SourceIdentificationProblem, x, y)
s = 0.0
for src in prob.sources
r² = (x - src.x)^2 + (y - src.y)^2
s += src.strength * exp(-r² / (2 * src.width^2))
end
return s
end
"""
load_problem(path::String) -> SourceIdentificationProblem
Load a problem definition from a TOML file.
"""
function load_problem(path::String)
data = TOML.parsefile(path)
# Physics
phys = data["physics"]
vx = get(phys, "vx", 1.0)
vy = get(phys, "vy", 0.0)
D = get(phys, "D", 0.05)
domain_arr = get(phys, "domain", [0.0, 1.0, 0.0, 1.0])
domain = tuple(domain_arr...)
c_inflow = get(phys, "c_inflow", 0.0)
# Sources
sources = GaussianSource[]
if haskey(data, "sources")
for src in data["sources"]
push!(sources, GaussianSource(
src["x"],
src["y"],
src["strength"],
src["width"]
))
end
end
# Observations
observations = Observation[]
if haskey(data, "observations")
for obs in data["observations"]
push!(observations, Observation(obs["x"], obs["y"]))
end
end
# Noise
noise = get(data, "noise", Dict())
noise_std = get(noise, "std", 0.1)
noise_seed = get(noise, "seed", 42)
return SourceIdentificationProblem(
vx, vy, D, domain, c_inflow,
sources, observations,
noise_std, noise_seed
)
end
"""
save_problem(path::String, prob::SourceIdentificationProblem)
Save a problem definition to a TOML file.
"""
function save_problem(path::String, prob::SourceIdentificationProblem)
data = Dict{String, Any}()
# Physics
data["physics"] = Dict(
"vx" => prob.vx,
"vy" => prob.vy,
"D" => prob.D,
"domain" => collect(prob.domain),
"c_inflow" => prob.c_inflow
)
# Sources
data["sources"] = [
Dict("x" => s.x, "y" => s.y, "strength" => s.strength, "width" => s.width)
for s in prob.sources
]
# Observations
data["observations"] = [
Dict("x" => o.x, "y" => o.y)
for o in prob.observations
]
# Noise
data["noise"] = Dict(
"std" => prob.noise_std,
"seed" => prob.noise_seed
)
open(path, "w") do io
TOML.print(io, data)
end
end
"""
observation_coords(prob::SourceIdentificationProblem)
Return observation coordinates as (xs, ys) tuple of vectors.
"""
function observation_coords(prob::SourceIdentificationProblem)
xs = [o.x for o in prob.observations]
ys = [o.y for o in prob.observations]
return xs, ys
end
"""
n_observations(prob::SourceIdentificationProblem)
Return the number of observations.
"""
n_observations(prob::SourceIdentificationProblem) = length(prob.observations)
"""
n_sources(prob::SourceIdentificationProblem)
Return the number of sources.
"""
n_sources(prob::SourceIdentificationProblem) = length(prob.sources)
# Pretty printing
function Base.show(io::IO, prob::SourceIdentificationProblem)
println(io, "SourceIdentificationProblem:")
println(io, " Physics: vx=$(prob.vx), vy=$(prob.vy), D=$(prob.D)")
println(io, " Domain: $(prob.domain)")
println(io, " Sources: $(n_sources(prob))")
for (i, s) in enumerate(prob.sources)
println(io, " [$i] ($(s.x), $(s.y)), strength=$(s.strength), width=$(s.width)")
end
println(io, " Observations: $(n_observations(prob))")
println(io, " Noise: std=$(prob.noise_std), seed=$(prob.noise_seed)")
end