Skip to main content

fpm_rs/callbacks/
progress.rs

1use crate::{Result, diagnostics::DiagnosticRequest};
2
3use super::{Callback, CallbackAction, CallbackHook, StepContext};
4
5/// Prints iteration, objective, and elapsed-time progress to standard error.
6pub struct ProgressLogger {
7    frequency: usize,
8}
9
10impl ProgressLogger {
11    /// Creates a logger active every `frequency` iterations; zero is normalized to one.
12    pub fn new(frequency: usize) -> Self {
13        Self {
14            frequency: frequency.max(1),
15        }
16    }
17}
18
19impl Default for ProgressLogger {
20    fn default() -> Self {
21        Self::new(1)
22    }
23}
24
25impl Callback for ProgressLogger {
26    fn requires(&self) -> Vec<DiagnosticRequest> {
27        vec![DiagnosticRequest::Objective]
28    }
29
30    fn requires_for(&self, hook: CallbackHook, iteration: usize) -> Vec<DiagnosticRequest> {
31        if hook == CallbackHook::IterationEnd && iteration.is_multiple_of(self.frequency) {
32            self.requires()
33        } else {
34            Vec::new()
35        }
36    }
37
38    fn on_iteration_end(&mut self, context: &StepContext<'_>) -> Result<CallbackAction> {
39        if context.iteration.is_multiple_of(self.frequency)
40            && let Some(objective) = context.diagnostics.objective
41        {
42            eprintln!(
43                "iteration {:>5}: objective {objective:.6e}",
44                context.iteration
45            );
46        }
47        Ok(CallbackAction::Continue)
48    }
49}