On this page
EngineeringLib
Engineering mathematics domain covering fluid dynamics, thermodynamics, signal processing, and comprehensive unit conversion for Free Pascal.
Depends on: MathBase
Learning routes
Beginner route
Copy and run the double-real engineering quick start. It checks a Reynolds number, Carnot efficiency, and typed length conversion, including the output 1 m = 3.2808 ft. These scalar calls allocate no numerical workspace.
Common tasks and algorithm choice
| Task | Start with | Contract or failure guidance |
|---|---|---|
| Fluid/pipe calculation | TFluidDynamicsKit |
Fluid methods |
| Heat/thermodynamic calculation | TThermodynamicsKit |
Thermodynamic methods |
| FFT convolution or filtering | TDSPKit |
DSP selection |
| Legacy power-of-two spectrum | TSignalKit |
Signal methods |
| Physical unit conversion | TUnitConversionKit |
Conversion contract |
Advanced route
Run example 19 for spectral and streaming DSP or example 21 for block convolution and filters. Array results allocate by default; stateful filters retain bounded state. Complex spectra and reusable state are explicit steps beyond the same double-real signal arrays.
Units
| Unit | File | Class |
|---|---|---|
EngineeringLib.Common |
EngineeringLib.Common.pas | Shared typed exception hierarchy |
EngineeringLib.FluidDynamics |
EngineeringLib.FluidDynamics.pas | TFluidDynamicsKit — core implementation |
EngineeringLib.Thermodynamics |
EngineeringLib.Thermodynamics.pas | TThermodynamicsKit |
EngineeringLib.Signal |
EngineeringLib.Signal.pas | TSignalKit |
EngineeringLib.DSP |
EngineeringLib.DSP.pas | TDSPKit, TOverlapAddConvolver, TOverlapSaveConvolver, TStreamingFIR, TStreamingBiquad |
EngineeringLib.UnitConversion |
EngineeringLib.UnitConversion.pas | TUnitConversionKit |
EngineeringLib.Velocity |
EngineeringLib.Velocity.pas | Alias → TVelocityKit = TFluidDynamicsKit |
EngineeringLib.Pressure |
EngineeringLib.Pressure.pas | Alias → TPressureKit = TFluidDynamicsKit |
---
Applied DSP in 1.8
EngineeringLib.DSP adds arbitrary-length, batched, and 2-D FFTs, explicit normalisation, direct/FFT and overlap-add/save convolution, rational resampling, spectral estimation, analytic/cross spectra, an orthonormal Haar transform, and bounded-state FIR/biquad processing. Selection, accuracy, ownership, and state-size contracts are in the applied numerics guide.
| Workflow | Stable entry point | State/output convention |
|---|---|---|
| Independent same-or-mixed length FFT jobs | TDSPKit.TransformBatch |
One owned spectrum per input; no shared transform state |
| Finite block convolution | TOverlapAddConvolver.ProcessBlock then Flush |
Block outputs followed by exactly the pending tail |
| Continuous block convolution | TOverlapSaveConvolver.ProcessBlock |
Output length equals input block length; history is taps minus one |
| Dyadic Haar analysis/synthesis | TDSPKit.HaarTransform(Input, Inverse) |
Orthonormal scaling; power-of-two length |
| Ordinary causal FIR | TStreamingFIR.ProcessBlock |
Coefficient snapshot plus taps-minus-one history |
All stateful processors validate an entire block before committing state. Independent record instances are reentrant; concurrent mutation of one record requires caller synchronization. The portable serial direct and FFT paths are the stable oracle. Equiripple and Chebyshev/elliptic/Bessel design, wavelet packets, and parallel/SIMD dispatch remain outside 1.8.
Exception Hierarchy
EEngineeringError
├── EFluidDynamicsError
├── EThermodynamicsError
├── ESignalError
└── EUnitConversionError
The focused alias units also export EVelocityError = EFluidDynamicsError and EPressureError = EFluidDynamicsError, so existing applications importing only one focused unit keep the identical exception type. New code should use EFluidDynamicsError with the common TFluidDynamicsKit path. The focused aliases remain supported and receive no 1.9.3 deprecation warning.
Catch a specific subtype when recovering from one engineering domain, or EEngineeringError when a caller handles all EngineeringLib validation errors uniformly. Try... unit-name APIs continue to return False for unknown input; non-Try APIs raise EUnitConversionError.
---
EngineeringLib.FluidDynamics — TFluidDynamicsKit
FluidDynamics Constants
| Constant | Value | Description |
|---|---|---|
GravityAcceleration |
9.80665 m/s² | Standard gravity |
WaterDensity |
997.0 kg/m³ | Water at 25 °C |
AirDensity |
1.225 kg/m³ | Air at standard conditions |
DynamicViscosityAir |
1.81 × 10⁻⁵ Pa·s | Air at 25 °C |
KinematicViscosityAir |
1.48 × 10⁻⁵ m²/s | Air at 25 °C |
Bernoulli's Principle
Bernoulli equation for incompressible, inviscid flow: P₁ + ½ρv₁² + ρgh₁ = P₂ + ½ρv₂² + ρgh₂
class function BernoulliPressure(Density, Pressure1, Velocity1, Height1, Velocity2, Height2: Double): Double;
class function BernoulliVelocity(Density, Pressure1, Velocity1, Height1, Pressure2, Height2: Double): Double;
class function BernoulliHeight(Density, Pressure1, Velocity1, Height1, Pressure2, Velocity2: Double): Double;
Flow Rate
class function CalculateVolumeFlowRate(Area, Velocity: Double): Double; // Q = A·v
class function MassFlowRate(Density, Area, Velocity: Double): Double; overload; // ṁ = ρ·A·v
class function MassFlowRate(Density, VolumeFlowRate: Double): Double; overload; // ṁ = ρ·Q
Reynolds Number
class function ReynoldsNumber(Density, Velocity, CharacteristicLength, DynamicViscosity: Double): Double;
class function ReynoldsNumberKinematic(Velocity, CharacteristicLength, KinematicViscosity: Double): Double;
Pipe Flow
| Method | Description |
|---|---|
FrictionHeadLoss(f, L, D, v) |
Darcy-Weisbach: hf = f·(L/D)·(v²/2g) |
HazenWilliamsHeadLoss(L, D, Q, CHW) |
Hazen-Williams formula for water pipes |
LaminarFrictionFactor(Re) |
f = 64/Re (laminar flow) |
TurbulentFrictionFactor(Re, ε/D [, Tol, MaxIter]) |
Colebrook-White equation; Re >= 4000, Tol > 0, MaxIter > 0 |
BlasiusFrictionFactor(Re) |
f = 0.316/Re^0.25 (smooth pipes, 4000 ≤ Re ≤ 10⁵) |
Dimensionless Numbers
| Method | Formula | Significance |
|---|---|---|
FroudeNumber(v, L) |
Fr = v/√(g·L) | Inertial vs gravitational forces |
WeberNumber(ρ, v, L, σ) |
We = ρv²L/σ | Inertial vs surface tension |
EulerNumber(ΔP, ρ, v) |
Eu = ΔP/(ρv²) | Pressure vs inertial forces |
MachNumber(v, c) |
Ma = v/c | Flow vs speed of sound |
StrouhalNumber(f, L, v) |
St = fL/v | Oscillating flow |
PrandtlNumber(μ, cp, k) |
Pr = μcp/k | Momentum vs thermal diffusivity |
NusseltNumber(h, L, k) |
Nu = hL/k | Convective vs conductive heat transfer |
Aerodynamics
class function LiftForce(CL, Density, Velocity, ReferenceArea: Double): Double;
class function DragForce(CD, Density, Velocity, ReferenceArea: Double): Double;
class function DynamicPressure(Density, Velocity: Double): Double; // q = ½ρv²
class function StagnationPressure(StaticPressure, DynamicPressure: Double): Double;
class function PressureCoefficient(P, P_inf, Rho_inf, V_inf: Double): Double;
Compressible Flow
class function SpeedOfSound(SpecificHeatRatio, GasConstant, Temperature: Double): Double; // c = √(γRT)
class function StagnationTemperatureRatio(MachNumber, SpecificHeatRatio: Double): Double;
class function StagnationPressureRatio(MachNumber, SpecificHeatRatio: Double): Double;
class function IsentropicAreaRatio(MachNumber, SpecificHeatRatio: Double): Double;
Pumps and Turbines
class function PumpPower(Density, FlowRate, Head, Efficiency: Double): Double; // P = ρgQH/η
class function PumpHead(PressureDiff, Density, InletVelocity,
OutletVelocity, HeightDiff: Double): Double;
class function PumpSpecificSpeed(RPM, FlowRate, Head: Double): Double; // Ns = N√Q/H^(3/4)
class function TurbinePower(Efficiency, Density, FlowRate, Head: Double): Double; // P = η·ρgQH
PumpHead uses the Bernoulli energy-head relation ΔP/(ρg) + (v₂²-v₁²)/(2g) + Δz. PressureDiff and HeightDiff are signed outlet-minus-inlet differences. Pump/turbine flow rate and head must be non-negative, density must be positive, and efficiency must be in (0, 1].
Open Channel Flow
class function ChezyVelocity(C, R, S: Double): Double; // v = C·√(R·S)
class function ManningVelocity(n, R, S: Double): Double; // v = (1/n)·R^(2/3)·S^(1/2)
class function CriticalDepthRectangular(UnitDischarge: Double): Double; // yc = (q²/g)^(1/3)
class function OpenChannelFroudeNumber(Velocity, Depth: Double): Double;
Fluid Properties
class function DensityWater: Double; // ≈ 997 kg/m³ at 25 °C
class function DynamicViscosityWater: Double; // Pa·s at 25 °C
class function KinematicViscosityWater: Double; // m²/s at 25 °C
---
EngineeringLib.Thermodynamics — TThermodynamicsKit
Thermodynamics Constants
| Constant | Value |
|---|---|
BoltzmannConstant |
1.380649 × 10⁻²³ J/K |
StefanBoltzmannConstant |
5.670374419 × 10⁻⁸ W/(m²·K⁴) |
IdealGasConstant |
8.314462618 J/(mol·K) |
AvogadroConstant |
6.02214076 × 10²³ mol⁻¹ |
StandardAtmosphere |
101325 Pa |
StandardTempK |
273.15 K (= 0 °C) |
Heat Transfer
| Method | Formula | Description |
|---|---|---|
HeatConductionRate(k, A, ΔT, d) |
Q = k·A·ΔT/d | Fourier's law (conduction) |
HeatConvectionRate(h, A, ΔT) |
Q = h·A·ΔT | Newton's law of cooling |
HeatRadiationRate(ε, A, T_s, T_sur) |
Q = ε·σ·A·(T_s⁴ − T_sur⁴) | Stefan-Boltzmann radiation; temperatures in K |
HeatEnergyChange(m, c, ΔT) |
Q = m·c·ΔT | Sensible heat |
Entropy
class function EntropyChangeReversible(HeatTransfer, AbsoluteTempK: Double): Double; // ΔS = Q/T
class function EntropyChangeHeating(Mass, Cp, T_initial, T_final: Double): Double; // ΔS = m·c·ln(T2/T1)
class function EntropyChangeIsothermalExpansion(Moles, V_initial, V_final: Double): Double; // ΔS = nR·ln(V2/V1)
Ideal Gas Law (PV = nRT)
class function IdealGasPressure(Moles, Volume, AbsoluteTempK: Double): Double;
class function IdealGasVolume(Moles, Pressure, AbsoluteTempK: Double): Double;
class function IdealGasTemperature(Pressure, Volume, Moles: Double): Double;
class function IdealGasMoles(Pressure, Volume, AbsoluteTempK: Double): Double;
Phase Transitions
class function HeatOfFusion(Mass, LatentHeatOfFusion: Double): Double; // Q = m·Lf
class function HeatOfVaporization(Mass, LatentHeatOfVaporization: Double): Double; // Q = m·Lv
Efficiency
class function CarnotEfficiency(HotTempK, ColdTempK: Double): Double; // η = 1 − T_c/T_h
class function ThermalEfficiency(WorkOutput, HeatInput: Double): Double; // η = W/Q_in
class function CoefficientOfPerformanceRefrigeration(Q_cold, WorkInput: Double): Double;
class function CoefficientOfPerformanceHeatPump(Q_hot, WorkInput: Double): Double;
Thermodynamic Cycles
| Method | Description |
|---|---|
OttoCycleEfficiency(r, γ) |
η = 1 − 1/r^(γ−1); spark-ignition |
DieselCycleEfficiency(r, α, γ) |
Diesel cycle; r = compression ratio, α = cutoff ratio |
BraytonCycleEfficiency(r, γ) |
η = 1 − 1/r^((γ−1)/γ); gas turbine |
RankineCycleEfficiency(W_turbine, W_pump, Q_in) |
Steam power cycle |
Adiabatic Process
All pressures, volumes, and absolute temperatures supplied here must be positive, and the specific-heat ratio γ must be greater than 1.
class function AdiabaticPressure(P1, V1, V2, γ: Double): Double; // P1·V1^γ = P2·V2^γ
class function AdiabaticVolume(P1, V1, P2, γ: Double): Double;
class function AdiabaticTemperature(T1, V1, V2, γ: Double): Double; // T1·V1^(γ−1) = T2·V2^(γ−1)
class function AdiabaticTemperatureFromPressure(T1, P1, P2, γ: Double): Double;
Compressible Flow (Isentropic)
class function CriticalPressureRatio(SpecificHeatRatio: Double): Double;
class function MachNumberFromPressureRatio(PressureRatio, SpecificHeatRatio: Double): Double;
class function IsentropicTemperatureRatio(MachNumber, SpecificHeatRatio: Double): Double;
class function IsentropicPressureRatio(MachNumber, SpecificHeatRatio: Double): Double;
class function IsentropicDensityRatio(MachNumber, SpecificHeatRatio: Double): Double;
CriticalPressureRatio, MachNumberFromPressureRatio, IsentropicPressureRatio, and IsentropicDensityRatio use static-to-stagnation ratios (p/p₀ or ρ/ρ₀), which lie in (0, 1]. By contrast, TFluidDynamicsKit.StagnationPressureRatio returns p₀/p, which is at least 1.
Psychrometrics
class function RelativeHumidity(ActualVaporPressure, SaturatedVaporPressure: Double): Double;
class function SaturatedVaporPressure(TemperatureC: Double): Double; // Pa; water, 1-100°C
class function HumidityRatio(VaporPressure, AtmosphericPressure: Double): Double; // 0 <= Pv < P
class function DewPointTemperature(TemperatureC, RelativeHumidityPercent: Double): Double;
class function MoistAirEnthalpy(TemperatureC, HumidityRatioValue: Double): Double;
Unit Conversion Helpers
class function CelsiusToKelvin(TempC: Double): Double;
class function KelvinToCelsius(TempK: Double): Double;
class function BarToPascal(Bar: Double): Double;
class function PascalToBar(Pascal: Double): Double;
CelsiusToKelvin rejects values below −273.15 °C, and KelvinToCelsius rejects negative Kelvin values.
---
EngineeringLib.Signal — TSignalKit
Filtering
class function MovingAverage(const InputSignal: TDoubleArray; WindowSize: Integer): TDoubleArray;
Sliding-window simple moving average. Elements before the first full window are filled with the first valid average.
Window Functions
type TWindowType = (wtRectangular, wtHamming, wtHann, wtBlackman);
class function GenerateWindow(WindowType: TWindowType; Size: Integer): TDoubleArray;
class function ApplyWindow(const InputSignal, Window: TDoubleArray): TDoubleArray;
| Window | First/last sample | Centre gain | Sidelobe attenuation |
|---|---|---|---|
| Rectangular | 1.0 | 1.0 | ~13 dB |
| Hann | 0.0 | 1.0 | ~31 dB |
| Hamming | 0.08 | 1.0 | ~41 dB |
| Blackman | 0.0 | 1.0 | ~57 dB |
FFT / Spectral Analysis
Cooley-Tukey radix-2 DIT FFT. The in-place FFT input length must be a power of 2, and its real and imaginary arrays must have equal lengths.
{ In-place FFT/IFFT — modifies RealPart and ImagPart in place }
class procedure FFT(var RealPart, ImagPart: TDoubleArray; Inverse: Boolean = False);
{ Equivalent in-place operation on MathBase.Complex.TComplexArray. }
class procedure FFT(var Data: TComplexArray; Inverse: Boolean = False);
{ Convenience wrapper: real input → complete N-bin complex spectrum.
Zero-pads to the next power of 2; never truncates. }
class procedure CalculateFFT(const InputSignal: TDoubleArray;
out OutRealPart, OutImagPart: TDoubleArray);
class procedure CalculateFFT(const InputSignal: TDoubleArray;
out OutputSpectrum: TComplexArray);
{ Inverse FFT: equal-length complete spectrum → real-valued signal }
class procedure CalculateIFFT(const InRealPart, InImagPart: TDoubleArray;
out OutputSignal: TDoubleArray);
class procedure CalculateIFFT(const InputSpectrum: TComplexArray;
out OutputSignal: TDoubleArray);
{ Complete N-bin magnitude and phase spectra }
class procedure CalculateFFTMagnitudePhase(const InputSignal: TDoubleArray;
out Magnitude, Phase: TDoubleArray);
CalculateFFT(nil, ...) returns two empty arrays. Passing two empty arrays to CalculateIFFT returns an empty array. Mismatched real/imaginary input lengths raise ESignalError. For a real input signal, callers wanting a one-sided view can consume bins 0..N div 2 from the complete returned spectrum.
TComplexArray is the FFT implementation's native representation. The split-array overloads remain source-compatible adapters. Both forms preserve the same length, zero-padding, and inverse-scaling rules while making complex signal code easier to compose with MathBase.Complex and AlgebraLib.Vectors.
Key properties verified by the test suite:
- Impulse at index 0 → flat magnitude spectrum (all 1s)
- Parseval's theorem:
Σ|x[n]|² = (1/N) Σ|X[k]|² - Linearity:
FFT(a·x + b·y) = a·FFT(x) + b·FFT(y) - Round-trip:
IFFT(FFT(x)) = xto floating-point precision
FIR Filter Design (windowed-sinc)
All cutoff frequencies are normalised: 0 < fc < 0.5, where 0.5 = Nyquist frequency. All designs produce symmetric (linear-phase) coefficients. Order must be at least 2. An odd order is incremented to the next even value, so the returned coefficient count is adjusted order + 1.
{ Low-pass: passes frequencies below CutoffFreq }
class function DesignFIRLowPass(CutoffFreq: Double; Order: Integer;
WindowType: TWindowType = wtHamming): TDoubleArray;
{ High-pass: passes frequencies above CutoffFreq }
class function DesignFIRHighPass(CutoffFreq: Double; Order: Integer;
WindowType: TWindowType = wtHamming): TDoubleArray;
{ Band-pass: passes frequencies between LowCutoff and HighCutoff }
class function DesignFIRBandPass(LowCutoff, HighCutoff: Double; Order: Integer;
WindowType: TWindowType = wtHamming): TDoubleArray;
{ Band-stop (notch): blocks frequencies between LowCutoff and HighCutoff }
class function DesignFIRBandStop(LowCutoff, HighCutoff: Double; Order: Integer;
WindowType: TWindowType = wtHamming): TDoubleArray;
{ Direct-form convolution. Output length = Length(Signal) + Length(Coeffs) - 1 }
class function ApplyFIRFilter(const Signal, Coeffs: TDoubleArray): TDoubleArray;
Quick example — low-pass filter:
uses EngineeringLib.Signal;
var
Coeffs, Filtered: TDoubleArray;
Signal: TDoubleArray;
begin
Signal := TDoubleArray.Create(1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
// Normalised cutoff 0.2 (20% of Nyquist), order 32, Hamming window
Coeffs := TSignalKit.DesignFIRLowPass(0.2, 32, wtHamming);
Filtered := TSignalKit.ApplyFIRFilter(Signal, Coeffs);
end.
Signal Properties
class function SignalPower(const InputSignal: TDoubleArray): Double; // Mean of squared samples
class function SignalEnergy(const InputSignal: TDoubleArray): Double; // Sum of squared samples
class function RootMeanSquare(const InputSignal: TDoubleArray): Double;
---
EngineeringLib.UnitConversion — TUnitConversionKit
Supported Quantity Types
TUnitType = (utLength, utMass, utTime, utTemperature, utForce, utEnergy,
utPower, utPressure, utVelocity, utArea, utVolume, utAngle, utDensity,
utElectricalCurrent, utElectricalPotential, utFrequency);
Conversion Methods
| Method | Enum Type |
|---|---|
ConvertLength(Value, FromUnit, ToUnit) |
TLengthUnit |
ConvertMass(Value, FromUnit, ToUnit) |
TMassUnit |
ConvertTime(Value, FromUnit, ToUnit) |
TTimeUnit |
ConvertTemperature(Value, FromUnit, ToUnit) |
TTemperatureUnit |
ConvertForce(Value, FromUnit, ToUnit) |
TForceUnit |
ConvertEnergy(Value, FromUnit, ToUnit) |
TEnergyUnit |
ConvertPower(Value, FromUnit, ToUnit) |
TPowerUnit |
ConvertPressure(Value, FromUnit, ToUnit) |
TPressureUnit |
ConvertVelocity(Value, FromUnit, ToUnit) |
TVelocityUnit |
ConvertArea(Value, FromUnit, ToUnit) |
TAreaUnit |
ConvertVolume(Value, FromUnit, ToUnit) |
TVolumeUnit |
ConvertAngle(Value, FromUnit, ToUnit) |
TAngleUnit |
ConvertDensity(Value, FromUnit, ToUnit) |
TDensityUnit |
ConvertElectricalCurrent(Value, FromUnit, ToUnit) |
TElectricalCurrentUnit |
ConvertElectricalPotential(Value, FromUnit, ToUnit) |
TElectricalPotentialUnit |
ConvertFrequency(Value, FromUnit, ToUnit) |
TFrequencyUnit |
All enum-based conversions first convert through the category's base unit. A negative value is preserved mathematically; the converter does not impose a physical-domain policy. Temperature conversions are affine rather than simple scale-factor conversions.
Time conversions use fixed-duration conventions: tuMonth is 2,628,000 seconds (365/12 days) and tuYear is 31,536,000 seconds (365 days). They are duration conversions, not calendar arithmetic.
Unit Enumerations
TLengthUnit:luMeter,luKilometer,luCentimeter,luMillimeter,luMicrometer,luNanometer,luMile,luYard,luFoot,luInch,luNauticalMile,luAngstrom,luLightYearTMassUnit:muKilogram,muGram,muMilligram,muMicrogram,muTonne,muPound,muOunce,muStone,muUSton,muImperialTonTTimeUnit:tuSecond,tuMinute,tuHour,tuDay,tuWeek,tuMonth,tuYear,tuMillisecond,tuMicrosecond,tuNanosecondTTemperatureUnit:tpKelvin,tpCelsius,tpFahrenheit,tpRankine,tpReaumurTForceUnit:fuNewton,fuKilonewton,fuPoundForce,fuDyne,fuKilogramForceTEnergyUnit:euJoule,euKilojoule,euCalorie,euKilocalorie,euWattHour,euKilowattHour,euElectronvolt,euBTU,euTherm,euFootPoundTPowerUnit:puWatt,puKilowatt,puMegawatt,puHorsepower,puBTUPerHourTPressureUnit:prPascal,prKilopascal,prBar,prAtmosphere,prTorr,prPSITVelocityUnit:vuMeterPerSecond,vuKilometerPerHour,vuMilePerHour,vuFootPerSecond,vuKnotTAreaUnit:auSquareMeter,auSquareKilometer,auHectare,auAre,auSquareMile,auAcre,auSquareYard,auSquareFoot,auSquareInchTVolumeUnit:voLiter,voCubicMeter,voMilliliter,voCubicCentimeter,voGallonUS,voGallonUK,voFluidOunceUS,voFluidOunceUK,voCubicFoot,voCubicInchTAngleUnit:anDegree,anRadian,anGradian,anMinuteOfArc,anSecondOfArc,anRevolutionTDensityUnit:deKilogramPerCubicMeter,deGramPerCubicCentimeter,dePoundPerCubicFoot,dePoundPerCubicInchTElectricalCurrentUnit:ecAmpere,ecMilliampere,ecMicroampereTElectricalPotentialUnit:epVolt,epKilovolt,epMillivolt,epMicrovoltTFrequencyUnit:frHertz,frKilohertz,frMegahertz,frGigahertz,frCyclePerSecond
Unit Names and Formatting
Each category has a matching name function:
GetLengthUnitName GetMassUnitName GetTimeUnitName
GetTemperatureUnitName GetForceUnitName GetEnergyUnitName
GetPowerUnitName GetPressureUnitName GetVelocityUnitName
GetAreaUnitName GetVolumeUnitName GetAngleUnitName
GetDensityUnitName GetElectricalCurrentUnitName
GetElectricalPotentialUnitName GetFrequencyUnitName
They return canonical symbols such as m, kg, °C, m/s, m², L, and Hz. Formatting helpers are:
class function FormatWithUnit(Value: Double; AUnitName: string;
Decimals: Integer = 2): string;
class function FormatWithScientificNotation(Value: Double; AUnitName: string;
SignificantDigits: Integer = 3): string;
class function RoundToSignificantDigits(Value: Double;
SignificantDigits: Integer): Double;
Decimals must be non-negative and SignificantDigits must be between 1 and 15; otherwise EUnitConversionError is raised. Values must be finite. Significant-digit ties use round-half-to-even consistently on 32- and 64-bit targets. Formatting uses the process's current Free Pascal locale settings, including its decimal separator.
String-Based Conversion and Parsing
class function TryConvertByUnitName(Value: Double;
FromAUnitName, ToAUnitName: string; out ConvertedValue: Double): Boolean;
class function GetUnitTypeFromUnitName(AUnitName: string): TUnitType;
class function TryParseValueWithUnit(const ValueStr: string;
out Value: Double; out AUnitName: string): Boolean;
class function TryParseAndConvert(const ValueStr, ToAUnitName: string;
out ConvertedValue: Double): Boolean;
Unit-name matching is exact and case-sensitive: use the canonical strings returned by the Get*UnitName functions. The Try... APIs return False for unknown, malformed, or incompatible input. GetUnitTypeFromUnitName raises EUnitConversionError for an unknown name. Numeric parsing follows the process's current locale.
The 16 category-specific parsers are:
TryGetLengthUnitFromName TryGetMassUnitFromName
TryGetTimeUnitFromName TryGetTemperatureUnitFromName
TryGetForceUnitFromName TryGetEnergyUnitFromName
TryGetPowerUnitFromName TryGetPressureUnitFromName
TryGetVelocityUnitFromName TryGetAreaUnitFromName
TryGetVolumeUnitFromName TryGetAngleUnitFromName
TryGetDensityUnitFromName TryGetElectricalCurrentUnitFromName
TryGetElectricalPotentialUnitFromName
TryGetFrequencyUnitFromName
Each returns True and writes the corresponding enum value when the symbol is known; otherwise it returns False.
Compatibility, Enumeration, and Base Units
class function AreUnitsCompatible(UnitType1, UnitType2: TUnitType): Boolean;
class function AreUnitNamesCompatible(AUnitName1, AUnitName2: string): Boolean;
class function GetAllUnitsOfType(UnitType: TUnitType): TStringArray;
class function GetAllUnitTypes: TStringArray;
class function GetBaseUnit(UnitType: TUnitType): string;
GetAllUnitsOfType returns canonical symbols. GetAllUnitTypes returns the display names Length, Mass, and so on. Base units are m, kg, s, K, N, J, W, Pa, m/s, m², m³, rad, kg/m³, A, V, and Hz.
Common Shortcuts
class function MilesToKilometers(Miles: Double): Double;
class function KilometersToMiles(Kilometers: Double): Double;
class function PoundsToKilograms(Pounds: Double): Double;
class function KilogramsToPounds(Kilograms: Double): Double;
class function CelsiusToFahrenheit(Celsius: Double): Double;
class function FahrenheitToCelsius(Fahrenheit: Double): Double;
---
Quick Start
uses EngineeringLib.FluidDynamics, EngineeringLib.Thermodynamics, EngineeringLib.UnitConversion;
var
Re, Efficiency, LengthInFeet: Double;
begin
// Reynolds number for water flow in a pipe
Re := TFluidDynamicsKit.ReynoldsNumber(997, 2.0, 0.05, 1.0e-3);
Writeln('Re = ', Re:0:0); // ≈ 99700 (turbulent)
// Carnot efficiency between 500 K and 300 K
Efficiency := TThermodynamicsKit.CarnotEfficiency(500, 300);
Writeln('Carnot η = ', Efficiency:0:4); // 0.4000
// Convert 1 metre to feet
LengthInFeet := TUnitConversionKit.ConvertLength(1.0, luMeter, luFoot);
Writeln('1 m = ', LengthInFeet:0:4, ' ft'); // ≈ 3.2808
end.
Expected output:
Re = 99700
Carnot η = 0.4000
1 m = 3.2808 ft
Unit Aliases
// EngineeringLib.Velocity:
EVelocityError = EFluidDynamicsError;
TVelocityKit = TFluidDynamicsKit;
// EngineeringLib.Pressure:
EPressureError = EFluidDynamicsError;
TPressureKit = TFluidDynamicsKit;
These focused units intentionally contain aliases, not duplicate implementations. The one obvious path for new pressure, velocity, and flow code is EngineeringLib.FluidDynamics.TFluidDynamicsKit; TVelocityKit and TPressureKit remain exact supported aliases. Their migration and package boundary are reviewed in 1.9.7 before any deprecation decision. Physical unit conversions remain in TUnitConversionKit.ConvertVelocity and ConvertPressure.