Skip to content

Commit 9131f44

Browse files
feat: add src/EarthProps/ directory
1 parent f16ffb2 commit 9131f44

15 files changed

Lines changed: 3412 additions & 0 deletions

src/EarthProps/dataframe.jl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""
2+
$(TYPEDSIGNATURES)
3+
4+
Generates a `DataFrame` summarizing basic properties of earth layers from an [`EarthModel`](@ref).
5+
6+
# Arguments
7+
8+
- `earth_model`: Instance of [`EarthModel`](@ref) containing earth layers.
9+
10+
# Returns
11+
12+
- A `DataFrame` with columns:
13+
- `rho_g`: Base (DC) resistivity of each layer \\[Ω·m\\].
14+
- `epsr_g`: Base (DC) relative permittivity of each layer \\[dimensionless\\].
15+
- `mur_g`: Base (DC) relative permeability of each layer \\[dimensionless\\].
16+
- `thickness`: Thickness of each layer \\[m\\].
17+
18+
# Examples
19+
20+
```julia
21+
df = $(FUNCTIONNAME)(earth_model)
22+
println(df)
23+
```
24+
"""
25+
function DataFrame(earth_model::EarthModel)
26+
layers = earth_model.layers
27+
28+
base_rho_g = [layer.base_rho_g for layer in layers]
29+
base_epsr_g = [layer.base_epsr_g for layer in layers]
30+
base_mur_g = [layer.base_mur_g for layer in layers]
31+
thickness = [layer.t for layer in layers]
32+
33+
return DataFrame(
34+
rho_g=base_rho_g,
35+
epsr_g=base_epsr_g,
36+
mur_g=base_mur_g,
37+
thickness=thickness,
38+
)
39+
end

src/EarthProps/fdprops.jl

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
"""
2+
$(TYPEDEF)
3+
4+
Abstract type representing different frequency-dependent earth models (FDEM). Used in the multi-dispatch implementation of [`_calc_earth_properties`](@ref).
5+
6+
# Currently available formulations
7+
8+
- [`CPEarth`](@ref): Constant properties (CP) model.
9+
"""
10+
abstract type AbstractFDEMFormulation end
11+
12+
"""
13+
$(TYPEDEF)
14+
15+
Represents an earth model with constant properties (CP), i.e. frequency-invariant electromagnetic properties.
16+
"""
17+
struct CPEarth <: AbstractFDEMFormulation end
18+
19+
20+
"""
21+
$(TYPEDSIGNATURES)
22+
23+
Computes frequency-dependent earth properties using the [`CPEarth`](@ref) formulation, which assumes frequency-invariant values for resistivity, permittivity, and permeability.
24+
25+
# Arguments
26+
27+
- `frequencies`: Vector of frequency values \\[Hz\\].
28+
- `base_rho_g`: Base (DC) electrical resistivity of the soil \\[Ω·m\\].
29+
- `base_epsr_g`: Base (DC) relative permittivity of the soil \\[dimensionless\\].
30+
- `base_mur_g`: Base (DC) relative permeability of the soil \\[dimensionless\\].
31+
- `formulation`: Instance of a subtype of [`AbstractFDEMFormulation`](@ref) defining the computation method.
32+
33+
# Returns
34+
35+
- `rho`: Vector of resistivity values \\[Ω·m\\] at the given frequencies.
36+
- `epsilon`: Vector of permittivity values \\[F/m\\] at the given frequencies.
37+
- `mu`: Vector of permeability values \\[H/m\\] at the given frequencies.
38+
39+
# Examples
40+
41+
```julia
42+
frequencies = [1e3, 1e4, 1e5]
43+
44+
# Using the CP model
45+
rho, epsilon, mu = $(FUNCTIONNAME)(frequencies, 100, 10, 1, CPEarth())
46+
println(rho) # Output: [100, 100, 100]
47+
println(epsilon) # Output: [8.854e-11, 8.854e-11, 8.854e-11]
48+
println(mu) # Output: [1.2566e-6, 1.2566e-6, 1.2566e-6]
49+
```
50+
51+
# See also
52+
53+
- [`EarthLayer`](@ref)
54+
- [`AbstractFDEMFormulation`](@ref)
55+
"""
56+
function _calc_earth_properties(
57+
frequencies::Vector{<:Float64},
58+
base_rho_g::T,
59+
base_epsr_g::T,
60+
base_mur_g::T,
61+
::CPEarth,
62+
) where {T<:Union{Float64,Measurement{Float64}}}
63+
64+
# Preallocate for performance
65+
n_freq = length(frequencies)
66+
rho = Vector{T}(undef, n_freq)
67+
epsilon = Vector{typeof(ε₀ * base_epsr_g)}(undef, n_freq)
68+
mu = Vector{typeof(μ₀ * base_mur_g)}(undef, n_freq)
69+
70+
# Vectorized assignment
71+
fill!(rho, base_rho_g)
72+
fill!(epsilon, ε₀ * base_epsr_g)
73+
fill!(mu, μ₀ * base_mur_g)
74+
75+
return rho, epsilon, mu
76+
end
77+
78+
_get_description(::CPEarth) = "CP model"

src/EarthProps/io.jl

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"""
2+
$(TYPEDSIGNATURES)
3+
4+
Defines the display representation of a [`EarthModel`](@ref) object for REPL or text output.
5+
6+
# Arguments
7+
8+
- `io`: The output stream to write the representation to \\[IO\\].
9+
- `mime`: The MIME type for plain text output \\[MIME"text/plain"\\].
10+
- `model`: The [`EarthModel`](@ref) instance to be displayed.
11+
12+
13+
# Returns
14+
15+
- Nothing. Modifies `io` to format the output.
16+
"""
17+
function show(io::IO, ::MIME"text/plain", model::EarthModel)
18+
# Determine model type based on num_layers and vertical_layers flag
19+
num_layers = length(model.layers)
20+
model_type = num_layers == 2 ? "homogeneous" : "multilayer"
21+
orientation = model.vertical_layers ? "vertical" : "horizontal"
22+
layer_word = (num_layers - 1) == 1 ? "layer" : "layers"
23+
24+
# Count frequency samples from the first layer's property arrays
25+
num_freq_samples = length(model.layers[1].rho_g)
26+
freq_word = (num_freq_samples) == 1 ? "sample" : "samples"
27+
28+
# Print header with key information
29+
println(
30+
io,
31+
"EarthModel with $(num_layers-1) $(orientation) earth $(layer_word) ($(model_type)) and $(num_freq_samples) frequency $(freq_word)",
32+
)
33+
34+
# Print layers in treeview style
35+
for i in 1:num_layers
36+
layer = model.layers[i]
37+
# Determine prefix based on whether it's the last layer
38+
prefix = i == num_layers ? "└─" : "├─"
39+
40+
# Format thickness value
41+
thickness_str = isinf(layer.t) ? "" : "$(round(layer.t, sigdigits=4))"
42+
43+
# Format layer name
44+
layer_name = i == 1 ? "Layer $i (air)" : "Layer $i"
45+
46+
# Print layer properties with proper formatting
47+
println(
48+
io,
49+
"$prefix $layer_name: [rho_g=$(round(layer.base_rho_g, sigdigits=4)), " *
50+
"epsr_g=$(round(layer.base_epsr_g, sigdigits=4)), " *
51+
"mur_g=$(round(layer.base_mur_g, sigdigits=4)), " *
52+
"t=$thickness_str]",
53+
)
54+
end
55+
56+
# Add formulation information as child nodes
57+
if !isnothing(model.FDformulation)
58+
formulation_tag = _get_description(model.FDformulation)
59+
println(io, " Frequency-dependent model: $(formulation_tag)")
60+
end
61+
62+
end

0 commit comments

Comments
 (0)