Reference

OpenFOAM case directory manipulation

This module allows the building and manipulating OpenFOAM case directories.

OpenFOAM files are mapped into Python objects using the following conventions:

  • Dictionaries map to python dict.
  • Keyword data entries map to tuple when the number of data entries is greater than one. Otherwise the single data entry is the keyword’s value.
  • Lists are mapped to Python list.
  • Dimension are represented via the Dimension type.
class firefish.case.Case(root_dir_path, create=True)

Object representing an OpenFOAM case on disk.

root_dir_path

path to case directory

add_tri_surface(name, geom, clobber_existing=False)

Add a triangulated surface to the case.

Adds the geometry specified in geom to the case under the constant/triSurface directory. The geometry is saved in STL format.

The geometry is added with the given name. If name is foo, for example, it will be saved with the filename foo.stl.

Note

Do not add the .stl extension to name. Future versions of this method may wish to allow other ways of specifying file format.

Parameters:
  • name (str) – name to save surface as
  • geom (stl.mesh.Mesh) – geometry representing surface
  • clobber_existing (bool) – if False, do not overwrite an existing file
Raises:

CaseAlreadyExists – if a surface with the given name already exists and clobber_existing was not True.

mutable_data_file(path, create_class=<FileClass.DICTIONARY: 'dictionary'>, create=True)

A context manager representing a dict. Changes to the dict are written back to disk.

Parameters:
  • path (str or FileName) – relative path to dictionary
  • create_class (str or FileClass) – specify the class of created files
  • create (bool) – create file if it does not exist
>>> case = getfixture('tmpcase')
>>> with case.mutable_data_file('system/blockMeshDict') as d:
...     d['boundary'] = { 'foo': { 'type': 'empty' } }
>>> case.read_data_file('system/blockMeshDict')['boundary']['foo']
{'type': 'empty'}
>>> case = getfixture('tmpcase')
>>> items = { 'application': 'simpleFoam', 'description': 'mycase' }
>>> with case.mutable_data_file(FileName.CONTROL) as d:
...     d.update(items)
>>> control = case.read_data_file(FileName.CONTROL)
>>> control['application']
'simpleFoam'
>>> control['description']
'mycase'
read_data_file(path)

Read the contents of the control dictionary.

Parameters:path (str or FileName) – relative path to dictionary
Raises:IOError – the control dictionary could not be opened
run_tool(tool_name, flags='')

Run an OpenFOAM tool on the case.

It is assumed that the tool accepts the standard “-case” argument.

Parameters:

tool_name (str) – name of tool to run (e.g. “icoFoam”)

Raises:
  • CaseToolRunFailed – if the tool exits with an error
  • OSError – if the tool could not be started
exception firefish.case.CaseAlreadyExists

Some resource already existed.

exception firefish.case.CaseDoesNotExist

A case directory did not exist when we expected it to.

exception firefish.case.CaseException

Base class for exceptions raised by firefish.case module.

exception firefish.case.CaseToolRunFailed

There was a failure running a tool on a case directory.

class firefish.case.Dimension(*dims)

Represents a value’s dimensions in OpenFOAM cases.

A dimension represents the units used to describe a physical value e.g. one might measure velocity in metres per second or kilometres per hour.

In OpenFoam these dimensions must be built up from the standard SI units of kilograms, metres, seconds, Kelvins, moles, Amps and candelas.

To construct a dimension we raise each unit to a given exponent and multiply them all together e.g. metres per second is m s -1

Some commonly used units such as the Newton are not SI. We must therefore express them as a combination of SI units e.g. we know F=ma and so the Newton must be kg m s -2

In order to do this in OpenFoam we must pass it a tuple containing the list of exponents for each fundamental SI unit. These are given in the order kg, m, s, K, mol, A, cd.

e.g. for acceleration (m s -2 )

>>> d = Dimension(0, 1, -2, 0, 0, 0, 0)

e.g. for pressure (kg m -1 s -2 )

>>> d = Dimension(1, -1, -2, 0, 0, 0, 0)
Parameters:PFDataStructs.Dimension – A tuple containing the exponents to be used for each SI unit. These are given in the order kg, m ,s, K, mol, A, cd

Example usage:

>>> d = Dimension(0, 1, -2, 0, 0, 0, 0)
>>> str(d) # PyFOAM data file representation
'[ 0 1 -2 0 0 0 0 ]'
>>> d.unit
'ms^-2'
>>> repr(d)
'firefish.case.Dimension(0, 1, -2, 0, 0, 0, 0)'

The class also supports indexing and the sequence property

>>> d[2]
-2
>>> [v+1 for v in d]
[1, 2, -1, 1, 1, 1, 1]
>>> d[0] = 2
>>> d.unit
'kg^2ms^-2'
class firefish.case.FileClass

Well known OpenFOAM dictionary classes.

class firefish.case.FileName

An enumeration of well known OpenFOAM file locations.

class firefish.case.MeshGenerator

An eumeration of different mesh generation methods

class firefish.case.StandardFluid

An enumeration of commonly used fluids

AIR

generates the recommended OpenFoam thermophysicalProperties for air. The dictionary produced is taken from the rhoCentralFoam shock tube tutorial

DIMENSIONLESS_AIR

generates a normalised gas whith gamma=7/5 and with the property that at 1 temperature unit the speed of sound is 1 velocity unit. The dictionary produced is taken from the rhoCentralFoam wedge15Ma5 tutorial

firefish.case.read_data_file(path)

Read and parse an OpenFOAM dict into a Python dictionary.

Parameters:path (str) – path to the OpenFOAM dict on disk
Returns:A dict representing a Python transliteration of the dict.
Raises:IOError – the path could not be read from
firefish.case.write_standard_thermophysical_properties(case, fluid)

” Writes a thermophysicalProperties dict in the given case for the specified fluid.

Parameters:

IO

This module contains IO utility functions for amateur rocketry file formats.

class firefish.io.Engine

An individual engine record.

The thrust curve data is represented by a pandas DataFrame object, with the following columns: time (seconds), force (Newtons), mass (grams).

manufacturer

A string containing the manufacturer, or None

code

A string containing the maufacturer’s product code, or None

comments

A string containing any comments, or None

data

A pandas DataFrame, see above

exception firefish.io.RSEParseError

Raised when there is an error parsing a RockSim file.

firefish.io.rse_load(path)

Load a RockSim format engine database from disk.

Parameters:path (str) – path name to .rse file
Returns:A list of Engine instances.
Raises:RSEParseError – when the .rse file is invalid

Geometry manipulation

This module deals with the loading, saving and manipulation of geometry.

Most manipulation functions deal with instances of stl.mesh.Mesh. See the numpy-stl documentation for more information.

class firefish.geometry.Geometry(geomType, path, name, case)

This class encapsulates the geometry functionality

extract_features()

Extracts surface features from geometry using the surfaceFeatureExtract tool

recentre()

Recentres the geometry

save(path)

copies the stl from source directory into path

Args: path: the path to copy the stl file into

scale(factor)

Scales geometry by factor

Parameters:factor – The factor to scale the gometry by
translate(delta)

Translates geometry by delta

Parameters:delta – The vector to translate the geometry by
class firefish.geometry.GeometryFormat

An enumeration of different geometry formats

class firefish.geometry.MeshQualitySettings

Controls the mesh quality settings associated with the gometry

write_settings(case)

Writes the quality settings to a separate dict that can be included

firefish.geometry.load_multiple_geometries(geomType, paths, names, case)

Loads multiple geometries of the same type and returns as a list

Parameters:
  • geomType (firefish.geometry.GeometryFormat) – indicates what type these geometries are
  • paths – list of paths to each geometry file eg. stls/foo.stl
  • names – the list of names of each geometry e.g. body, fin etc.
  • case (firefish.case.Case) – the case to place each geometry in
firefish.geometry.stl_bounds(geom)

Compute the bounding box of the geometry.

Parameters:geom (stl.mesh.Mesh) – STL geometry
Returns:A pair giving the minimum and maximum X, Y and Z co-ordinates as three-dimensional array-likes.
firefish.geometry.stl_copy(geom)

Copy a geometry.

Use this function sparingly. Geometry can be quite heavyweight as data structures go.

Parameters:geom (stl.mesh.Mesh) – STL geometry
Returns:A deep copy of the geometry.
firefish.geometry.stl_geometric_centre(geom)

Compute the centre of the bounding box.

Parameters:geom (stl.mesh.Mesh) – STL geometry
Returns:An array like giving the X, Y and Z co-ordinates of the centre.
firefish.geometry.stl_load(path)

Convenience function to load a stl.mesh.Mesh from disk.

Note

The save() method on stl.mesh.Mesh may be used to write geometry to disk.

Parameters:path (str) – pathname to STL file
Returns:an new instance of stl.mesh.Mesh
firefish.geometry.stl_recentre(geom)

Centre a geometry such that its bounding box is centred on the origin.

This function modifies the passed geometry.

Equivalent to:

translate(geom, -geometric_centre(geom))
Parameters:geom (stl.mesh.Mesh) – STL geometry
Returns:The passed geometry to allow for easy chaining of calls.
firefish.geometry.stl_scale(geom, factor)

Scale geometry by a fixed factor.

This function modifies the passed geometry. If the scale factor is a single scalar it is applied to each axis. If it is a 3-vector then the elements specify the scaling along the X, Y and Z axes.

Parameters:
  • geom (stl.mesh.Mesh) – STL geometry
  • factor (scalar or array like) – scale factor to apply
Returns:

The passed geometry to allow for easy chaining of calls.

firefish.geometry.stl_translate(geom, delta)

Translate a geometry along some vector.

This function modifies the passed geometry.

Parameters:
  • geom (stl.mesh.Mesh) – STL geometry
  • delta (array like) – 3-vector giving translation in X, Y and Z
Returns:

The passed geometry to allow for easy chaining of calls.

Mesh generation

This module provides tools for building and running SnappyHexMesh

class firefish.meshsnappy.SnappyHexMesh(geometries, surfaceRefinement, case)

Encapsulates all the snappyHexMesh settings

add_mesh_features(file_list)

test function which runs add_features in order to write the surfaceFeatureExtractDict

generate_mesh()

Generates the mesh

Note

This extracts surface features, writes the main SHM dict, a mesh quality dict and then runs SHM. We assume that an underlying block mesh has already been produced

write_snappy_dict()

Writes the SHM dictionary

Note

This is called by SnappyHexMesh when it generates the mesh

Fin-flutter

Calculation of fin flutter vs. altitude.

The transonic flutter velocity code comes from “Peak of flight” newsletter issue 291, which is itself a modified version of the equation in NACA paper 4197.

The supersonic flutter criterion is from a thesis by J. Simmons at the Air Force Institute of Technology, Ohio. (AFIT/GSS/ENY/09-J02), the torsional and bending frequencies have to be calculated for different geometries using finite element analysis in Solidworks.

This module provides a simple API for computing fin-flutter velocity as a function of altitude. These can then be plotted. For example:

import matplotlib.pyplot as plt
import numpy as np
from firefish import finflutter

zs = np.linspace(0, 50000, 200)
ps, _, ss = finflutter.model_atmosphere(zs)
vs = finflutter.flutter_velocity_transonic(ps, ss, root_chord=20, +
    tip_chord=10, semi_span=10, thickness=0.2)

plt.plot(zs * 1e-3, vs)
plt.grid()
plt.title('Flutter velocity versus altitude')
plt.xlabel('Altitude [km]')
plt.ylabel('Flutter velocity [ms${}^{-1}$]')
plt.show()

(Source code)

firefish.finflutter.flutter_velocity_supersonic(air_densities, torsional_frequency, bending_frequency, mass, semi_span, radius_of_gyration, distance_to_COG, Mach_number)

Calculate transonic flutter velocities for a given fin design. The equation is valid for freestream flow in the supersonic regime (>~M2.5)

Fin analysis have to be done for Solidworks in order to find the frequencies for bending and torsional modes, as well as the radius_of_gyration and distance_to_COG. Torsional and bending frequency are in rad/s, the semi-span, radius of gyration, and distance to COG will be given in metres.

>>> import numpy as np
>>> zs = np.linspace(0, 30000, 100)
>>> ps, ts, ss = model_atmosphere(zs)
>>> rhos = (ps/1000) / (0.2869 * (ts + 273.1))
>>> vels = flutter_velocity_supersonic(rhos, 380, 104, 1, 0.1, 0.2, 0.1, 3)
>>> assert vels.shape == ps.shape
Parameters:
  • semi_span – fin semi-span (m)
  • air_densities – 1-d array of air density in kg/m^3 (np.array)
  • frequency (torsional) – uncoupled torsional frequency (rad/s)
  • bending_frequency – uncoupled bending frequency of the fin (rad/s)
  • mass – mass of fin (kg)
  • Mach_number – mach number of rocket
  • distance_to_COG – distance of COG to axis of rotation (m)
  • radius_of_gyration – distance at which all the mass of the fin can be though to be concenreated, =sqrt(I/M)
Returns:

A 1-d array containing corresponding flutter velocities in m/s.

firefish.finflutter.flutter_velocity_transonic(pressures, speeds_of_sound, root_chord, tip_chord, semi_span, thickness, shear_modulus=26200000000.0)

Calculate transonic flutter velocities for a given fin design. The equation is valid if the rocket is travelling at < M2.5 at the given altitude.

Fin dimensions are given via the root_chord, tip_chord, semi_span and thickness arguments. All dimensions are in centimetres.

Use shear_modulus to specify the shear modulus of the fin material in Pascals.

>>> import numpy as np
>>> zs = np.linspace(0, 30000, 100)
>>> ps, _, ss = model_atmosphere(zs)
>>> vels = flutter_velocity_transonic(ps, ss, 20, 10, 10, 0.2)
>>> assert vels.shape == ps.shape
Parameters:
  • pressures (np.array) – 1-d array of atmospheric pressures in Pascals
  • speeds_of_sound (np.array) – 1-d array of speeds of sound in m/s
  • root_chord – fin root chord (cm)
  • tip_chord – fin tip chord (cm)
  • semi_span – fin semi-span (cm)
  • thickness – fin thickness (cm)
  • shear_modulus – fin material shear modulus (Pascals)
Returns:

A 1-d array containing corresponding flutter velocities in m/s.

firefish.finflutter.model_atmosphere(altitudes)

Model atmospheric pressure, temperature and speed of sound.

Parameters:altitudes (np.array) – 1-d array of geopotential altitudes in metres
Returns:A triple giving corresponding 1-d arrays of estimated pressure, temperature and speed of sound. Units are Pascals, Celsius and m/s respectively.
>>> import numpy as np
>>> zs = np.linspace(0, 30000, 100)
>>> ps, ts, ss = model_atmosphere(zs)
>>> assert ps.shape == zs.shape
>>> assert ts.shape == zs.shape
>>> assert ss.shape == zs.shape

Kinematics

This module deals with kinematic models used in rocket simulation

class firefish.kinematics.KinematicBody(mass, inertias)

Encapsulates information about the kinematic body

update_moi()

We update moments of inertias. Any class inheriting KinematicBody must overload this if it has non-constant moments of inertia

class firefish.kinematics.KinematicSimulation(body, gravity, duration, dt)

Encapsulates all the simulation logic and time stepping

time_step(forces, torques, mdot)

Performs a single time step

Parameters:
  • forces ([float]) – A list of the forces on the body in N in the form [Fx,Fy,Fz]
  • torques ([float]) – A lst of the moments acting on the body in Nm in the form [Mxx,Myy,Mzz]
  • modt (float) – Mass flow rate of the motor. i.e. 0.1 implies the motor is ejection 0.1 kgs^-1