///|
pub(all) struct VlasovSummary {
density_mean : Double
density_minimum : Double
density_maximum : Double
momentum_mean : Double
kinetic_energy : Double
entropy : Double
} derive(Debug, ToJson)
///|
pub fn distribution_minimum(state : VlasovState) -> Double {
min_value(state.distribution, 0.0)
}
///|
pub fn distribution_maximum(state : VlasovState) -> Double {
max_value(state.distribution, 0.0)
}
///|
pub fn distribution_integral(state : VlasovState) -> Double {
sum_values(state.distribution) * state.config.grid.dx * state.config.dv()
}
///|
pub fn distribution_positive_part(state : VlasovState) -> Array[Double] {
state.distribution.map(fn(value) { value.max(0.0) })
}
///|
pub fn distribution_negative_mass(state : VlasovState) -> Double {
state.distribution.fold(init=0.0, fn(acc, value) {
if value < 0.0 {
acc - value
} else {
acc
}
}) *
state.config.grid.dx *
state.config.dv()
}
///|
pub fn distribution_entropy(state : VlasovState) -> Double {
let positive = distribution_positive_part(state)
let mut entropy = 0.0
for value in positive {
if value > 0.0 {
entropy = entropy - value * approximate_log(value)
}
}
entropy * state.config.grid.dx * state.config.dv()
}
///|
pub fn velocity_marginal(state : VlasovState) -> Array[Double] {
let output = zeros(state.config.velocity_bins)
for iv in 0.. Array[Double] {
let output = zeros(state.config.grid.cells)
for ix in 0.. Double {
let mut total = 0.0
for ix in 0.. VlasovSummary {
let moments = vlasov_moments(state)
{
density_mean: mean(moments.density),
density_minimum: min_value(moments.density, 0.0),
density_maximum: max_value(moments.density, 0.0),
momentum_mean: mean(moments.momentum),
kinetic_energy: distribution_kinetic_energy(state, mass),
entropy: distribution_entropy(state),
}
}
///|
pub fn vlasov_density_error(state : VlasovState, expected : Double) -> Double {
(mean(position_marginal(state)) - expected).abs()
}
///|
pub fn vlasov_time_series(
state : VlasovState,
steps : Int,
) -> Array[VlasovSummary] {
let output : Array[VlasovSummary] = []
let mut current = state
for _ in 0.. String {
let output = StringBuilder()
output.write_string("x,velocity,distribution\n")
for ix in 0.. VlasovState {
let distribution = zeros(state.distribution.length())
for ix in 0.. Double {
(distribution_integral(first) - distribution_integral(second)).abs()
}
///|
pub fn vlasov_summary_to_csv(values : ArrayView[VlasovSummary]) -> String {
let output = StringBuilder()
output.write_string(
"density_mean,density_minimum,density_maximum,momentum_mean,kinetic_energy,entropy\n",
)
for value in values {
output.write_string(
"\{value.density_mean},\{value.density_minimum},\{value.density_maximum},\{value.momentum_mean},\{value.kinetic_energy},\{value.entropy}\n",
)
}
output.to_string()
}