1use std::collections::BTreeMap;
2use std::fmt;
3
4use serde::de::{self, Visitor};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
8#[serde(rename_all = "snake_case")]
9pub enum RefinementStrategy {
10 None,
11 Uniform,
12 Adaptive,
13 Auto,
14}
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
17#[serde(rename_all = "snake_case")]
18pub enum RefinementFocusLevel {
19 Off,
20 Normal,
21 Fine,
22}
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
25#[serde(rename_all = "snake_case")]
26pub enum RefinementIndicatorMode {
27 Auto,
28 On,
29 Off,
30}
31
32impl<'de> Deserialize<'de> for RefinementIndicatorMode {
33 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
34 where
35 D: serde::Deserializer<'de>,
36 {
37 struct ModeVisitor;
38
39 impl Visitor<'_> for ModeVisitor {
40 type Value = RefinementIndicatorMode;
41
42 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
43 formatter.write_str("auto, on, off, true, or false")
44 }
45
46 fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
47 where
48 E: de::Error,
49 {
50 Ok(if value {
51 RefinementIndicatorMode::On
52 } else {
53 RefinementIndicatorMode::Off
54 })
55 }
56
57 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
58 where
59 E: de::Error,
60 {
61 match value.trim().to_ascii_lowercase().as_str() {
62 "auto" => Ok(RefinementIndicatorMode::Auto),
63 "on" | "true" => Ok(RefinementIndicatorMode::On),
64 "off" | "false" => Ok(RefinementIndicatorMode::Off),
65 other => Err(E::custom(format!(
66 "invalid refinement indicator mode `{other}`, expected auto, on, or off"
67 ))),
68 }
69 }
70
71 fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
72 where
73 E: de::Error,
74 {
75 self.visit_str(&value)
76 }
77 }
78
79 deserializer.deserialize_any(ModeVisitor)
80 }
81}
82
83#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
84pub struct RefinementIndicatorOverrides {
85 #[serde(default, flatten)]
86 pub namespaces: BTreeMap<String, BTreeMap<String, RefinementIndicatorMode>>,
87}
88
89#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
90pub struct RefinementFocusOptions {
91 pub loads: RefinementFocusLevel,
92 pub constraints: RefinementFocusLevel,
93 pub interfaces: RefinementFocusLevel,
94 pub curvature: bool,
95 pub small_features: bool,
96}
97
98impl Default for RefinementFocusOptions {
99 fn default() -> Self {
100 Self {
101 loads: RefinementFocusLevel::Fine,
102 constraints: RefinementFocusLevel::Fine,
103 interfaces: RefinementFocusLevel::Normal,
104 curvature: true,
105 small_features: true,
106 }
107 }
108}
109
110#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
111pub struct RefinementConvergenceOptions {
112 pub field_change_tolerance: f64,
113 pub energy_change_tolerance: f64,
114 #[serde(default)]
115 pub residual_tolerance: Option<f64>,
116}
117
118impl Default for RefinementConvergenceOptions {
119 fn default() -> Self {
120 Self {
121 field_change_tolerance: 0.05,
122 energy_change_tolerance: 0.02,
123 residual_tolerance: None,
124 }
125 }
126}
127
128#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
129pub struct MeshRefinementOptions {
130 pub strategy: RefinementStrategy,
131 pub max_iterations: usize,
132 pub convergence: RefinementConvergenceOptions,
133 pub focus: RefinementFocusOptions,
134 #[serde(default)]
135 pub indicators: RefinementIndicatorOverrides,
136}
137
138impl Default for MeshRefinementOptions {
139 fn default() -> Self {
140 Self {
141 strategy: RefinementStrategy::Auto,
142 max_iterations: 4,
143 convergence: RefinementConvergenceOptions::default(),
144 focus: RefinementFocusOptions::default(),
145 indicators: RefinementIndicatorOverrides::default(),
146 }
147 }
148}
149
150pub type AdaptiveMeshingOptions = MeshRefinementOptions;