1use crate::common::IntegrateFloat;
8use crate::error::{IntegrateError, IntegrateResult};
9use scirs2_core::ndarray::{Array1, Array2};
10use std::collections::{HashMap, HashSet};
11
12pub struct AdvancedAMRManager<F: IntegrateFloat> {
14 pub mesh_hierarchy: MeshHierarchy<F>,
16 pub refinement_criteria: Vec<Box<dyn RefinementCriterion<F>>>,
18 pub load_balancer: Option<Box<dyn LoadBalancer<F>>>,
20 pub max_levels: usize,
22 pub min_cell_size: F,
24 pub coarsening_tolerance: F,
26 pub refinement_tolerance: F,
28 pub adaptation_frequency: usize,
30 current_step: usize,
32}
33
34#[derive(Debug, Clone)]
36pub struct MeshHierarchy<F: IntegrateFloat> {
37 pub levels: Vec<AdaptiveMeshLevel<F>>,
39 pub hierarchy_map: HashMap<CellId, Vec<CellId>>,
41 pub ghost_cells: HashMap<usize, Vec<CellId>>, }
44
45#[derive(Debug, Clone)]
47pub struct AdaptiveMeshLevel<F: IntegrateFloat> {
48 pub level: usize,
50 pub cells: HashMap<CellId, AdaptiveCell<F>>,
52 pub grid_spacing: F,
54 pub boundary_cells: HashSet<CellId>,
56}
57
58#[derive(Debug, Clone)]
60pub struct AdaptiveCell<F: IntegrateFloat> {
61 pub id: CellId,
63 pub center: Array1<F>,
65 pub size: F,
67 pub solution: Array1<F>,
69 pub error_estimate: F,
71 pub refinement_flag: RefinementFlag,
73 pub is_active: bool,
75 pub neighbors: Vec<CellId>,
77 pub parent: Option<CellId>,
79 pub children: Vec<CellId>,
81}
82
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
85pub struct CellId {
86 pub level: usize,
87 pub index: usize,
88}
89
90#[derive(Debug, Clone, Copy, PartialEq)]
92pub enum RefinementFlag {
93 None,
95 Refine,
97 Coarsen,
99 Tagged,
101}
102
103pub trait RefinementCriterion<F: IntegrateFloat>: Send + Sync {
105 fn evaluate(&self, cell: &AdaptiveCell<F>, neighbors: &[&AdaptiveCell<F>]) -> F;
107
108 fn name(&self) -> &'static str;
110
111 fn weight(&self) -> F {
113 F::one()
114 }
115}
116
117pub struct GradientRefinementCriterion<F: IntegrateFloat> {
119 pub component: Option<usize>,
121 pub threshold: F,
123 pub relative_tolerance: F,
125}
126
127pub struct FeatureDetectionCriterion<F: IntegrateFloat> {
129 pub threshold: F,
131 pub feature_types: Vec<FeatureType>,
133 pub window_size: usize,
135}
136
137pub struct CurvatureRefinementCriterion<F: IntegrateFloat> {
139 pub threshold: F,
141 pub approximation_order: usize,
143}
144
145pub trait LoadBalancer<F: IntegrateFloat>: Send + Sync {
147 fn balance(&self, hierarchy: &mut MeshHierarchy<F>) -> IntegrateResult<()>;
149}
150
151pub struct GeometricLoadBalancer<F: IntegrateFloat> {
153 pub num_partitions: usize,
155 pub imbalance_tolerance: F,
157 pub method: PartitioningMethod,
159}
160
161#[derive(Debug, Clone, Copy, PartialEq)]
163pub enum FeatureType {
164 SharpGradient,
166 Discontinuity,
168 LocalExtremum,
170 Oscillation,
172 BoundaryLayer,
174}
175
176#[derive(Debug, Clone, Copy)]
178pub enum PartitioningMethod {
179 RCB,
181 SFC,
183 Graph,
185}
186
187pub struct AMRAdaptationResult<F: IntegrateFloat> {
189 pub cells_refined: usize,
191 pub cells_coarsened: usize,
193 pub total_active_cells: usize,
195 pub load_balance_quality: F,
197 pub memory_change: i64,
199 pub adaptation_time: std::time::Duration,
201}
202
203impl<F: IntegrateFloat> AdvancedAMRManager<F> {
204 pub fn new(_initial_mesh: AdaptiveMeshLevel<F>, max_levels: usize, min_cellsize: F) -> Self {
206 let mesh_hierarchy = MeshHierarchy {
207 levels: vec![_initial_mesh],
208 hierarchy_map: HashMap::new(),
209 ghost_cells: HashMap::new(),
210 };
211
212 Self {
213 mesh_hierarchy,
214 refinement_criteria: Vec::new(),
215 load_balancer: None,
216 max_levels,
217 min_cell_size: min_cellsize,
218 coarsening_tolerance: F::from(0.1).expect("Failed to convert constant to float"),
219 refinement_tolerance: F::from(1.0).expect("Failed to convert constant to float"),
220 adaptation_frequency: 1,
221 current_step: 0,
222 }
223 }
224
225 pub fn add_criterion(&mut self, criterion: Box<dyn RefinementCriterion<F>>) {
227 self.refinement_criteria.push(criterion);
228 }
229
230 pub fn set_load_balancer(&mut self, balancer: Box<dyn LoadBalancer<F>>) {
232 self.load_balancer = Some(balancer);
233 }
234
235 pub fn adapt_mesh(&mut self, solution: &Array2<F>) -> IntegrateResult<AMRAdaptationResult<F>> {
237 let start_time = std::time::Instant::now();
238 let initial_cells = self.count_active_cells();
239
240 self.current_step += 1;
241
242 if !self.current_step.is_multiple_of(self.adaptation_frequency) {
244 return Ok(AMRAdaptationResult {
245 cells_refined: 0,
246 cells_coarsened: 0,
247 total_active_cells: initial_cells,
248 load_balance_quality: F::one(),
249 memory_change: 0,
250 adaptation_time: start_time.elapsed(),
251 });
252 }
253
254 self.update_cell_solutions(solution)?;
256
257 self.evaluate_refinement_criteria()?;
259
260 let _refine_count_coarsen_count = self.flag_cells_for_adaptation()?;
262
263 let cells_refined = self.refine_flagged_cells()?;
265
266 let cells_coarsened = self.coarsen_flagged_cells()?;
268
269 let load_balance_quality = if let Some(ref balancer) = self.load_balancer {
271 balancer.balance(&mut self.mesh_hierarchy)?;
272 self.assess_load_balance()
273 } else {
274 F::one()
275 };
276
277 self.update_ghost_cells()?;
279
280 let final_cells = self.count_active_cells();
281 let memory_change = (final_cells as i64 - initial_cells as i64) * 8; Ok(AMRAdaptationResult {
284 cells_refined,
285 cells_coarsened,
286 total_active_cells: final_cells,
287 load_balance_quality,
288 memory_change,
289 adaptation_time: start_time.elapsed(),
290 })
291 }
292
293 fn update_cell_solutions(&mut self, solution: &Array2<F>) -> IntegrateResult<()> {
295 for level in &mut self.mesh_hierarchy.levels {
298 for cell in level.cells.values_mut() {
299 if cell.is_active {
300 let i = (cell.center[0] * F::from(solution.nrows()).expect("Operation failed"))
302 .to_usize()
303 .unwrap_or(0)
304 .min(solution.nrows() - 1);
305 let j = if solution.ncols() > 1 && cell.center.len() > 1 {
306 (cell.center[1] * F::from(solution.ncols()).expect("Operation failed"))
307 .to_usize()
308 .unwrap_or(0)
309 .min(solution.ncols() - 1)
310 } else {
311 0
312 };
313
314 if cell.solution.len() == 1 {
316 cell.solution[0] = solution[[i, j]];
317 }
318 }
319 }
320 }
321 Ok(())
322 }
323
324 fn evaluate_refinement_criteria(&mut self) -> IntegrateResult<()> {
326 for level in &mut self.mesh_hierarchy.levels {
327 let cellids: Vec<CellId> = level.cells.keys().cloned().collect();
328
329 for cellid in cellids {
330 if let Some(cell) = level.cells.get(&cellid) {
331 if !cell.is_active {
332 continue;
333 }
334
335 let neighbor_cells: Vec<&AdaptiveCell<F>> = cell
337 .neighbors
338 .iter()
339 .filter_map(|&neighbor_id| level.cells.get(&neighbor_id))
340 .collect();
341
342 let mut total_error = F::zero();
344 let mut total_weight = F::zero();
345
346 for criterion in &self.refinement_criteria {
347 let error = criterion.evaluate(cell, &neighbor_cells);
348 let weight = criterion.weight();
349 total_error += error * weight;
350 total_weight += weight;
351 }
352
353 let error_estimate = if total_weight > F::zero() {
355 total_error / total_weight
356 } else {
357 F::zero()
358 };
359
360 if let Some(cell) = level.cells.get_mut(&cellid) {
362 cell.error_estimate = error_estimate;
363 }
364 }
365 }
366 }
367 Ok(())
368 }
369
370 fn flag_cells_for_adaptation(&mut self) -> IntegrateResult<(usize, usize)> {
372 let mut refine_count = 0;
373 let mut coarsen_count = 0;
374
375 let mut cells_to_check: Vec<(usize, CellId, F, usize, F)> = Vec::new();
377
378 for level in &self.mesh_hierarchy.levels {
379 for cell in level.cells.values() {
380 if cell.is_active {
381 cells_to_check.push((
382 level.level,
383 cell.id,
384 cell.error_estimate,
385 level.level,
386 cell.size,
387 ));
388 }
389 }
390 }
391
392 for (level_idx, cellid, error_estimate, level_num, cell_size) in cells_to_check {
394 if let Some(level) = self.mesh_hierarchy.levels.get_mut(level_idx) {
395 if let Some(cell) = level.cells.get_mut(&cellid) {
396 if error_estimate > self.refinement_tolerance
398 && level_num < self.max_levels
399 && cell_size > self.min_cell_size
400 {
401 cell.refinement_flag = RefinementFlag::Refine;
402 refine_count += 1;
403 }
404 else if error_estimate < self.coarsening_tolerance && level_num > 0 {
406 cell.refinement_flag = RefinementFlag::Coarsen;
407 coarsen_count += 1;
408 } else {
409 cell.refinement_flag = RefinementFlag::None;
410 }
411 }
412 }
413 }
414
415 Ok((refine_count, coarsen_count))
416 }
417
418 fn can_coarsen_cell(&self, cell: &AdaptiveCell<F>) -> bool {
420 if let Some(parent_id) = cell.parent {
421 if let Some(parent_children) = self.mesh_hierarchy.hierarchy_map.get(&parent_id) {
423 for &child_id in parent_children {
424 if let Some(level) = self.mesh_hierarchy.levels.get(child_id.level) {
425 if let Some(sibling) = level.cells.get(&child_id) {
426 if sibling.refinement_flag != RefinementFlag::Coarsen {
427 return false;
428 }
429 }
430 }
431 }
432 return true;
433 }
434 }
435 false
436 }
437
438 fn refine_flagged_cells(&mut self) -> IntegrateResult<usize> {
440 let mut cells_refined = 0;
441
442 for level_idx in 0..self.mesh_hierarchy.levels.len() {
444 let cells_to_refine: Vec<CellId> = self.mesh_hierarchy.levels[level_idx]
445 .cells
446 .values()
447 .filter(|cell| cell.refinement_flag == RefinementFlag::Refine)
448 .map(|cell| cell.id)
449 .collect();
450
451 for cellid in cells_to_refine {
452 self.refine_cell(cellid)?;
453 cells_refined += 1;
454 }
455 }
456
457 Ok(cells_refined)
458 }
459
460 fn refine_cell(&mut self, cellid: CellId) -> IntegrateResult<()> {
462 let parent_cell = if let Some(level) = self.mesh_hierarchy.levels.get(cellid.level) {
463 level.cells.get(&cellid).cloned()
464 } else {
465 return Err(IntegrateError::ValueError("Invalid cell level".to_string()));
466 };
467
468 let parent_cell =
469 parent_cell.ok_or_else(|| IntegrateError::ValueError("Cell not found".to_string()))?;
470
471 let child_level = cellid.level + 1;
473 while self.mesh_hierarchy.levels.len() <= child_level {
474 let new_level = AdaptiveMeshLevel {
475 level: self.mesh_hierarchy.levels.len(),
476 cells: HashMap::new(),
477 grid_spacing: if let Some(last_level) = self.mesh_hierarchy.levels.last() {
478 last_level.grid_spacing
479 / F::from(2.0).expect("Failed to convert constant to float")
480 } else {
481 F::one()
482 },
483 boundary_cells: HashSet::new(),
484 };
485 self.mesh_hierarchy.levels.push(new_level);
486 }
487
488 let num_children = 2_usize.pow(parent_cell.center.len() as u32);
490 let mut child_ids = Vec::new();
491 let child_size =
492 parent_cell.size / F::from(2.0).expect("Failed to convert constant to float");
493
494 for child_idx in 0..num_children {
495 let child_id = CellId {
496 level: child_level,
497 index: self.mesh_hierarchy.levels[child_level].cells.len(),
498 };
499
500 let mut child_center = parent_cell.center.clone();
502 let offset = child_size / F::from(2.0).expect("Failed to convert constant to float");
503
504 for dim in 0..parent_cell.center.len() {
506 if (child_idx >> dim) & 1 == 1 {
507 child_center[dim] += offset;
508 } else {
509 child_center[dim] -= offset;
510 }
511 }
512
513 let child_cell = AdaptiveCell {
514 id: child_id,
515 center: child_center,
516 size: child_size,
517 solution: parent_cell.solution.clone(), error_estimate: F::zero(),
519 refinement_flag: RefinementFlag::None,
520 is_active: true,
521 neighbors: Vec::new(),
522 parent: Some(cellid),
523 children: Vec::new(),
524 };
525
526 self.mesh_hierarchy.levels[child_level]
527 .cells
528 .insert(child_id, child_cell);
529 child_ids.push(child_id);
530 }
531
532 self.mesh_hierarchy
534 .hierarchy_map
535 .insert(cellid, child_ids.clone());
536
537 if let Some(parent) = self.mesh_hierarchy.levels[cellid.level]
539 .cells
540 .get_mut(&cellid)
541 {
542 parent.is_active = false;
543 parent.children = child_ids;
544 }
545
546 self.update_neighbor_relationships(child_level)?;
548
549 Ok(())
550 }
551
552 fn coarsen_flagged_cells(&mut self) -> IntegrateResult<usize> {
554 let mut cells_coarsened = 0;
555
556 for level_idx in (1..self.mesh_hierarchy.levels.len()).rev() {
558 let parent_cells_to_activate: Vec<CellId> = self.mesh_hierarchy.levels[level_idx]
559 .cells
560 .values()
561 .filter(|cell| cell.refinement_flag == RefinementFlag::Coarsen)
562 .filter_map(|cell| cell.parent)
563 .collect::<HashSet<_>>()
564 .into_iter()
565 .collect();
566
567 for parent_id in parent_cells_to_activate {
568 if self.coarsen_to_parent(parent_id)? {
569 cells_coarsened += 1;
570 }
571 }
572 }
573
574 Ok(cells_coarsened)
575 }
576
577 fn coarsen_to_parent(&mut self, parentid: CellId) -> IntegrateResult<bool> {
579 let child_ids = if let Some(children) = self.mesh_hierarchy.hierarchy_map.get(&parentid) {
580 children.clone()
581 } else {
582 return Ok(false);
583 };
584
585 for &child_id in &child_ids {
587 if let Some(level) = self.mesh_hierarchy.levels.get(child_id.level) {
588 if let Some(child) = level.cells.get(&child_id) {
589 if child.refinement_flag != RefinementFlag::Coarsen {
590 return Ok(false);
591 }
592 }
593 }
594 }
595
596 let mut avg_solution = Array1::zeros(child_ids.len());
598 if !child_ids.is_empty() {
599 if let Some(first_child_level) = self.mesh_hierarchy.levels.get(child_ids[0].level) {
600 if let Some(first_child) = first_child_level.cells.get(&child_ids[0]) {
601 avg_solution = Array1::zeros(first_child.solution.len());
602
603 for &child_id in &child_ids {
604 if let Some(child_level) = self.mesh_hierarchy.levels.get(child_id.level) {
605 if let Some(child) = child_level.cells.get(&child_id) {
606 avg_solution = &avg_solution + &child.solution;
607 }
608 }
609 }
610 avg_solution /= F::from(child_ids.len()).expect("Operation failed");
611 }
612 }
613 }
614
615 if let Some(parent_level) = self.mesh_hierarchy.levels.get_mut(parentid.level) {
617 if let Some(parent) = parent_level.cells.get_mut(&parentid) {
618 parent.is_active = true;
619 parent.solution = avg_solution;
620 parent.children.clear();
621 parent.refinement_flag = RefinementFlag::None;
622 }
623 }
624
625 for &child_id in &child_ids {
627 if let Some(child_level) = self.mesh_hierarchy.levels.get_mut(child_id.level) {
628 child_level.cells.remove(&child_id);
629 }
630 }
631
632 self.mesh_hierarchy.hierarchy_map.remove(&parentid);
634
635 Ok(true)
636 }
637
638 fn update_neighbor_relationships(&mut self, level: usize) -> IntegrateResult<()> {
640 let mut all_neighbor_relationships: Vec<(CellId, Vec<CellId>)> = Vec::new();
642
643 if let Some(mesh_level) = self.mesh_hierarchy.levels.get(level) {
644 let cellids: Vec<CellId> = mesh_level.cells.keys().cloned().collect();
645
646 let mut spatial_hash: HashMap<(i32, i32, i32), Vec<CellId>> = HashMap::new();
648 let grid_spacing = mesh_level.grid_spacing;
649
650 for cellid in &cellids {
652 if let Some(cell) = mesh_level.cells.get(cellid) {
653 if cell.center.len() >= 3 {
654 let hash_x = (cell.center[0] / grid_spacing)
655 .floor()
656 .to_i32()
657 .unwrap_or(0);
658 let hash_y = (cell.center[1] / grid_spacing)
659 .floor()
660 .to_i32()
661 .unwrap_or(0);
662 let hash_z = (cell.center[2] / grid_spacing)
663 .floor()
664 .to_i32()
665 .unwrap_or(0);
666
667 spatial_hash
668 .entry((hash_x, hash_y, hash_z))
669 .or_default()
670 .push(*cellid);
671 }
672 }
673 }
674
675 for cellid in &cellids {
676 if let Some(cell) = mesh_level.cells.get(cellid) {
677 let mut neighbors = Vec::new();
678
679 if cell.center.len() >= 3 {
680 let hash_x = (cell.center[0] / grid_spacing)
681 .floor()
682 .to_i32()
683 .unwrap_or(0);
684 let hash_y = (cell.center[1] / grid_spacing)
685 .floor()
686 .to_i32()
687 .unwrap_or(0);
688 let hash_z = (cell.center[2] / grid_spacing)
689 .floor()
690 .to_i32()
691 .unwrap_or(0);
692
693 for dx in -1..=1 {
695 for dy in -1..=1 {
696 for dz in -1..=1 {
697 let hash_key = (hash_x + dx, hash_y + dy, hash_z + dz);
698
699 if let Some(potential_neighbors) = spatial_hash.get(&hash_key) {
700 for &neighbor_id in potential_neighbors {
701 if neighbor_id != *cellid {
702 if let Some(neighbor_cell) =
703 mesh_level.cells.get(&neighbor_id)
704 {
705 if self.are_cells_neighbors(cell, neighbor_cell)
707 {
708 neighbors.push(neighbor_id);
709 }
710 }
711 }
712 }
713 }
714 }
715 }
716 }
717 }
718 all_neighbor_relationships.push((*cellid, neighbors));
719 }
720 }
721 }
722
723 if let Some(mesh_level) = self.mesh_hierarchy.levels.get_mut(level) {
725 for (cellid, neighbors) in all_neighbor_relationships {
726 if let Some(cell) = mesh_level.cells.get_mut(&cellid) {
727 cell.neighbors = neighbors;
728 }
729 }
730 }
731
732 let cellids: Vec<CellId> = if let Some(mesh_level) = self.mesh_hierarchy.levels.get(level) {
734 mesh_level.cells.keys().cloned().collect()
735 } else {
736 Vec::new()
737 };
738
739 for cellid in cellids {
740 self.update_interlevel_neighbors(cellid, level)?;
741 }
742
743 Ok(())
744 }
745
746 fn are_cells_neighbors(&self, cell1: &AdaptiveCell<F>, cell2: &AdaptiveCell<F>) -> bool {
748 if cell1.center.len() != cell2.center.len() || cell1.center.len() < 3 {
749 return false;
750 }
751
752 let max_size = cell1.size.max(cell2.size);
753 let tolerance = max_size * F::from(1.1).expect("Failed to convert constant to float"); let mut distance_squared = F::zero();
757 for i in 0..cell1.center.len() {
758 let diff = cell1.center[i] - cell2.center[i];
759 distance_squared += diff * diff;
760 }
761
762 let distance = distance_squared.sqrt();
763
764 let expected_distance =
766 (cell1.size + cell2.size) / F::from(2.0).expect("Failed to convert constant to float");
767
768 distance <= tolerance
769 && distance
770 >= expected_distance * F::from(0.7).expect("Failed to convert constant to float")
771 }
772
773 fn update_interlevel_neighbors(&mut self, cellid: CellId, level: usize) -> IntegrateResult<()> {
775 let mut coarser_neighbors = Vec::new();
777 let mut finer_neighbors = Vec::new();
778
779 if level > 0 {
781 if let (Some(current_level), Some(coarser_level)) = (
782 self.mesh_hierarchy.levels.get(level),
783 self.mesh_hierarchy.levels.get(level - 1),
784 ) {
785 if let Some(current_cell) = current_level.cells.get(&cellid) {
786 for (coarser_cellid, coarser_cell) in &coarser_level.cells {
787 if self.are_cells_neighbors(current_cell, coarser_cell) {
788 coarser_neighbors.push(*coarser_cellid);
789 }
790 }
791 }
792 }
793 }
794
795 if level + 1 < self.mesh_hierarchy.levels.len() {
797 if let (Some(current_level), Some(finer_level)) = (
798 self.mesh_hierarchy.levels.get(level),
799 self.mesh_hierarchy.levels.get(level + 1),
800 ) {
801 if let Some(current_cell) = current_level.cells.get(&cellid) {
802 for (finer_cellid, finer_cell) in &finer_level.cells {
803 if self.are_cells_neighbors(current_cell, finer_cell) {
804 finer_neighbors.push(*finer_cellid);
805 }
806 }
807 }
808 }
809 }
810
811 if let Some(current_level) = self.mesh_hierarchy.levels.get_mut(level) {
813 if let Some(current_cell) = current_level.cells.get_mut(&cellid) {
814 for coarser_id in coarser_neighbors {
815 if !current_cell.neighbors.contains(&coarser_id) {
816 current_cell.neighbors.push(coarser_id);
817 }
818 }
819
820 for finer_id in finer_neighbors {
821 if !current_cell.neighbors.contains(&finer_id) {
822 current_cell.neighbors.push(finer_id);
823 }
824 }
825 }
826 }
827
828 Ok(())
829 }
830
831 fn update_ghost_cells(&mut self) -> IntegrateResult<()> {
833 self.mesh_hierarchy.ghost_cells.clear();
835
836 for level_idx in 0..self.mesh_hierarchy.levels.len() {
838 let mut ghost_cells_for_level = Vec::new();
839 let mut boundary_cells = HashSet::new();
840
841 let expected_neighbors = self.calculate_expected_neighbors();
843
844 if let Some(mesh_level) = self.mesh_hierarchy.levels.get(level_idx) {
845 for (cellid, cell) in &mesh_level.cells {
846 if cell.neighbors.len() < expected_neighbors
849 || mesh_level.boundary_cells.contains(cellid)
850 {
851 boundary_cells.insert(*cellid);
852 }
853 }
854
855 for boundary_cellid in &boundary_cells {
857 if let Some(boundary_cell) = mesh_level.cells.get(boundary_cellid) {
858 let ghost_cells =
860 self.create_ghost_cells_for_boundary(boundary_cell, level_idx)?;
861 ghost_cells_for_level.extend(ghost_cells);
862 }
863 }
864
865 self.create_interlevel_ghost_cells(level_idx, &mut ghost_cells_for_level)?;
867 }
868
869 self.mesh_hierarchy
870 .ghost_cells
871 .insert(level_idx, ghost_cells_for_level);
872 }
873
874 Ok(())
875 }
876
877 fn calculate_expected_neighbors(&self) -> usize {
879 6
883 }
884
885 fn create_ghost_cells_for_boundary(
887 &self,
888 boundary_cell: &AdaptiveCell<F>,
889 level: usize,
890 ) -> IntegrateResult<Vec<CellId>> {
891 let mut ghost_cells = Vec::new();
892
893 if boundary_cell.center.len() >= 3 {
894 let cell_size = boundary_cell.size;
895
896 let directions = [
898 [F::one(), F::zero(), F::zero()], [-F::one(), F::zero(), F::zero()], [F::zero(), F::one(), F::zero()], [F::zero(), -F::one(), F::zero()], [F::zero(), F::zero(), F::one()], [F::zero(), F::zero(), -F::one()], ];
905
906 for (dir_idx, direction) in directions.iter().enumerate() {
907 let mut ghost_center = boundary_cell.center.clone();
909 for i in 0..3 {
910 ghost_center[i] += direction[i] * cell_size;
911 }
912
913 if !self.cell_exists_at_position(&ghost_center, level) {
915 let ghost_id = CellId {
917 level,
918 index: 1_000_000 + boundary_cell.id.index * 10 + dir_idx,
919 };
920
921 ghost_cells.push(ghost_id);
922 }
923 }
924 }
925
926 Ok(ghost_cells)
927 }
928
929 fn create_interlevel_ghost_cells(
931 &self,
932 level: usize,
933 ghost_cells: &mut Vec<CellId>,
934 ) -> IntegrateResult<()> {
935 if level > 0 {
939 if let Some(current_level) = self.mesh_hierarchy.levels.get(level) {
940 for (cellid, cell) in ¤t_level.cells {
941 if cell.parent.is_none() {
944 let ghost_id = CellId {
945 level: level - 1,
946 index: 2_000_000 + cellid.index,
947 };
948 ghost_cells.push(ghost_id);
949 }
950 }
951 }
952 }
953
954 if level + 1 < self.mesh_hierarchy.levels.len() {
956 if let Some(current_level) = self.mesh_hierarchy.levels.get(level) {
957 for (cellid, cell) in ¤t_level.cells {
958 if !cell.children.is_empty() {
961 let ghost_id = CellId {
962 level: level + 1,
963 index: 3_000_000 + cellid.index,
964 };
965 ghost_cells.push(ghost_id);
966 }
967 }
968 }
969 }
970
971 Ok(())
972 }
973
974 fn cell_exists_at_position(&self, position: &Array1<F>, level: usize) -> bool {
976 if let Some(mesh_level) = self.mesh_hierarchy.levels.get(level) {
977 let tolerance = mesh_level.grid_spacing
978 * F::from(0.1).expect("Failed to convert constant to float");
979
980 for cell in mesh_level.cells.values() {
981 if position.len() == cell.center.len() {
982 let mut distance_squared = F::zero();
983 for i in 0..position.len() {
984 let diff = position[i] - cell.center[i];
985 distance_squared += diff * diff;
986 }
987
988 if distance_squared.sqrt() < tolerance {
989 return true;
990 }
991 }
992 }
993 }
994 false
995 }
996
997 fn count_active_cells(&self) -> usize {
999 self.mesh_hierarchy
1000 .levels
1001 .iter()
1002 .map(|level| level.cells.values().filter(|cell| cell.is_active).count())
1003 .sum()
1004 }
1005
1006 fn assess_load_balance(&self) -> F {
1008 let total_cells = self.count_active_cells();
1009 if total_cells == 0 {
1010 return F::one(); }
1012
1013 let cell_distribution_balance = self.calculate_cell_distribution_balance();
1015 let computational_load_balance = self.calculate_computational_load_balance();
1016 let communication_overhead_balance = self.calculate_communication_balance();
1017 let memory_distribution_balance = self.calculate_memory_balance();
1018
1019 let weight_cell = F::from(0.3).expect("Failed to convert constant to float");
1021 let weight_compute = F::from(0.4).expect("Failed to convert constant to float");
1022 let weight_comm = F::from(0.2).expect("Failed to convert constant to float");
1023 let weight_memory = F::from(0.1).expect("Failed to convert constant to float");
1024
1025 let overall_balance = weight_cell * cell_distribution_balance
1026 + weight_compute * computational_load_balance
1027 + weight_comm * communication_overhead_balance
1028 + weight_memory * memory_distribution_balance;
1029
1030 overall_balance.min(F::one()).max(F::zero())
1032 }
1033
1034 fn calculate_cell_distribution_balance(&self) -> F {
1036 if self.mesh_hierarchy.levels.is_empty() {
1037 return F::one();
1038 }
1039
1040 let mut cells_per_level: Vec<usize> = Vec::new();
1042 let mut total_cells = 0;
1043
1044 for level in &self.mesh_hierarchy.levels {
1045 let active_cells = level.cells.values().filter(|c| c.is_active).count();
1046 cells_per_level.push(active_cells);
1047 total_cells += active_cells;
1048 }
1049
1050 if total_cells == 0 {
1051 return F::one();
1052 }
1053
1054 let mean_cells = total_cells as f64 / cells_per_level.len() as f64;
1056 let variance: f64 = cells_per_level
1057 .iter()
1058 .map(|&count| {
1059 let diff = count as f64 - mean_cells;
1060 diff * diff
1061 })
1062 .sum::<f64>()
1063 / cells_per_level.len() as f64;
1064
1065 let std_dev = variance.sqrt();
1066 let coefficient_of_variation = if mean_cells > 0.0 {
1067 std_dev / mean_cells
1068 } else {
1069 0.0
1070 };
1071
1072 let balance = (1.0 - coefficient_of_variation.min(1.0)).max(0.0);
1074 F::from(balance).unwrap_or(F::zero())
1075 }
1076
1077 fn calculate_computational_load_balance(&self) -> F {
1079 let mut level_computational_loads: Vec<F> = Vec::new();
1080 let mut total_load = F::zero();
1081
1082 for level in &self.mesh_hierarchy.levels {
1083 let mut level_load = F::zero();
1084
1085 for cell in level.cells.values() {
1086 if cell.is_active {
1087 let cell_cost = cell.error_estimate * cell.size * cell.size; level_load += cell_cost;
1090 }
1091 }
1092
1093 level_computational_loads.push(level_load);
1094 total_load += level_load;
1095 }
1096
1097 if total_load <= F::zero() {
1098 return F::one();
1099 }
1100
1101 let mean_load =
1103 total_load / F::from(level_computational_loads.len()).expect("Operation failed");
1104 let mut variance = F::zero();
1105
1106 for &load in &level_computational_loads {
1107 let diff = load - mean_load;
1108 variance += diff * diff;
1109 }
1110
1111 variance /= F::from(level_computational_loads.len()).expect("Operation failed");
1112 let std_dev = variance.sqrt();
1113
1114 let coeff_var = if mean_load > F::zero() {
1115 std_dev / mean_load
1116 } else {
1117 F::zero()
1118 };
1119
1120 let balance = F::one() - coeff_var.min(F::one());
1122 balance.max(F::zero())
1123 }
1124
1125 fn calculate_communication_balance(&self) -> F {
1127 let mut level_comm_costs: Vec<F> = Vec::new();
1128 let mut total_comm_cost = F::zero();
1129
1130 for (level_idx, level) in self.mesh_hierarchy.levels.iter().enumerate() {
1131 let active_cells = level.cells.values().filter(|c| c.is_active).count();
1132 let ghost_cells = self
1133 .mesh_hierarchy
1134 .ghost_cells
1135 .get(&level_idx)
1136 .map(|ghosts| ghosts.len())
1137 .unwrap_or(0);
1138
1139 let comm_cost = if active_cells > 0 {
1141 F::from(ghost_cells as f64 / active_cells as f64).unwrap_or(F::zero())
1142 } else {
1143 F::zero()
1144 };
1145
1146 level_comm_costs.push(comm_cost);
1147 total_comm_cost += comm_cost;
1148 }
1149
1150 if level_comm_costs.is_empty() || total_comm_cost <= F::zero() {
1151 return F::one();
1152 }
1153
1154 let mean_comm =
1156 total_comm_cost / F::from(level_comm_costs.len()).expect("Operation failed");
1157 let mut variance = F::zero();
1158
1159 for &cost in &level_comm_costs {
1160 let diff = cost - mean_comm;
1161 variance += diff * diff;
1162 }
1163
1164 variance /= F::from(level_comm_costs.len()).expect("Operation failed");
1165 let std_dev = variance.sqrt();
1166
1167 let coeff_var = if mean_comm > F::zero() {
1168 std_dev / mean_comm
1169 } else {
1170 F::zero()
1171 };
1172
1173 let balance = F::one() - coeff_var.min(F::one());
1175 balance.max(F::zero())
1176 }
1177
1178 fn calculate_memory_balance(&self) -> F {
1180 let mut level_memory_usage: Vec<F> = Vec::new();
1181 let mut total_memory = F::zero();
1182
1183 for level in &self.mesh_hierarchy.levels {
1184 let cell_count = level.cells.len();
1186 let total_neighbors: usize = level.cells.values().map(|c| c.neighbors.len()).sum();
1187
1188 let solution_size: usize = level.cells.values().map(|c| c.solution.len()).sum();
1189
1190 let memory_estimate = F::from(cell_count + total_neighbors + solution_size)
1192 .expect("Failed to convert to float");
1193 level_memory_usage.push(memory_estimate);
1194 total_memory += memory_estimate;
1195 }
1196
1197 if level_memory_usage.is_empty() || total_memory <= F::zero() {
1198 return F::one();
1199 }
1200
1201 let mean_memory =
1203 total_memory / F::from(level_memory_usage.len()).expect("Operation failed");
1204 let mut variance = F::zero();
1205
1206 for &memory in &level_memory_usage {
1207 let diff = memory - mean_memory;
1208 variance += diff * diff;
1209 }
1210
1211 variance /= F::from(level_memory_usage.len()).expect("Operation failed");
1212 let std_dev = variance.sqrt();
1213
1214 let coeff_var = if mean_memory > F::zero() {
1215 std_dev / mean_memory
1216 } else {
1217 F::zero()
1218 };
1219
1220 let balance = F::one() - coeff_var.min(F::one());
1222 balance.max(F::zero())
1223 }
1224}
1225
1226impl<F: IntegrateFloat + Send + Sync> RefinementCriterion<F> for GradientRefinementCriterion<F> {
1228 fn evaluate(&self, cell: &AdaptiveCell<F>, neighbors: &[&AdaptiveCell<F>]) -> F {
1229 if neighbors.is_empty() {
1230 return F::zero();
1231 }
1232
1233 let mut max_gradient = F::zero();
1234
1235 for neighbor in neighbors {
1236 let gradient = if let Some(comp) = self.component {
1237 if comp < cell.solution.len() && comp < neighbor.solution.len() {
1238 (cell.solution[comp] - neighbor.solution[comp]).abs() / cell.size
1239 } else {
1240 F::zero()
1241 }
1242 } else {
1243 let diff = &cell.solution - &neighbor.solution;
1245 diff.mapv(|x| x.powi(2)).sum().sqrt() / cell.size
1246 };
1247
1248 max_gradient = max_gradient.max(gradient);
1249 }
1250
1251 let solution_magnitude = if let Some(comp) = self.component {
1253 cell.solution
1254 .get(comp)
1255 .map(|&x| x.abs())
1256 .unwrap_or(F::zero())
1257 } else {
1258 cell.solution.mapv(|x| x.abs()).sum()
1259 };
1260
1261 if solution_magnitude > F::zero() {
1262 max_gradient / solution_magnitude
1263 } else {
1264 max_gradient
1265 }
1266 }
1267
1268 fn name(&self) -> &'static str {
1269 "Gradient"
1270 }
1271}
1272
1273impl<F: IntegrateFloat + Send + Sync> RefinementCriterion<F> for FeatureDetectionCriterion<F> {
1274 fn evaluate(&self, cell: &AdaptiveCell<F>, neighbors: &[&AdaptiveCell<F>]) -> F {
1275 let mut feature_score = F::zero();
1276
1277 for &feature_type in &self.feature_types {
1278 match feature_type {
1279 FeatureType::SharpGradient => {
1280 if neighbors.len() >= 2 {
1282 let gradients: Vec<F> = neighbors
1283 .iter()
1284 .map(|n| (&cell.solution - &n.solution).mapv(|x| x.abs()).sum())
1285 .collect();
1286
1287 let max_grad = gradients.iter().fold(F::zero(), |acc, &x| acc.max(x));
1288 let avg_grad = gradients.iter().fold(F::zero(), |acc, &x| acc + x)
1289 / F::from(gradients.len()).expect("Operation failed");
1290
1291 if avg_grad > F::zero() {
1292 feature_score += max_grad / avg_grad;
1293 }
1294 }
1295 }
1296 FeatureType::LocalExtremum => {
1297 let cell_value = cell.solution.mapv(|x| x.abs()).sum();
1299 let mut is_extremum = true;
1300
1301 for neighbor in neighbors {
1302 let neighbor_value = neighbor.solution.mapv(|x| x.abs()).sum();
1303 if (neighbor_value - cell_value).abs() < self.threshold {
1304 is_extremum = false;
1305 break;
1306 }
1307 }
1308
1309 if is_extremum {
1310 feature_score += F::one();
1311 }
1312 }
1313 _ => {
1314 }
1316 }
1317 }
1318
1319 feature_score
1320 }
1321
1322 fn name(&self) -> &'static str {
1323 "FeatureDetection"
1324 }
1325}
1326
1327impl<F: IntegrateFloat + Send + Sync> RefinementCriterion<F> for CurvatureRefinementCriterion<F> {
1328 fn evaluate(&self, cell: &AdaptiveCell<F>, neighbors: &[&AdaptiveCell<F>]) -> F {
1329 if neighbors.len() < 2 {
1330 return F::zero();
1331 }
1332
1333 let mut curvature = F::zero();
1335
1336 for component in 0..cell.solution.len() {
1337 let center_value = cell.solution[component];
1338 let neighbor_values: Vec<F> = neighbors
1339 .iter()
1340 .filter_map(|n| n.solution.get(component).copied())
1341 .collect();
1342
1343 if neighbor_values.len() >= 2 {
1344 let avg_neighbor = neighbor_values.iter().fold(F::zero(), |acc, &x| acc + x)
1346 / F::from(neighbor_values.len()).expect("Operation failed");
1347
1348 let second_diff = (avg_neighbor - center_value).abs() / (cell.size * cell.size);
1349 curvature += second_diff;
1350 }
1351 }
1352
1353 curvature
1354 }
1355
1356 fn name(&self) -> &'static str {
1357 "Curvature"
1358 }
1359}
1360
1361#[cfg(test)]
1362mod tests {
1363 use super::*;
1364
1365 #[test]
1366 fn test_amr_manager_creation() {
1367 let initial_level = AdaptiveMeshLevel {
1368 level: 0,
1369 cells: HashMap::new(),
1370 grid_spacing: 1.0,
1371 boundary_cells: HashSet::new(),
1372 };
1373
1374 let amr = AdvancedAMRManager::new(initial_level, 5, 0.01);
1375 assert_eq!(amr.max_levels, 5);
1376 assert_eq!(amr.mesh_hierarchy.levels.len(), 1);
1377 }
1378
1379 #[test]
1380 fn test_gradient_criterion() {
1381 let cell = AdaptiveCell {
1382 id: CellId { level: 0, index: 0 },
1383 center: Array1::from_vec(vec![0.5, 0.5]),
1384 size: 0.1,
1385 solution: Array1::from_vec(vec![1.0]),
1386 error_estimate: 0.0,
1387 refinement_flag: RefinementFlag::None,
1388 is_active: true,
1389 neighbors: vec![],
1390 parent: None,
1391 children: vec![],
1392 };
1393
1394 let neighbor = AdaptiveCell {
1395 id: CellId { level: 0, index: 1 },
1396 center: Array1::from_vec(vec![0.6, 0.5]),
1397 size: 0.1,
1398 solution: Array1::from_vec(vec![2.0]),
1399 error_estimate: 0.0,
1400 refinement_flag: RefinementFlag::None,
1401 is_active: true,
1402 neighbors: vec![],
1403 parent: None,
1404 children: vec![],
1405 };
1406
1407 let criterion = GradientRefinementCriterion {
1408 component: Some(0),
1409 threshold: 1.0,
1410 relative_tolerance: 0.1,
1411 };
1412
1413 let neighbors = vec![&neighbor];
1414 let result = criterion.evaluate(&cell, &neighbors);
1415 assert!(result > 0.0);
1416 }
1417}