Physics Based Example

Physics Based Example#

This example demonstrates using the pipefunc for a physics-based simulation. The goal is to create a pipeline for geometry creation, meshing, material assignment, and electrostatics calculations, culminating in computing the average charge.

Note: this example is based on the aiida-dynamic-workflows tutorial.

We start with defining a few dataclasses to represent the geometry, mesh, and material properties. We then define functions to create the geometry, mesh it, assign materials, and calculate the electrostatics.

from dataclasses import dataclass


@dataclass(frozen=True)
class Geometry:
    x: float
    y: float


@dataclass(frozen=True)
class Mesh:
    geometry: Geometry
    mesh_size: float


@dataclass(frozen=True)
class Materials:
    geometry: Geometry
    materials: list[str]


@dataclass(frozen=True)
class Electrostatics:
    mesh: Mesh
    materials: Materials
    voltages: list[float]
import numpy as np

from pipefunc import Pipeline, pipefunc
from pipefunc.map import load_outputs


@pipefunc(output_name="geo")
def make_geometry(x: float, y: float) -> Geometry:
    """Create a geometry object with given dimensions.

    Args:
        x: Width of the geometry
        y: Height of the geometry

    Returns:
        The created geometry object
    """
    return Geometry(x, y)


@pipefunc(output_name=("mesh", "coarse_mesh"))
def make_mesh(
    geo: Geometry,
    mesh_size: float,
    coarse_mesh_size: float = 0.1,
) -> tuple[Mesh, Mesh]:
    """Create fine and coarse meshes for the given geometry.

    Args:
        geo: Geometry to mesh
        mesh_size: Cell size for the fine mesh
        coarse_mesh_size: Cell size for the coarse mesh

    Returns:
        A tuple containing:
            - The fine mesh
            - The coarse mesh
    """
    return Mesh(geo, mesh_size), Mesh(geo, coarse_mesh_size)


@pipefunc(output_name="materials")
def make_materials(geo: Geometry) -> Materials:
    """Create materials for the given geometry.

    Args:
        geo: Geometry to create materials for

    Returns:
        The created materials object
    """
    return Materials(geo, ["i", "j", "c"])


@pipefunc(output_name="electrostatics", mapspec="V_left[i], V_right[j] -> electrostatics[i, j]")
def run_electrostatics(
    mesh: Mesh,
    materials: Materials,
    V_left: float,
    V_right: float,
) -> Electrostatics:
    """Run electrostatics simulation with given boundary conditions.

    Args:
        mesh: Mesh to run simulation on
        materials: Material properties
        V_left: Left boundary voltage
        V_right: Right boundary voltage

    Returns:
        Results of electrostatics simulation
    """
    return Electrostatics(mesh, materials, [V_left, V_right])


@pipefunc(output_name="charge", mapspec="electrostatics[i, j] -> charge[i, j]")
def get_charge(electrostatics: Electrostatics) -> float:
    """Calculate charge from electrostatics results.

    Parameters
    ----------
    electrostatics
        Results from electrostatics simulation

    Returns
    -------
    float
        Calculated charge (sum of voltages)
    """
    # obviously not actually the charge; but we should return _some_ number that
    # is "derived" from the electrostatics.
    return sum(electrostatics.voltages)


# No mapspec: function receives the full 2D array of charges!
@pipefunc(output_name="average_charge")
def average_charge(charge: np.ndarray) -> float:
    """Calculate average charge across all simulations.

    :param charge: 2D array of charges from all simulations
    :return: Mean charge value
    """
    return np.mean(charge)


pipeline_charge = Pipeline(
    [make_geometry, make_mesh, make_materials, run_electrostatics, get_charge, average_charge],
)
pipeline_charge.visualize(orient="TB")
cluster_legend Legend x x  : float make_geometry(...) → geo make_geometry(...) geo  : Geometry x->make_geometry(...) → geo x y y  : float y->make_geometry(...) → geo y mesh_size mesh_size  : float make_mesh(...) → mesh, coarse_mesh make_mesh(...) mesh  : Mesh coarse_mesh  : Mesh mesh_size->make_mesh(...) → mesh, coarse_mesh mesh_size coarse_mesh_size coarse_mesh_size  : float  = 0.1 coarse_mesh_size->make_mesh(...) → mesh, coarse_mesh coarse_mesh_size=0.1 V_left V_left[i]  : float run_electrostatics(...) → electrostatics run_electrostatics(...) electrostatics[i, j]  : Electrostatics V_left->run_electrostatics(...) → electrostatics V_left[i] V_right V_right[j]  : float V_right->run_electrostatics(...) → electrostatics V_right[j] make_geometry(...) → geo->make_mesh(...) → mesh, coarse_mesh geo make_materials(...) → materials make_materials(...) materials  : Materials make_geometry(...) → geo->make_materials(...) → materials geo make_mesh(...) → mesh, coarse_mesh->run_electrostatics(...) → electrostatics mesh make_materials(...) → materials->run_electrostatics(...) → electrostatics materials get_charge(...) → charge get_charge(...) charge[i, j]  : float run_electrostatics(...) → electrostatics->get_charge(...) → charge electrostatics[i, j] average_charge(...) → average_charge average_charge(...) average_charge  : float get_charge(...) → charge->average_charge(...) → average_charge charge legend_0 Argument legend_1 PipeFunc

We can also display autogenerated documentation for the pipeline:

pipeline_charge.print_documentation()
                                                    Parameters                                                     
 Parameter                Required    Description                                                                  
 V_left                      ✅       Left boundary voltage (type: float)                                          
 V_right                     ✅       Right boundary voltage (type: float)                                         
 coarse_mesh_size            ❌       Cell size for the coarse mesh (default: 0.1) (type: float)                   
 mesh_size                   ✅       Cell size for the fine mesh (type: float)                                    
 x                           ✅       Width of the geometry (type: float)                                          
 y                           ✅       Height of the geometry (type: float)                                         


                                           Function Output Descriptions                                            
 Function Name          Output Name           Description                                                          
 make_geometry          geo                   Create a geometry object with given dimensions.                      
 make_materials         materials             Create materials for the given geometry.                             
 make_mesh              mesh, coarse_mesh     Create fine and coarse meshes for the given geometry.                
 run_electrostatics     electrostatics        Run electrostatics simulation with given boundary conditions.        
 get_charge             charge                Calculate charge from electrostatics results.                        
 average_charge         average_charge        Calculate average charge across all simulations.                     


                                                   Return Values                                                   
 Output Name                Description                                                                            
 geo                        The created geometry object (type: Geometry)                                           
 materials                  The created materials object (type: Materials)                                         
 mesh, coarse_mesh          A tuple containing:                                                                    
                            - The fine mesh                                                                        
                            - The coarse mesh (type mesh: Mesh) (type coarse_mesh: Mesh)                           
 electrostatics             Results of electrostatics simulation (type: Electrostatics)                            
 charge                     Calculated charge (sum of voltages) (type: float)                                      
 average_charge             Mean charge value (type: float)                                                        


Let’s run the map for some inputs:

inputs = {
    "V_left": np.linspace(0, 2, 3),
    "V_right": np.linspace(-0.5, 0.5, 2),
    "x": 0.1,
    "y": 0.2,
    "mesh_size": 0.01,
    "coarse_mesh_size": 0.05,
}

run_folder = "my_run_folder"
results = pipeline_charge.map(inputs, run_folder=run_folder, parallel=False)
assert results["average_charge"].output == 1.0
assert results["average_charge"].output_name == "average_charge"
assert load_outputs("average_charge", run_folder=run_folder) == 1.0

This example highlighted how to run a simulation that included a map-reduce operation. Often we want to sweep this over multiple parameters. You could add all the mapspecs required to map an additional parameter. Alternatively, you can use the pipeline.add_mapspec_axis method to add an axis to parameters of the pipeline.

See the example below, where we extend the mapspecs.

# Add a cross-product of x and y
pipeline_charge.add_mapspec_axis("x", axis="a")
pipeline_charge.add_mapspec_axis("y", axis="b")

# And also a cross-product of the zipped mesh_size and coarse_mesh_size
pipeline_charge.add_mapspec_axis("mesh_size", axis="c")
pipeline_charge.add_mapspec_axis("coarse_mesh_size", axis="c")

# Finally, the mapspecs become, which shows a 3D array for the `average_charge`:
pipeline_charge.mapspecs_as_strings
['x[a], y[b] -> geo[a, b]',
 'geo[a, b] -> materials[a, b]',
 'geo[a, b], mesh_size[c], coarse_mesh_size[c] -> mesh[a, b, c], coarse_mesh[a, b, c]',
 'V_left[i], V_right[j], materials[a, b], mesh[a, b, c] -> electrostatics[i, j, a, b, c]',
 'electrostatics[i, j, a, b, c] -> charge[i, j, a, b, c]',
 'charge[:, :, a, b, c] -> average_charge[a, b, c]']
pipeline_charge.visualize(orient="TB")
cluster_legend Legend x x[a]  : float make_geometry(...) → geo make_geometry(...) geo[a, b]  : Geometry x->make_geometry(...) → geo x[a] y y[b]  : float y->make_geometry(...) → geo y[b] mesh_size mesh_size[c]  : float make_mesh(...) → mesh, coarse_mesh make_mesh(...) mesh[a, b, c]  : Mesh coarse_mesh[a, b, c]  : Mesh mesh_size->make_mesh(...) → mesh, coarse_mesh mesh_size[c] coarse_mesh_size coarse_mesh_size[c]  : float  = 0.1 coarse_mesh_size->make_mesh(...) → mesh, coarse_mesh coarse_mesh_size[c] V_left V_left[i]  : float run_electrostatics(...) → electrostatics run_electrostatics(...) electrostatics[i, j, a, b, c]  : Electrostatics V_left->run_electrostatics(...) → electrostatics V_left[i] V_right V_right[j]  : float V_right->run_electrostatics(...) → electrostatics V_right[j] make_geometry(...) → geo->make_mesh(...) → mesh, coarse_mesh geo[a, b] make_materials(...) → materials make_materials(...) materials[a, b]  : Materials make_geometry(...) → geo->make_materials(...) → materials geo[a, b] make_mesh(...) → mesh, coarse_mesh->run_electrostatics(...) → electrostatics mesh[a, b, c] make_materials(...) → materials->run_electrostatics(...) → electrostatics materials[a, b] get_charge(...) → charge get_charge(...) charge[i, j, a, b, c]  : float run_electrostatics(...) → electrostatics->get_charge(...) → charge electrostatics[i, j, a, b, c] average_charge(...) → average_charge average_charge(...) average_charge[a, b, c]  : float get_charge(...) → charge->average_charge(...) → average_charge charge[:, :, a, b, c] legend_0 Argument legend_1 PipeFunc

Let’s run it on a 2x2x2 grid of inputs:

inputs = {
    "V_left": np.linspace(0, 2, 3),
    "V_right": np.linspace(-0.5, 0.5, 2),
    "x": np.linspace(0.1, 0.2, 2),
    "y": np.linspace(0.2, 0.3, 2),
    "mesh_size": [0.01, 0.02],
    "coarse_mesh_size": [0.05, 0.06],
}
results = pipeline_charge.map(inputs, run_folder=run_folder, parallel=False)
output = results["average_charge"].output
print(f"Output shape: {output.shape}")
print(f"Output:\n{output}")
Output shape: (2, 2, 2)
Output:
[[[np.float64(1.0) np.float64(1.0)]
  [np.float64(1.0) np.float64(1.0)]]

 [[np.float64(1.0) np.float64(1.0)]
  [np.float64(1.0) np.float64(1.0)]]]

We can represent the results as a pandas.DataFrame or xarray.Dataset:

results.to_dataframe()
x y geo materials mesh coarse_mesh V_left V_right electrostatics charge average_charge coarse_mesh_size mesh_size
0 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 0.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... -0.5 1.0 0.05 0.01
1 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 0.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.05 0.01
2 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 1.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.05 0.01
3 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 1.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.05 0.01
4 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 2.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.05 0.01
5 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 2.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 2.5 1.0 0.05 0.01
6 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 0.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... -0.5 1.0 0.06 0.02
7 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 0.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.06 0.02
8 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 1.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.06 0.02
9 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 1.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.06 0.02
10 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 2.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.06 0.02
11 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 2.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 2.5 1.0 0.06 0.02
12 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 0.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... -0.5 1.0 0.05 0.01
13 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 0.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.05 0.01
14 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 1.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.05 0.01
15 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 1.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.05 0.01
16 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 2.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.05 0.01
17 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 2.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 2.5 1.0 0.05 0.01
18 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 0.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... -0.5 1.0 0.06 0.02
19 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 0.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.06 0.02
20 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 1.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.06 0.02
21 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 1.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.06 0.02
22 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 2.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.06 0.02
23 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 2.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 2.5 1.0 0.06 0.02
24 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 0.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... -0.5 1.0 0.05 0.01
25 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 0.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.05 0.01
26 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 1.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.05 0.01
27 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 1.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.05 0.01
28 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 2.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.05 0.01
29 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 2.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 2.5 1.0 0.05 0.01
30 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 0.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... -0.5 1.0 0.06 0.02
31 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 0.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.06 0.02
32 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 1.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.06 0.02
33 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 1.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.06 0.02
34 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 2.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.06 0.02
35 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 2.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 2.5 1.0 0.06 0.02
36 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 0.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... -0.5 1.0 0.05 0.01
37 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 0.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.05 0.01
38 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 1.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.05 0.01
39 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 1.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.05 0.01
40 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 2.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.05 0.01
41 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 2.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 2.5 1.0 0.05 0.01
42 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 0.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... -0.5 1.0 0.06 0.02
43 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 0.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.06 0.02
44 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 1.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.06 0.02
45 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 1.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.06 0.02
46 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 2.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.06 0.02
47 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 2.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 2.5 1.0 0.06 0.02
results.to_xarray()
<xarray.Dataset> Size: 1kB
Dimensions:                     (a: 2, b: 2, c: 2, i: 3, j: 2)
Coordinates:
    x                           (a) float64 16B 0.1 0.2
    y                           (b) float64 16B 0.2 0.3
    coarse_mesh_size:mesh_size  (c) object 16B (0.05, 0.01) (0.06, 0.02)
    V_left                      (i) float64 24B 0.0 1.0 2.0
    V_right                     (j) float64 16B -0.5 0.5
Dimensions without coordinates: a, b, c, i, j
Data variables:
    geo                         (a, b) object 32B Geometry(x=np.float64(0.1),...
    materials                   (a, b) object 32B Materials(geometry=Geometry...
    mesh                        (a, b, c) object 64B Mesh(geometry=Geometry(x...
    coarse_mesh                 (a, b, c) object 64B Mesh(geometry=Geometry(x...
    electrostatics              (i, j, a, b, c) object 384B Electrostatics(me...
    charge                      (i, j, a, b, c) float64 384B -0.5 -0.5 ... 2.5
    average_charge              (a, b, c) float64 64B 1.0 1.0 1.0 ... 1.0 1.0

We can also load all data as xarray.Dataset using just the run_folder:

from pipefunc.map import load_xarray_dataset

ds = load_xarray_dataset(run_folder=run_folder)
ds
<xarray.Dataset> Size: 1kB
Dimensions:                     (a: 2, b: 2, c: 2, i: 3, j: 2)
Coordinates:
    x                           (a) float64 16B 0.1 0.2
    y                           (b) float64 16B 0.2 0.3
    coarse_mesh_size:mesh_size  (c) object 16B (0.05, 0.01) (0.06, 0.02)
    V_left                      (i) float64 24B 0.0 1.0 2.0
    V_right                     (j) float64 16B -0.5 0.5
Dimensions without coordinates: a, b, c, i, j
Data variables:
    geo                         (a, b) object 32B Geometry(x=np.float64(0.1),...
    materials                   (a, b) object 32B Materials(geometry=Geometry...
    mesh                        (a, b, c) object 64B Mesh(geometry=Geometry(x...
    coarse_mesh                 (a, b, c) object 64B Mesh(geometry=Geometry(x...
    electrostatics              (i, j, a, b, c) object 384B Electrostatics(me...
    charge                      (i, j, a, b, c) object 384B -0.5 -0.5 ... 2.5
    average_charge              (a, b, c) object 64B 1.0 1.0 1.0 ... 1.0 1.0 1.0

Or specify the output_name to load only specific outputs:

avg_charge = load_xarray_dataset("average_charge", run_folder=run_folder)
avg_charge
<xarray.Dataset> Size: 112B
Dimensions:                     (a: 2, b: 2, c: 2)
Coordinates:
    x                           (a) float64 16B 0.1 0.2
    y                           (b) float64 16B 0.2 0.3
    coarse_mesh_size:mesh_size  (c) object 16B (0.05, 0.01) (0.06, 0.02)
Dimensions without coordinates: a, b, c
Data variables:
    average_charge              (a, b, c) object 64B 1.0 1.0 1.0 ... 1.0 1.0 1.0

Or as pandas.DataFrame:

from pipefunc.map import load_dataframe

load_dataframe(run_folder=run_folder)
x y geo materials mesh coarse_mesh V_left V_right electrostatics charge average_charge coarse_mesh_size mesh_size
0 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 0.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... -0.5 1.0 0.05 0.01
1 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 0.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.05 0.01
2 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 1.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.05 0.01
3 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 1.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.05 0.01
4 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 2.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.05 0.01
5 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 2.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 2.5 1.0 0.05 0.01
6 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 0.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... -0.5 1.0 0.06 0.02
7 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 0.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.06 0.02
8 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 1.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.06 0.02
9 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 1.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.06 0.02
10 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 2.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.06 0.02
11 0.1 0.2 Geometry(x=np.float64(0.1), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 2.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 2.5 1.0 0.06 0.02
12 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 0.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... -0.5 1.0 0.05 0.01
13 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 0.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.05 0.01
14 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 1.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.05 0.01
15 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 1.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.05 0.01
16 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 2.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.05 0.01
17 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 2.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 2.5 1.0 0.05 0.01
18 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 0.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... -0.5 1.0 0.06 0.02
19 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 0.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.06 0.02
20 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 1.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.06 0.02
21 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 1.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.06 0.02
22 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 2.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.06 0.02
23 0.1 0.3 Geometry(x=np.float64(0.1), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.1),... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... Mesh(geometry=Geometry(x=np.float64(0.1), y=np... 2.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 2.5 1.0 0.06 0.02
24 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 0.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... -0.5 1.0 0.05 0.01
25 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 0.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.05 0.01
26 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 1.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.05 0.01
27 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 1.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.05 0.01
28 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 2.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.05 0.01
29 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 2.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 2.5 1.0 0.05 0.01
30 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 0.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... -0.5 1.0 0.06 0.02
31 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 0.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.06 0.02
32 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 1.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.06 0.02
33 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 1.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.06 0.02
34 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 2.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.06 0.02
35 0.2 0.2 Geometry(x=np.float64(0.2), y=np.float64(0.2)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 2.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 2.5 1.0 0.06 0.02
36 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 0.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... -0.5 1.0 0.05 0.01
37 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 0.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.05 0.01
38 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 1.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.05 0.01
39 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 1.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.05 0.01
40 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 2.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.05 0.01
41 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 2.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 2.5 1.0 0.05 0.01
42 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 0.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... -0.5 1.0 0.06 0.02
43 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 0.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.06 0.02
44 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 1.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 0.5 1.0 0.06 0.02
45 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 1.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.06 0.02
46 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 2.0 -0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 1.5 1.0 0.06 0.02
47 0.2 0.3 Geometry(x=np.float64(0.2), y=np.float64(0.3)) Materials(geometry=Geometry(x=np.float64(0.2),... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... Mesh(geometry=Geometry(x=np.float64(0.2), y=np... 2.0 0.5 Electrostatics(mesh=Mesh(geometry=Geometry(x=n... 2.5 1.0 0.06 0.02

Now imagine that the electrostatics object is a very large object that we cannot afford to save and load from disk. For this purpose there is the pipfunc.NestedPipeFunc class that allows to combine multiple functions into a single function. We can then tell it to not return the output of the intermediate functions by specifying which outputs to return.

pipeline_charge2 = pipeline_charge.copy()
nested_func = pipeline_charge2.nest_funcs(
    {"electrostatics", "charge"},
    new_output_name="charge",
    # We can also specify `("charge", "electrostatics")` to get both outputs
)

This nested_func contains an internal pipeline:

nested_func.pipeline.visualize()
cluster_legend Legend mesh mesh  : Mesh run_electrostatics(...) → electrostatics run_electrostatics(...) electrostatics  : Electrostatics mesh->run_electrostatics(...) → electrostatics mesh materials materials  : Materials materials->run_electrostatics(...) → electrostatics materials V_left V_left  : float V_left->run_electrostatics(...) → electrostatics V_left V_right V_right  : float V_right->run_electrostatics(...) → electrostatics V_right get_charge(...) → charge get_charge(...) charge  : float run_electrostatics(...) → electrostatics->get_charge(...) → charge electrostatics legend_0 Argument legend_1 PipeFunc

When visualizing the pipeline, you can see that the NestedFunc is shown as a single node.

pipeline_charge2.visualize(orient="TB")
cluster_legend Legend x x[a]  : float make_geometry(...) → geo make_geometry(...) geo[a, b]  : Geometry x->make_geometry(...) → geo x[a] y y[b]  : float y->make_geometry(...) → geo y[b] mesh_size mesh_size[c]  : float make_mesh(...) → mesh, coarse_mesh make_mesh(...) mesh[a, b, c]  : Mesh coarse_mesh[a, b, c]  : Mesh mesh_size->make_mesh(...) → mesh, coarse_mesh mesh_size[c] coarse_mesh_size coarse_mesh_size[c]  : float  = 0.1 coarse_mesh_size->make_mesh(...) → mesh, coarse_mesh coarse_mesh_size[c] V_left V_left[i]  : float NestedPipeFunc_charge(...) → charge NestedPipeFunc_charge(...) charge[i, j, a, b, c]  : float V_left->NestedPipeFunc_charge(...) → charge V_left[i] V_right V_right[j]  : float V_right->NestedPipeFunc_charge(...) → charge V_right[j] make_geometry(...) → geo->make_mesh(...) → mesh, coarse_mesh geo[a, b] make_materials(...) → materials make_materials(...) materials[a, b]  : Materials make_geometry(...) → geo->make_materials(...) → materials geo[a, b] make_mesh(...) → mesh, coarse_mesh->NestedPipeFunc_charge(...) → charge mesh[a, b, c] make_materials(...) → materials->NestedPipeFunc_charge(...) → charge materials[a, b] average_charge(...) → average_charge average_charge(...) average_charge[a, b, c]  : float NestedPipeFunc_charge(...) → charge->average_charge(...) → average_charge charge[:, :, a, b, c] legend_0 Argument legend_1 PipeFunc legend_2 NestedPipeFunc