1use num_traits::{Float, FromPrimitive};
2
3use crate::{
4 ComplexScalar, Contour, ErrorNorm, IndentSide,
5 core::{GaussKronrodConfig, SingularityHandling},
6};
7
8#[derive(Clone, Debug)]
9pub struct ContourDeformation<F>
10where
11 F: ComplexScalar,
12{
13 pub indentations: Vec<Indentation<F>>,
15
16 pub tolerance: F,
19}
20
21#[derive(Clone, Debug)]
22pub struct Indentation<F>
23where
24 F: ComplexScalar,
25{
26 pub point: F::Complex,
28
29 pub radius: F,
31
32 pub side: IndentSide,
34}
35
36#[derive(Clone, Debug)]
46pub struct IntegratorConfig<F: ComplexScalar> {
47 pub(crate) store_segment_data: bool,
52
53 pub(crate) integrator_order: usize,
58
59 pub(crate) minimum_segment_width: F,
63
64 pub(crate) error_norm: ErrorNorm,
66
67 pub(crate) singularity_handling: SingularityHandling,
69
70 pub(crate) relative_tolerance: F,
72
73 pub(crate) absolute_tolerance: F,
75
76 pub(crate) max_function_evaluations: usize,
78
79 pub(crate) tolerance_window: usize,
84
85 pub(crate) contour_deformation: Option<ContourDeformation<F>>,
86}
87
88impl<F> Default for IntegratorConfig<F>
89where
90 F: Float + FromPrimitive + ComplexScalar,
91{
92 fn default() -> Self {
93 Self {
94 store_segment_data: false,
95 integrator_order: 10,
96 minimum_segment_width: F::from_f64(1e-12).unwrap(),
97 error_norm: ErrorNorm::Max,
98 singularity_handling: SingularityHandling::RecursiveSplit { max_depth: 32 },
99 relative_tolerance: F::from_f64(1.49e-8).unwrap(),
100 absolute_tolerance: F::from_f64(1.49e-8).unwrap(),
101 max_function_evaluations: 5000,
102 tolerance_window: 10,
103 contour_deformation: None,
104 }
105 }
106}
107
108impl<F> IntegratorConfig<F>
109where
110 F: Float + FromPrimitive + ComplexScalar,
111{
112 pub fn new() -> Self {
114 Self::default()
115 }
116
117 pub(crate) fn deform_contour(&self, mut contour: Contour<F>) -> Contour<F> {
118 if let Some(deformation) = &self.contour_deformation {
119 for indentation in &deformation.indentations {
120 contour = contour.indent(
121 indentation.point,
122 indentation.radius,
123 indentation.side,
124 deformation.tolerance,
125 );
126 }
127 }
128
129 contour
130 }
131
132 pub fn with_indentation(mut self, point: F::Complex, radius: F, side: IndentSide) -> Self {
134 let deformation = self
135 .contour_deformation
136 .get_or_insert_with(|| ContourDeformation {
137 indentations: Vec::new(),
138 tolerance: self.minimum_segment_width,
139 });
140
141 deformation.indentations.push(Indentation {
142 point,
143 radius,
144 side,
145 });
146
147 self
148 }
149
150 pub fn with_deformation_tolerance(mut self, tolerance: F) -> Self {
154 let deformation = self
155 .contour_deformation
156 .get_or_insert_with(|| ContourDeformation {
157 indentations: Vec::new(),
158 tolerance,
159 });
160
161 deformation.tolerance = tolerance;
162 self
163 }
164
165 pub fn store_segment_data(mut self) -> Self {
167 self.store_segment_data = true;
168 self
169 }
170
171 pub fn with_integrator_order(mut self, order: usize) -> Self {
173 self.integrator_order = order;
174 self
175 }
176
177 pub fn with_minimum_segment_width(mut self, width: F) -> Self {
179 self.minimum_segment_width = width;
180 self
181 }
182
183 pub fn with_error_norm(mut self, norm: ErrorNorm) -> Self {
185 self.error_norm = norm;
186 self
187 }
188
189 pub fn with_max_function_evalutions(mut self, max_function_evaluations: usize) -> Self {
191 self.max_function_evaluations = max_function_evaluations;
192 self
193 }
194
195 pub fn with_singularity_handling(mut self, handling: SingularityHandling) -> Self {
197 self.singularity_handling = handling;
198 self
199 }
200
201 pub fn with_relative_tolerance(mut self, tolerance: F) -> Self {
203 self.relative_tolerance = tolerance;
204 self
205 }
206
207 pub fn with_absolute_tolerance(mut self, tolerance: F) -> Self {
209 self.absolute_tolerance = tolerance;
210 self
211 }
212
213 pub fn with_tolerance_window(mut self, window: usize) -> Self {
215 self.tolerance_window = window;
216 self
217 }
218
219 pub(crate) fn gk_config(&self) -> GaussKronrodConfig<F>
220 where
221 F: Copy,
222 {
223 GaussKronrodConfig::new(
224 self.integrator_order,
225 self.minimum_segment_width,
226 self.error_norm,
227 self.singularity_handling,
228 )
229 }
230}