zig-dimal/src/Base.zig
2026-04-22 23:53:43 +02:00

252 lines
11 KiB
Zig
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const std = @import("std");
// Adjust these imports to match your actual file names
const Dimensions = @import("Dimensions.zig");
const Scales = @import("Scales.zig");
const Scalar = @import("Scalar.zig").Scalar;
fn PhysicalConstant(comptime d: Dimensions.ArgOpts, comptime val: f64, comptime s: Scales.ArgOpts) type {
return struct {
const dims = Dimensions.init(d);
const scales = Scales.init(s);
/// Instantiates the constant into a specific numeric type.
pub fn Of(comptime T: type) Scalar(T, d, s) {
return .{ .value = @as(T, @floatCast(val)) };
}
};
}
fn BaseScalar(comptime d: Dimensions.ArgOpts) type {
return struct {
const dims = Dimensions.init(d);
/// Creates a Scalar of this dimension using default scales.
/// Example: const V = Quantities.Velocity.Base(f32);
pub fn Of(comptime T: type) type {
return Scalar(T, d, .{});
}
/// Creates a Scalar of this dimension using custom scales.
/// Example: const Kmh = Quantities.Velocity.Scaled(f32, Scales.init(.{ .L = .k, .T = .hour }));
pub fn Scaled(comptime T: type, comptime s: Scales.ArgOpts) type {
return Scalar(T, d, s);
}
};
}
// ==========================================
// Physical Constants
// ==========================================
pub const Constants = struct {
/// Speed of light in vacuum (c) [m/s]
pub const SpeedOfLight = PhysicalConstant(.{ .L = 1, .T = -1 }, 299792458.0, .{});
/// Planck constant (h) [J⋅s = kg⋅m²⋅s⁻¹]
pub const Planck = PhysicalConstant(.{ .M = 1, .L = 2, .T = -1 }, 6.62607015e-34, .{ .M = .k });
/// Reduced Planck constant (ℏ) [J⋅s]
pub const ReducedPlanck = PhysicalConstant(.{ .M = 1, .L = 2, .T = -1 }, 1.054571817e-34, .{ .M = .k });
/// Boltzmann constant (k_B) [J⋅K⁻¹ = kg⋅m²⋅s⁻²⋅K⁻¹]
pub const Boltzmann = PhysicalConstant(.{ .M = 1, .L = 2, .T = -2, .Tp = -1 }, 1.380649e-23, .{ .M = .k });
/// Newtonian constant of gravitation (G) [m³⋅kg⁻¹⋅s⁻²]
pub const Gravitational = PhysicalConstant(.{ .M = -1, .L = 3, .T = -2 }, 6.67430e-11, .{ .M = .k });
/// StefanBoltzmann constant (σ) [W⋅m⁻²⋅K⁻⁴ = kg⋅s⁻³⋅K⁻⁴]
pub const StefanBoltzmann = PhysicalConstant(.{ .M = 1, .T = -3, .Tp = -4 }, 5.670374419e-8, .{ .M = .k });
/// Elementary charge (e) [C = A⋅s]
pub const ElementaryCharge = PhysicalConstant(.{ .T = 1, .I = 1 }, 1.602176634e-19, .{});
/// Vacuum magnetic permeability (μ_0) [N⋅A⁻² = kg⋅m⋅s⁻²⋅A⁻²]
pub const VacuumPermeability = PhysicalConstant(.{ .M = 1, .L = 1, .T = -2, .I = -2 }, 1.25663706127e-6, .{ .M = .k });
/// Vacuum electric permittivity (ε_0) [F⋅m⁻¹ = A²⋅s⁴⋅kg⁻¹⋅m⁻³]
pub const VacuumPermittivity = PhysicalConstant(.{ .M = -1, .L = -3, .T = 4, .I = 2 }, 8.8541878188e-12, .{ .M = .k });
/// Electron mass (m_e) [kg]
pub const ElectronMass = PhysicalConstant(.{ .M = 1 }, 9.1093837139e-31, .{ .M = .k });
/// Proton mass (m_p) [kg]
pub const ProtonMass = PhysicalConstant(.{ .M = 1 }, 1.67262192595e-27, .{ .M = .k });
/// Neutron mass (m_n) [kg]
pub const NeutronMass = PhysicalConstant(.{ .M = 1 }, 1.67492750056e-27, .{ .M = .k });
/// Fine-structure constant (α) [Dimensionless]
pub const FineStructure = PhysicalConstant(.{}, 0.0072973525643, .{});
/// Avogadro constant (N_A) [mol⁻¹]
/// Note: Assuming mol is currently treated as dimensionless in the base system,
/// otherwise requires adding an `.N` dimension to Dimensions.ArgOpts.
pub const Avogadro = PhysicalConstant(.{}, 6.02214076e23, .{});
};
// ==========================================
// Base Quantities
// ==========================================
pub const Dimless = BaseScalar(.{});
pub const Meter = BaseScalar(.{ .L = 1 });
pub const Second = BaseScalar(.{ .T = 1 });
pub const Gramm = BaseScalar(.{ .M = 1 });
pub const Kelvin = BaseScalar(.{ .Tr = 1 });
pub const ElectricCurrent = BaseScalar(.{ .I = 1 });
// ==========================================
// Electric
// ==========================================
pub const ElectricConductivity = BaseScalar(.{ .M = -1, .L = -3, .T = 3, .I = 2 });
pub const ElectricCharge = BaseScalar(.{ .T = 1, .I = 1 });
pub const ElectricPotential = BaseScalar(.{ .T = -3, .L = 2, .M = 1, .I = -1 });
pub const ElectricResistance = BaseScalar(.{ .M = 1, .L = 2, .T = -3, .I = -2 });
pub const ElectricResistivity = BaseScalar(.{ .M = 1, .L = 3, .T = -3, .I = -2 });
pub const ElectricCapacitance = BaseScalar(.{ .T = 4, .L = -2, .M = -1, .I = 2 });
pub const ElectricImpedance = ElectricResistance;
pub const MagneticFlux = BaseScalar(.{ .M = 1, .L = 2, .T = -2, .I = -1 });
pub const MagneticDensity = BaseScalar(.{ .M = 1, .T = -2, .I = -1 });
pub const MagneticStrength = BaseScalar(.{ .L = -1, .I = 1 }); // Fixed typo from MagneticStrengh
pub const MagneticMoment = BaseScalar(.{ .L = 2, .I = 1 });
// ==========================================
// Movement
// ==========================================
pub const Speed = BaseScalar(.{ .L = 1, .T = -1 });
pub const Acceleration = BaseScalar(.{ .L = 1, .T = -2 });
pub const Inertia = BaseScalar(.{ .M = 1, .L = 2 });
// ==========================================
// Forces / Energy
// ==========================================
pub const Force = BaseScalar(.{ .T = -2, .M = 1, .L = 1 });
pub const Pressure = BaseScalar(.{ .T = -2, .L = -1, .M = 1 });
pub const Energy = BaseScalar(.{ .T = -2, .L = 2, .M = 1 });
pub const Power = BaseScalar(.{ .T = -3, .L = 2, .M = 1 });
// ==========================================
// Dimension
// ==========================================
pub const Area = BaseScalar(.{ .L = 2 });
pub const Volume = BaseScalar(.{ .L = 3 });
pub const AreaDensity = BaseScalar(.{ .M = 1, .L = -2 });
pub const Density = BaseScalar(.{ .M = 1, .L = -3 });
// ==========================================
// Thermal
// ==========================================
pub const ThermalHeat = Energy;
pub const ThermalWork = Energy;
pub const ThermalCapacity = BaseScalar(.{ .M = 1, .L = 2, .T = -2, .Tr = -1 });
pub const ThermalCapacityPerMass = BaseScalar(.{ .L = 2, .T = -2, .Tr = -1 });
pub const ThermalFluxDensity = BaseScalar(.{ .M = 1, .T = -3 }); // Fixed typo from ThermalluxDensity
pub const ThermalConductance = BaseScalar(.{ .M = 1, .L = 2, .T = -3, .Tr = -1 });
pub const ThermalConductivity = BaseScalar(.{ .M = 1, .L = 1, .T = -3, .Tr = -1 });
pub const ThermalResistance = BaseScalar(.{ .M = -1, .L = -2, .T = 3, .Tr = 1 });
pub const ThermalResistivity = BaseScalar(.{ .M = -1, .L = -1, .T = 3, .Tr = 1 });
pub const ThermalEntropy = BaseScalar(.{ .M = 1, .L = 2, .T = -2, .Tr = -1 });
// ==========================================
// Others
// ==========================================
pub const Frequency = BaseScalar(.{ .T = -1 });
pub const Viscosity = BaseScalar(.{ .M = 1, .L = -1, .T = -1 });
pub const SurfaceTension = BaseScalar(.{ .M = 1, .T = -2 }); // Corrected from MT-2a
test "BaseQuantities - Core dimensions instantiation" {
// Basic types via generic wrappers
const M = Meter.Of(f32);
const distance = M{ .value = 100.0 };
try std.testing.expectEqual(100.0, distance.value);
try std.testing.expectEqual(1, M.dims.get(.L));
try std.testing.expectEqual(0, M.dims.get(.T));
// Test specific scale variants
const Kmh = Speed.Scaled(f32, .{ .L = .k, .T = .hour });
const speed = Kmh{ .value = 120.0 };
try std.testing.expectEqual(120.0, speed.value);
try std.testing.expectEqual(.k, @TypeOf(speed).scales.get(.L));
try std.testing.expectEqual(.hour, @TypeOf(speed).scales.get(.T));
}
test "BaseQuantities - Kinematics equations" {
const d = Meter.Of(f32){ .value = 50.0 };
const t = Second.Of(f32){ .value = 2.0 };
// Velocity = Distance / Time
const v = d.div(t);
try std.testing.expectEqual(25.0, v.value);
try std.testing.expect(Speed.dims.eql(@TypeOf(v).dims));
// Acceleration = Velocity / Time
const a = v.div(t);
try std.testing.expectEqual(12.5, a.value);
try std.testing.expect(Acceleration.dims.eql(@TypeOf(a).dims));
}
test "BaseQuantities - Dynamics (Force and Work)" {
// 10 kg
const m = Gramm.Scaled(f32, .{ .M = .k }){ .value = 10.0 };
// 9.8 m/s^2
const a = Acceleration.Of(f32){ .value = 9.8 };
// Force = mass * acceleration
const f = m.mul(a);
try std.testing.expectEqual(98, f.value);
try std.testing.expect(Force.dims.eql(@TypeOf(f).dims));
// Energy (Work) = Force * distance
const distance = Meter.Of(f32){ .value = 5.0 };
const energy = f.mul(distance);
try std.testing.expectEqual(490, energy.value);
try std.testing.expect(Energy.dims.eql(@TypeOf(energy).dims));
}
test "BaseQuantities - Electric combinations" {
const current = ElectricCurrent.Of(f32){ .value = 2.0 }; // 2 A
const time = Second.Of(f32){ .value = 3.0 }; // 3 s
// Charge = Current * time
const charge = current.mul(time);
try std.testing.expectEqual(6.0, charge.value);
try std.testing.expect(ElectricCharge.dims.eql(@TypeOf(charge).dims));
}
test "Constants - Initialization and dimension checks" {
// Speed of Light
const c = Constants.SpeedOfLight.Of(f64);
try std.testing.expectEqual(299792458.0, c.value);
try std.testing.expectEqual(1, @TypeOf(c).dims.get(.L));
try std.testing.expectEqual(-1, @TypeOf(c).dims.get(.T));
// Electron Mass (verifying scale as well)
const me = Constants.ElectronMass.Of(f64);
try std.testing.expectEqual(9.1093837139e-31, me.value);
try std.testing.expectEqual(1, @TypeOf(me).dims.get(.M));
try std.testing.expectEqual(.k, @TypeOf(me).scales.get(.M)); // Should be scaled to kg
// Boltzmann Constant (Complex derived dimensions)
const kb = Constants.Boltzmann.Of(f64);
try std.testing.expectEqual(1.380649e-23, kb.value);
try std.testing.expectEqual(1, @TypeOf(kb).dims.get(.M));
try std.testing.expectEqual(2, @TypeOf(kb).dims.get(.L));
try std.testing.expectEqual(-2, @TypeOf(kb).dims.get(.T));
try std.testing.expectEqual(-1, @TypeOf(kb).dims.get(.Tp));
try std.testing.expectEqual(.k, @TypeOf(kb).scales.get(.M));
// Vacuum Permittivity
const eps0 = Constants.VacuumPermittivity.Of(f64);
try std.testing.expectEqual(8.8541878188e-12, eps0.value);
try std.testing.expectEqual(-1, @TypeOf(eps0).dims.get(.M));
try std.testing.expectEqual(-3, @TypeOf(eps0).dims.get(.L));
try std.testing.expectEqual(4, @TypeOf(eps0).dims.get(.T));
try std.testing.expectEqual(2, @TypeOf(eps0).dims.get(.I));
// Fine Structure Constant (Dimensionless)
const alpha = Constants.FineStructure.Of(f64);
try std.testing.expectEqual(0.0072973525643, alpha.value);
try std.testing.expectEqual(0, @TypeOf(alpha).dims.get(.M));
try std.testing.expectEqual(0, @TypeOf(alpha).dims.get(.L));
}