use dirt_atom::MaterialTable;
use serde::Deserialize;
use soil_core::region::Region;
fn default_neg_inf() -> f64 {
f64::NEG_INFINITY
}
fn default_pos_inf() -> f64 {
f64::INFINITY
}
fn default_wall_type() -> String {
"plane".to_string()
}
pub(crate) fn curved_or_region_wall_surface_energy_warning(
wall: &WallDef,
material_table: &MaterialTable,
material_index: usize,
) -> Option<String> {
let geometry = match wall.wall_type.as_str() {
"cylinder" => "cylinder",
"sphere" => "sphere",
"region" => "region",
_ => return None,
};
let surface_energy = *material_table.surface_energy.get(material_index)?;
if surface_energy <= 0.0 {
return None;
}
let wall_name = wall
.name
.as_ref()
.map(|name| format!(" named '{name}'"))
.unwrap_or_default();
Some(format!(
"WARNING: {geometry} wall{wall_name} uses material '{}' with \
surface_energy = {surface_energy}, but JKR/DMT `surface_energy` is \
plane-wall-only and is ignored by cylinder, sphere, and region walls. \
Use a plane wall for JKR/DMT wall adhesion, or use `cohesion_energy` \
for unchanged SJKR cohesion on curved/region walls.",
wall.material
))
}
#[derive(Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct OscillateDef {
pub amplitude: f64,
pub frequency: f64,
}
#[derive(Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct ServoDef {
pub target_force: f64,
pub max_velocity: f64,
pub gain: f64,
}
#[derive(Deserialize, Clone)]
pub struct WallDef {
#[serde(default = "default_wall_type", rename = "type")]
pub wall_type: String,
#[serde(default)]
pub point_x: f64,
#[serde(default)]
pub point_y: f64,
#[serde(default)]
pub point_z: f64,
#[serde(default)]
pub normal_x: f64,
#[serde(default)]
pub normal_y: f64,
#[serde(default)]
pub normal_z: f64,
#[serde(default)]
pub axis: Option<String>,
#[serde(default)]
pub center: Option<Vec<f64>>,
#[serde(default)]
pub radius: Option<f64>,
#[serde(default)]
pub lo: Option<f64>,
#[serde(default)]
pub hi: Option<f64>,
#[serde(default)]
pub inside: Option<bool>,
pub material: String,
#[serde(default)]
pub name: Option<String>,
#[serde(default = "default_neg_inf")]
pub bound_x_low: f64,
#[serde(default = "default_pos_inf")]
pub bound_x_high: f64,
#[serde(default = "default_neg_inf")]
pub bound_y_low: f64,
#[serde(default = "default_pos_inf")]
pub bound_y_high: f64,
#[serde(default = "default_neg_inf")]
pub bound_z_low: f64,
#[serde(default = "default_pos_inf")]
pub bound_z_high: f64,
#[serde(default)]
pub velocity: Option<[f64; 3]>,
#[serde(default)]
pub oscillate: Option<OscillateDef>,
#[serde(default)]
pub servo: Option<ServoDef>,
#[serde(default)]
pub region: Option<Region>,
#[serde(default)]
pub temperature: Option<f64>,
}