Skip to content

pyflange.stats

Probability distributions and random samplers for probabilistic flange analyses.

This module contains tools for the probabilistic analysis of flanged connections. In particular, two categories of tools are provided:

  • Probability distributions for some flange properties.
  • Samplers: random realization generators for flange properties.

The provided probability distributions are:

  • gap_height_distribution (IEC 61400-6 AMD1)
  • gap_height_distribution_ED2 and gap_angle_distribution_ED2 (IEC 61400-6 ED2)

The samplers are just Python generator functions that yield random values. Samplers can be used in a loop or to generate random values via the python next function. The following general-purpose samplers are available:

  • sampler
  • norm_sampler
  • lognorm_sampler
  • weibull_sampler
  • beta_sampler
  • product_sampler
  • clayton_copula_sampler
  • clayton_gap_sampler
  • fatigue_case_sampler

The following samplers implement the stochastic model of the IEC 61400-6 background documents (refs. [1] and [5]):

  • standard_gap_sampler
  • standard_gap_sampler_ED2
  • standard_PolynomialLFlangeSegment_sampler
  • standard_markov_matrix_sampler
  • standard_bolt_fatigue_curve_sampler

An example of how to use the above generators to perform a Monte Carlo simulation is given in the Monte Carlo in Python tutorial.

Random values are drawn from the numpy global random generator, so a simulation can be made reproducible with numpy.random.seed.

References

The reference numbers are the same in all the PyFlange modules (see the references page). This module cites:

  • [1] Seidel, M.: IEC 61400-6 AMD1 Background document. Fatigue design for ring flange connections in wind turbine support structures. Rev00, Siemens Gamesa, 2024. The stochastic model is given in its Table 7.
  • [2] IEC 61400-6:2020+AMD1:2025 CSV. Wind energy generation systems - Part 6: Tower and foundation design requirements. Consolidated version,
  • The design gap height is defined in section 6.7.5.2.
  • [5] Seidel, M.: IEC 61400-6 AMD1 & ED2 Background document. Rev01, draft 2026-08-04, Siemens Gamesa. The ED2 gap heights are given in section 2.2.4 and the stochastic model in section 6.4 (Table 8).

Functions:

gap_height_distribution

gap_height_distribution(flange_diameter, flange_flatness_tolerance, gap_length)

Evaluates the gap height probability distribution according to IEC 61400-6 AMD1.

The gap height is modeled as a log-normal random variable, whose mean value and coefficient of variation depend on the flange diameter, the flatness tolerance and the gap length (ref. [2], section 6.7.5.2, eqs. (32) to (38)). The design gap height is the 95% quantile of this distribution (ref. [2], eqs. (39) and (40)). The formulae may be used for flange diameters up to 10 m.

Parameters:

  • flange_diameter (float) –

    The outer diameter of the flange, expressed in meters.

  • flange_flatness_tolerance (float) –

    The local flatness tolerance u_tol,1m of ref. [2], expressed in mm/mm (non-dimensional, e.g. 0.0014 for 1.4 mm/m).

  • gap_length (float) –

    The length of the gap, expressed in meters and measured at the outer edge of the flange.

Returns:

  • rv_frozen –

    A frozen SciPy log-normal distribution (scipy.stats.lognorm) representing the gap height stochastic variable, expressed in meters.

Example

The following example creates a gap distribution and then calculates the 95% quantile of the gap height.

from pyflange.stats import gap_height_distribution

D = 7.50      # Flange diameter in meters
u = 0.0014    # Flatness tolerance (non-dimensional)
L = 1.22      # Gap length
gap_dist = gap_height_distribution(D, u, L)     # a lognorm distribution object

u95 = gap_dist.ppf(0.95)    # PPF is the inverse of CDF. See scipy.stats.lognorm documentation.

gap_height_distribution_ED2

gap_height_distribution_ED2(flange_diameter, flange_flatness_tolerance, gap_length)

Evaluates the gap height probability distribution proposed for IEC 61400-6 ED2.

The gap height is modeled as a Weibull random variable, whose shape and scale parameters depend on the flange diameter, the flatness tolerance and the gap angle (ref. [5], section 2.2.4, eqs. (25) to (28)). The ED2 design gap height is the 75% quantile of this distribution (ref. [5], eq. (24)).

Parameters:

  • flange_diameter (float) –

    The outer diameter of the flange, in meters.

  • flange_flatness_tolerance (float) –

    The flatness tolerance, in mm/mm (non-dimensional).

  • gap_length (float) –

    The length of the gap, in meters, measured at the outer edge of the flange.

Returns:

  • rv_frozen –

    A frozen SciPy Weibull distribution (scipy.stats.weibull_min) representing the gap height, in meters.

Example
from math import pi
from pyflange.stats import gap_height_distribution_ED2

D = 7.50                         # Flange diameter in meters
u = 0.0014                       # Flatness tolerance (1.4 mm/m)
L = pi/6 * D/2                   # Length of a 30 deg gap
dist = gap_height_distribution_ED2(D, u, L)
k_design = dist.ppf(0.75)        # ED2 design gap height (75% quantile)

gap_angle_distribution_ED2

gap_angle_distribution_ED2(flange_diameter, flange_flatness_tolerance)

Evaluates the gap angle probability distribution used for ED2 Monte Carlo simulations.

The gap angle is modeled as a Beta random variable defined over the interval [0, pi], whose parameters depend on the flange diameter and flatness tolerance. This distribution is used together with gap_height_distribution_ED2. Note that it is not given in refs. [2] and [5].

Parameters:

  • flange_diameter (float) –

    The outer diameter of the flange, in meters.

  • flange_flatness_tolerance (float) –

    The flatness tolerance, in mm/mm (non-dimensional).

Returns:

  • rv_frozen –

    A frozen SciPy Beta distribution (scipy.stats.beta) representing the gap angle, in radians.

sampler

sampler(random_variable)

Generic distribution-based sampler.

Parameters:

  • random_variable (rv_continuous) –

    Any SciPy continuous random variable.

Yields:

  • float –

    A random realization of the passed random variable, at every next call.

Example

The following example creates a Normal distribution sampler and generates three realizations.

from scipy.stats import norm
ndist = norm(12.0, 2.0) # normal distribution with mean value 12 and standard deviation 2.

samp = sampler(ndist)   # sampler based on the ndist distribution

val1 = next(samp)       # A random value from ndist distribution
val2 = next(samp)       # Another random value from ndist distribution
val3 = next(samp)       # Yet another random value from ndist distribution

norm_sampler

norm_sampler(mean, cv)

Sampler based on a Normal distribution.

Parameters:

  • mean (float) –

    Mean value of the normal distribution.

  • cv (float) –

    Coefficient of variation of the normal distribution.

Returns:

  • Generator –

    A normal distribution sampler with given mean value and coefficient of variation.

Example

The following example creates a Normal distribution sampler and generates three realizations.

samp = norm_sampler(12.0, 0.25)   # normal sampler with mean 12.0
                                  # and CoV = 0.25.

val1 = next(samp)   # A random value from the normal distribution
val2 = next(samp)   # Another random value from the normal distribution
val3 = next(samp)   # Yet another random value from the normal distribution

lognorm_sampler

lognorm_sampler(mean, cv)

Sampler based on a Log-Normal distribution.

Parameters:

  • mean (float) –

    Mean value of the log-normal distribution.

  • cv (float) –

    Coefficient of variation of the log-normal distribution.

Returns:

  • Generator –

    A log-normal distribution sampler with given mean value and coefficient of variation.

Example

The following example creates a Log-Normal distribution sampler and generates three realizations.

samp = lognorm_sampler(12.0, 0.25)  # log-normal sampler with
                                    # mean value 12.0 and CoV = 0.25.

val1 = next(samp)   # A random value from the log-normal distribution
val2 = next(samp)   # Another random value from the log-normal distribution
val3 = next(samp)   # Yet another random value from the log-normal distribution

weibull_sampler

weibull_sampler(shape, scale=1.0)

Sampler based on a Weibull distribution.

Parameters:

  • shape (float) –

    Shape parameter of the Weibull distribution.

  • scale (float, default: 1.0 ) –

    Scale parameter of the Weibull distribution. Defaults to 1.0.

Returns:

  • Generator –

    A Weibull distribution sampler with given scale and shape parameters.

Example

The following example creates a Weibull distribution sampler and generates three realizations.

samp = weibull_sampler(1.5, 2)  # Weibull sampler with  
                                # shape 1.5 and scale 2.0

val1 = next(samp)   # A random value from the Weibull distribution
val2 = next(samp)   # Another random value from the Weibull distribution
val3 = next(samp)   # Yet another random value from the Weibull distribution

beta_sampler

beta_sampler(a, b, x0=0, x1=1)

Sampler based on a Beta distribution.

Parameters:

  • a (float) –

    Shape parameter alpha.

  • b (float) –

    Shape parameter beta.

  • x0 (float, default: 0 ) –

    Lower bound of the variable definition interval. If omitted, it defaults to 0.

  • x1 (float, default: 1 ) –

    Upper bound of the variable definition interval. If omitted, it defaults to 1.

Returns:

  • Generator –

    A Beta distribution sampler with given shape parameters and definition interval boundaries.

Example

The following example creates a Beta distribution sampler and generates three realizations.

samp = beta_sampler(2, 5)  # Beta sampler with  
                           # alpha=2, beta=5, defined in [0,1].

val1 = next(samp)   # A random value from the Beta distribution
val2 = next(samp)   # Another random value from the Beta distribution
val3 = next(samp)   # Yet another random value from the Beta distribution

standard_gap_sampler

standard_gap_sampler(flange_diameter, flange_flatness_tolerance, gap_angle_sampler=lognorm_sampler(100 * deg, 1.0), gap_shape_factor_sampler=norm_sampler(1.0, 0.15), gap_height_cap=2.0)

Sampler that generates random flange gaps according to IEC 61400-6 AMD1.

For each realization, a gap angle is drawn from gap_angle_sampler, the gap height is then drawn from the distribution returned by gap_height_distribution for that angle (ref. [2], section 6.7.5.2), and the gap shape factor is drawn from gap_shape_factor_sampler. Realizations are discarded and redrawn when the gap angle is not between 0 and 180 degrees, or when the gap height exceeds gap_height_cap times the 95th percentile of its distribution.

The default shape factor distribution, N(1.0, 0.15), is the one of the stochastic model of ref. [1], Table 7. In ref. [5] (section 6.4.6) the shape factor is no longer used, because the shape effects are included in the ED2 gap height distribution (see standard_gap_sampler_ED2).

Parameters:

  • flange_diameter (float) –

    The outer diameter of the flange, in meters.

  • flange_flatness_tolerance (float) –

    The flatness tolerance in mm/mm.

  • gap_angle_sampler (Generator, default: lognorm_sampler(100 * deg, 1.0) ) –

    A sampler for the gap angle, in radians. Defaults to a log-normal sampler with mean 100 deg and CoV = 1.0.

  • gap_shape_factor_sampler (Generator, default: norm_sampler(1.0, 0.15) ) –

    A sampler for the gap shape factor. Defaults to a normal sampler with mean 1.0 and CoV = 0.15.

  • gap_height_cap (float, default: 2.0 ) –

    The generated gap height will be capped at gap_height_cap * p95, where p95 is the 95th percentile of the gap height distribution. If omitted, it defaults to 2.0.

Yields:

  • Gap –

    A random gap, with random height, angle and shape factor.

Example

The following example creates a standard gap sampler and generates three realizations.

# Gap sampler for a 7.5 m flange with flatness tolerance 1.4 mm/m
samp = standard_gap_sampler(7.5, 0.0014)

gap1 = next(samp)  # A random gap
gap2 = next(samp)  # Another random gap
gap3 = next(samp)  # Yet another random gap

print(gap1.height, gap1.angle, gap1.shape_factor)

standard_gap_sampler_ED2

standard_gap_sampler_ED2(flange_diameter, flange_flatness_tolerance)

Sampler that generates random flange gaps for IEC 61400-6 ED2.

For each realization, a gap angle is drawn from the distribution returned by gap_angle_distribution_ED2 and the gap height is then drawn from the distribution returned by gap_height_distribution_ED2 for that angle (ref. [5], section 2.2.4). The gap shape factor is always 1.0, because the shape effects are included in the gap height distribution (ref. [5], section 6.4.6).

Parameters:

  • flange_diameter (float) –

    The outer diameter of the flange, in meters.

  • flange_flatness_tolerance (float) –

    The flatness tolerance in mm/mm.

Yields:

  • Gap –

    A random gap, with random height and angle.

Example
# ED2 gap sampler for a 7.5 m flange with flatness tolerance 1.4 mm/m
samp = standard_gap_sampler_ED2(7.5, 0.0014)
gap = next(samp)

product_sampler

product_sampler(dist1, dist2)

Sampler of the product of two independent random variables.

Parameters:

  • dist1 (rv_frozen) –

    Distribution of the first factor.

  • dist2 (rv_frozen) –

    Distribution of the second factor.

Yields:

  • float –

    The product of a realization of dist1 and a realization of dist2.

Example
from scipy.stats import norm, lognorm
samp = product_sampler(norm(1.0, 0.1), lognorm(0.1))
value = next(samp)

clayton_copula_sampler

clayton_copula_sampler(theta, marginal_dist1, marginal_dist2)

Sampler of two random variables joined by a Clayton copula.

The copula realizations are generated with the conditional inverse method: given two independent uniform variables u and w, the second copula variable is

\[v = \left(u^{-\theta} \left(w^{-\theta/(1+\theta)} - 1\right) + 1\right)^{-1/\theta}\]

and the two variables are then mapped to the marginal distributions via their inverse cumulative distribution functions. The Kendall's rank correlation of the two variables is \(\tau = \theta / (\theta + 2)\).

Parameters:

  • theta (float) –

    Clayton copula parameter. Must be positive.

  • marginal_dist1 (rv_frozen) –

    Marginal distribution of the first variable.

  • marginal_dist2 (rv_frozen) –

    Marginal distribution of the second variable.

Yields:

  • ndarray –

    An array [x1, x2] containing a joint realization of the two variables.

Raises:

  • ValueError –

    If theta is not positive.

Example
from scipy.stats import norm, lognorm
samp = clayton_copula_sampler(2.0, norm(10, 1), lognorm(0.5))
x1, x2 = next(samp)

clayton_gap_sampler

clayton_gap_sampler(theta, height_marginal_dist, angle_marginal_dist, shape_factor_sampler)

Sampler that generates random flange gaps with correlated height and angle.

The gap height and gap angle are generated as two variables joined by a Clayton copula (see clayton_copula_sampler), while the gap shape factor is generated independently.

Parameters:

  • theta (float) –

    Clayton copula parameter. Must be positive.

  • height_marginal_dist (rv_frozen) –

    Marginal distribution of the gap height, in meters.

  • angle_marginal_dist (rv_frozen) –

    Marginal distribution of the gap angle, in radians.

  • shape_factor_sampler (Generator) –

    A sampler for the gap shape factor.

Yields:

  • Gap –

    A random gap.

standard_PolynomialLFlangeSegment_sampler

standard_PolynomialLFlangeSegment_sampler(a, b, s, t, R, central_angle, Zg, bolt, Do, washer, nut, preload_sampler, ppl_sampler, dft_sampler, gap_sampler, tilt_sampler=lognorm_sampler(0.1 * deg, 0.5), E=210000000000.0, G=80770000000.0, s_ratio=1.0, r=0.01, k_shell='interp', settlement_factor=1.0, segment_class=None)

A sampler that yields random pyflange PolynomialLFlangeSegment objects.

For each realization, a random gap and a random flange tilt are drawn, and the bolt preload is sampled and averaged over the bolts affected by the gap (half of the bolts subtended by the gap angle, at least one), to account for the larger preload scatter at small gap angles (ref. [5], sections 4.4 and 6.4.1). The returned segment already includes the effect of the sampled preload losses (settlement and plastic), so its PPL and DFT attributes are zero.

The stochastic model of ref. [5], section 6.4 suggests a plastic loss with mean 0.03 and standard deviation 0.01 (norm_sampler(0.03, 1/3)), a dry film thickness with mean 250 µm and standard deviation 30 µm (norm_sampler(250e-6, 0.12)) and an inside flange inclination LN(0.1°, 0.5) (the default tilt_sampler).

Parameters:

  • a (float) –

    Distance between inner face of the flange and center of the bolt hole.

  • b (float) –

    Distance between center of the bolt hole and center-line of the shell.

  • s (float) –

    Shell thickness.

  • t (float) –

    Flange thickness.

  • R (float) –

    Shell outer curvature radius.

  • central_angle (float) –

    Angle subtended by the flange segment.

  • Zg (float) –

    Load applied to the flange segment shell at rest (normally dead weight of tower + RNA, divided by the number of bolts). Negative if compression.

  • bolt (Bolt) –

    Bolt object representing the flange segment bolt.

  • Do (float) –

    Bolt hole diameter.

  • washer (Washer) –

    Bolt washer.

  • nut (Nut) –

    Bolt nut.

  • preload_sampler (Generator) –

    Random preload sampler.

  • ppl_sampler (Generator) –

    Sampler of the percentage of pretension losses due to plastic deformation (non-dimensional, e.g. 0.03 for 3%).

  • dft_sampler (Generator) –

    Dry film thickness sampler.

  • gap_sampler (Generator) –

    Sampler of pyflange.flangesegments.Gap objects, such as standard_gap_sampler.

  • tilt_sampler (Generator, default: lognorm_sampler(0.1 * deg, 0.5) ) –

    Random tilt angle sampler. Sampled angles are reduced to the interval [0, pi]. Defaults to lognorm_sampler(0.1*deg, 0.50).

  • E (float, default: 210000000000.0 ) –

    Young modulus of the flange. Defaults to 210e9.

  • G (float, default: 80770000000.0 ) –

    Shear modulus of the flange. Defaults to 80.77e9.

  • s_ratio (float, default: 1.0 ) –

    Ratio of bottom shell thickness over s. Defaults to 1.0.

  • r (float, default: 0.01 ) –

    Rounding between flange and shell. Defaults to 0.01.

  • k_shell (str | float | None, default: 'interp' ) –

    Custom shell stiffness. If 'interp' (default), the stiffness is interpolated from the tabulated FEA results, as a function of the gap angle (see pyflange.flangesegments.shell_stiffness). If a number, it's used as the stiffness. If None, a simplified formula is used.

  • settlement_factor (float, default: 1.0 ) –

    Factor reducing the amount of bolt settlement, to be taken as 1.0 for torque tightening and 0.5 for tension tightening. If omitted, it defaults to 1.0.

  • segment_class (type, default: None ) –

    The class of the generated flange segments: PolynomialLFlangeSegment or one of its subclasses, such as PolynomialLFlangeSegmentED2. If omitted, it defaults to PolynomialLFlangeSegment.

Yields:

Example

The following example creates a L-Flange segment sampler and generates three random flange segments.

from math import pi
from metrum.units import mm, um, kN, deg

import pyflange.stats as stats
from pyflange.bolts import StandardMetricBolt, RoundNut
N_BOLTS = 156

fseg_samp = standard_PolynomialLFlangeSegment_sampler (
        a = 150*mm,        # distance between inner face of the flange and center of the bolt hole
        b = 122*mm,        # distance between center of the bolt hole and center-line of the shell
        s =  54*mm,        # shell thickness
        t = 172*mm,        # flange thickness
        R = 4000*mm,       # shell outer curvature radius
        central_angle = 2*pi / N_BOLTS,  # angle subtended by the flange segment

        Zg = -18044*kN / N_BOLTS,      # load applied to the flange segment shell at rest

        # Bolt object representing the flange segment bolt
        bolt = StandardMetricBolt("M80", "10.9", shank_length=160*mm,
                shank_diameter_ratio=76.1/80, stud=True),

        Do = 86*mm,               # Bolt hole diameter
        washer = None,            # Bolt washer
        nut = RoundNut("M80"),    # Bolt nut

        # bolt preload random sampler and preload losses parameters
        preload_sampler = stats.norm_sampler(2932.24*kN, 0.03), 
        ppl_sampler = stats.norm_sampler(0.03, 1/3),
        dft_sampler = stats.norm_sampler(250*um, 0.12),

        # gap object random sampler
        gap_sampler = stats.standard_gap_sampler(
                    flange_diameter = 8000*mm,
                    flange_flatness_tolerance = 0.0014,   # 1.4 mm/m
                    gap_angle_sampler = stats.lognorm_sampler(100*deg, 1.0),
                    gap_shape_factor_sampler = stats.norm_sampler(1.0, 0.15)
                ),

        s_ratio = 1.0,              # Ratio of bottom shell thickness over s.
        settlement_factor = 0.50    # Settlement reduction for tension tightening.
    )

fseg1 = next(fseg_samp)     # A random L-Flange segment object
fseg2 = next(fseg_samp)     # Another random L-Flange segment object
fseg3 = next(fseg_samp)     # Yet another random L-Flange segment object

standard_markov_matrix_sampler

standard_markov_matrix_sampler(markov_matrix, mean_range_coeff=1.0, range_CoV=0.12)

Sampler that generates a random Markov matrix.

Each realization has the same cycles, means and duration as the design Markov matrix, while its ranges are scaled by a single log-normally distributed coefficient: the fatigue load factor X_FLS of the stochastic model of refs. [1] (Table 7) and [5] (section 6.3.1 and Table 8), with mean 1.0 and CoV 0.12. As explained in ref. [5], section 6.3.1, only the load ranges are scaled, not the mean values.

Parameters:

  • markov_matrix (MarkovMatrix) –

    The deterministic design Markov matrix.

  • mean_range_coeff (float, default: 1.0 ) –

    The mean value of the coefficient multiplying the load ranges of markov_matrix, assumed log-normally distributed. Defaults to 1.0.

  • range_CoV (float, default: 0.12 ) –

    The coefficient of variation of the coefficient multiplying the load ranges. Defaults to 0.12.

Yields:

standard_bolt_fatigue_curve_sampler

standard_bolt_fatigue_curve_sampler(bolt_nominal_diameter, mean_stress_factor=1.0, stress_factor_CoV=0.1, DS_ref_mean=62 * MPa)

Sampler that generates random bolt S-N curves.

The reference stress range of each curve is the product of DS_ref_mean and a normally distributed random coefficient: with the default values, this is the variable X_FAT ~ N(62 MPa, 0.10) of the stochastic model of refs. [1] (Table 7) and [5] (Table 8). The curves have the slopes, knee point and size effect of pyflange.fatigue.BoltFatigueCurve and no material safety factor (gamma_M = 1.0).

Parameters:

  • bolt_nominal_diameter (float) –

    The nominal diameter of the bolt, in meters.

  • mean_stress_factor (float, default: 1.0 ) –

    The mean value of the fatigue class coefficient, assumed normally distributed. Defaults to 1.

  • stress_factor_CoV (float, default: 0.1 ) –

    The coefficient of variation of the fatigue class coefficient, assumed normally distributed. Defaults to 0.10.

  • DS_ref_mean (float, default: 62 * MPa ) –

    The mean value of the fatigue curve reference stress range. If unknown it could be calculated as 1.24 times the fatigue class. If omitted, it defaults to 62 MPa.

Yields:

fatigue_case_sampler

fatigue_case_sampler(fseg_samp, markov_matrix_samp, fatigue_curve_samp, allowable_damage_samp, SMF=1.0)

Sampler that generates random fatigue cases.

Each realization combines one realization of each of the given samplers. The stochastic model of refs. [1] and [5] uses a log-normal allowable damage (Miner's rule model uncertainty) with mean 1.0 and CoV 0.30, e.g. lognorm_sampler(1.0, 0.30).

Parameters:

  • fseg_samp (Generator) –

    A pyflange.flangesegments.FlangeSegment sampler, such as standard_PolynomialLFlangeSegment_sampler.

  • markov_matrix_samp (Generator) –

    A pyflange.fatigue.MarkovMatrix sampler.

  • fatigue_curve_samp (Generator) –

    A pyflange.fatigue.BoltFatigueCurve sampler.

  • allowable_damage_samp (Generator) –

    A float sampler that generates random allowable damages.

  • SMF (float | Generator, default: 1.0 ) –

    Stress Multiplication Factor. If it is a sampler, a new SMF will be generated for every next fatigue case. If it is a float, it will be applied to every next fatigue case. If omitted, it defaults to 1.0.

Yields: