1use super::core::{MessageCategory, MessageKey, MessageTemplate, MessageType};
4use std::collections::HashMap;
5
6pub fn initialize_ode_messages(registry: &mut HashMap<MessageKey, MessageTemplate>) {
8 initialize_separable_messages(registry);
9 initialize_linear_ode_messages(registry);
10 initialize_homogeneous_messages(registry);
11 initialize_exact_messages(registry);
12 initialize_bernoulli_messages(registry);
13 initialize_second_order_messages(registry);
14}
15
16fn initialize_separable_messages(registry: &mut HashMap<MessageKey, MessageTemplate>) {
17 registry.insert(
18 MessageKey::new(
19 MessageCategory::OrdinaryDifferentialEquation,
20 MessageType::ODESeparable,
21 0,
22 ),
23 MessageTemplate::new(
24 "Separable ODE Identified",
25 "This is a separable ODE: dy/dx = {rhs}\nWe can write it as: dy/dx = g({independent})*h({dependent})",
26 &["rhs", "independent", "dependent"],
27 ),
28 );
29
30 registry.insert(
31 MessageKey::new(
32 MessageCategory::OrdinaryDifferentialEquation,
33 MessageType::ODESeparable,
34 1,
35 ),
36 MessageTemplate::new(
37 "Separate Variables",
38 "Separate variables by dividing both sides:\n(1/h({dependent})) d{dependent} = g({independent}) d{independent}",
39 &["dependent", "independent"],
40 ),
41 );
42
43 registry.insert(
44 MessageKey::new(
45 MessageCategory::OrdinaryDifferentialEquation,
46 MessageType::ODESeparable,
47 2,
48 ),
49 MessageTemplate::new(
50 "Integrate Both Sides",
51 "Integrate both sides:\n∫ {y_integral} d{dependent} = ∫ {x_integral} d{independent}",
52 &["y_integral", "dependent", "x_integral", "independent"],
53 ),
54 );
55
56 registry.insert(
57 MessageKey::new(
58 MessageCategory::OrdinaryDifferentialEquation,
59 MessageType::ODESeparable,
60 3,
61 ),
62 MessageTemplate::new(
63 "General Solution",
64 "After integration and adding constant C:\n{solution}",
65 &["solution"],
66 ),
67 );
68}
69
70fn initialize_linear_ode_messages(registry: &mut HashMap<MessageKey, MessageTemplate>) {
71 registry.insert(
72 MessageKey::new(
73 MessageCategory::OrdinaryDifferentialEquation,
74 MessageType::ODELinear,
75 0,
76 ),
77 MessageTemplate::new(
78 "Linear First-Order ODE",
79 "This is a linear first-order ODE: dy/dx + P({independent}){dependent} = Q({independent})\nWhere P({independent}) = {p_func} and Q({independent}) = {q_func}",
80 &["independent", "dependent", "p_func", "q_func"],
81 ),
82 );
83
84 registry.insert(
85 MessageKey::new(
86 MessageCategory::OrdinaryDifferentialEquation,
87 MessageType::ODEIntegratingFactor,
88 0,
89 ),
90 MessageTemplate::new(
91 "Compute Integrating Factor",
92 "Compute integrating factor μ({independent}) = exp(∫ P({independent}) d{independent})\nμ({independent}) = exp(∫ {p_func} d{independent}) = {integrating_factor}",
93 &["independent", "p_func", "integrating_factor"],
94 ),
95 );
96
97 registry.insert(
98 MessageKey::new(
99 MessageCategory::OrdinaryDifferentialEquation,
100 MessageType::ODELinear,
101 1,
102 ),
103 MessageTemplate::new(
104 "Multiply by Integrating Factor",
105 "Multiply both sides by μ({independent}) = {integrating_factor}:\nd/d{independent}[μ({independent}) {dependent}] = μ({independent}) Q({independent})",
106 &["independent", "integrating_factor", "dependent"],
107 ),
108 );
109
110 registry.insert(
111 MessageKey::new(
112 MessageCategory::OrdinaryDifferentialEquation,
113 MessageType::ODELinear,
114 2,
115 ),
116 MessageTemplate::new(
117 "Integrate to Solve",
118 "Integrate both sides:\nμ({independent}) {dependent} = ∫ μ({independent}) Q({independent}) d{independent}\n{dependent} = (1/μ({independent})) [∫ {integral_expr} d{independent} + C]",
119 &["independent", "dependent", "integral_expr"],
120 ),
121 );
122
123 registry.insert(
124 MessageKey::new(
125 MessageCategory::OrdinaryDifferentialEquation,
126 MessageType::ODELinear,
127 3,
128 ),
129 MessageTemplate::new(
130 "General Solution",
131 "General solution:\n{dependent}({independent}) = {solution}",
132 &["dependent", "independent", "solution"],
133 ),
134 );
135}
136
137fn initialize_homogeneous_messages(registry: &mut HashMap<MessageKey, MessageTemplate>) {
138 registry.insert(
139 MessageKey::new(
140 MessageCategory::OrdinaryDifferentialEquation,
141 MessageType::ODEHomogeneous,
142 0,
143 ),
144 MessageTemplate::new(
145 "Homogeneous ODE Identified",
146 "This is a homogeneous ODE: dy/dx = f({dependent}/{independent})\nThe right-hand side depends only on the ratio {dependent}/{independent}",
147 &["dependent", "independent"],
148 ),
149 );
150
151 registry.insert(
152 MessageKey::new(
153 MessageCategory::OrdinaryDifferentialEquation,
154 MessageType::ODESubstitution,
155 0,
156 ),
157 MessageTemplate::new(
158 "Substitution v = y/x",
159 "Let v = {dependent}/{independent}, so {dependent} = v{independent}\nThen dy/d{independent} = v + {independent}(dv/d{independent})",
160 &["dependent", "independent"],
161 ),
162 );
163
164 registry.insert(
165 MessageKey::new(
166 MessageCategory::OrdinaryDifferentialEquation,
167 MessageType::ODEHomogeneous,
168 1,
169 ),
170 MessageTemplate::new(
171 "Transform to Separable",
172 "Substituting into the ODE:\nv + {independent}(dv/d{independent}) = f(v)\n{independent}(dv/d{independent}) = f(v) - v\nThis is now separable!",
173 &["independent"],
174 ),
175 );
176
177 registry.insert(
178 MessageKey::new(
179 MessageCategory::OrdinaryDifferentialEquation,
180 MessageType::ODEHomogeneous,
181 2,
182 ),
183 MessageTemplate::new(
184 "Back-Substitute",
185 "After solving for v, substitute back v = {dependent}/{independent}:\n{solution}",
186 &["dependent", "independent", "solution"],
187 ),
188 );
189}
190
191fn initialize_exact_messages(registry: &mut HashMap<MessageKey, MessageTemplate>) {
192 registry.insert(
193 MessageKey::new(
194 MessageCategory::OrdinaryDifferentialEquation,
195 MessageType::ODEExact,
196 0,
197 ),
198 MessageTemplate::new(
199 "Exact ODE Identified",
200 "This is an exact ODE: M({independent}, {dependent})d{independent} + N({independent}, {dependent})d{dependent} = 0\nWhere ∂M/∂{dependent} = ∂N/∂{independent}",
201 &["independent", "dependent"],
202 ),
203 );
204
205 registry.insert(
206 MessageKey::new(
207 MessageCategory::OrdinaryDifferentialEquation,
208 MessageType::ODEExact,
209 1,
210 ),
211 MessageTemplate::new(
212 "Find Potential Function",
213 "Find function F({independent}, {dependent}) such that:\n∂F/∂{independent} = M({independent}, {dependent})\n∂F/∂{dependent} = N({independent}, {dependent})",
214 &["independent", "dependent"],
215 ),
216 );
217
218 registry.insert(
219 MessageKey::new(
220 MessageCategory::OrdinaryDifferentialEquation,
221 MessageType::ODEExact,
222 2,
223 ),
224 MessageTemplate::new(
225 "Implicit Solution",
226 "The solution is given implicitly by:\nF({independent}, {dependent}) = C\nWhere {solution_implicit}",
227 &["independent", "dependent", "solution_implicit"],
228 ),
229 );
230}
231
232fn initialize_bernoulli_messages(registry: &mut HashMap<MessageKey, MessageTemplate>) {
233 registry.insert(
234 MessageKey::new(
235 MessageCategory::OrdinaryDifferentialEquation,
236 MessageType::ODEBernoulli,
237 0,
238 ),
239 MessageTemplate::new(
240 "Bernoulli Equation",
241 "This is a Bernoulli equation: dy/dx + P({independent}){dependent} = Q({independent}){dependent}^n\nWith n = {n_value}, P = {p_func}, Q = {q_func}",
242 &["independent", "dependent", "n_value", "p_func", "q_func"],
243 ),
244 );
245
246 registry.insert(
247 MessageKey::new(
248 MessageCategory::OrdinaryDifferentialEquation,
249 MessageType::ODESubstitution,
250 1,
251 ),
252 MessageTemplate::new(
253 "Substitution to Linearize",
254 "Let v = {dependent}^(1-n) = {dependent}^{exponent}\nThen dv/d{independent} = (1-n){dependent}^(-n) d{dependent}/d{independent}",
255 &["dependent", "exponent", "independent"],
256 ),
257 );
258
259 registry.insert(
260 MessageKey::new(
261 MessageCategory::OrdinaryDifferentialEquation,
262 MessageType::ODEBernoulli,
263 1,
264 ),
265 MessageTemplate::new(
266 "Linear ODE in v",
267 "After substitution, we get a linear ODE:\ndv/d{independent} + (1-n)P({independent})v = (1-n)Q({independent})\nSolve this linear ODE for v, then substitute back",
268 &["independent"],
269 ),
270 );
271}
272
273fn initialize_second_order_messages(registry: &mut HashMap<MessageKey, MessageTemplate>) {
274 registry.insert(
275 MessageKey::new(
276 MessageCategory::OrdinaryDifferentialEquation,
277 MessageType::ODEConstantCoefficients,
278 0,
279 ),
280 MessageTemplate::new(
281 "Second-Order Constant Coefficients",
282 "This is a second-order linear ODE with constant coefficients:\na{y_double_prime} + b{y_prime} + c{dependent} = {rhs}\nCoefficients: a = {a_val}, b = {b_val}, c = {c_val}",
283 &["y_double_prime", "y_prime", "dependent", "rhs", "a_val", "b_val", "c_val"],
284 ),
285 );
286
287 registry.insert(
288 MessageKey::new(
289 MessageCategory::OrdinaryDifferentialEquation,
290 MessageType::ODECharacteristicEquation,
291 0,
292 ),
293 MessageTemplate::new(
294 "Characteristic Equation",
295 "Form the characteristic equation by assuming {dependent} = exp(r{independent}):\nar^2 + br + c = 0\n{a_val}r^2 + {b_val}r + {c_val} = 0",
296 &["dependent", "independent", "a_val", "b_val", "c_val"],
297 ),
298 );
299
300 registry.insert(
301 MessageKey::new(
302 MessageCategory::OrdinaryDifferentialEquation,
303 MessageType::ODECharacteristicEquation,
304 1,
305 ),
306 MessageTemplate::new(
307 "Solve for Roots",
308 "Using quadratic formula:\nr = (-b ± sqrt(b^2 - 4ac)) / (2a)\nr = {roots}\nDiscriminant: {discriminant}",
309 &["roots", "discriminant"],
310 ),
311 );
312
313 registry.insert(
314 MessageKey::new(
315 MessageCategory::OrdinaryDifferentialEquation,
316 MessageType::ODEConstantCoefficients,
317 1,
318 ),
319 MessageTemplate::new(
320 "Homogeneous Solution (Real Distinct Roots)",
321 "Since roots r1 = {r1} and r2 = {r2} are real and distinct:\n{dependent}_h({independent}) = C1*exp({r1}{independent}) + C2*exp({r2}{independent})",
322 &["r1", "r2", "dependent", "independent"],
323 ),
324 );
325
326 registry.insert(
327 MessageKey::new(
328 MessageCategory::OrdinaryDifferentialEquation,
329 MessageType::ODEConstantCoefficients,
330 2,
331 ),
332 MessageTemplate::new(
333 "Homogeneous Solution (Repeated Root)",
334 "Since roots are equal r1 = r2 = {r}:\n{dependent}_h({independent}) = (C1 + C2{independent})*exp({r}{independent})",
335 &["r", "dependent", "independent"],
336 ),
337 );
338
339 registry.insert(
340 MessageKey::new(
341 MessageCategory::OrdinaryDifferentialEquation,
342 MessageType::ODEConstantCoefficients,
343 3,
344 ),
345 MessageTemplate::new(
346 "Homogeneous Solution (Complex Roots)",
347 "Since roots are complex r = {alpha} ± {beta}i:\n{dependent}_h({independent}) = exp({alpha}{independent})[C1*cos({beta}{independent}) + C2*sin({beta}{independent})]",
348 &["alpha", "beta", "dependent", "independent"],
349 ),
350 );
351
352 registry.insert(
353 MessageKey::new(
354 MessageCategory::OrdinaryDifferentialEquation,
355 MessageType::ODEUndeterminedCoefficients,
356 0,
357 ),
358 MessageTemplate::new(
359 "Method of Undetermined Coefficients",
360 "For non-homogeneous ODE with {rhs_type} forcing:\nGuess particular solution form: {particular_guess}",
361 &["rhs_type", "particular_guess"],
362 ),
363 );
364
365 registry.insert(
366 MessageKey::new(
367 MessageCategory::OrdinaryDifferentialEquation,
368 MessageType::ODEVariationParameters,
369 0,
370 ),
371 MessageTemplate::new(
372 "Variation of Parameters",
373 "Use variation of parameters for general forcing function.\nAssume {dependent}_p = u1({independent}){y1} + u2({independent}){y2}\nWhere {y1}, {y2} are homogeneous solutions",
374 &["dependent", "independent", "y1", "y2"],
375 ),
376 );
377
378 registry.insert(
379 MessageKey::new(
380 MessageCategory::OrdinaryDifferentialEquation,
381 MessageType::ODECauchyEuler,
382 0,
383 ),
384 MessageTemplate::new(
385 "Cauchy-Euler Equation",
386 "This is a Cauchy-Euler (equidimensional) equation:\na{independent}^2{y_double_prime} + b{independent}{y_prime} + c{dependent} = 0\nSubstitute {dependent} = {independent}^r",
387 &["independent", "y_double_prime", "y_prime", "dependent"],
388 ),
389 );
390
391 registry.insert(
392 MessageKey::new(
393 MessageCategory::OrdinaryDifferentialEquation,
394 MessageType::ODECauchyEuler,
395 1,
396 ),
397 MessageTemplate::new(
398 "Indicial Equation",
399 "After substitution, the indicial equation is:\nar(r-1) + br + c = 0\n{indicial_eq}\nSolve for r",
400 &["indicial_eq"],
401 ),
402 );
403}