1. cst_modeling

1.1. cst_modeling.basic

Basic classes for sections and surfaces, and fundamental functions

class cst_modeling.basic.BasicSection(thick=None, chord=1.0, twist=0.0, lTwistAroundLE=True)[source]

Bases: object

Coordinates of the 2D unit curve (profile) and the 3D curve (section).

Parameters:
  • thick ({float, None}, optional) – specified maximum relative thickness, by default None.

  • chord (float) – chord length (m), by default 1.

  • twist (float) – twist angle, by default 0.

  • lTwistAroundLE (bool) – whether the twist center is LE, otherwise TE, by default True.

Examples

>>> sec = BasicSection(thick=None, chord=1.0, twist=0.0, lTwistAroundLE=True)

Notes

  • +x: flow direction (m)

  • +y: upside (m)

  • +z: span-wise (m)

  • chord: chord length (m)

  • thick: relative maximum thickness

  • tail: absolute tail thickness (m)

  • twist: rotation angle about the z-axis, +z direction (deg)

  • rot_x: rotation angle about the x-axis, +x direction (deg)

  • rot_y: rotation angle about the y-axis, +y direction (deg)

xLE, yLE, zLE

coordinates of the leading edge.

Type:

float

thick

actual maximum relative thickness.

Type:

float

chord

chord length.

Type:

float

twist

twist angle (degree), i.e., rotation angle about z axis (rot_z).

Type:

float

rot_x, rot_y

rotation angle (degree) about x and y axis.

Type:

float

specified_thickness

specified maximum relative thickness, by default None.

Type:

float or None

lTwistAroundLE

whether the twist center is LE, otherwise TE.

Type:

bool

xx, yy, yu, yl

the 2D unit curve coordinates. When it is an open section, only yy is available. When it is a closed section, only yu and yl are available. They are then concatenated to one curve, e.g., an airfoil.

Type:

ndarray

x, y, z

the 3D curve coordinates. The 3D curve is generated from the 2D curve through translation, scale, and rotation.

Type:

ndarray

get_profile() List[ndarray][source]

Get the 2D profile (unit curve) coordinates. If it is a closed curve, the upper and lower surface curves are combined.

Returns:

profile – the 2D profile coordinates, [profile_x, profile_y].

Return type:

List[np.ndarray] [2][n_point_section]

property has_profile: bool

Whether the 2D profile (unit curve) is constructed

property has_section: bool

Whether the 3D section is constructed

property is_open_curve: bool

Whether the section is an open curve

property n_point_profile: int

Number of points in the 2D profile (unit curve)

property n_point_section: int

Number of points in the 3D section (3D curve)

property rot_z: float

Rotation angle (degree) about z axis, i.e., the twist angle.

property scale: float

Scale factor, e.g., chord length (m).

section(flip_x=False, projection=True, nn=None) None[source]

Calculate the 3D curve coordinates from the known 2D curve.

Parameters:
  • flip_x (bool) – whether flip xx in the reverse order, by default False.

  • projection (bool) – whether keeps the projection length the same when rotating the section, by default True.

  • nn (int) – number of points in xx, yy, yu, and yl. It’s here for the consistency with Section.section and BasicSurface.update_sections.

Examples

>>> sec.section(flip_x=False, projection=True)
class cst_modeling.basic.BasicSurface(n_sec=1, name='Surf', nn=1001, ns=101, projection=True)[source]

Bases: object

Multi-section surface based on BasicSection.

Parameters:
  • n_sec (int) – number of control sections.

  • name (str) – name of the object, by default ‘Surf’.

  • nn (int) – number of points in the unit 2D curve’s xx, by default 1001.

  • ns (int) – number of points in the sweep direction between sections, by default 101.

  • projection (bool) – whether keeps the projection length the same when rotating the section, by default True.

Examples

>>> surf = BasicSurface(n_sec=1, name='Surf', nn=1001, ns=101, projection=True)

Notes

  • +x: flow direction (m)

  • +y: upside (m)

  • +z: span-wise (m)

l2d

whether this is a 3D surface for a 2D curve (unit span). It is True when n_sec is 0 or 1.

Type:

bool

secs

section objects.

Type:

list of BasicSection

surfs

surface coordinates. List surfs contains n_sec-1 sub-lists. Each sub-list is the coordinates of the 3D surface, which contains 3 ndarray. The 3 arrays are the X, Y, Z coordinates of the surface. For example, surfs = [[x0, y0, z0], [x1, y1, z1]] when n_sec=3.

Type:

list of list of ndarray

half_span

half span for plotting.

Type:

float

center

surface center for plotting.

Type:

ndarray

add_sec(location: list, axis='Z') None[source]

Add sections to the surface, the new sections are interpolated from existed ones.

Parameters:
  • location (list) – span-wise locations (must within current sections).

  • axis (str) – the direction for interpolation, i.e., Y, Z.

Notes

  1. Must run before update_sections(), geo(), geo_axisymmetric() and flip()

  2. This will automatically update the curves of all sections

  3. X is the flow direction (chord direction)

bend(i_sec0: int, i_sec1: int, leader=None, kx=None, ky=None, kc=None, rot_x=False) None[source]

Bend surfaces by a guide curve, i.e., leader.

Parameters:
  • i_sec0 (int) – the index of the start section and the end section.

  • i_sec1 (int) – the index of the start section and the end section.

  • leader (List[List[float]] or None) –

    coordinates of the leader curve control points (and chord length).

    The leader is a spline curve defined by a list of control points. The leading edge point at both ends are automatically included in leader.

    leader = [[x,y,z(,c)], [x,y,z(,c)], …].

  • kx ({None, float}) – X-axis slope (dx/dz) at both ends [kx0, kx1].

  • ky ({None, float}) – Y-axis slope (dy/dz) at both ends [ky0, ky1].

  • kc ({None, float}) – chord slope (dc/dz) at both ends [kc0, kc1].

  • rot_x (bool) – if True, rotate sections in x-axis to make the section vertical to the leader.

Notes

Regenerate the surface between section i_sec0 and i_sec1.

X is the flow direction (chord direction).

Examples

>>> bend(i_sec0: int, i_sec1: int, leader=None,
>>>         kx=None, ky=None, kc=None, rot_x=False)
flip(axis='None', plane='None') None[source]

Flip surfaces and layout center. This should be the last action before output.

Parameters:
  • axis (str) – turn 90 degrees about axis: +X, -X, +Y, -Y, +Z, -Z.

  • plane (str) – get symmetry about plane: ‘XY’, ‘YZ’, ‘ZX’.

Notes

The axis and plane can be a single phrase, or a string contains multiple actions to take in order, e.g., ‘+X +Y’.

geo(flip_x=False, update_sec=True) None[source]

Generate surface geometry.

First, update sections by calling sec.section() (optional):

  1. update the 2D curve sec.xx, sec.yy, sec.yu, sec.yl;

  2. transform the 2D curve to the 3D curve sec.x, sec.y, sec.z;

Then, interpolate the 3D surface [surf_x, surf_y, sur_z] from 3D curves.

Parameters:
  • flip_x (bool) – whether flip xx in the reverse order, by default False.

  • update_sec (bool) – whether update sections, by default True.

geo_axisymmetric(phi, flip_x=False, update_sec=True) None[source]

Generate axisymmetric surface geometry.

Parameters:
  • phi (list or ndarray) – position angle of control sections.

  • flip_x (bool) – whether flip xx in the reverse order, by default False.

  • update_sec (bool) – whether update sections, by default True.

layout_center() None[source]

Locate layout center for plot

linear_interpolate_z(z: float, key='x') dict[source]

Linear interpolation of key by a given z.

Parameters:
  • z (float) – location of the value

  • key (str) – the value to be interpolated: ‘x’ or ‘X’, ‘y’ or ‘Y’, ‘c’ or ‘C’ or ‘chord’, ‘t’ or ‘thick’ or ‘thickness’, ‘twist’.

property n_sec: int

Number of sections

output_plot3d(fname=None) None[source]

Output the surface to *.xyz in plot3d format.

Parameters:

fname (str) – name of the output file.

output_section(fname=None, TwoD=True) None[source]

Output the control sections.

Parameters:
  • fname (str) – name of the output file.

  • TwoD (bool) – if True, output the 2D unit curves. Otherwise, output the 3D control sections.

output_tecplot(fname=None, one_piece=False) None[source]

Output the surface to *.dat in Tecplot format.

Parameters:
  • fname (str) – name of the output file.

  • one_piece (bool) – if True, combine the span-wise sections into one piece.

plot(fig_id=1, type='wireframe', show=True)[source]

Plot surface (the figure is not closed).

Parameters:
  • fig_id (int) – ID of the figure

  • type (str) – ‘wireframe’, or ‘surface’

  • show (bool) – whether plot on screen

Returns:

figure (subplot) handle

Return type:

ax

read_cylinder_origins(fname: str) None[source]

Read in origins of each section from file.

Parameters:

fname (str) – settings file name

Examples

>>> origins = read_cylinder_origins(fname)
read_setting(fname: str) None[source]

Read in Surface layout parameters from file

Parameters:

fname (str) – parameter file name.

scale(scale=1.0, X0=0.0, Y0=0.0, Z0=0.0) None[source]

Scale surface coordinates about point [X0, Y0, Z0].

static scaled_sigmoid(x, b=1)[source]
static section2surf(sec0: BasicSection, sec1: BasicSection, ns=101) List[ndarray][source]

Interpolate surface from section 3D curves.

Parameters:
  • sec0 (BasicSection) – sections on both ends of the surface.

  • sec1 (BasicSection) – sections on both ends of the surface.

  • ns (int) – number of points in the interpolation direction.

Returns:

surf – coordinates of the surface, [surf_x, surf_y, surf_z], surf_x’s shape is [ns, nn].

Return type:

list of ndarray

Examples

>>> surf = section2surf(sec0, sec1, ns)
static section_surf_axisymmetric(sec0: BasicSection, sec1: BasicSection, phi0: float, phi1: float, ns=101) List[ndarray][source]

Interpolate axisymmetric surface section between curves.

Parameters:
  • sec0 (BasicSection) – sections on both ends of the surface.

  • sec1 (BasicSection) – sections on both ends of the surface.

  • phi0 (float) – angle (degree) about X-axis (X-Y plane is 0 degree).

  • phi1 (float) – angle (degree) about X-axis (X-Y plane is 0 degree).

  • ns (int) – number of points in the interpolation direction.

Returns:

surf – coordinates of the surface, [surf_x, surf_y, surf_z], surf_x’s shape is [ns, nn].

Return type:

list of ndarray

Examples

>>> surf = section_surf_axisymmetric(sec0, sec1, phi0, phi1, ns)
smooth(i_sec0: int, i_sec1: int, smooth0=False, smooth1=False, dyn0=None, ratio_end=10) None[source]

Smooth the span-wise curve between i_sec0 and i_sec1.

Parameters:
  • i_sec0 (int) – The index of surface surfs to be smoothed is i_sec0, …, i_sec1-1. They usually are the starting and ending section index of the smooth region.

  • i_sec1 (int) – The index of surface surfs to be smoothed is i_sec0, …, i_sec1-1. They usually are the starting and ending section index of the smooth region.

  • smooth0 (bool) – whether have smooth transition to the neighboring surfaces.

  • smooth1 (bool) – whether have smooth transition to the neighboring surfaces.

  • dyn0 ({None, float}) – If float, sets the slope of y-z curve at the end of section 0, i.e., (dy/dz)|n. If None, the slope at section 0 is not specified.

  • ratio_end ({float, list of float}) –

    the ratio controls how fast changing to the original geometry at both ends of the curve (ip=0, n_point-1).

    If input a list, ratio_end=[a0, a1, b].

    If input a float a, do not change to the original geometry when a <= 0, ratio_end=[a, a, 1] when a > 0.

    a0, a1: larger the faster.

    b: controls the width of the original geometry at both ends.

    b<=1: no width, b>1: larger the wider.

smooth_axisymmetric(i_sec0: int, i_sec1: int, phi, linear_TEx=True, RTE=None, RTE_=None, func_trans=None)[source]

Smooth the axisymmetric curve between i_sec0 and i_sec1

Parameters:
  • i_sec0 (int) – the starting and ending section index of the smooth region

  • i_sec1 (int) – the starting and ending section index of the smooth region

  • phi (list or ndarray) – position angle (degree) of control sections: i_sec0 ~ i_sec1

  • linear_TEx (bool) – if True, the x coordinates of trailing edge curve are piece-wise linear distribution. Otherwise, they can be nonlinear distribution due to the leading edge curve.

  • RTE ({None, float}) – if None, the trailing edge curve in YZ plane is generated by the layout parameters. If provided a float, then the trailing edge curve in YZ plane is set to a circle. Its origin is (0,0), radius is RTE.

  • RTE – if RTE_ is provided, it means the control sections are close sections, i.e., both upper and lower surfaces of the control section exist. Then, RTE_ is the inner circle radius.

  • func_trans ({None, function}) –

    if None, ratio = tx.

    If a function ratio = func_trans(tx) is provided: ratio is a float (0~1), representing how much the YZ-plane curve is similar to a circle.

    When ratio is 1, the curve is the specified circle of which the radius is RTE. tx is a float (0~1), representing the relative x-axis location of the YZ-plane curve.

static smooth_ramp_function(x: ndarray, a=1) ndarray[source]

Smooth ramp function, x`<=0, `y in [0,1].

static smooth_ratio_function(x: ndarray, a0=4, a1=4, b=1) ndarray[source]

Smooth ratio function, x in [0,1], ratio in [0,1].

A larger a gives a steeper ramp, a larger b gives a longer plateau at both ends.

split(ips: list) None[source]

Split each surface surfs into several pieces. Length of surfs is multiplied by len(ips)+1.

Parameters:

ips (list of int) – split point indices on each section curves

Notes

surf is a list of ndarray, i.e., [surf_x, surf_y, surf_z], the shape of each element is [ns, nn].

surf_to_cylinder(flip=True, origin=None) None[source]

Bend the surface (surfs) to cylinder (turbomachinery). The original surface is constructed by 2D sections.

Parameters:
  • flip (bool) – whether flip xx in the reverse order, by default False.

  • origin ({None, list of ndarray}) – the cylinder origin axis, by default None. If None, the cylinder origin axis is Z-axis for all sections. Otherwise, origin = [O0, O1, …], list length is the number of sections. Each element is the cylinder origin of that section, i.e., [xOi, yOi] (i=0,1,…), it can be a ndarray or list.

translate(dX=0.0, dY=0.0, dZ=0.0) None[source]

Translate surface coordinates

update_sections(flip_x=False) None[source]

Update surface sections, including the construction of 2D unit curves (optional) and transforming to 3D curves.

Parameters:

flip_x (bool) – whether flip xx in the reverse order, by default False.

property zLEs: List[float]

List of section zLE

cst_modeling.basic.interp_basic_sec(sec0: BasicSection, sec1: BasicSection, ratio: float) BasicSection[source]

Interpolate a basic section by ratio.

Parameters:
  • sec0 (BasicSection) – sections at both ends.

  • sec1 (BasicSection) – sections at both ends.

  • ratio (float) – interpolation ratio.

Examples

>>> sec = interp_basic_sec(sec0, sec1, ratio)

1.2. cst_modeling.section

Construct airfoil with CST

class cst_modeling.section.OpenSection(thick=None, chord=1.0, twist=0.0, lTwistAroundLE=True)[source]

Bases: BasicSection

Section 3D curve generated by CST curve (open curve)

Examples

>>> sec = OpenSection(thick=None, chord=1.0, twist=0.0, lTwistAroundLE=True)
cst

cst coefficients of the curve

Type:

ndarray

refine

cst coefficients of the refinement curve

Type:

{None, ndarray}

section(cst=None, nn=1001, flip_x=False, projection=True)[source]

Generating the section (3D) by cst_curve. First construct the 2D unit curve, then transform it to the 3D curve.

Parameters:
  • nn (int) – number of points in xx, yy, yu, and yl.

  • cst (ndarray) – CST coefficients of upper and lower surfaces (optional)

  • flip_x (bool) – whether flip xx in the reverse order, by default False.

  • projection (bool) – whether keeps the projection length the same when rotating the section, by default True.

Examples

>>> sec.section(cst=None, nn=1001, flip_x=False, projection=True)
class cst_modeling.section.RoundTipSection(xLE: float, yLE: float, zLE: float, chord: float, thick: float, twist: float, tail: float, cst_u: ndarray, cst_l: ndarray, base_le_ratio: float, base_te_ratio: float, base_abs_thick: float, base_le_radius: float, base_te_radius: float, aLE=0.0, aTE=0.0, i_split=None, nn=501, lTwistAroundLE=False)[source]

Bases: BasicSection

Section 3D curve generated by CST foil and base shape (upper & lower surface)

Suitable for round trailing edge foils or blades, or plates.

Parameters:
  • xLE (float,) – coordinates of the leading edge

  • yLE (float,) – coordinates of the leading edge

  • zLE (float,) – coordinates of the leading edge

  • chord (float) – chord length (m)

  • thick (float) – maximum relative thickness

  • twist (float) – twist angle (deg)

  • tail (float) – actual thickness of TE (m)

  • cst_u (ndarray) – cst coefficients of the upper and lower surfaces

  • cst_l (ndarray) – cst coefficients of the upper and lower surfaces

  • base_le_radius (float) – relative radius of base shape function leading edge

  • base_te_radius (float) – relative radius of base shape function trailing edge

  • base_abs_thick (float) – actual thickness of the base shape

  • base_le_ratio (float) – ratio of the leading edge region

  • base_te_ratio (float) – ratio of the trailing edge region

  • aLE (float) – angle (deg) of the slope at leading edge (a>0 => dy/dx>0)

  • aTE (float) – angle (deg) of the slope at trailing edge (a<0 => dy/dx<0)

  • i_split ({None, int}) – active when leading edge and trailing edge curves are intersected

  • nn (int) – number of points in xx, yy, yu, and yl.

  • lTwistAroundLE (bool) – whether the twist center is LE, otherwise TE, by default True.

static base_camber(x: ndarray, a_LE=0.0, a_TE=0.0) ndarray[source]

Camber curve of the base shape function (in 3rd order spline)

Parameters:
  • x (ndarray) – actual x distribution

  • a_LE (float) – angle (deg) of the slope at leading edge (a>0 => dy/dx>0)

  • a_TE (float) – angle (deg) of the slope at trailing edge (a<0 => dy/dx<0)

Examples

>>> dy = base_camber(x, a_LE, a_TE)
static base_shape(x_ref: ndarray, x_LE: float, x_TE: float, l_LE: float, l_TE: float, r_LE: float, r_TE: float, h: float, i_split=None) Tuple[ndarray, ndarray][source]

Base shape function of wing sections.

Parameters:
  • x_ref (ndarray [nn]) – reference point distribution in [0,1]

  • x_LE (float) – leading edge location

  • x_TE (float) – trailing edge location

  • l_LE (float) – length of leading edge curve/ramp

  • l_TE (float) – length of trailing edge curve/ramp

  • r_LE (float) – relative radius of leading edge

  • r_TE (float) – relative radius of trailing edge

  • h (float) – height

  • i_split ({None, int}) – active when leading edge and trailing edge curves are intersected

Notes

Base shape:

_______________________________________________

(______________________________________________)

Examples

>>> x, y = base_shape(x_ref, x_LE, x_TE, l_LE, l_TE, r_LE, r_TE, h, i_split=None)
static general_eqn(x: ndarray, l: float, rr: float, h: float) ndarray[source]

General equations to define the leading edge semi-thickness, the flat plate semi-thickness, the trailing edge closure semi-thickness, and the transverse radius of the sting fairing.

Experimental Surface Pressure Data Obtained on 65° Delta Wing Across Reynolds Number and Mach Number Ranges (Volume 2—Small-Radius Leading Edges)

https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19960025648.pdf

Parameters:
  • x (ndarray) – current location

  • l (float) – range of x

  • rr (float) – relative radius

  • h (float) – height

Examples

>>> phi = general_eqn(x, l, rr, t) # phi >= 0
class cst_modeling.section.Section(thick=None, chord=1.0, twist=0.0, tail=0.0, lTwistAroundLE=True)[source]

Bases: BasicSection

Section 3D curve generated by CST foil (upper & lower surface)

Examples

>>> sec = Section(thick=None, chord=1.0, twist=0.0, tail=0.0, lTwistAroundLE=True)
tail

tail thickness (m)

Type:

float

RLE

relative leading edge radius

Type:

float

te_angle

trailing edge angle (degree)

Type:

float

te_slope

slope of the mean camber line at trailing edge (dy/dx)

Type:

float

cst_u, cst_l

cst coefficients of the upper and lower surfaces

Type:

ndarray

refine_u, refine_l

cst coefficients of the refinement curve on upper and lower surfaces

Type:

{None, ndarray}

section(cst_u=None, cst_l=None, nn=1001, flip_x=False, projection=True) None[source]

Generating the section (3D) by cst_foil. First construct the 2D unit curve, then transform it to the 3D curve.

Parameters:
  • nn (int) – number of points in xx, yy, yu, and yl.

  • cst_u (ndarray) – CST coefficients of upper and lower surfaces (optional)

  • cst_l (ndarray) – CST coefficients of upper and lower surfaces (optional)

  • flip_x (bool) – whether flip xx in the reverse order, by default False.

  • projection (bool) – whether keeps the projection length the same when rotating the section, by default True.

Examples

>>> sec.section(cst_u=None, cst_l=None, nn=1001, flip_x=False, projection=True)
cst_modeling.section.bump_function(x: ndarray, xc: float, h: float, s: float, kind='G') ndarray[source]

A bump distribution [x, y].

Parameters:
  • x (ndarray) – current curve, x in [0,1]

  • y (ndarray) – current curve, x in [0,1]

  • xc (float) – x of the bump center

  • h (float) – height of the bump

  • s (float) – span of the bump

  • kind (str) – bump function type. ‘G’: Gaussian, less cpu cost ‘H’: Hicks-Henne, better when near leading edge

Returns:

y_bump – coordinates

Return type:

ndarray

Examples

>>> y_bump = bump_function(x, xc, h, s, kind)
cst_modeling.section.cst_foil_fit(xu: ndarray, yu: ndarray, xl: ndarray, yl: ndarray, n_cst=7, xn1=0.5, xn2=1.0) Tuple[ndarray, ndarray][source]

Using CST method to fit an airfoil

Parameters:
  • xu (ndarray) – coordinates

  • yu (ndarray) – coordinates

  • xl (ndarray) – coordinates

  • yl (ndarray) – coordinates

  • n_cst (int) – number of CST coefficients

  • xn1 (float) – CST parameters

  • xn2 (float) – CST parameters

Returns:

cst_u, cst_l – CST coefficients

Return type:

ndarray

Examples

>>> cst_u, cst_l = cst_foil_fit(xu, yu, xl, yl, n_cst=7, xn1=0.5, xn2=1.0)

Notes

This function allows the airfoil has non-zero tail thickness. Also allows the airfoil chord length not equals to one. But yu[0] yl[0] should be 0.

cst_modeling.section.fit_curve(x: ndarray, y: ndarray, n_cst=7, xn1=0.5, xn2=1.0)[source]

Using least square method to fit a CST curve.

Parameters:
  • x (ndarray) – coordinates

  • y (ndarray) – coordinates

  • n_cst (int) – number of CST coefficients

  • xn1 (float) – CST parameters

  • xn2 (float) – CST parameters

Returns:

coef – CST coefficients

Return type:

ndarray [n_cst]

Notes

y[0] should be 0.

Examples

>>> coef = fit_curve(x, y, n_cst=7, xn1=0.5, xn2=1.0)
cst_modeling.section.fit_curve_partial(x: ndarray, y: ndarray, n_cst=7, ip0=0, ip1=0, ic0=0, ic1=0, xn1=0.5, xn2=1.0)[source]

Using least square method to fit a part of a unit curve

Parameters:
  • x (ndarray) – coordinates

  • y (ndarray) – coordinates

  • n_cst (int) – number of CST coefficients

  • ip0 (int) – index of the partial curve x[ip0:ip1]

  • ip1 (int) – index of the partial curve x[ip0:ip1]

  • ic0 (int) – index of the CST parameters cst[ic0:ic1] that are not 0

  • ic1 (int) – index of the CST parameters cst[ic0:ic1] that are not 0

  • xn1 (float) – CST parameters

  • xn2 (float) – CST parameters

Returns:

coef – CST coefficients

Return type:

ndarray [n_cst]

Examples

>>> coef = fit_curve_partial(x: np.array, y: np.array, ip0=0, ip1=0, n_cst=7, xn1=0.5, xn2=1.0)
cst_modeling.section.fit_curve_with_twist(x: ndarray, y: ndarray, n_cst=7, xn1=0.5, xn2=1.0) Tuple[ndarray, float, float, float][source]

Using least square method to fit a CST curve

Parameters:
  • x (ndarray) – coordinates

  • y (ndarray) – coordinates

  • n_cst (int) – number of CST coefficients

  • xn1 (float) – CST parameters

  • xn2 (float) – CST parameters

Returns:

  • coef (ndarray [n_cst]) – CST coefficients

  • chord (float) – distance between two ends of the curve

  • twist (float) – degree, +z axis

  • thick (float) – maximum relative thickness

Examples

>>> coef, chord, twist, thick = fit_curve_with_twist(x, y, n_cst, xn1, xn2)
cst_modeling.section.foil_bump_modify(x: ndarray, yu: ndarray, yl: ndarray, xc: float, h: float, s: float, side=1, n_cst=0, return_cst=False, keep_tmax=True)[source]

Add bumps on the airfoil

Parameters:
  • x (ndarray) – coordinates of the airfoil

  • yu (ndarray) – coordinates of the airfoil

  • yl (ndarray) – coordinates of the airfoil

  • xc (float) – x of the bump center

  • h (float) – relative height of the bump (to maximum thickness)

  • s (float) – span of the bump

  • side (int) – +1/-1 upper/lower side of the airfoil

  • n_cst (int) – if specified (>0), then use CST to fit the new foil

  • return_cst (bool) – if True, also return cst_u, cst_l when n_cst > 0

  • keep_tmax (bool) – if True, keep the maximum thickness unchanged scale the opposite side of ‘side’ to keep thickness

Returns:

  • yu_new, yl_new (ndarray) – coordinates

  • cst_u, cst_l (ndarray) – CST coefficients

Examples

>>> yu_new, yl_new (, cst_u, cst_l) = foil_bump_modify(
>>>         x: np.array, yu: np.array, yl: np.array,
>>>         xc: float, h: float, s: float, side=1,
>>>         n_cst=0, return_cst=False, keep_tmax=True)
cst_modeling.section.foil_increment(x, yu, yl, cst_u=None, cst_l=None, t=None) Tuple[ndarray, ndarray][source]

Add cst curve by incremental curves

Parameters:
  • x (ndarray) – coordinates of the baseline airfoil.

  • yu (ndarray) – coordinates of the baseline airfoil.

  • yl (ndarray) – coordinates of the baseline airfoil.

  • cst_u (ndarray or None) – if not None, CST parameters of the incremental curves. The number of CST parameters is arbitrary.

  • cst_l (ndarray or None) – if not None, CST parameters of the incremental curves. The number of CST parameters is arbitrary.

  • t (float or None) – relative maximum thickness.

Returns:

yu_new, yl_new – coordinates of the new airfoil.

Return type:

ndarray

Examples

>>> yu_new, yl_new = foil_increment(x, yu, yl, cst_u, cst_l, t=None)
cst_modeling.section.foil_increment_curve(x: ndarray, yu: ndarray, yl: ndarray, yu_i=None, yl_i=None, t=None) Tuple[ndarray, ndarray][source]

Add cst curve by incremental curves

Parameters:
  • x (ndarray) – coordinates of the baseline airfoil.

  • yu (ndarray) – coordinates of the baseline airfoil.

  • yl (ndarray) – coordinates of the baseline airfoil.

  • yu_i ({None, ndarray}) – if not None, coordinates of the incremental curves.

  • yl_i ({None, ndarray}) – if not None, coordinates of the incremental curves.

  • t ({None, float}) – relative maximum thickness.

Returns:

yu_, yl_ – coordinates of the new airfoil.

Return type:

ndarray

Examples

>>> yu_, yl_ = foil_increment_curve(x, yu, yl, yu_i, yl_i, t=None)
cst_modeling.section.normalize_foil(xu: ndarray, yu: ndarray, xl: ndarray, yl: ndarray)[source]

Transform the airfoil to a unit airfoil.

Parameters:
  • xu (ndarray) – coordinates of the airfoil

  • yu (ndarray) – coordinates of the airfoil

  • xl (ndarray) – coordinates of the airfoil

  • yl (ndarray) – coordinates of the airfoil

Returns:

  • xu_, yu_, xl_, yl_ (ndarray) – coordinates of the airfoil

  • twist (float) – twist angle (degree)

  • chord (float) – chord length

  • tail (float) – tail height relative to chord length

Examples

>>> xu_, yu_, xl_, yl_, twist, chord, tail = normalize_foil(xu, yu, xl, yl)
cst_modeling.section.scale_cst(x: ndarray, yu: ndarray, yl: ndarray, cst_u, cst_l, t: float, tail=0.0)[source]

Scale CST coefficients, so that the airfoil has the maximum thickness of t.

Parameters:
  • x (ndarray [nn]) – baseline airfoil. x, yu, yl must be directly generated by CST, without scaling.

  • yu (ndarray [nn]) – baseline airfoil. x, yu, yl must be directly generated by CST, without scaling.

  • yl (ndarray [nn]) – baseline airfoil. x, yu, yl must be directly generated by CST, without scaling.

  • cst_u (list or ndarray) – CST coefficients of the upper and lower surfaces

  • cst_l (list or ndarray) – CST coefficients of the upper and lower surfaces

  • t (float) – specified relative maximum thickness

  • tail (float) – relative tail thickness (optional)

Examples

>>> cst_u_new, cst_l_new = scale_cst(yu, yl, cst_u, cst_l, t)

1.3. cst_modeling.surface

Construct surface with sections/open-sections

class cst_modeling.surface.OpenSurface(n_sec=0, name='Patch', nn=1001, ns=101, projection=True)[source]

Bases: BasicSurface

Open surface defined by multiple OpenSection objects.

Examples

>>> surf = OpenSurface(n_sec=0, name='Patch', nn=1001, ns=101, projection=True)
read_setting(fname) None[source]

Read in Surface layout and CST parameters from file.

Parameters:

fname (str) – settings file name

class cst_modeling.surface.Surface(n_sec=0, name='Wing', nn=1001, ns=101, projection=True)[source]

Bases: BasicSurface

Surface defined by multiple Section objects, i.e., foils

Examples

>>> surf = Surface(n_sec=0, name='Wing', nn=1001, ns=101, projection=True)
output_plot3d(fname=None, split=False) None[source]

Output the surface to *.xyz in plot3d format.

Parameters:
  • fname (str) – name of the output file.

  • split (bool) – if True, split to upper and lower surfaces.

output_tecplot(fname=None, one_piece=False, split=False) None[source]

Output the surface to *.dat in Tecplot format.

Parameters:
  • fname (str) – name of the output file.

  • one_piece (bool) – if True, combine the span-wise sections into one piece.

  • split (bool) – if True, split to upper and lower surfaces.

read_setting(fname, tail=0.0) None[source]

Read in Surface layout and CST parameters from file

Parameters:
  • fname (str) – settings file name.

  • tail (float or list) – tail thickness (m) of each section.

cst_modeling.surface.surf_axisymmetric(xx: ndarray, yy: ndarray, phi0=0.0, phi1=360.0, ns=1001) List[ndarray][source]

Axisymmetric surface between curves.

Parameters:
  • xx (ndarray) – generatrix profile

  • yy (ndarray) – generatrix profile

  • phi0 (float) – angle (degree) about X-axis (X-Y plane is 0 degree)

  • phi1 (float) – angle (degree) about X-axis (X-Y plane is 0 degree)

  • ns (int) – number of points in the interpolated direction.

Returns:

surf – coordinates of the surface, [surf_x, surf_y, surf_z], surf_x’s shape is [ns, nn].

Return type:

list of ndarray

Examples

>>> surf = surf_axisymmetric(xx, yy, phi0=0.0, phi1=360.0, ns=1001)

1.4. cst_modeling.surface2

#TODO: Modify Surface Class to use Lofting

class cst_modeling.surface2.BasicSurface(n_sec=1, name='Surf', nn=1001, ns=101, smooth_surface=False, smooth_sections: List[Tuple[int, int]] | None = None, rotate_x_section=False, rotation_sections: List[Tuple[int, int]] | None = None, is_guide_curve_at_LE=True)[source]

Bases: object

Multi-section surface based on BasicSection and Lofting.

Parameters:
  • n_section (int) – number of control sections.

  • name (str) – name of the object, by default ‘Surf’.

  • nn (int) – number of points in the unit 2D curve’s xx, by default 1001.

  • ns (int) – number of points in the span-wise direction between sections, by default 101.

  • smooth_surface (bool) – whether to smooth the surface, by default False.

  • smooth_sections (List[Tuple[int, int]]) – surfaces to be smoothed, by default None. None means all surfaces are smoothed. The tuple is (start, end) index of the sections. For example, [(0, 1), (2, 4)] means the surfaces between the 0-1 and 2-4 sections are smoothed.

  • rotate_x_section (bool) – whether to rotate the section about the x-axis, by default False.

  • rotation_sections (List[Tuple[int, int]]) – sections to be rotated about the x-axis, by default None. None means all sections are rotated. The tuple is (start, end) index of the sections. For example, [(0, 1), (2, 4)] means the sections between the 0-1 and 2-4 sections are rotated.

  • is_guide_curve_at_LE (bool) – whether the guide curve runs through the leading edge, by default True. Details can be found in the Lofting class.

Notes

  • +x: flow direction (m)

  • +y: upside (m)

  • +z: span-wise (m)

sections

section objects.

Type:

list of BasicSection

surfaces

surface coordinates, i.e., a list of [surf_x, surf_y, surf_z]. The surface coordinates surf_* are 2D arrays with shape (ns, nn).

Type:

List[List[np.ndarray]] [n_section-1][3][ns, nn]

section_s_loc

span-wise parametric locations of the sections.

Type:

List[float]

half_size

half of the size of the entire surface for plotting.

Type:

float

center

surface center for plotting.

Type:

ndarray

add_sec(*args, **kwargs) None[source]

Obsolete function.

assemble_to_one_piece() Tuple[ndarray, ndarray, ndarray][source]

Assemble the span-wise surfaces into one surface.

Returns:

surf_x, surf_y, surf_z – 3D surface coordinates.

Return type:

np.ndarray

bend(*args, **kwargs) None[source]

Obsolete function.

flip(axis='None', plane='None') None[source]

Flip surfaces and layout center. This should be the last action before output.

Parameters:
  • axis (str) – turn 90 degrees about axis: +X, -X, +Y, -Y, +Z, -Z.

  • plane (str) – get symmetry about plane: ‘XY’, ‘YZ’, ‘ZX’.

Notes

The axis and plane can be a single phrase, or a string contains multiple actions to take in order, e.g., ‘+X +Y’.

geo() None[source]

Interpolate the 3D surface.

Notes

The prepare() method should be called first to prepare the profiles and lofting object.

get_default_guide_curve(custom_control_points=None, smooth_keys=['x', 'y', 'scale', 'rot_z']) GuideCurve[source]

Initialize the default guide curve object. It has a piecewise linear distribution along the span, defined by the section parameters.

Parameters:
  • custom_control_points (dict) – user-defined control points for the guide curve, by default None.

  • smooth_keys (list of str) – keys for smoothing the guide curve, by default [‘x’, ‘y’, ‘scale’, ‘rot_z’].

Returns:

guide – default guide curve object.

Return type:

GuideCurve

get_profiles() List[List[ndarray]][source]

Get the 2D profiles for all sections.

Returns:

profiles – 2D profiles for each section, i.e., a list of [xx, yu, yl].

Return type:

List[List[np.ndarray]]

get_surface_coordinates(i_surface: int) Tuple[ndarray, ndarray, ndarray][source]

Get the surface coordinates for the surface.

Parameters:

i_surface (int) – index of the surface.

Returns:

surf_x, surf_y, surf_z – 3D surface coordinates.

Return type:

np.ndarray

property is_2d: bool

Whether this is a 3D surface for a 2D curve (unit span).

property n_piece: int

Number of span-wise surface sections

property n_section: int

Number of sections

property n_surface: int

Number of span-wise surfaces

output_guide_curve(fname=None) None[source]

Output the guide curve to *.dat in Tecplot format.

Parameters:

fname (str) – name of the output file.

output_plot3d(fname=None, scale=1.0, one_piece=False) None[source]

Output the surface to *.xyz in plot3d format.

Parameters:
  • fname (str) – name of the output file.

  • scale (float) – scaling factor for the coordinates

  • one_piece (bool) – if True, combine the span-wise surfaces into one piece.

output_tecplot(fname=None, one_piece=False, append=False) None[source]

Output the surface to *.dat in Tecplot format.

Parameters:
  • fname (str) – name of the output file.

  • one_piece (bool) – if True, combine the span-wise surfaces into one piece.

  • append (bool) – if True, append the data to the existing file

plot(fig_id=1, type='wireframe', show=True)[source]

Plot surface (the figure is not closed).

Parameters:
  • fig_id (int) – ID of the figure

  • type (str) – ‘wireframe’, or ‘surface’

  • show (bool) – whether plot on screen

Returns:

figure (subplot) handle

Return type:

ax

prepare(guide: GuideCurve | None = None, update_section_profile=True, smooth_keys=['x', 'y', 'scale', 'rot_z']) None[source]

Prepare the profiles, guide curve and lofting object for surface generation.

Parameters:
  • guide (GuideCurve) – user-defined GuideCurve object, by default None.

  • update_section_profile (bool) – whether to update the section profile curves, by default True.

  • smooth_keys (list of str) – keys for smoothing the guide curve, by default [‘x’, ‘y’, ‘scale’, ‘rot_z’].

Notes

In the BasicSurface class, the update_section method is not implemented. Therefore, the profile curves are not generated.

read_setting(fname: str) None[source]

Read the surface layout parameters from file

Parameters:

fname (str) – parameter file name.

smooth(*args, **kwargs) None[source]

Obsolete function.

property spanwise_locations: ndarray

Span-wise locations of the sections, i.e., zLE for each section.

split(index_splitting_point: List[int]) None[source]

Split each surface into several pieces in the nn direction.

Parameters:

index_splitting_point (list of int) – index of the split points on each section curves

translate(dX=0.0, dY=0.0, dZ=0.0) None[source]

Translate surface coordinates

update_layout_center() None[source]

Update the layout center for plotting

update_section() None[source]

Update all sections’ profile curves.

class cst_modeling.surface2.OpenSurface(n_sec=1, name='Surf', nn=1001, ns=101, smooth_surface=False, smooth_sections: List[Tuple[int, int]] | None = None, rotate_x_section=False, rotation_sections: List[Tuple[int, int]] | None = None, is_guide_curve_at_LE=True)[source]

Bases: BasicSurface

Open surface defined by multiple OpenSection objects.

read_setting(fname) None[source]

Read in Surface layout and CST parameters from file.

Parameters:

fname (str) – settings file name

update_section() None[source]

Update all sections’ profile curves.

class cst_modeling.surface2.Surface(n_sec=1, name='Surf', nn=1001, ns=101, smooth_surface=False, smooth_sections: List[Tuple[int, int]] | None = None, rotate_x_section=False, rotation_sections: List[Tuple[int, int]] | None = None, is_guide_curve_at_LE=True)[source]

Bases: BasicSurface

Surface defined by multiple Section objects, i.e., foils

output_plot3d(fname=None, scale=1.0, one_piece=False, split=False) None[source]

Output the surface to *.xyz in plot3d format.

Parameters:
  • fname (str) – name of the output file.

  • scale (float) – scaling factor for the coordinates

  • one_piece (bool) – if True, combine the span-wise surfaces into one piece.

  • split (bool) – if True, split to upper and lower surfaces.

output_tecplot(fname=None, one_piece=False, split=False, append=False) None[source]

Output the surface to *.dat in Tecplot format.

Parameters:
  • fname (str) – name of the output file.

  • one_piece (bool) – if True, combine the span-wise surfaces into one piece.

  • split (bool) – if True, split to upper and lower surfaces.

  • append (bool) – if True, append the data to the existing file

read_setting(fname, tail=0.0) None[source]

Read in Surface layout and CST parameters from file

Parameters:
  • fname (str) – settings file name.

  • tail (float or list) – tail thickness (m) of each section.

static split_surface(surf_x: ndarray, surf_y: ndarray, surf_z: ndarray) Tuple[ndarray, ndarray, ndarray, ndarray, ndarray, ndarray][source]

Split the surface into upper and lower surfaces.

Parameters:
  • surf_x (np.ndarray) – 3D surface coordinates.

  • surf_y (np.ndarray) – 3D surface coordinates.

  • surf_z (np.ndarray) – 3D surface coordinates.

Returns:

  • surf_x_u, surf_y_u, surf_z_u (np.ndarray) – upper surface coordinates.

  • surf_x_l, surf_y_l, surf_z_l (np.ndarray) – lower surface coordinates.

update_section() None[source]

Update all sections’ profile curves.

1.5. cst_modeling.foil

Airfoil geometric features and modification functions

class cst_modeling.foil.FoilGeoFeatures(x: ndarray, yu: ndarray, yl: ndarray)[source]

Bases: object

Airfoil geometric features (unit chord length and sharp trailing edge)

Parameters:
  • x (np.ndarray) – Airfoil x-coordinates

  • yu (np.ndarray) – Airfoil surface y-coordinates

  • yl (np.ndarray) – Airfoil surface y-coordinates

property feature_names: Tuple[str]
get_average_camber() float[source]

Get airfoil average camber, i.e., the area of camber line.

c_mean = (the area of camber line) / (the chord length)

Returns:

c_mean – Average camber

Return type:

float

get_average_camber_front_60p() float[source]

Get airfoil average camber in the front 60% of the chord length, i.e., the area of camber line in the front 60% of the chord length.

Returns:

c_f60 – Average camber in the front 60% of the chord length

Return type:

float

get_average_camber_rear_40p() float[source]

Get airfoil average camber in the rear 40% of the chord length, i.e., the area of camber line in the rear 40% of the chord length.

Returns:

c_r40 – Average camber in the rear 40% of the chord length

Return type:

float

get_curvature() Tuple[ndarray, ndarray][source]

Get airfoil curvature. Curvature is the second derivative of the camber line.

Returns:

curvature_upper, curvature_lower – Curvature of airfoil upper surface and lower surface

Return type:

np.ndarray

get_feature(feature_name: str)[source]
get_leading_edge_radius() float[source]

Get airfoil leading edge radius.

Returns:

r_le – Leading edge radius

Return type:

float

get_leading_edge_slope_angle() float[source]

Get airfoil leading edge slope angle.

Returns:

slope_angle – Leading edge slope angle (degree)

Return type:

float

get_lower_crest_point() Tuple[float, float, int][source]

Get airfoil lower crest position and curvature.

Returns:

  • x_lc (float) – X-coordinate of the lower crest point

  • y_lc (float) – Y-coordinate of the lower crest point

  • i_lc (int) – Index of the lower crest point

get_maximum_camber() Tuple[float, float, int][source]

Get airfoil maximum camber

Returns:

  • c_max (float) – Maximum camber

  • x_c (float) – Maximum camber location

  • i_c (int) – Maximum camber location index

get_maximum_thickness() Tuple[float, float, int][source]

Get airfoil maximum thickness and its location

Returns:

  • t_max (float) – Maximum thickness

  • x_t (float) – Maximum thickness location

  • i_t (int) – Maximum thickness location index

get_thickness_at(x0: float) float[source]

Get airfoil thickness at a specific location

Parameters:

x0 (float) – X-coordinate location

Returns:

t0 – Airfoil thickness at x0

Return type:

float

get_trailing_edge_slope_angle() float[source]

Get airfoil trailing edge slope angle.

Returns:

slope_angle – Trailing edge slope angle (degree)

Return type:

float

get_trailing_edge_wedge_angle() float[source]

Get airfoil trailing edge wedge angle.

Returns:

wedge_angle – Trailing edge wedge angle (degree)

Return type:

float

get_upper_crest_point() Tuple[float, float, int][source]

Get airfoil upper crest position and curvature.

Returns:

  • x_uc (float) – X-coordinate of the upper crest point

  • y_uc (float) – Y-coordinate of the upper crest point

  • i_uc (int) – Index of the upper crest point

get_volume() float[source]

Get airfoil volume. Volume is also a measure of the airfoil thickness.

Returns:

volume – Airfoil volume

Return type:

float

get_weighted_average_camber() Tuple[float, float][source]

Get airfoil weighted average camber, i.e., the camber is averaged by using thickness as weights.

Returns:

  • c_weight_mean (float) – Weighted average camber

  • x_c_weight_mean (float) – Weighted average camber location

interp_y(x0: float, side='upper') float[source]

Interpolate value from the airfoil surfaces

Parameters:

x0 (float or ndarray) – ndarray/value of x locations to be interpolated.

Returns:

y0 – interpolated coordinates

Return type:

float or ndarray

class cst_modeling.foil.FoilModification(x: ndarray, yu: ndarray, yl: ndarray, n_cst=10)[source]

Bases: object

Modify an airfoil by specifying geometric features and adding bumps

Parameters:
  • x (np.ndarray) – Airfoil x-coordinates

  • yu (np.ndarray) – Airfoil surface y-coordinates

  • yl (np.ndarray) – Airfoil surface y-coordinates

  • n_cst (int) – Number of CST coefficients for the upper and lower surfaces

add_bump(bumps: List[Tuple[float, float, float, str, str]], keep_tmax=False) Tuple[ndarray, ndarray, float, float][source]

Add bumps to the airfoil

Parameters:
  • bumps (list of tuple) – Bump parameters: (xc, h, w, side, kind)

  • keep_tmax (bool) – Keep the maximum thickness of the airfoil

Returns:

  • cst_u, cst_l (np.ndarray) – CST coefficients of the upper and lower surfaces

  • tmax (float) – Maximum thickness of the airfoil

  • rLE (float) – Leading edge radius

add_bump_to_camber(xc: float, h: float, w: float, kind='H') Tuple[ndarray, ndarray, float, float][source]

Add a bump to the airfoil camber.

Parameters:
  • xc (float) – Bump location

  • h (float) – Bump height

  • w (float) – Bump width

  • kind (str) – Bump function type, i.e., ‘G’, ‘H’.

Returns:

  • cst_u, cst_l (np.ndarray) – CST coefficients of the upper and lower surfaces

  • tmax (float) – Maximum thickness of the airfoil

  • rLE (float) – Leading edge radius

add_bump_to_thickness(xc: float, h: float, w: float, kind='H', keep_tmax=False) Tuple[ndarray, ndarray, float, float][source]

Add a bump to the airfoil thickness.

Parameters:
  • xc (float) – Bump location

  • h (float) – Bump height

  • w (float) – Bump width

  • kind (str) – Bump function type, i.e., ‘G’, ‘H’.

  • keep_tmax (bool) – Keep the maximum thickness of the airfoil

Returns:

  • cst_u, cst_l (np.ndarray) – CST coefficients of the upper and lower surfaces

  • tmax (float) – Maximum thickness of the airfoil

  • rLE (float) – Leading edge radius

add_cst_incremental_curves(increment_cst_u=None, increment_cst_l=None, keep_tmax=False) Tuple[ndarray, ndarray, float, float][source]

Add incremental CST curves to the airfoil.

Parameters:
  • increment_cst_u (ndarray or None) – Incremental CST coefficients for the upper or lower surface

  • increment_cst_l (ndarray or None) – Incremental CST coefficients for the upper or lower surface

  • keep_tmax (bool) – Keep the maximum thickness of the airfoil

get_cst_coefficients() Tuple[ndarray, ndarray][source]

Get CST coefficients for the current airfoil

set_camber(c_new: float) Tuple[ndarray, ndarray, float, float][source]

Change the airfoil average camber.

set_camber_front(c_new: float, width_bump=0.9) Tuple[ndarray, ndarray, float, float][source]

Change the airfoil average camber of the front 60% part.

set_camber_rear(c_new: float, width_bump=0.6) Tuple[ndarray, ndarray, float, float][source]

Change the airfoil average camber of the rear 40% part.

set_leading_edge_radius(rLE_new: float, width_bump=0.8) Tuple[ndarray, ndarray, float, float][source]

Change airfoil leading edge radius to a new value (the maximum thickness is kept).

Parameters:
  • rLE_new (float) – New leading edge radius

  • width_bump (float) – Width of the bump added to the airfoil thickness

Returns:

  • cst_u, cst_l (ndarray) – CST coefficients of the upper and lower surfaces

  • tmax (float) – Maximum thickness of the airfoil

  • rLE (float) – Leading edge radius

set_leading_edge_slope_angle(slope_angle_new: float, width_bump=0.2) Tuple[ndarray, ndarray, float, float][source]

Change airfoil leading edge slope angle to a new value.

Parameters:
  • slope_angle_new (float) – New leading edge slope angle

  • width_bump (float) – Width of the bump added to the airfoil thickness

Returns:

  • cst_u, cst_l (np.ndarray) – CST coefficients of the upper and lower surfaces

  • tmax (float) – Maximum thickness of the airfoil

  • slope_angle_new (float) – Leading edge slope angle (degree)

set_maximum_thickness_location(x_t_new: float, slope0=1.0, slope1=1.0) None[source]

Change airfoil maximum thickness location

set_thickness(t_new: float) None[source]

Change airfoil thickness to a new value

set_thickness_at(x0: float, t_new: float, width_bump=0.4) Tuple[ndarray, ndarray, float, float][source]

Change the airfoil thickness at location x0 to a new value t_new.

set_trailing_edge_slope_angle(slope_angle_new: float, width_bump=0.2) Tuple[ndarray, ndarray, float, float][source]

Change airfoil trailing edge slope angle to a new value.

Parameters:
  • slope_angle_new (float) – New trailing edge slope angle

  • width_bump (float) – Width of the bump added to the airfoil thickness

Returns:

  • cst_u, cst_l (np.ndarray) – CST coefficients of the upper and lower surfaces

  • tmax (float) – Maximum thickness of the airfoil

  • slope_angle_new (float) – Trailing edge slope angle (degree)

set_trailing_edge_wedge_angle(wedge_angle_new: float, width_bump=0.2) Tuple[ndarray, ndarray, float, float][source]

Change airfoil trailing edge wedge angle to a new value.

Parameters:
  • wedge_angle_new (float) – New trailing edge wedge angle

  • width_bump (float) – Width of the bump added to the airfoil thickness

Returns:

  • cst_u, cst_l (np.ndarray) – CST coefficients of the upper and lower surfaces

  • tmax (float) – Maximum thickness of the airfoil

  • wedge_angle_new (float) – Trailing edge wedge angle (degree)

property tail: float

Airfoil trailing edge thickness

cst_modeling.foil.check_validity(x: ndarray, yu: ndarray, yl: ndarray, eps=1e-06) bool[source]

Check if the airfoil is valid

Returns:

is_valid – True if the airfoil is valid, False otherwise

Return type:

bool

1.6. cst_modeling.math

Math functions for the CST modeling package.

class cst_modeling.math.CoordinateTransformation[source]

Bases: object

Transform (x) coordinates to another (x’) coordinates, i.e., x’ = f(x), x in [0,1], x’ in [0,1].

set_function(func: Callable[[ndarray], ndarray]) None[source]

Set the transformation function.

Parameters:

func (Callable[[np.ndarray], np.ndarray]) – transformation function.

set_function_by_interpolation(x: List[float], xp: List[float], slope0=None, slope1=None) None[source]

Set the transformation function by interpolation.

Parameters:
  • x (list of float) – coordinates of the points to be interpolated.

  • xp (list of float) – coordinates of the points to be interpolated.

  • slope0 (float or None) – slope at the two ends, i.e., d(x’)/dx at x=0 and x=1.

  • slope1 (float or None) – slope at the two ends, i.e., d(x’)/dx at x=0 and x=1.

transform(x: ndarray) ndarray[source]

Transform x to x’.

Parameters:

x (ndarray) – input values.

Returns:

x’ – transformed values.

Return type:

ndarray

cst_modeling.math.angle_between_vectors(a: ndarray, b: ndarray, n=None, in_degree=True) float[source]

Calculate the angle between two vectors.

Parameters:
  • a (ndarray [3]) – vectors

  • b (ndarray [3]) – vectors

  • n (ndarray [3]) – positive normal vector, by default None. If None, the angle is in [0, 180] or [0, pi].

  • in_degree (bool) – if True, return the angle in degree.

Returns:

angle – angle between two vectors, in [-180, 180] or [-pi, pi].

Return type:

float

cst_modeling.math.clustcos(i: int, nn: int, a0=0.0079, a1=0.96, beta=1.0) float[source]

Point distribution on x-axis [0, 1]. (More points at both ends)

Parameters:
  • i (int) – index of current point (start from 0)

  • nn (int) – total amount of points

  • a0 (float) – Parameter for distributing points near x=0. Smaller a0, more points near x=0.

  • a1 (float) – Parameter for distributing points near x=1. Larger a1, more points near x=1.

  • beta (float) – Parameter for distribution points.

Return type:

float

Examples

>>> c = clustcos(i, n, a0, a1, beta)
cst_modeling.math.cst_curve(nn: int, coef: array, x=None, xn1=0.5, xn2=1.0, a0=0.0079, a1=0.96) Tuple[ndarray, ndarray][source]

Generating single curve based on CST method.

CST: class shape transformation method (Kulfan, 2008)

Parameters:
  • nn (int) – total amount of points

  • coef (ndarray) – CST coefficients

  • x (ndarray [nn]) – coordinates of x distribution in [0,1] (optional)

  • xn1 (float) – CST parameters

  • xn12 (float) – CST parameters

Returns:

x, y – coordinates

Return type:

ndarray

Examples

>>> x, y = cst_curve(nn, coef, x, xn1, xn2)
cst_modeling.math.cst_foil(nn: int, cst_u, cst_l, x=None, t=None, tail=0.0, xn1=0.5, xn2=1.0, a0=0.0079, a1=0.96)[source]

Constructing upper and lower curves of an airfoil based on CST method

CST: class shape transformation method (Kulfan, 2008)

Parameters:
  • nn (int) – total amount of points

  • cst_u (list or ndarray) – CST coefficients of the upper and lower surfaces

  • cst_l (list or ndarray) – CST coefficients of the upper and lower surfaces

  • x (ndarray [nn]) – x coordinates in [0,1] (optional)

  • t (float) – specified relative maximum thickness (optional)

  • tail (float) – relative tail thickness (optional)

  • xn1 (float) – CST parameters

  • xn12 (float) – CST parameters

Returns:

  • x, yu, yl (ndarray) – coordinates

  • t0 (float) – actual relative maximum thickness

  • R0 (float) – leading edge radius

Examples

>>> x_, yu, yl, t0, R0 = cst_foil(nn, cst_u, cst_l, x, t, tail)
cst_modeling.math.curve_curvature(x: ndarray, y: ndarray) ndarray[source]

Calculate curvature of points in the curve

Parameters:
  • x (ndarray) – coordinates of the curve

  • y (ndarray) – coordinates of the curve

Returns:

curvature – curvature distribution

Return type:

ndarray

Examples

>>> curvature = curve_curvature(x, y)
cst_modeling.math.dis_matrix(xs1: ndarray, xs2: ndarray) ndarray[source]

Calculate the distance between vectors in xs1 and xs2.

Parameters:
  • xs1 (ndarray [n1, nx]) – vectors of all samples.

  • xs2 (ndarray [n2, nx]) – vectors of all samples.

Returns:

RRdis=sqrt(sum((x1-x2)**2)/nx)

Return type:

ndarray [n1, n2]

Examples

>>> RR = dis_matrix(xs1, xs2)

Notes

Suggest each components of vectors in x1 and x2 is 0~1.

cst_modeling.math.dist_clustcos(nn: int, a0=0.0079, a1=0.96, beta=1.0) ndarray[source]

Point distribution on x-axis [0, 1]. (More points at both ends)

Parameters:
  • nn (int) – total amount of points

  • a0 (float) – Parameter for distributing points near x=0. Smaller a0, more points near x=0.

  • a1 (float) – Parameter for distributing points near x=1. Larger a1, more points near x=1.

  • beta (float) – Parameter for distribution points.

Examples

>>> xx = dist_clustcos(n, a0, a1, beta)
cst_modeling.math.extract_slice(data: List[ndarray], locations: List[float], Pref: ndarray, dir_norm: ndarray, dir_ref=array([1., 0., 0.]), zone_id=[], index_xyz=[0, 1, 2], index_var=None, arrange_method='join')[source]

Extract data sliced by planes.

Parameters:
  • data (List[ndarray] [n_zone][ni,nj,nk,nv]) – data of all surfaces.

  • locations (List[float]) – list of distances to the reference point in the given direction.

  • Pref (ndarray [3]) – coordinates of the reference point.

  • dir_norm (ndarray [3]) – direction vector normal to the slice plane (will be normalized).

  • dir_ref (ndarray [3]) – direction vector that roughly sets the xi-axis in the slice plane.

  • fname (str) – file name.

  • zone_id (List[int]) – index of zones in the tecplot format file, start from 0.

  • index_xyz (List[int]) – index of variables in the data for X, Y and Z.

  • index_var (List[int] or None) – index of variables of interest in the data.

  • arrange_method (str) – if ‘join’, keeps the original order of points (suitable for surface with a few blocks). If ‘rearrange’, rearrange points by minimal distance.

Returns:

sections – coordinates and data on the slice.

Return type:

list of ndarray [:,3+nv]

Examples

>>> sections = extract_slice(data, locations, Pref, dir_norm, dir_ref=np.array([1.,0.,0.]),
                zone_id=[], index_xyz=[0,1,2], arrange_method='join')
cst_modeling.math.find_circle_3p(p1, p2, p3) Tuple[float, ndarray][source]

Determine the radius and origin of a circle by 3 points (2D)

Parameters:
  • p1 (list or ndarray [2]) – coordinates of points, [x, y]

  • p2 (list or ndarray [2]) – coordinates of points, [x, y]

  • p3 (list or ndarray [2]) – coordinates of points, [x, y]

Returns:

  • R (float) – radius

  • XC (ndarray [2]) – circle center

Examples

>>> R, XC = find_circle_3p(p1, p2, p3)
cst_modeling.math.fromCylinder(x: ndarray, y: ndarray, z: ndarray, flip=True, origin=[0, 0]) Tuple[ndarray, ndarray, ndarray][source]

Bend the cylinder curve to a 2D plane curve.

Parameters:
  • x (ndarray) – coordinates of the curve on a cylinder. x and y must not be 0 at the same time.

  • y (ndarray) – coordinates of the curve on a cylinder. x and y must not be 0 at the same time.

  • z (ndarray) – coordinates of the curve on a cylinder. x and y must not be 0 at the same time.

  • flip (bool) – if True, flip the X of the extracted plane curve.

  • origin (array_like) – the cylinder origin, [x0, y0] (or [x0, y0, 0]).

Returns:

X, Y, Z – coordinates of the curve bent to the 2D X-Y plane

Return type:

ndarray

Notes

The cylinder’s default origin is (0,0,0), axis is z-axis.

The origin of cylinder and plane curves is the same (0,0,0).

Cylinder: x, y, z ~~ r, theta, z

Plane: X, Y, Z

theta = arctan(y/x)

r = sqrt(x^2+y^2)

z = z

X = r*theta

Y = z

Z = r

cst_modeling.math.interp_from_curve(x0: float | ndarray, x: ndarray, y: ndarray, extrapolate=False) float | ndarray[source]

Interpolate points from curve represented points [x, y].

Parameters:
  • x0 (Union[float, np.ndarray]) – ndarray/value of x locations to be interpolated.

  • x (ndarray) – coordinates of the curve.

  • y (ndarray) – coordinates of the curve.

Returns:

y0 – interpolated coordinates

Return type:

Union[float, np.ndarray]

Examples

>>> y0 = interp_from_curve(x0, x, y)
cst_modeling.math.interpolate_IDW(x0: ndarray, xs: ndarray, ys: ndarray, eps=1e-10) ndarray[source]

Inverse distance weighted interpolation.

Parameters:
  • x0 (ndarray) – coordinates to be interpolated, shape [n0,3].

  • xs (ndarray) – coordinates of the reference points, shape [n, 3].

  • ys (ndarray) – values at the reference points, shape [n, ny].

  • eps (float) – critical distance between x0 to xs.

Returns:

y0 – interpolated values, shape [n0,ny].

Return type:

ndarray

Examples

>>> y0 = interpolate_IDW(x0, xs, ys, eps=1e-10)
cst_modeling.math.intersect_index(x1, y1, x2, y2)[source]

Find the intersect index between two curves.

Parameters:
  • x1 (list or ndarray) – coordinates of curve 1.

  • y1 (list or ndarray) – coordinates of curve 1.

  • x2 (list or ndarray) – coordinates of curve 2.

  • y2 (list or ndarray) – coordinates of curve 2.

Returns:

  • i1, i2 (int) – index of the closest points in curve 1 & 2.

  • points (tuple of ndarray) – tuple of two closest points in curve 1 & 2.

Examples

>>> i1, i2, points = intersect_index(x1, y1, x2, y2)
cst_modeling.math.intersect_point(p1: ndarray, p2: ndarray, p3: ndarray, p4: ndarray)[source]

Calculate intersection point of two segments p1p2 & p3p4.

Parameters:
  • p1 (ndarray) – ndarray [2] or [:,2]

  • p2 (ndarray) – ndarray [2] or [:,2]

  • p3 (ndarray) – ndarray [2] or [:,2]

  • p4 (ndarray) – ndarray [2] or [:,2]

Returns:

pi – ndarray [2] or [:,2]

Return type:

ndarray

cst_modeling.math.intersect_surface_plane(surface: ndarray, P0: ndarray, P1: ndarray, P3: ndarray, within_bounds=False, original_order=False)[source]

Calculate the intersection curve of a surface and a plane.

Parameters:
  • surface (ndarray [ni,nj,3]) – coordinates of surface.

  • P0 (ndarray [3]) – coordinates of three points of plane P0123

  • P1 (ndarray [3]) – coordinates of three points of plane P0123

  • P3 (ndarray [3]) – coordinates of three points of plane P0123

  • within_bounds (bool) – if True, only keep the curve within the bounds of P0123.

  • original_order (bool) – if False, rearrange points to form a smooth curve.

Returns:

  • curve (list of ndarray [3]) – intersection curve.

  • ij_curve (list of [i,j]) – the index of nearest point in surface to each point of curve.

  • xi_curve, yt_curve (ndarray [:]) – relative coordinates in the plane P0123, range in [0,1].

Examples

>>> curve, ij_curve, xi_curve, yt_curve = intersect_surface_plane(surface, P0, P1, P3)
cst_modeling.math.intersect_vec_plane(V0: ndarray, V1: ndarray, P0: ndarray, P1: ndarray, P3: ndarray) Tuple[ndarray, float, float, float][source]

Calculate the intersection point of a vector and a plane.

Parameters:
  • V0 (ndarray [3]) – coordinates of vector: V01.

  • V1 (ndarray [3]) – coordinates of vector: V01.

  • P0 (ndarray [3]) – coordinates of three points of plane P0123.

  • P1 (ndarray [3]) – coordinates of three points of plane P0123.

  • P3 (ndarray [3]) – coordinates of three points of plane P0123.

Returns:

  • xi (ndarray [3]) – intersection point

  • t1, t3 (float) – ratio of xi in P01, P03 direction.

  • rv (float) – ratio of xi in V01 direction.

Examples

>>> xi, t1, t3, rv = intersect_vec_plane(V0, V1, P0, P1, P3)
cst_modeling.math.join_curves(curves: List[ndarray], cri_dup=1e-06) ndarray[source]

Join several curves into one piece.

Parameters:
  • curves (list of ndarray [:,3 or 3+nv]) – coordinates and data of the curves.

  • cri_dup (float) – critical distance to drop duplicated points.

Returns:

new_curve – new curve

Return type:

ndarray [:,3 or 3+nv]

Examples

>>> new_curve = join_curves(curves: list, cri_dup=1e-6)
cst_modeling.math.plane_3points(P0: ndarray, P1: ndarray, P3: ndarray, xs: ndarray, ys: ndarray) ndarray[source]

Calculate the plane function and the coordinates of given points (xs, ys).

The plane function is a*x+b*y+c*z+d=0.

Parameters:
  • P0 (ndarray [3]) – coordinates of three points of plane P0123.

  • P1 (ndarray [3]) – coordinates of three points of plane P0123.

  • P3 (ndarray [3]) – coordinates of three points of plane P0123.

  • xs (ndarray [:] or [:,:]) – X and Y coordinates of plane points.

  • ys (ndarray [:] or [:,:]) – X and Y coordinates of plane points.

Returns:

zs

Return type:

ndarray [:] or [:,:]

Examples

>>> xs = plane_3points(P0, P1, P3, xs, ys)
cst_modeling.math.project_vector_to_plane(v: ndarray, n: ndarray) ndarray[source]

Project a vector v to a plane with normal vector n.

Parameters:
  • v (ndarray [3]) – vector to be projected.

  • n (ndarray [3]) – normal vector of the plane.

Returns:

vp – projected vector.

Return type:

ndarray [3]

cst_modeling.math.rearrange_points(xi: ndarray, yt: ndarray, avg_dir=None, cri_break=0.02, cri_dup=1e-06) Tuple[ndarray, List[int]][source]

Rearrange a list of points in a 2D curve.

Parameters:
  • xi (ndarray [n]) – 2D coordinates of the points.

  • yt (ndarray [n]) – 2D coordinates of the points.

  • avg_dir (None or ndarray [2]) – if ndarray, specified average direction, the start point is fixed for the curve.

  • cri_break (float) – critical ratio to decide whether the point is the end point of the curve.

  • cri_dup (float) – critical distance to drop duplicated points.

Returns:

  • new_curve (ndarray [n,2]) – new curve.

  • old_index (list of int) – the index of point in the original curve.

Examples

>>> new_curve, old_index = rearrange_points(xi, yt, avg_dir=None, cri_break=0.1)

Notes

There are a few assumptions:

  1. it is an open curve with no intersections

2. most of the points are in the correct (local) order, this gives us a average direction of the curve, which can help us find the starting/end point of the curve

  1. the next point is its closest point or the closest point in the average direction

  2. drop duplicated points

cst_modeling.math.reconstruct_curve_by_length(curve: ndarray, n: int) ndarray[source]

Reconstruct the curve with equidistant points.

Parameters:
  • curve (ndarray [:,3]) – coordinates of the curve

  • n (int) – number of points

Returns:

new_curve – coordinates of the new curve

Return type:

ndarray [n,3]

cst_modeling.math.rotate(x: ndarray, y: ndarray, z: ndarray, angle=0.0, origin=[0.0, 0.0, 0.0], axis='X') Tuple[ndarray, ndarray, ndarray][source]

Rotate the 3D curve according to origin

Parameters:
  • x (ndarray) – coordinates of the curve

  • y (ndarray) – coordinates of the curve

  • z (ndarray) – coordinates of the curve

  • angle (float) – rotation angle (deg)

  • origin (list of float) – rotation origin

  • axis ({'X', 'Y', 'Z'}) – rotation axis (angle is defined by the right-hand rule along this axis)

Returns:

x_, y_, z_ – coordinates of the rotated curve

Return type:

ndarray

Examples

>>> x_, y_, z_ = rotate(x, y, z, angle=0.0, origin=[0.0, 0.0, 0.0], axis='X')
cst_modeling.math.rotate_vector(x, y, z, angle=0, origin=[0, 0, 0], axis_vector=[0, 0, 1]) ndarray[source]

Rotate 3D points (vectors) by axis-angle representation.

Parameters:
  • x (float or ndarray [:]) – coordinates of the points.

  • y (float or ndarray [:]) – coordinates of the points.

  • z (float or ndarray [:]) – coordinates of the points.

  • angle (float) – rotation angle (deg) about the axis (right-hand rule).

  • origin (ndarray [3]) – origin of the rotation axis.

  • axis_vector (ndarray [3]) – indicating the direction of an axis of rotation. The input axis_vector will be normalized to a unit vector e. The rotation vector, or Euler vector, is angle*e.

Returns:

points – coordinates of the rotated points

Return type:

ndarray [3] or [:,3]

Examples

>>> points = rotate_vector(x, y, z, angle=0, origin=[0, 0, 0], axis_vector=[0,0,1])

References

https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.transform.Rotation.html#scipy.spatial.transform.Rotation

https://en.wikipedia.org/wiki/Axis%E2%80%93angle_representation

https://en.wikipedia.org/wiki/Rotation_matrix

cst_modeling.math.rotation_3d(pp: ndarray, origin: ndarray, axis: ndarray, angle: float)[source]

The rotation_3d is derived from Chenyu Wu. 2022. 11. 5

### Description This function rotate a set of points based on the origin and the axis given by the inputs

### Inputs pp: The point set that is going to be rotated. pp.shape = (n_points, 3)

origin: The numpy array that defines the origin of the rotation axis. The shape must be (3,0)

axis: The direction of the rotation axis. This axis does not need to be normalized. The shape must be (3,0)

angle: The rotation angle in degree

### Outputs xnew, ynew, znew: The rotated points.

cst_modeling.math.scaled_sigmoid(x: ndarray, b=1) ndarray[source]

Scaled Sigmoid function.

Parameters:
  • x (ndarray) – input values. The sharp transition is at x=0, therefore, x should be in [-1,1].

  • b (float) – sharpness of the sigmoid. A larger b gives a steeper sigmoid. When x in [-1,1], b = 1 gives a almost linear function, b = 10 gives a sigmoid transition with width about 1.0, b = 50 gives a sigmoid transition with width about 0.1.

Returns:

y – output values, scaled to [0,1], i.e., y at x[0] is 0, y at x[-1] is 1.

Return type:

ndarray

cst_modeling.math.smooth_omega_shape_function(x: ndarray, c0=0.1, c1=0.9, b0=50, b1=50) ndarray[source]

Smooth Omega-shape function, the output equals 0 at both ends, 1 at the middle. There can be plateau at the middle and both ends. The function is smooth.

Parameters:
  • x (ndarray) – input values, range in [0,1].

  • c0 (float) – sharp transition location at both ends.

  • c1 (float) – sharp transition location at both ends.

  • b0 (float) – sharpness of the sigmoid at both ends. b = 1 gives an almost A shape function, b = 25 gives a sigmoid transition with width about 0.1, b = 50 gives a sigmoid transition with width about 0.05.

  • b1 (float) – sharpness of the sigmoid at both ends. b = 1 gives an almost A shape function, b = 25 gives a sigmoid transition with width about 0.1, b = 50 gives a sigmoid transition with width about 0.05.

Returns:

y – output values, scaled to [0,1]. The output equals 0 at both ends, 1 at the middle.

Return type:

ndarray

cst_modeling.math.stretch_fixed_point(x: ndarray, y: ndarray, dx=0.0, dy=0.0, xm=None, ym=None, xf=None, yf=None) Tuple[ndarray, ndarray][source]

Linearly stretch a 2D curve when a certain point (on the curve) is fixed.

Parameters:
  • x (ndarray) – coordinates of the 2D curve

  • y (ndarray) – coordinates of the 2D curve

  • dx (float) – movement of the stretched point

  • dy (float) – movement of the stretched point

  • xm ({None, float}) – coordinates of the stretched point. If None, the stretched point is the first element of the curve.

  • ym ({None, float}) – coordinates of the stretched point. If None, the stretched point is the first element of the curve.

  • xf ({None, float}) – coordinates of the fixed point. If None, the fixed point is the last element of the curve.

  • yf ({None, float}) – coordinates of the fixed point. If None, the fixed point is the last element of the curve.

Returns:

x_, y_ – coordinates of the stretched curve

Return type:

ndarray

Examples

>>> x_, y_ = stretch_fixed_point(x, y, dx, dy, xm, ym, xf, yf)
cst_modeling.math.toCylinder(X: ndarray, Y: ndarray, Z: ndarray, flip=True, origin=[0, 0]) Tuple[ndarray, ndarray, ndarray][source]

Bend the plane sections to curves on a cylinder.

Parameters:
  • X (ndarray) – coordinates of the curve on a plane. Z must not be 0.

  • Y (ndarray) – coordinates of the curve on a plane. Z must not be 0.

  • Z (ndarray) – coordinates of the curve on a plane. Z must not be 0.

  • flip (bool) – if True, flip the X of the extracted plane curve.

  • origin (array_like) – the cylinder origin, [x0, y0] (or [x0, y0, 0]).

Returns:

x, y ,z – coordinates of the curve bent to a cylinder.

Return type:

ndarray

Notes

The cylinder’s default origin is (0,0,0), axis is z-axis.

The origin of cylinder and plane curves is the same (0,0,0).

Cylinder: x, y, z ~~ r, theta, z

Plane: X, Y, Z

theta = arctan(y/x)

r = sqrt(x^2+y^2)

z = z

X = r*theta

Y = z

Z = r

cst_modeling.math.transform(xu: ndarray, xl: ndarray, yu: ndarray, yl: ndarray, scale=1.0, rot=None, x0=None, y0=None, xr=None, yr=None, dx=0.0, dy=0.0, projection=False) Tuple[ndarray, ndarray, ndarray, ndarray][source]

Apply chord length, twist angle(deg) and leading edge position to a 2D curve.

The transformation is applied in the following order:

  1. Translation

  2. Scaling

  3. Rotation

Parameters:
  • xu (ndarray) – current 2D curve or unit 2D airfoil.

  • xl (ndarray) – current 2D curve or unit 2D airfoil.

  • yu (ndarray) – current 2D curve or unit 2D airfoil.

  • yl (ndarray) – current 2D curve or unit 2D airfoil.

  • scale (bool) – scale factor, e.g., chord length.

  • rot ({None, float}) – rotate angle (deg), +z direction for x-y plane, e.g., twist angle.

  • x0 (float) – coordinates of the scale center.

  • y0 (float) – coordinates of the scale center.

  • xr (float) – coordinates of the rotation center (rotate after translation and scale).

  • yr (float) – coordinates of the rotation center (rotate after translation and scale).

  • dx (float) – translation vector, e.g., leading edge location.

  • dy (float) – translation vector, e.g., leading edge location.

  • projection (bool) – whether keeps the projection length the same when rotating the section, by default True.

Returns:

xu_new, xl_new, yu_new, yl_new – coordinates of the new 2D curve.

Return type:

ndarray

cst_modeling.math.transform_curve(xx: ndarray, yy: ndarray, dx=0.0, dy=0.0, dz=0.0, scale=1.0, x0=None, y0=None, rot_z=0.0, rot_x=0.0, rot_y=0.0, rot_axis=0.0, xr=None, yr=None, zr=None) Tuple[ndarray, ndarray, ndarray][source]

Transform a 2D (unit) curve to a 3D curve by translation, scaling and rotation.

The transformation is applied in the following order:

  1. Translation

  2. Scaling

    • Scale center: (x0, y0), the first point of the curve by default.

    • Scale factor.

  3. Rotation

    • Rotate about the z axis by rot_z degree.

    • Rotate about the x axis by rot_x degree.

    • Rotate about the y axis by rot_y degree.

    • Rotate about the main axis of the curve by rot_axis degree.

    • Rotate center: (xr, yr, zr), the scale center by default.

Parameters:
  • xx (ndarray) – a 2D (unit) curve.

  • yy (ndarray) – a 2D (unit) curve.

  • dx (float) – translation vector, e.g., leading edge location.

  • dy (float) – translation vector, e.g., leading edge location.

  • scale (bool) – scale factor.

  • x0 (float) – the scale center for the 2D curve in the x-y plane.

  • y0 (float) – the scale center for the 2D curve in the x-y plane.

  • rot_x (float) – rotate angle (degree) about the x, y, z axis.

  • rot_y (float) – rotate angle (degree) about the x, y, z axis.

  • rot_z (float) – rotate angle (degree) about the x, y, z axis.

  • rot_axis (float) – rotate angle (degree) about the main axis of the curve, e.g., the chord line of an airfoil.

  • xr (float) – the rotation center for the 2D curve

  • yr (float) – the rotation center for the 2D curve

  • zr (float) – the rotation center for the 2D curve

Returns:

x, y, z – coordinates of the 3D curve.

Return type:

ndarray

1.7. cst_modeling.io

Input and Output functions for the CST modeling package.

cst_modeling.io.idataline(ni: int, nj: int)[source]

Function for plot3d_to_igs

cst_modeling.io.knotx(ni: int, n_offset=4) ndarray[source]

Function for plot3d_to_igs.

Returns [0, 0, 0, 0, …(ni-n_offset)…, 1.0, 1.0, 1.0, 1.0].

cst_modeling.io.output_curve(x: ndarray, y: ndarray, fname='curve.dat', ID=0) None[source]

Output airfoil data to tecplot ASCII format file.

Parameters:
  • x (ndarray) – coordinates of the curve.

  • y (ndarray) – coordinates of the curve.

  • ID (int) – if ID`=0, create new file and write header. If `ID>0, append to existed file.

cst_modeling.io.output_curves_igs(x: ndarray, y: ndarray, z: ndarray, fname='curve.igs', n_degree=3, is_planar=True)[source]

Output curves in the Initial Graphics Exchange Specification (IGES) format.

Parameters:
  • x (ndarray) – coordinates of the curve(s), [:] or [n_curve,:]

  • y (ndarray) – coordinates of the curve(s), [:] or [n_curve,:]

  • z (ndarray) – coordinates of the curve(s), [:] or [n_curve,:]

  • fname (str) – file name.

  • n_degree (int) – degree of basis functions. 0=Determined by data; 1=Line; 2=Circular arc; 3=Elliptical arc; 4=Parabolic arc; 5=Hyperbolic arc.

  • is_planar (bool) – whether is planar curve in X-Y plane.

References

https://wiki.eclipse.org/IGES_file_Specification

https://filemonger.com/specs/igs/devdept.com/version6.pdf

cst_modeling.io.output_foil(x: ndarray, yu: ndarray, yl: ndarray, fname='airfoil.dat', ID=0) None[source]

Output airfoil data to tecplot ASCII format file

Parameters:
  • x (ndarray) – coordinates of the baseline airfoil.

  • yu (ndarray) – coordinates of the baseline airfoil.

  • yl (ndarray) – coordinates of the baseline airfoil.

  • ID (int) – if ID`=0, create new file and write header. If `ID>0, append to existed file.

cst_modeling.io.output_plot3d(Xs: List[ndarray], Ys: List[ndarray], Zs: List[ndarray], fname='plot3d.xyz', scale=1.0) None[source]

Output surface to fname in plot3d format.

Parameters:
  • Xs (List[np.ndarray] [n0][ns,nn]) – coordinates of multiple surfaces

  • Ys (List[np.ndarray] [n0][ns,nn]) – coordinates of multiple surfaces

  • Zs (List[np.ndarray] [n0][ns,nn]) – coordinates of multiple surfaces

  • fname (str) – the name of the file (*.xyz)

  • scale (float) – scaling factor.

cst_modeling.io.output_plot3d_for_parts(fname: str, *args, scale=1.0) None[source]

Output surfaces of multiple parts in plot3d format.

Parameters:
  • fname (str) – file name.

  • *args (List[List[np.ndarray]]) –

    surfaces of different parts, i.e., part1.surfaces, part2.surfaces, …

    part.surfaces = [[surf_x, surf_y, surf_z], [surf_x, surf_y, surf_z], …]

  • scale (float) – scaling factor.

Examples

>>> output_plot3d_for_surfaces(fname='plot3d', surf1, surf2, surf3)
cst_modeling.io.output_surface(surf: List[ndarray], fname: str, ID=0, zone_name=None) None[source]

Output the surface to *.dat in Tecplot format.

Parameters:
  • surf (List[np.ndarray]) – surface coordinates, i.e., [surf_x, surf_y, surf_z].

  • fname (str) – name of the output file.

  • ID (int) – if ID`=0, create new file and write header. If `ID>0, append to existed file.

  • zone_name (str) – name of the zone.

cst_modeling.io.plot3d_to_igs(fname='igs', plot3d_ext='.xyz', igs_ext='.igs')[source]

Converts Plot3d surface grid file [fname.xyz] to IGES file [fname.igs].

Original Fortran version by Prof. Zhang Yufei: zhangyufei@tsinghua.edu.cn.

Ref: https://wiki.eclipse.org/IGES_file_Specification

cst_modeling.io.read_block_plot3d(lines: list, iLine0: int, ni: int, nj: int, nk: int) Tuple[ndarray, int][source]

Read block data from lines.

Parameters:
  • lines (list of str) – f.readlines() of the entire plot3d formate file

  • iLine0 (int) – the first line of this block is lines[iLine0]

  • ni (int) – size of this block

  • nj (int) – size of this block

  • nk (int) – size of this block

Returns:

  • xyz (ndarray) – coordinates, shape [ni,nj,nk,3].

  • iLine0_new (int) – index of line after read.

Examples

>>> xyz, iLine0_new = read_block_plot3d(lines, iLine0, ni, nj, nk)
cst_modeling.io.read_tecplot(fname='tecplot.dat')[source]

Read a tecplot format data file.

Parameters:

fname (str) – file name.

Returns:

  • data (list of ndarray) – data of all zones, shape [ni,nj,nk,nv].

  • name_var (list of str) – name of variables.

  • titles (list of str) – title of zones

Examples

>>> data, name_var, titles = read_tecplot(fname='tecplot.dat')

1.8. cst_modeling.operation

Classes and functions for the operation of surfaces.

class cst_modeling.operation.GuideCurve(n_section=2, n_spanwise=101, section_s_loc=[0.0, 1.0])[source]

Bases: object

Guide curve for surface lofting.

Parameters:
  • n_section (int) – The number of sections to loft.

  • n_spanwise (int) – The number of spanwise points for the surface between the two sections.

  • section_s_loc (List[float]) – The parametric coordinates of the sections along the guide curve, range in [0, 1].

n_total

The total number of points for the guide curve.

Type:

int

global_guide_curve

The global guide curve to sweep the sections.

Type:

Dict[str, np.ndarray] [n_total]

Notes

The guide curve is defined by the parametric coordinates of the sections along the curve. The guide curve contains the following attributes:

  • ‘s’ : The parametric coordinates of the guide curve, range in [0, 1].

  • ‘x’ : The x-coordinates of the guide curve.

  • ‘y’ : The y-coordinates of the guide curve.

  • ‘z’ : The z-coordinates of the guide curve.

  • ‘scale’ : The scaling factor of the profile at s.

  • ‘rot_x’ : The rotation angle (degree) about the x-axis of the profile at s.

  • ‘rot_y’ : The rotation angle (degree) about the y-axis of the profile at s.

  • ‘rot_z’ : The rotation angle (degree) about the z-axis of the profile at s.

  • ‘rot_axis’ : The rotation angle (degree) about the main axis of the profile at s.

generate_by_interp1d(global_control_s: ndarray, global_values: ndarray, key='x', kind='linear') None[source]

Update the global guide curve by a linear interpolation.

Parameters:
  • global_control_s (np.ndarray [n_point]) – The global parametric coordinates of the control points, range in [0, 1].

  • global_values (np.ndarray [n_point]) – The global values of the control points.

  • key (str) – The key of the global guide curve to update.

  • kind (str) – The kind of interpolation. See scipy.interpolate.interp1d.

generate_by_spline(global_control_s: ndarray, global_values: ndarray, slope_s0=None, slope_s1=None, key='x', periodic=False) None[source]

Update the global guide curve by a spline interpolation.

Parameters:
  • global_control_s (np.ndarray [n_point]) – The global parametric coordinates of the control points, range in [0, 1].

  • global_values (np.ndarray [n_point]) – The global values of the control points.

  • slope_s0 (float) – The slope of the curve at the start and end points.

  • slope_s1 (float) – The slope of the curve at the start and end points.

  • key (str) – The key of the global guide curve to update.

generate_rotation_angle_with_tangent(key='all') None[source]

Generate the rotation angle with the tangent of the guide curve.

Parameters:

key (str) –

The key of the global guide curve to update. It can be ‘all’, ‘rot_axis’, ‘rot_x’, ‘rot_y’, ‘rot_z’.

  • ’all’ means all rotation angles are updated based on the tangent of the guide curve.

  • ’rot_axis’ means the main axis of the section is firstly defined by ‘rot_z’, the section is then rotated about the main axis.

generate_with_value(**kwargs) None[source]

Generate the global guide curve for a new key, or update the value of an existed key.

Parameters:

kwargs (Dict[str, np.ndarray]) – The keyword arguments to update the guide curve.

get_local_guide_curve(i_sec0: int) Dict[str, ndarray][source]

Get the local guide curve.

Parameters:

i_sec0 (int) – The index of the section with smaller index of the two sections that construct a surface.

get_local_parametric_coordinate(i_sec0: int) Tuple[ndarray, int, int][source]

Get the local parametric coordinates of the guide curve.

Parameters:

i_sec0 (int) – The index of the section with smaller index of the two sections that construct a surface.

Returns:

  • local_s (np.ndarray [n_spanwise]) – The local parametric coordinates of the guide curve, range in [0, 1].

  • index0, index1 (int) – The indices of the two sections in the global guide curve.

get_value(key: str, i_span_point: int) float[source]

Get the value of the guide curve at a specific point.

Parameters:
  • key (str) – The key of the guide curve.

  • i_span_point (int) – The index of the spanwise point, in range [0, n_total-1].

Returns:

value – The value of the guide curve at the specified point.

Return type:

float

init_guide_curve() None[source]

Initialize the 3D guide curve, a straight line segment by default.

output(fname='guide-curve.dat')[source]

Output the guide curve to a file.

set_value(key: str, i_span_point: int, value: float) None[source]

Set the value of the guide curve at a specific point.

Parameters:
  • key (str) – The key of the guide curve.

  • i_span_point (int) – The index of the spanwise point, in range [0, n_total-1].

  • value (float) – The value to set.

update_by_spline(control_s: ndarray, values: ndarray, slope_s0=None, slope_s1=None, key='x', periodic=False) None[source]

Update a segment of the global guide curve by a spline interpolation. The segment is determined by the global parametric coordinates of the control points.

Parameters:
  • control_s (np.ndarray [n_point]) – The global parametric coordinates of the control points, range in [0, 1].

  • values (np.ndarray [n_point]) – The global values of the control points.

  • slope_s0 (float) – The slope of the curve at the start and end points.

  • slope_s1 (float) – The slope of the curve at the start and end points.

  • key (str) – The key of the global guide curve to update.

update_rotation_angle_with_tangent(key='all', sections: List[Tuple[int, int]] | None = None) None[source]

Update a segment of the global guide curve, changing the rotation angle based on the tangent of guide curve.

Parameters:
  • key (str) – The key of the global guide curve to update. It can be ‘all’, ‘rot_x’, ‘rot_y’, ‘rot_z’, ‘rot_axis’.

  • sections (List[Tuple[int, int]]) – sections to be rotated, by default None. None means all sections are rotated. The tuple is (start, end) index of the sections. For example, [(0, 1), (2, 4)] means the sections between the 0-1 and 2-4 sections are rotated.

update_section_with_value(key: str, interp_func: callable, sections: Tuple[int, int] | None = None) None[source]

Update a segment of the global guide curve, changing the rotation angle based on the tangent of guide curve.

Parameters:
  • key (str) – The key of the global guide curve to update. Including ‘x’, ‘y’, ‘z’, ‘scale’, ‘rot_x’, ‘rot_y’, ‘rot_z’, ‘rot_axis’.

  • interp_func (callable) – The interpolation function to update the section. y = interp_func(s), where s is the local parametric coordinates of the guide curve between the specified sections, s ranges in [0, 1].

  • section (Tuple[int, int]) – index of sections, the surface between the start and end sections are updated. By default None, means the entire surface is updated.

update_with_value(**kwargs) None[source]

Update the global guide curve.

Parameters:

kwargs (Dict[str, np.ndarray]) – The keyword arguments to update the guide curve. Including ‘x’, ‘y’, ‘z’, ‘scale’, ‘rot_x’, ‘rot_y’, ‘rot_z’, ‘rot_axis’.

class cst_modeling.operation.Lofting(profiles: List[List[ndarray]], global_guide_curve: GuideCurve, is_guide_curve_at_LE=True)[source]

Bases: object

Create a surface by sweeping and blending multiple 2D profiles (unit curves), using a guide curve that runs through the leading/trailing edge point of each profile.

Parameters:
  • profiles (List[List[np.ndarray]] [n_profile][2][n_point]) – The 2D profiles.

  • global_guide_curve (GuideCurve) – The global guide curve to sweep the profiles.

  • is_guide_curve_at_LE (bool) –

    If True, the guide curve runs through the leading edge point (0,0) of each 2D profile. Otherwise, it runs through the point (1,0) of each 2D profile, which is the trailing edge of a unit curve.

    This changes the scaling and rotation center of the profiles, which consequently affects the actual x,y-coordinates of the leading edge. When the rotation center is at the leading edge, the coordinates of the leading edge are directly defined by the xLE, yLE, zLE attributes of the profiles. However, when the rotation center is at the trailing edge, the coordinates of the leading edge are defined by the xLE, yLE, zLE attributes of the profiles, and the scaling factor and rotation angle.

n_profile

The number of profiles to loft.

Type:

int

n_spanwise

The number of spanwise points for the surface between the two profiles.

Type:

int

n_total

The total number of points for the guide curve.

Type:

int

surfs

The 3D coordinates of the surfaces.

Type:

List[List[np.ndarray]] [n_profile-1][3][n_spanwise, n_point]

create_spanwise_profiles(kind='linear') List[List[ndarray]][source]

Create the spanwise profiles for the surface.

Returns:

spanwise_profiles – The profiles for transformation along the spanwise direction.

Return type:

List[List[np.ndarray, np.ndarray]] [n_total][2][n_point]

sweep(interp_profile_kind=None) List[List[ndarray]][source]

Sweep the profiles along the guide curve.

Parameters:

interp_profile_kind (str) – The kind of interpolation for the spanwise profiles. If None, the profiles are interpolated linearly from the two end profiles. Otherwise, the profiles are interpolated by the specified kind. See scipy.interpolate.interp1d.

Returns:

surfs – The 3D coordinates of the surfaces.

Return type:

List[List[np.ndarray]] [n_profile-1][3][n_spanwise, n_point]

class cst_modeling.operation.Lofting_2Profile(profile_0: List[ndarray], profile_1: List[ndarray], n_spanwise=101, is_guide_curve_at_LE=True)[source]

Bases: object

Create a surface by sweeping and blending two 2D profiles (unit curves), using a guide curve that runs through the leading/trailing edge point of each profile.

Parameters:
  • profile_0 (List[np.ndarray] [2][n_point]) – The 2D profiles for interpolation, [profile_x, profile_y].

  • profile_1 (List[np.ndarray] [2][n_point]) – The 2D profiles for interpolation, [profile_x, profile_y].

  • n_spanwise (int) – The number of spanwise points for the surface between the two profiles.

  • is_guide_curve_at_LE (bool) –

    If True, the guide curve runs through the leading edge point (0,0) of each 2D profile. Otherwise, it runs through the point (1,0) of each 2D profile, which is the trailing edge of a unit curve.

    This changes the scaling and rotation center of the profiles, which consequently affects the actual x,y-coordinates of the leading edge. When the rotation center is at the leading edge, the coordinates of the leading edge are directly defined by the xLE, yLE, zLE attributes of the profiles. However, when the rotation center is at the trailing edge, the coordinates of the leading edge are defined by the xLE, yLE, zLE attributes of the profiles, and the scaling factor and rotation angle.

parametric_coord

The parametric coordinates of the guide curve, range in [0, 1].

Type:

np.ndarray [n_spanwise]

guide_curve

The guide curve to sweep the profiles.

  • ‘s’ : The parametric coordinates of the guide curve, range in [0, 1].

  • ‘x’ : The x-coordinates of the guide curve.

  • ‘y’ : The y-coordinates of the guide curve.

  • ‘z’ : The z-coordinates of the guide curve.

  • ‘scale’ : The scaling factor of the profile at s.

  • ‘rot_x’ : The rotation angle about the x-axis of the profile at s.

  • ‘rot_y’ : The rotation angle about the y-axis of the profile at s.

  • ‘rot_z’ : The rotation angle about the z-axis of the profile at s.

  • ‘rot_axis’ : The rotation angle about the main axis of the profile at s.

Type:

Dict[str, np.ndarray] [n_spanwise]

n_point

The number of points in the 2D profiles.

Type:

int

check_profiles() None[source]

Check the two profiles.

init_guide_curve() None[source]

Initialize the 3D guide curve, a straight line segment by default.

sweep(spanwise_profiles=None) Tuple[ndarray, ndarray, ndarray][source]

Sweep the two 2D profiles along the guide curve.

Parameters:

spanwise_profiles (List[List[np.ndarray]] [n_spanwise][2][n_point]) – The profiles for transformation along the spanwise direction. If None, the profiles are interpolated linearly from the two end profiles.

Returns:

surf_x, surf_y, surf_z – The 3D coordinates of the surface.

Return type:

Tuple[np.ndarray, np.ndarray, np.ndarray]

update_guide_curve(**kwargs) None[source]

Update the guide curve.

Parameters:

kwargs (Dict[str, np.ndarray]) – The keyword arguments to update the guide curve. Including ‘x’, ‘y’, ‘z’, ‘scale’, ‘rot_x’, ‘rot_y’, ‘rot_z’, ‘rot_axis’.

class cst_modeling.operation.Lofting_Revolution(profiles: List[List[ndarray]], n_spanwise=101, section_s_loc=[0.0, 0.25, 0.5, 0.75], section_x: float | List[float] = 0.0, section_radius: float | List[float] = 0.0, section_scale: float | List[float] = 1.0)[source]

Bases: object

Create a surface of revolution by sweeping and blending multiple 2D profiles (unit curve), using a guide curve that runs through the reference point of each profile. The default rotation axis is the x-axis.

Parameters:
  • profiles (List[List[np.ndarray]] [n_profile][2][n_point]) – The 2D profiles.

  • n_spanwise (int) – The number of circumferential (spanwise) points for the surface between the two sections.

  • section_s_loc (List[float] [n_profile]) – The parametric coordinates of the sections along the guide curve, range in [0, 1].

  • section_radius (Union[float, List[float]]) – The radius of the sections. If float, the radius is constant for all sections.

  • section_x (Union[float, List[float]]) – The x-coordinate of the leading edge of the sections. If float, the x-coordinate is constant for all sections.

  • section_scale (Union[float, List[float]]) – The scaling factor of the sections. If float, the scaling factor is constant for all sections.

n_profile

The number of profiles to loft.

Type:

int

n_section

The number of sections in the surface, i.e., n_profile + 1.

Type:

int

n_point

The number of points in the 2D profiles.

Type:

int

n_total

The total number of points for the guide curve.

Type:

int

guide_curve

The global guide curve to sweep the profiles.

Type:

GuideCurve

surfs

The 3D coordinates of the surfaces.

Type:

List[List[np.ndarray]] [n_profile][3][n_spanwise, n_point]

check_profiles() None[source]

Check the two profiles.

create_circumferential_profiles(kind='linear') List[List[ndarray]][source]

Create the circumferential profiles for the surface.

Parameters:

kind (str) – The kind of interpolation for the circumferential profiles. See scipy.interpolate.interp1d. Another option is ‘periodic’.

Returns:

spanwise_profiles – The profiles for transformation along the circumferential direction, i.e., [profile_x, profile_y].

Return type:

List[List[np.ndarray, np.ndarray]] [n_total][2][n_point]

init_default_guide_curve(section_s_loc: List[float]) None[source]

Initialize the default guide curve object. It has a piecewise linear distribution along the span, defined by the section parameters.

Parameters:

section_s_loc (List[float] [n_section]) – The parametric coordinates of the sections along the guide curve, range in [0, 1].

property section_s_loc: List[float]

The parametric coordinates of the sections along the guide curve, range in [0, 1].

length: n_section

sweep(interp_profile_kind='linear') List[List[ndarray]][source]

Sweep the profiles along the guide curve.

Parameters:

interp_profile_kind (str) – The kind of interpolation for the circumferential profiles. See scipy.interpolate.interp1d.

Returns:

surfs – The 3D coordinates of the surfaces.

Return type:

List[List[np.ndarray]] [n_profile][3][n_spanwise, n_point]

2. cst_modeling.tools

2.1. tools.naca

Python 2 and 3 code to generate 4 and 5 digit NACA profiles

Notes

The NACA airfoils are airfoil shapes for aircraft wings developed by the National Advisory Committee for Aeronautics (NACA). The shape of the NACA airfoils is described using a series of digits following the word “NACA”. The parameters in the numerical code can be entered into equations to precisely generate the cross-section of the airfoil and calculate its properties.

Reference:

https://en.wikipedia.org/wiki/NACA_airfoil

Code reference:

https://github.com/dgorissen/naca

Pots of the Matlab code available here:

http://www.mathworks.com/matlabcentral/fileexchange/19915-naca-4-digit-airfoil-generator http://www.mathworks.com/matlabcentral/fileexchange/23241-naca-5-digit-airfoil-generator

Copyright (C) 2011 by Dirk Gorissen <dgorissen@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

cst_modeling.tools.naca.interpolate(xa, ya, queryPoints)[source]

A cubic spline interpolation on a given set of points (x,y) Recalculates everything on every call which is far from efficient but does the job for now should eventually be replaced by an external helper class

cst_modeling.tools.naca.linspace(start, stop, np)[source]

Emulate Matlab linspace

cst_modeling.tools.naca.naca(number: str, n: int, finite_TE=False, half_cosine_spacing=False)[source]

Generate NACA 4 or 5 series airfoil.

Parameters:
  • number (str) – NACA airfoil number.

  • n (int) – number of points on upper/lower surface.

  • finite_TE (bool) – if True, generate an airfoil with a finite thickness trailing edge. Otherwise, the airfoil has a zero thickness trailing edge.

  • half_cosine_spacing (bool) – if True, the point distribution in the x-axis is half-cosine-based spacing. Otherwise, uses linear spacing.

Returns:

X, Z – airfoil coordinates, length 2*n+1.

Return type:

ndarray

cst_modeling.tools.naca.naca4(number, n, finite_TE=False, half_cosine_spacing=False)[source]

Returns 2*n+1 points in [0 1] for the given 4 digit NACA number string

cst_modeling.tools.naca.naca5(number, n, finite_TE=False, half_cosine_spacing=False)[source]

Returns 2*n+1 points in [0 1] for the given 5 digit NACA number string

cst_modeling.tools.naca.naca_to_cst(NACA_series: str, n_cst=7, nn=51) Tuple[ndarray, ndarray][source]

Get CST parameters of a NACA series airfoil.

Parameters:
  • NACA_series (str) – 4 or 5 digit NACA number string

  • n_cst (int) – number of CST coefficients

  • nn (int) – total amount of points

Returns:

cst_u, cst_l – CST coefficients

Return type:

ndarray

Examples

>>> cst_u, cst_l = naca_to_cst(NACA_series, n_cst, nn)

2.2. tools.auxiliary

Auxiliary functions for surface modeling

class cst_modeling.tools.auxiliary.DeflectSurf(surf: Surface, z0, z1, r0, r1, trans_len=0.5)[source]

Bases: object

Deflecting surface by axis defined by (x0, y0, z0) and (z1, y1, z1).

Movable region: chord-wise ratio from r0 to 1, span-wise from z0 to z1

>>> DeflectSurf(surf: Surface, z0, z1, r0, r1, trans_len=0.5)
Parameters:
  • z0 (float) – span-wise coordinates of the start and end sections

  • z1 (float) – span-wise coordinates of the start and end sections

  • r0 (float) – chord-wise ratio defining the deflection axis

  • r1 (float) – chord-wise ratio defining the deflection axis

  • trans_len (float) – span-wise transition length (m)

LE0, LE1, TE0, TE1

[x, y, z], LE & TE coordinates of the two end sections of the deflection region

Type:

ndarray

AX0, AX1

[x, y, z], axis ends coordinates. By default, AX = (1-r)*LE + r*TE

Type:

ndarray

i_sec0, i_sec1

section index to locate z0 and z1

Type:

int

set_axis(x0, y0, x1, y1)[source]

Define the rotation axis.

AX0, AX1: ndarray, [x, y, z], axis ends coordinates

If by default, (x, y) = (1-r)*LE + r*TE.

class cst_modeling.tools.auxiliary.WingVariableCamber(n_sec=0, name='WingVC', fname='Wing.txt', **kwargs)[source]

Bases: Surface

Wing with variable camber, sub-class of surface class.

Parameters:
  • n_sec (int) – number of control sections (2D if set to 0 or 1)

  • tail (float) – tail thickness (m)

  • name (str) – name of the surface

  • fname (str) – name of control file

  • nn (int) – number of points in the unit 2D curve’s xx, by default 1001.

  • ns (int) – number of points in the sweep direction between sections, by default 101.

  • projection (bool) – whether keeps the projection length the same when rotating the section, by default True.

  • flap_loc (List[float] [2*n_flap]) – z coordinates of the flap ends, i.e., [z_flap1_1, z_flap1_2, z_flap2_1, z_flap2_2, …]

  • flap_trans (float) – transition length of the flap deflection

  • flap_angle (List[float] [n_flap]) – deflection angle of the flaps

  • axis_xloc (List[float] [n_flap]) – chord-wise ratio of the flap rotation axis

  • axis_dy (List[float] [n_flap]) – scaled y location of the rotation axis

Notes

  • +x: flow direction (m)

  • +y: upside (m)

  • +z: span-wise (m)

  • twist: +z direction (deg)

  • chord: chord length (m)

  • thick: relative maximum thickness

  • tail: absolute tail thickness (m)

build(split=True, one_piece=False, f_tecplot='Wing.dat', f_plot3d='Wing.xyz')[source]

Build wing geometry.

Parameters:
  • split (bool) – generate [surfs] as upper and lower separately

  • one_piece (bool) – combine the spanwise sections into one piece (for tecplot format)

  • f_tecplot (str) – file name of tecplot format file. If None, do not output.

  • f_plot3d (str) – file name of tecplot format file. If None, do not output.

cst_modeling.tools.auxiliary.section_flap(sec: Section, ratio: float, angle: float, dy_axis=None) None[source]

Deflect flap by angle (degree) of a section. Flap starts from chord-wise ratio = ratio.

Parameters:
  • sec (Section object) – section to be deflected

  • ratio (float) – chord-wise ratio of the flap rotation axis

  • angle (float) – deflection angle (degree), +z direction for x-y plane

  • dy_axis (float, optional) – scaled y location of the rotation axis

2.3. tools.nacelle

Nacelle profiles for lofting to a surface of revolution.

  • flow through nacelle (FTN);

  • powered engine nacelle (PEN), or with powered nacelle (WPN);

References

[1] “Comparison of Overwing and Underwing Nacelle Aeropropulsion Optimization for Subsonic Transport Aircraft”, Journal of Aircraft, 2024, Vol. 61, No. 2.

https://doi.org/10.2514/1.C037508

[2] “Non-axisymmetric aero-engine nacelle design by surrogate-based methods”, Aerospace Science and Technology, 2021, Vol. 117, 106890.

https://doi.org/10.1016/j.ast.2021.106890

[3] “Impact of Droop and Scarf on the Aerodynamic Performance of Compact Aero-Engine Nacelles”, AIAA SciTech, 2020.

https://doi.org/10.2514/6.2020-1522

class cst_modeling.tools.nacelle.NacelleIntakeHighlight(l_intake: float, theta_droop: float, theta_scarf: float, n_circum=101, circum_control_psi=[0.0, 90.0, 180.0, 270.0], circum_control_r_highlight: float | List[float] = 1.0)[source]

Bases: object

The three-dimensional highlight point curve of the intake face.

Parameters:
  • offset_y_intake (float) – Offset of the intake face center from the axis of rotation.

  • l_intake (float) – Offset of the intake face center from the fan face, i.e., the intake length.

  • theta_droop (float) – Centre-line droop angle (degree), i.e., arctan(offset_y_intake/l_intake). After the revolution around the engine axis, the contoured intake was morphed by the droop angle, measured as the offset between the engine and the inlet centre-line.

  • theta_scarf (float) – Highlight scarf angle (degree). The geometry was scarfed by rotating the highlight plane around the intake face center.

  • n_circum (int) – The number of circumferential points for the intake highlight curve.

  • circum_control_psi (List[float]) – Circumferential location of control sections.

  • circum_control_r_highlight (Union[float, List[float]]) – Radius of the intake highlight point to the intake face center. If float, the radius is constant for all sections.

calculate() Tuple[ndarray, ndarray][source]

Calculate highlight point curve of the intake.

Returns:

  • curve (np.ndarray [n_n_circum, 3]) – Highlight point coordinates in 3D space, i.e., (x, y, z).

  • psi_curve (np.ndarray [n_n_circum, 4]) – Highlight point coordinates in 3D space, described in parametric coordinates, i.e., (psi, x, y, z).

get_coordinate_2d(psi: float) ndarray[source]

Get the highlight point coordinate at a given circumferential angle.

Parameters:

psi (float) – Circumferential angle (degree).

Returns:

point – Highlight point coordinate in 3D space, i.e., (x, y, z).

Return type:

np.ndarray [3]

get_coordinate_3d(psi: float) ndarray[source]

Get the highlight point coordinate at a given circumferential angle.

Parameters:

psi (float) – Circumferential angle (degree).

Returns:

point – Highlight point coordinate in 3D space, i.e., (x, y, z).

Return type:

np.ndarray [3]

class cst_modeling.tools.nacelle.PoweredNacelleProfile(psi=0.0, n_point_segment=201)[source]

Bases: object

Two-dimensional profile of a powered engine nacelle.

The reference point (0,0) is located at the intersection of rotation axis and the fan inlet face. The definition of the profile parameters can be found in Figure 1 of [2].

The intake face center is the same for all profiles in different meridional angles, which locates at (-l_intake, offset_y_intake, 0.0).

Nacelle profile consists of the following curves:

  • Outer cowl surface: (3,4);

  • Inlet surface: (3,2);

  • Bypass duct outer and inner surfaces: (5,4), (6,7);

  • Core duct outer and inner surfaces: (9,8), (10,11);

  • Spinner (conical surface): (0,1);

  • Core cowl (conical surface): (7, 8);

  • Core plug (conical surface): (11,12);

  • Fan face intake (planar surface): (1,2);

  • Bypass duct inlet (planar surface): (5,6);

  • Core duct inlet (planar surface): (9,10);

Nacelle profile has the following features:

  • l_fore: fore-body length;

  • l_lip: lip length;

  • r_if: initial fore-body radius;

  • r_throat: inlet throat radius;

  • r_max: maximum radius;

  • theta_airfoil: airfoil geometric incidence angle (degree);

  • theta_bp = bypass exit angle (degree);

  • theta_cr = core exit angle (degree);

  • theta_nac = nacelle boat tail angle (degree);

  • x_max: Axial location of maximum radius;

  • x_thr: Axial location of inlet throat;

Parameters:
  • psi (float) – Profile’s meridional angle (degree), [0, 360]. Zero angle corresponds to the half x-y plane with positive y.

  • n_point_segment (int, optional) – Number of points for each segment of the profile. The default is 201.

params

Nacelle profile parameters.

Type:

Dict[str, float]

segment_points

Nacelle profile segment points.

Type:

Dict[int, np.ndarray]

profile_segments

Nacelle profile segments.

Type:

Dict[str, np.ndarray]

features

Nacelle profile features.

Type:

Dict[str, float]

profile_x, profile_y

Nacelle profile coordinates.

Type:

np.ndarray [n_point_profile]

bypass_duct_inner_profile() None[source]

Generate bypass duct inner surface curve, i.e., profile segment (6) between segment points (6,7).

bypass_duct_outer_profile() None[source]

Generate bypass duct outer surface curve, i.e., profile segment (4) between segment points (4,5).

Must run after outer_cowl_profile.

calculate_profile_features() None[source]

Calculate nacelle profile features:

  • l_fore: fore-body length;

  • l_lip: lip length;

  • r_if: initial fore-body radius;

  • r_throat: inlet throat radius;

  • r_max: maximum radius;

  • theta_airfoil: airfoil geometric incidence angle (degree);

  • theta_bp = bypass exit angle (degree);

  • theta_cr = core exit angle (degree);

  • theta_nac = nacelle boat tail angle (degree);

  • x_max: Axial location of maximum radius;

  • x_thr: Axial location of inlet throat;

calculate_profile_segments() None[source]

Calculate nacelle profile segments:

  • Spinner (conical surface): (0,1);

  • Fan face intake (planar surface): (1,2);

  • Inlet surface: (3,2);

  • Outer cowl surface: (3,4);

  • Bypass duct outer surface: (5,4);

  • Bypass duct inlet (planar surface): (5,6);

  • Bypass duct inner surface: (6,7);

  • Core cowl (conical surface): (7, 8);

  • Core duct outer surface: (9,8);

  • Core duct inlet (planar surface): (9,10);

  • Core duct inner surface: (10,11);

  • Core plug (conical surface): (11,12);

calculate_segment_points() None[source]

Calculate nacelle profile segment end points based on the profile parameters.

core_duct_inner_profile() None[source]

Generate core duct inner surface curve, i.e., profile segment (10) between segment points (10,11).

core_duct_outer_profile() None[source]

Generate core duct outer surface curve, i.e., profile segment (8) between segment points (8,9).

create_straight_line(x0: float, y0: float, x1: float, y1: float) ndarray[source]

Generate a straight line

Parameters:
  • x0 (float) – Starting point coordinates.

  • y0 (float) – Starting point coordinates.

  • x1 (float) – Ending point coordinates.

  • y1 (float) – Ending point coordinates.

Returns:

line – Straight line coordinates.

Return type:

np.ndarray [n_point_segment, 2]

get_profile() Dict[ndarray, ndarray][source]

Get nacelle profile segments.

Returns:

profile_x, profile_y – Nacelle profile coordinates.

Return type:

np.ndarray

inlet_profile() None[source]

Generate inlet curve, i.e., profile segment (2) between segment points (2,3).

Must run after outer_cowl_profile.

property n_point_profile: int

Number of points for the nacelle profile.

property n_segment: int

Number of nacelle profile segments.

outer_cowl_profile() None[source]

Generate outer cowl curve, i.e., profile segment (3) between segment points (3,4).

plot(show=True) None[source]

Plot nacelle profile.

set_parameters(theta_spinner: float, r_spinner: float, r_fan: None | float, highlight_x: float, highlight_y: float, intake_face_center: ndarray, l_nacelle: float, r_te: float, l_fan: float, r_bypass_outer: float, r_bypass_inner: float, x_core_cowl_0: float, y_core_cowl_0: float, x_core_cowl_1: float, y_core_cowl_1: float, x_core_duct: float, r_core_outer: float, r_core_inner: float, x_core_plug_0: float, y_core_plug_0: float, x_core_plug_1: float, cst_u: List[float], cst_l: List[float], bypass_inner_angle: float = 0.0, bypass_inner_control_points: List[Tuple[float, float]] | None = None, core_outer_control_points: List[Tuple[float, float]] | None = None, core_inner_control_points: List[Tuple[float, float]] | None = None) None[source]

Set profile parameters.

Parameters:
  • cst_u (List[float]) – Upper and lower CST coefficients of the airfoil profile.

  • cst_l (List[float]) – Upper and lower CST coefficients of the airfoil profile.

  • bypass_inner_angle (float) – Bypass duct inner surface half-angle (degree) at point (6).

  • bypass_inner_control_points (List[Tuple[float, float]], optional) – Control points for the bypass duct inner surface. The default is None.

  • core_outer_control_points (List[Tuple[float, float]], optional) – Control points for the core duct outer surface. The default is None.

  • core_inner_control_points (List[Tuple[float, float]], optional) – Control points for the core duct inner surface. The default is None.

  • parameters (Profile)

  • theta_spinner (-)

  • r_spinner (-)

  • r_fan (-)

  • intake_face_center (-)

  • highlight_x (-)

  • highlight_y (-)

  • l_nacelle (-)

  • r_te (-)

  • l_fan (-)

  • r_bypass_outer (-)

  • r_bypass_inner (-)

  • x_core_cowl_0 (-)

  • y_core_cowl_0 (-)

  • x_core_cowl_1 (-)

  • y_core_cowl_1 (-)

  • x_core_duct (-)

  • r_core_outer (-)

  • r_core_inner (-)

  • x_core_plug_0 (-)

  • y_core_plug_0 (-)

  • x_core_plug_1 (-)