Peano
Loading...
Searching...
No Matches
RegularGridGenerator.py
Go to the documentation of this file.
1# This file is part of the ExaHyPE2 project. For conditions of distribution and
2# use, please see the copyright notice at www.peano-framework.org
3import numpy as np
4from ..Tree import Tree
5
6"""
7Regular Grid Generator for Peano Load Balancing API
8
9This module provides functionality to create artificial regular grids for testing and benchmarking
10the offline load balancing API. It serves as one of the primary input generators for controlled
11experiments and algorithm development.
12
13## Purpose and Context
14
15The RegularGridGenerator is designed for testing and development scenarios where controlled,
16predictable mesh structures are needed. Instead of reading complex adaptive meshes from files,
17this module enables:
18
191. **Algorithm Testing**: Create predictable test cases for splitting strategy development
202. **Performance Benchmarking**: Generate grids of known complexity for performance analysis
213. **Controlled Experiments**: Ensure reproducible test conditions across different scenarios
224. **Development Support**: Provide simple test cases during API development and debugging
23
24## Integration with Load Balancing API
25
26This module integrates with other components of the load balancing API:
27
28- **Tree Class**: Generates Tree objects with uniform structure (see Tree.py)
29- **OfflineDecomposition**: Used by the main script for artificial grid generation
30- **SplitTrees**: Provides uniform tree data for splitting strategy testing
31- **TreeVisualizer**: Enables visualization of generated regular structures
32
33## Workflow Integration
34
35This module fits into the standard load balancing workflow:
36
371. **Development Phase**: Create controlled test cases for algorithm development
382. **Grid Generation**: Generate uniform grids with specified refinement levels
393. **Baseline Establishment**: Provide known starting conditions for experiments
404. **Strategy Testing**: Apply splitting strategies to predictable structures
415. **Performance Analysis**: Measure algorithm performance on uniform loads
426. **Comparison Studies**: Compare different strategies on identical input structures
43
44## Usage Examples
45
46```python
47# Generate a 2D regular grid with 4 refinement levels
48tree_2d = RegularGridGenerator(
49 name="Test2D_Uniform",
50 max_level=4,
51 dimensions=2
52)
53
54# Generate a 3D regular grid for performance testing
55tree_3d = RegularGridGenerator(
56 name="Benchmark3D",
57 max_level=3,
58 dimensions=3
59)
60```
61
62## Advantages for Testing
63
64- **Reproducibility**: Same parameters always generate identical trees
65- **Scalability**: Easy to create grids of different complexities
66- **Predictability**: Known cell counts and distribution patterns
67- **Simplicity**: No file dependencies or complex input processing
68- **Speed**: Fast generation for rapid testing cycles
69
70## Comparison with GridPatchFileReader
71
72| Aspect | RegularGridGenerator | GridPatchFileReader |
73|--------|---------------------|-------------------|
74| **Data Source** | Artificially generated | Real simulation checkpoints |
75| **Structure** | Uniform regular grids | Adaptive mesh refinement |
76| **Predictability** | Completely predictable | Depends on simulation |
77| **Complexity** | Simple uniform patterns | Complex adaptive patterns |
78| **Use Case** | Testing and benchmarking | Real-world optimization |
79
80## Integration with Main Script
81
82The `src/toolbox/loadbalancing/api/OfflineDecomposition.py` script uses this generator when:
83
84```bash
85# Generate 2D regular grid with 4 levels
86python3 OfflineDecomposition.py -d 2 -l 4
87
88# Generate 3D regular grid with visualization
89python3 OfflineDecomposition.py -d 3 -l 3 -p
90
91# Generate and split regular grid
92python3 OfflineDecomposition.py -d 3 -l 3 -p -s 4
93```
94
95See the load balancing API documentation for complete workflow integration details.
96"""
97
98def RegularGridGenerator(name=None, max_level=None, dimensions=None):
99 """
100 Generate an artificial regular grid with uniform refinement for testing purposes.
101
102 This function creates a complete regular grid structure where all regions are
103 refined uniformly to the specified maximum level. All cells are initially
104 assigned to subtree 0, providing a clean starting point for load balancing
105 experiments and algorithm testing.
106
107 ## Grid Structure
108
109 The generated grid follows Peano's hierarchical structure:
110 - Level 0: 3^1 cells per dimension (3x3 for 2D, 3x3x3 for 3D)
111 - Level k: 3^(k+1) cells per dimension
112 - All cells have weight=1 (exist) and subtree_id=0 (single resource)
113
114 ## Use Cases
115
116 - **Algorithm Development**: Test splitting strategies on predictable structures
117 - **Performance Benchmarking**: Measure algorithm performance with known complexity
118 - **Regression Testing**: Ensure consistent behavior across code changes
119 - **Educational Examples**: Demonstrate API functionality with simple cases
120
121 Args:
122 name (str, optional): Descriptive name for the generated tree (e.g., "TestGrid_L4").
123 If not provided, a deterministic default name is generated from dimensions and level.
124 max_level (int): Maximum refinement level (must be > 0)
125 dimensions (int): Spatial dimensions (2 for 2D, 3 for 3D)
126
127 Returns:
128 Tree: Tree object with complete regular grid structure
129
130 Example:
131 ```python
132 # Create a 2D regular grid for testing
133 test_tree = RegularGridGenerator(
134 name="Uniform_Test_2D",
135 max_level=4,
136 dimensions=2
137 )
138
139 print(f"Generated tree: {test_tree._name}")
140 print(f"Total cells: {test_tree._leaf_count}")
141 print(f"Levels: {test_tree._max_level}")
142
143 # Apply splitting for load balancing test
144 from strategies.SplitTrees import split_tree
145 split_tree(test_tree, number_of_subtrees=3)
146 ```
147
148 Note:
149 - Domain offset and size are set to placeholder values (origin and unit size)
150 - For large max_level values, memory usage grows as 3^(dimensions * max_level)
151 - Generated trees are deterministic - same parameters always produce identical results
152 """
153 if max_level is None:
154 raise ValueError("max_level must be provided")
155
156 if dimensions is None:
157 raise ValueError("dimensions must be provided")
158
159 if max_level <= 0:
160 raise ValueError(f"max_level must be > 0, got {max_level}")
161
162 if dimensions not in [2, 3]:
163 raise ValueError(f"dimensions must be 2 or 3, got {dimensions}")
164
165 if name is None:
166 name = f"regular-grid-{dimensions}d-l{max_level}"
167
168 print(f"Generating {dimensions}D regular grid '{name}' with {max_level} levels")
169
170 # Calculate the tree matrices
171 artificial_arrays = []
172 total_cells = 0
173
174 for level in range(max_level):
175 size = 3**(level+1)
176 level_cells = size ** dimensions
177 total_cells += level_cells
178
179 print(f" Level {level+1}: {size}^{dimensions} = {level_cells:,} cells")
180
181 if dimensions == 3:
182 array = np.empty((size, size, size), dtype=object)
183 for a in range(size):
184 for b in range(size):
185 for c in range(size):
186 array[a][b][c] = (1, 0) # weight=1, subtree_id=0
187 elif dimensions == 2:
188 array = np.empty((size, size), dtype=object)
189 for a in range(size):
190 for b in range(size):
191 array[a][b] = (1, 0) # weight=1, subtree_id=0
192
193 artificial_arrays.append(array)
194
195 print(f"Total cells generated: {total_cells:,}")
196
197 # Create the Tree class and assign properly
198 # Domain offset and size are placeholder values for artificial grids
199 if dimensions == 3:
200 offset = [0, 0, 0]
201 size = [1, 1, 1]
202 elif dimensions == 2:
203 offset = [0, 0]
204 size = [1, 1]
205
206 # Create and populate the tree
207 peano_tree = Tree(name, dimensions, offset, size)
208 peano_tree.read_in_tree_from_artificial(
209 input_artificial_arrays=artificial_arrays,
210 max_level=max_level,
211 weighted=False
212 )
213
214 print(f"Regular grid generation completed successfully")
215 print(f" Tree: {peano_tree._name}")
216 print(f" Leaf count: {peano_tree._leaf_count}")
217 print(f" Subtree count: {peano_tree._subtree_count}")
218
219 return peano_tree