pyCFS

A companion library for openCFS

Part 2: Data manipulation

Focus

  • Test case generation
    • Create .cfs files from scratch
  • Pre-Processing
    • Mesh preparation
    • Data processing
  • Post-Processing
    • Compare to analytic computations
    • Plot time series (faster than ParaView)
  • Small to medium size problems!
    • Many parts are parallelized
    • Some Python operations are still slow for large problems

Getting started

Installation

  • Install in pip environment
pip install pyCFS
#### Update from current main branch ```pip pip install git+https://gitlab.com/openCFS/pycfs@main --upgrade --force-reinstall ```

Additional dependencies

  • Large dependencies excluded from standard install
  • Install dependencies for all functionality
pip install pyCFS[data]

Documentation

Functionality

Overview

Structured into submodules

from pyCFS.data import io, operators, util, extras
  • io
    • I/O operations for CFS type HDF5 format
  • operators
    • Basic mesh/data operations
  • util
    • Various useful functions when working with pyCFS
  • extras
    • I/O compatibilty methods to other file formats
    • Additional functionality not directly related to openCFS

I/O (CFSReader)

from pyCFS.data.io import CFSReader
  • Reading CFS-type HDF5 files
    • Mesh
    • Data (on Nodes/Elements, History data)
    <surfRegionResult type="acouPower">
      <surfRegionList>
        <surfRegion name="S_body" outputIds="hdf5" writeAsHistResult="yes"/>
      </surfRegionList>
    </surfRegionResult>
    

I/O (CFSReader)

Usage

with CFSReader(filename="file.cfs") as reader:
    # Print file information
    print(reader)

    # Read the whole mesh
    mesh = reader.MeshData

    # Read coordinates, connectivity
    coordinates = reader.Coordinates
    connectivity = reader.Connectivity

    # Read node coordinates of a specific region
    reg_1 = reader.get_mesh_region_coordinates(region="S_CAPACITOR")

    # Read all result data for sequence step 2
    reader.set_multi_step(multi_step_id=2)
    results_2 = reader.MultiStepData

    # Read data for a specific quantity and region
    result_1 = reader.get_multi_step_data(multi_step_id=1, 
                                          quantities=["elecPotential"], 
                                          regions=["S_CAPACITOR"])
  

I/O (CFSWriter)

from pyCFS.data.io import CFSWriter
  • Creating new CFS-type HDF5 files
  • Writing to existing CFS-type HDF5 files

Usage

with CFSWriter(filename="file.cfs") as writer:
  # Create new file
  writer.create_file(mesh=mesh, result=result_1)

  # Write additional squence step
  writer.write_multistep(result=results_2, multi_step_id=2)

I/O (CFSMeshData)

from pyCFS.data.io import CFSMeshData
  • Container object for all mesh related data
  • Various mesh operations

I/O (CFSMeshData)

Usage examples

# Create mesh object of point cloud
mesh_points = CFSMeshData.from_coordinates_connectivity(
    coordinates=coordinates,
    region_name="P_measurement"
)

# Create mesh object from coordinates and connectivity
mesh = CFSMeshData.from_coordinates_connectivity(
    coordinates=coordinates, 
    connectivity=connectivity, 
    element_dimension=2,
    region_name="S_plate"
)

# Merge mesh objects
mesh = mesh + mesh_points

# Print information
print(mesh)

# Compute element normals for a region
mesh.get_region_centroids(region="S_plate")

# Get closest node/element to a coordinate
mesh.get_closest_node(coordinate=[0.1, 0.2, 0.3], region="S_plate")
mesh.get_closest_element(coordinate=[0.1, 0.2, 0.3], region="S_plate")

# Split mesh into regions by element clusters
mesh.split_regions_by_connectivity()

I/O (CFSRegData)

from pyCFS.data.io import CFSRegData
  • Container object for all region related data

I/O (CFSResultArray)

from pyCFS.data.io import CFSResultArray
  • Custom numpy array type
    (compatible with all operations numpy.ndarray is compatible!)
  • Including all meta data for write operations

I/O (CFSResultArray)

Usage examples

# Create a result array object
np_array = np.ones((5, 10, 3))
cfs_array = CFSResultArray(np_array)

# Set meta data for the result array
cfs_array.set_meta_data(
    quantity="elecPotential",
    region="S_CAPACITOR",
    step_values=np.array([0, 1, 2, 3]),
    # dim_names=["-"],
    res_type=cfs_result_type.NODE,
    # is_complex=False,
    # multi_step_id=1,
    analysis_type=cfs_analysis_type.TRANSIENT,
)

I/O (CFSResultContainer)

from pyCFS.data.io import CFSResultContainer
  • Container object for data of a single multistep / sequence step

I/O (CFSResultContainer)

Usage examples

# Create a result container object
result = CFSResultContainer(analysis_type=cfs_analysis_type.TRANSIENT, 
                       multi_step_id=2, data=[array_1, array_2])

# Print information
print(result)

# Extract certain time steps
result_1 = result[0:5]

# Extract certain region and quantity
result_2 = result.extract_quantity_region(quantity="elecPotential", region="S_CAPACITOR")

# Add data to result object (define different multi step ID)
result.add_data_array(data=cfs_array, multi_step_id=2)

I/O (Other)

from pyCFS.data.io import cfs_types, cfs_util
  • cfs_types
    • Enum definitions based on openCFS source code
  • cfs_util
    • Functions to check object validity

Operators

from pyCFS.data.operators import (transformation, interpolators,
                                  projection_interpolation, sngr)
  • interpolators
    • Basic interpolators
      • Node2Cell
      • Cell2Node
      • Nearest Neighbor (bidirectional)
  • projection_interpolation
    • Projection-based interpolation

Operators

from pyCFS.data.operators import (transformation, interpolators,
                                  projection_interpolation, sngr)
  • transformation
    • Translate / rotate / extrude / revolve mesh
    • Fit mesh onto target mesh
  • sngr
    • Compute fluctuating flow field from stationary RANS solution

Extra functionality

  • Read mesh and data from various formats
    • ansys_io (Ansys Mechanical: .rst)
    • ensight_io (various CFD software: .case)
    • psv_io (Polytec PSV export: .unv)
    • nihu_io (NiHu simulation export: .mat)
    • Planned: exodus_io (Cubit mesh export)

Example workflow

I/O

Tasks

  1. Read mesh and result data
  2. View connectivity array and node coordinates of a specific region
  3. Multiply result with factor
  4. Add result to existing file as a new sequence step (multi step)

Code

# Import necessary modules
from pyCFS.data import io

# Read file
with io.CFSReader(filename="file.cfs") as f:
  # Read mesh data
  mesh = f.MeshData
  # Read results of sequence step 1
  results = f.get_multi_step_data(multi_step_id=1)

# View connectivity array, get coordinates of V_air
conn = print(mesh.Connectivity)
reg_coord = mesh.get_region_coordinates(region="V_air")

# Get data array of elecPotential in region V_air
elec_pot = results.get_data_array(quantity="elecPotential", region="V_air")

# Manipulate result
igte_factor = 1e0
elec_pot *= igte_factor

# Write "corrected" result to new sequence step
result_write = io.CFSResultContainer(data=[elec_pot], multi_step_id=2,
                                     analysis_type=elec_pot.AnalysisType)
with io.CFSWriter("file.cfs") as f:
  f.write_multistep(result=result_write)

Debugging in PyCharm (1)

Debugging in PyCharm (2)

Example workflow

Operators

Tasks

  1. Read mesh and result data
  2. Perform Node-to-Cell interpolation
  3. Add interpolated data to existing results
  4. Write mesh and results to a new file

Code

# Import necessary modules
from pyCFS.data import io
from pyCFS.data.operators import interpolators

# Read source file
with io.CFSReader(filename="file.cfs") as h5r:
  print(h5r)
  mesh = h5r.MeshData
  results = h5r.MultiStepData

# Perform interpolation
results_interpolated = interpolators.interpolate_node_to_cell(
  mesh=mesh, 
  result=results, 
  regions=["V_air"],
  quantity_names={"elecPotential": "interpolated_elecPotential"},
)

# Add interpolated result to results container
results.combine_with(results_interpolated)

# Check results container
print(results)

# Write output file
with io.CFSWriter("file_out.cfs") as h5w:
  # Write mesh and results to new file
  h5w.create_file(mesh=mesh, result=results)

Interactive mode in VS Code (1)

Interactive mode in VS Code (2)

Interactive mode in VS Code (3)