Multiblock Arrays

A WolfArray object stores data in a matrix format, leveraging Numpy arrays for efficient numerical operations.

A WolfArrayMB object organizes data as a dictionary of WolfArray objects, effectively creating a tiled structure of multiple WolfArray instances. This structure allows for seamless handling of datasets that are too large to fit into a single array, enabling efficient data manipulation and analysis.

Each block can be parameterized independently, offering flexibility in data representation.

The WOLF CPU code is designed to work with multiblock models. The WolfArrayMB class ensures compatibility with the Fortran-based WOLF code, maintaining consistency and interoperability between the two implementations.

[1]:
import _add_path # add parent directory to path - debug mode only
from wolfhece.wolf_array import WolfArray, WolfArrayMB, header_wolf
import numpy as np

Creating a Multiblock Array from scratch

You need multiple WolfArray objects to create a WolfArrayMB object.

[2]:
h1 = header_wolf()
h1.shape = (10,10)       # 10x10 pixels
h1.set_resolution(1.,1.) # 1x1 meters per pixel
h1.set_origin(-1.,-1.)     # origin at (-1.,-1.) meters

h2 = header_wolf()
h2.shape = (5,5)           # 5x5 pixels
h2.set_resolution(0.5,0.5) # 0.5x0.5 meters per pixel
h2.set_origin(15.,15.)     # origin at (15,15) meters

block1 = WolfArray(srcheader=h1)
block2 = WolfArray(srcheader=h2)

block1.array[:,:] = np.arange(100).reshape((10,10)) # Populate with 0-99
block2.array[:,:] = np.arange(25).reshape((5,5))    # Populate with 0-24

# Print the blocks
block1.plot_matplotlib(with_legend=True)
block2.plot_matplotlib(with_legend=True)
D:\ProgrammationGitLab\HECEPython\docs\source\tutorials\../../..\wolfhece\wolf_array.py:10215: UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect.
  fig.tight_layout()
D:\ProgrammationGitLab\HECEPython\docs\source\tutorials\../../..\wolfhece\wolf_array.py:10215: UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect.
  fig.tight_layout()
[2]:
(<Figure size 640x480 with 2 Axes>, <Axes: >)
../_images/tutorials_wolfaarray_multiblocks_3_2.png
../_images/tutorials_wolfaarray_multiblocks_3_3.png
[16]:
mb = WolfArrayMB() # a void WolfArrayMB()
mb.add_block(block1, force_idx=True) # add the first block - by reference
mb.add_block(block2, force_idx=True) # add the second block - by reference
mb.set_header_from_added_blocks() # construct the header from the added blocks
mb.plot_matplotlib()

print(mb)

# In the mb header :
#  - The shape os the mb is (1,1)
#  - The origin is the lower-left corner of the added blocks
#  - The resolution is the footprint of the added blocks
Shape  : 1 x 1
Resolution  : 18.5 x 18.5
Spatial extent :
   - Origin : (-1.0 ; -1.0)
   - End : (17.5 ; 17.5)
   - Width x Height : 18.5 x 18.5
   - Translation : (0.0 ; 0.0)
Null value : 0

Number of blocks : 2

Block block1 :

Shape  : 10 x 10
Resolution  : 1.0 x 1.0
Spatial extent :
   - Origin : (-1.0 ; -1.0)
   - End : (9.0 ; 9.0)
   - Width x Height : 10.0 x 10.0
   - Translation : (0.0 ; 0.0)
Null value : 0.0

Block block2 :

Shape  : 5 x 5
Resolution  : 0.5 x 0.5
Spatial extent :
   - Origin : (15.0 ; 15.0)
   - End : (17.5 ; 17.5)
   - Width x Height : 2.5 x 2.5
   - Translation : (0.0 ; 0.0)
Null value : 0.0


../_images/tutorials_wolfaarray_multiblocks_4_1.png

By Reference or By Value?

When adding a block to a WolfArrayMB object, you can choose to add it either by reference or by value.

  • By Reference: By default, the add_block method does not create a copy of the WolfArray object. This means that any modifications to the WolfArrayMB object will directly affect the original WolfArray object, and vice versa.

  • By Value: If you want to create a copy of the WolfArray object while adding it, you can set the copy parameter to True. This ensures that the original WolfArray object remains unchanged, even if the WolfArrayMB object is modified.

Key Considerations:

  • Adding by reference is memory-efficient but links the objects, so changes in one will reflect in the other.

  • Adding by value ensures independence between the objects but requires additional memory for the copy.

[17]:
block2.array[:,:] = 5.
mb.plot_matplotlib() # plot the mb again
[17]:
(<Figure size 640x480 with 1 Axes>, <Axes: >)
../_images/tutorials_wolfaarray_multiblocks_6_1.png

Accessing the Blocks

Blocks within a WolfArrayMB object are stored in the myblocks dictionary and can be accessed using their keys.

Key Format

The keys follow the format blockn, where n is the block number (1-based index). For example:

  • The first block has the key block1.

  • The second block has the key block2.

Access Methods

You can access blocks in two ways:

  1. Using Keys: Access blocks directly using their string keys, e.g., mb.myblocks['block1'].

  2. Using Indexing: The __getitem__ method allows you to use Python’s 0-based indexing convention, e.g., mb[0] for the first block.

This flexibility makes it easy to retrieve and manipulate individual blocks within the multiblock array.

[ ]:
# keys
print(mb.myblocks.keys()) # get the keys of the blocks

ref1 = mb[0] # get the first block
ref2 = mb['block1']

print(ref1.is_like(block1)) # check
print(ref1.is_like(ref2)) # check
dict_keys(['block1', 'block2'])
True
True

Convert to WolfArray “single” block

The WolfArrayMB object can be converted to a single WolfArray object using the as_WolfArray method. This method concatenates all blocks and rebin if necessary.

[ ]:
single = mb.as_WolfArray() # convert to a single WolfArray

print(single)

single.plot_matplotlib() # plot the single WolfArray
Shape  : 37 x 37
Resolution  : 0.5 x 0.5
Spatial extent :
   - Origin : (-1.0 ; -1.0)
   - End : (17.5 ; 17.5)
   - Width x Height : 18.5 x 18.5
   - Translation : (0.0 ; 0.0)
Null value : 0.0


(<Figure size 640x480 with 1 Axes>, <Axes: >)
../_images/tutorials_wolfaarray_multiblocks_10_2.png

And More…

WolfArrayMB philosophy plays a crucial role in the WOLF code, especially within the Wolfresults_2D class, where the same idea is used to store and manage the results of 2D simulations. The ability to handle large datasets efficiently makes it indispensable for complex numerical workflows.

To gain a deeper understanding of how WolfArrayMB is utilized in the WOLF codebase, explore the source code and documentation. This will provide valuable insights into its integration and application in real-world scenarios.