diff --git a/README.md b/README.md
index df5105d..741a819 100644
--- a/README.md
+++ b/README.md
@@ -46,6 +46,18 @@ Speed vesselSpeed = Speed.FromKnots(8);
A nautical mile is exactly 1852 m, and a knot is one nautical mile per hour. Nautical helpers do not generate SI-prefixed variants.
+Add `DimensionalQuantities.Extensions.CgsEmag` for practical CGS mechanical, electromagnetic (EMU), and magnetic conversions. Import its namespace to use helpers such as:
+
+```csharp
+using DimensionalQuantities.Extensions.CgsEmag;
+
+MagneticFluxDensity field = MagneticFluxDensity.FromGauss(10_000);
+MagneticFieldStrength strength = MagneticFieldStrength.FromOersteds(1);
+Energy work = Energy.FromErgs(1_000_000);
+```
+
+It includes dynes, ergs, baryes, gals, the common `ab` electrical units, maxwells, gauss and oersteds. These are named conversions into coherent SI quantities; the package does not model a separate CGS electromagnetic dimension system or generate SI-prefixed variants. See [NIST's CGS unit definitions](https://www.nist.gov/pml/special-publication-811/nist-guide-si-chapter-5-units-outside-si) for the distinction between EMU, ESU and Gaussian systems.
+
```csharp
Voltage voltage = Voltage.FromVolts(12);
Current current = Current.FromAmps(3);
diff --git a/src/DimensionalQuantities.Extensions.CgsEmag.Tests/CgsEmagConversionsTests.cs b/src/DimensionalQuantities.Extensions.CgsEmag.Tests/CgsEmagConversionsTests.cs
new file mode 100644
index 0000000..ae9df6b
--- /dev/null
+++ b/src/DimensionalQuantities.Extensions.CgsEmag.Tests/CgsEmagConversionsTests.cs
@@ -0,0 +1,83 @@
+using System.Reflection;
+using DimensionalQuantities.Extensions.CgsEmag;
+using Xunit;
+
+namespace DimensionalQuantities.Extensions.CgsEmag.Tests;
+
+public sealed class CgsEmagConversionsTests
+{
+ [Fact]
+ public void MechanicalUnitsConvertToCoherentSi()
+ {
+ Assert.Multiple(
+ () => Assert.Equal(1e-5, Force.FromDynes(1).AsSiBaseUnit()),
+ () => Assert.Equal(1e-7, Energy.FromErgs(1).AsSiBaseUnit()),
+ () => Assert.Equal(0.1, Pressure.FromBaryes(1).AsSiBaseUnit()),
+ () => Assert.Equal(0.01, Acceleration.FromGals(1).AsSiBaseUnit()));
+ }
+
+ [Fact]
+ public void ElectromagneticUnitsConvertToCoherentSi()
+ {
+ Assert.Multiple(
+ () => Assert.Equal(10, Current.FromAbamperes(1).AsSiBaseUnit()),
+ () => Assert.Equal(10, Current.FromBiots(1).AsSiBaseUnit()),
+ () => Assert.Equal(10, ElectricCharge.FromAbcoulombs(1).AsSiBaseUnit()),
+ () => Assert.Equal(1e-8, Voltage.FromAbvolts(1).AsSiBaseUnit()),
+ () => Assert.Equal(1e-9, Resistance.FromAbohms(1).AsSiBaseUnit()),
+ () => Assert.Equal(1e-9, Inductance.FromAbhenries(1).AsSiBaseUnit()),
+ () => Assert.Equal(1e9, Capacitance.FromAbfarads(1).AsSiBaseUnit()),
+ () => Assert.Equal(1e-8, MagneticFlux.FromMaxwells(1).AsSiBaseUnit()),
+ () => Assert.Equal(1e-4, MagneticFluxDensity.FromGauss(1).AsSiBaseUnit()));
+
+ double oersted = MagneticFieldStrength.FromOersteds(1).AsSiBaseUnit();
+ Assert.InRange(oersted, 1000 / (4 * Math.PI) - 1e-12, 1000 / (4 * Math.PI) + 1e-12);
+ }
+
+ [Fact]
+ public void AccessorsReturnOriginalCgsMagnitude()
+ {
+ Assert.Multiple(
+ () => Assert.Equal(1, Force.FromSiBaseUnit(1e-5).AsDynes()),
+ () => Assert.Equal(1, Energy.FromSiBaseUnit(1e-7).AsErgs()),
+ () => Assert.Equal(1, Pressure.FromSiBaseUnit(0.1).AsBaryes()),
+ () => Assert.Equal(1, Acceleration.FromSiBaseUnit(0.01).AsGals()),
+ () => Assert.Equal(1, Current.FromSiBaseUnit(10).AsAbamperes()),
+ () => Assert.Equal(1, Current.FromSiBaseUnit(10).AsBiots()),
+ () => Assert.Equal(1, ElectricCharge.FromSiBaseUnit(10).AsAbcoulombs()),
+ () => Assert.Equal(1, Voltage.FromSiBaseUnit(1e-8).AsAbvolts()),
+ () => Assert.Equal(1, Resistance.FromSiBaseUnit(1e-9).AsAbohms()),
+ () => Assert.Equal(1, Inductance.FromSiBaseUnit(1e-9).AsAbhenries()),
+ () => Assert.Equal(1, Capacitance.FromSiBaseUnit(1e9).AsAbfarads()),
+ () => Assert.Equal(1, MagneticFlux.FromSiBaseUnit(1e-8).AsMaxwells()),
+ () => Assert.Equal(1, MagneticFluxDensity.FromSiBaseUnit(1e-4).AsGauss()));
+
+ double oersted = MagneticFieldStrength.FromSiBaseUnit(1000 / (4 * Math.PI)).AsOersteds();
+ Assert.InRange(oersted, 1 - 1e-14, 1 + 1e-14);
+ }
+
+ [Fact]
+ public void SharedDimensionAliasesUseTheConversions()
+ {
+ Assert.Multiple(
+ () => Assert.Equal(1e-7, Torque.FromErgs(1).AsSiBaseUnit()),
+ () => Assert.Equal(0.1, Stress.FromBaryes(1).AsSiBaseUnit()),
+ () => Assert.Equal(0.1, YoungsModulus.FromBaryes(1).AsSiBaseUnit()),
+ () => Assert.Equal(1e-8, FluxLinkage.FromMaxwells(1).AsSiBaseUnit()),
+ () => Assert.Equal(1e-4, RemanentFluxDensity.FromGauss(1).AsSiBaseUnit()));
+ }
+
+ [Fact]
+ public void ProviderDoesNotGeneratePrefixConversions()
+ {
+ string[] names = Assembly.Load("DimensionalQuantities.Extensions.CgsEmag").GetExportedTypes()
+ .Where(type => type.Namespace == "DimensionalQuantities.Extensions.CgsEmag")
+ .SelectMany(type => type.GetMethods()).Select(method => method.Name).ToArray();
+
+ Assert.Multiple(
+ () => Assert.DoesNotContain("FromPrefixedUnits", names),
+ () => Assert.DoesNotContain("AsPrefixedUnits", names),
+ () => Assert.DoesNotContain("FromKiloGauss", names),
+ () => Assert.DoesNotContain("AsKiloGauss", names));
+ }
+}
diff --git a/src/DimensionalQuantities.Extensions.CgsEmag.Tests/DimensionalQuantities.Extensions.CgsEmag.Tests.csproj b/src/DimensionalQuantities.Extensions.CgsEmag.Tests/DimensionalQuantities.Extensions.CgsEmag.Tests.csproj
new file mode 100644
index 0000000..f919681
--- /dev/null
+++ b/src/DimensionalQuantities.Extensions.CgsEmag.Tests/DimensionalQuantities.Extensions.CgsEmag.Tests.csproj
@@ -0,0 +1,19 @@
+
+
+ net11.0
+ false
+ true
+ Exe
+ true
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/DimensionalQuantities.Extensions.CgsEmag/CgsEmagSymbols.cs b/src/DimensionalQuantities.Extensions.CgsEmag/CgsEmagSymbols.cs
new file mode 100644
index 0000000..7c761ca
--- /dev/null
+++ b/src/DimensionalQuantities.Extensions.CgsEmag/CgsEmagSymbols.cs
@@ -0,0 +1,35 @@
+using DimensionalQuantities.Units.Declarations;
+
+namespace DimensionalQuantities.Extensions.CgsEmag;
+
+internal static class CgsEmagSymbols
+{
+ [UnitSymbol("Dyne", "Dynes", "dyn", Scale = 1e-5)]
+ internal sealed class Dyne { }
+ [UnitSymbol("Erg", "Ergs", "erg", Scale = 1e-7)]
+ internal sealed class Erg { }
+ [UnitSymbol("Barye", "Baryes", "Ba", Scale = 0.1)]
+ internal sealed class Barye { }
+ [UnitSymbol("Gal", "Gals", "Gal", Scale = 0.01)]
+ internal sealed class Gal { }
+ [UnitSymbol("Abampere", "Abamperes", "abA", Scale = 10)]
+ internal sealed class Abampere { }
+ [UnitSymbol("Biot", "Biots", "Bi", Scale = 10)]
+ internal sealed class Biot { }
+ [UnitSymbol("Abcoulomb", "Abcoulombs", "abC", Scale = 10)]
+ internal sealed class Abcoulomb { }
+ [UnitSymbol("Abvolt", "Abvolts", "abV", Scale = 1e-8)]
+ internal sealed class Abvolt { }
+ [UnitSymbol("Abohm", "Abohms", "abΩ", Scale = 1e-9)]
+ internal sealed class Abohm { }
+ [UnitSymbol("Abhenry", "Abhenries", "abH", Scale = 1e-9)]
+ internal sealed class Abhenry { }
+ [UnitSymbol("Abfarad", "Abfarads", "abF", Scale = 1e9)]
+ internal sealed class Abfarad { }
+ [UnitSymbol("Maxwell", "Maxwells", "Mx", Scale = 1e-8)]
+ internal sealed class Maxwell { }
+ [UnitSymbol("Gauss", "Gauss", "G", Scale = 1e-4)]
+ internal sealed class Gauss { }
+ [UnitSymbol("Oersted", "Oersteds", "Oe", Scale = 79.57747154594767)]
+ internal sealed class Oersted { }
+}
diff --git a/src/DimensionalQuantities.Extensions.CgsEmag/CgsEmagUnits.cs b/src/DimensionalQuantities.Extensions.CgsEmag/CgsEmagUnits.cs
new file mode 100644
index 0000000..cd40fe0
--- /dev/null
+++ b/src/DimensionalQuantities.Extensions.CgsEmag/CgsEmagUnits.cs
@@ -0,0 +1,69 @@
+using DimensionalQuantities.Units.Declarations;
+
+namespace DimensionalQuantities.Extensions.CgsEmag;
+
+[UnitProvider]
+internal static class CgsEmagUnits
+{
+ [QuantityUnit(typeof(Force))]
+ [UnitFactor(typeof(CgsEmagSymbols.Dyne))]
+ private sealed class ForceUnit { }
+
+ [QuantityUnit(typeof(Energy))]
+ [QuantityUnit(typeof(Torque))]
+ [UnitFactor(typeof(CgsEmagSymbols.Erg))]
+ private sealed class EnergyUnit { }
+
+ [QuantityUnit(typeof(Pressure))]
+ [QuantityUnit(typeof(Stress))]
+ [QuantityUnit(typeof(YoungsModulus))]
+ [UnitFactor(typeof(CgsEmagSymbols.Barye))]
+ private sealed class PressureUnit { }
+
+ [QuantityUnit(typeof(Acceleration))]
+ [UnitFactor(typeof(CgsEmagSymbols.Gal))]
+ private sealed class AccelerationUnit { }
+
+ [QuantityUnit(typeof(Current))]
+ [UnitFactor(typeof(CgsEmagSymbols.Abampere))]
+ [AdditionalUnit(typeof(BiotUnit))]
+ private sealed class CurrentUnit { }
+
+ [UnitFactor(typeof(CgsEmagSymbols.Biot))]
+ private sealed class BiotUnit { }
+
+ [QuantityUnit(typeof(ElectricCharge))]
+ [UnitFactor(typeof(CgsEmagSymbols.Abcoulomb))]
+ private sealed class ChargeUnit { }
+
+ [QuantityUnit(typeof(Voltage))]
+ [UnitFactor(typeof(CgsEmagSymbols.Abvolt))]
+ private sealed class VoltageUnit { }
+
+ [QuantityUnit(typeof(Resistance))]
+ [UnitFactor(typeof(CgsEmagSymbols.Abohm))]
+ private sealed class ResistanceUnit { }
+
+ [QuantityUnit(typeof(Inductance))]
+ [UnitFactor(typeof(CgsEmagSymbols.Abhenry))]
+ private sealed class InductanceUnit { }
+
+ [QuantityUnit(typeof(Capacitance))]
+ [UnitFactor(typeof(CgsEmagSymbols.Abfarad))]
+ private sealed class CapacitanceUnit { }
+
+ [QuantityUnit(typeof(MagneticFlux))]
+ [QuantityUnit(typeof(FluxLinkage))]
+ [UnitFactor(typeof(CgsEmagSymbols.Maxwell))]
+ private sealed class MagneticFluxUnit { }
+
+ [QuantityUnit(typeof(MagneticFluxDensity))]
+ [QuantityUnit(typeof(RemanentFluxDensity))]
+ [UnitFactor(typeof(CgsEmagSymbols.Gauss))]
+ private sealed class MagneticFluxDensityUnit { }
+
+ [QuantityUnit(typeof(MagneticFieldStrength))]
+ [QuantityUnit(typeof(CoerciveFieldStrength))]
+ [UnitFactor(typeof(CgsEmagSymbols.Oersted))]
+ private sealed class MagneticFieldStrengthUnit { }
+}
diff --git a/src/DimensionalQuantities.Extensions.CgsEmag/DimensionalQuantities.Extensions.CgsEmag.csproj b/src/DimensionalQuantities.Extensions.CgsEmag/DimensionalQuantities.Extensions.CgsEmag.csproj
new file mode 100644
index 0000000..02e4ef8
--- /dev/null
+++ b/src/DimensionalQuantities.Extensions.CgsEmag/DimensionalQuantities.Extensions.CgsEmag.csproj
@@ -0,0 +1,35 @@
+
+
+ netstandard2.0
+ GoSim
+ MIT
+ README.md
+ https://github.com/GoSimulate/DimensionalQuantities
+ Named CGS electromagnetic and mechanical conversions for dimensional quantities.
+ git
+ true
+ $(BaseIntermediateOutputPath)$(Configuration)/$(TargetFramework)/generated
+ true
+ snupkg
+ true
+ true
+ true
+ portable
+
+
+
+
+
+
+
+
+
+
+ <_ProjectReferencesWithVersions Update="@(_ProjectReferencesWithVersions)"
+ Condition="'%(_ProjectReferencesWithVersions.Filename)' == 'DimensionalQuantities'">
+ [$(PackageVersion)]
+
+
+
+
diff --git a/src/DimensionalQuantities.IntegrationTests/Packaging/PackagedGeneratorTests.cs b/src/DimensionalQuantities.IntegrationTests/Packaging/PackagedGeneratorTests.cs
index 77a5551..a49d900 100644
--- a/src/DimensionalQuantities.IntegrationTests/Packaging/PackagedGeneratorTests.cs
+++ b/src/DimensionalQuantities.IntegrationTests/Packaging/PackagedGeneratorTests.cs
@@ -124,6 +124,33 @@ public static class Consumer
() => Assert.Equal(1852d / 3600d, InvokeDouble(type, "ConvertSpeed")));
}
+ [Fact]
+ public void CgsEmagPackageProvidesConversionsThroughCoreDependency()
+ {
+ using PackageRepository repository = PackageRepository.Create(_scratch, new Uri("https://api.nuget.org/v3/index.json"));
+ PackCore(repository);
+ Package cgsEmag = PackSourceProject(repository, "DimensionalQuantities.Extensions.CgsEmag");
+ ProjectCreator consumer = CreateProject("CgsEmagConsumer", """
+ using DimensionalQuantities.Extensions.CgsEmag;
+
+ public static class Consumer
+ {
+ public static double ConvertFluxDensity() => MagneticFluxDensity.FromGauss(10_000).AsSiBaseUnit();
+ public static double ConvertCurrent() => Current.FromAbamperes(1).AsSiBaseUnit();
+ public static double ConvertCharge() => ElectricCharge.FromAbcoulombs(1).AsSiBaseUnit();
+ }
+ """, cgsEmag);
+ Build(consumer);
+
+ using PackageAssemblyContext context = new(OutputDirectory("CgsEmagConsumer"));
+ Type type = context.LoadFromAssemblyPath(Path.Combine(OutputDirectory("CgsEmagConsumer"), "CgsEmagConsumer.dll"))
+ .GetType("Consumer", throwOnError: true)!;
+ Assert.Multiple(
+ () => Assert.Equal(1, InvokeDouble(type, "ConvertFluxDensity")),
+ () => Assert.Equal(10, InvokeDouble(type, "ConvertCurrent")),
+ () => Assert.Equal(10, InvokeDouble(type, "ConvertCharge")));
+ }
+
[Fact]
public void MetricNamedConversionsRequireNamespaceImport()
{
diff --git a/src/DimensionalQuantities.IntegrationTests/Packaging/SymbolPackageTests.cs b/src/DimensionalQuantities.IntegrationTests/Packaging/SymbolPackageTests.cs
index 5bfeef4..03ce449 100644
--- a/src/DimensionalQuantities.IntegrationTests/Packaging/SymbolPackageTests.cs
+++ b/src/DimensionalQuantities.IntegrationTests/Packaging/SymbolPackageTests.cs
@@ -53,6 +53,7 @@ public void CoreSymbolPackageMatchesRuntimeAndAnalyzerAssemblies()
[InlineData("Metric")]
[InlineData("Imperial")]
[InlineData("Nautical")]
+ [InlineData("CgsEmag")]
public void ExtensionSymbolPackageMatchesAssemblyAndEmbedsGeneratedSource(string extension)
{
string projectName = "DimensionalQuantities.Extensions." + extension;
diff --git a/src/DimensionalQuantities.slnx b/src/DimensionalQuantities.slnx
index 75ae68d..2c6c5ff 100644
--- a/src/DimensionalQuantities.slnx
+++ b/src/DimensionalQuantities.slnx
@@ -15,6 +15,10 @@
+
+
+
+
diff --git a/src/DimensionalQuantities/Units/EngineeringQuantityAliases.cs b/src/DimensionalQuantities/Units/EngineeringQuantityAliases.cs
index 1679397..1233bbd 100644
--- a/src/DimensionalQuantities/Units/EngineeringQuantityAliases.cs
+++ b/src/DimensionalQuantities/Units/EngineeringQuantityAliases.cs
@@ -9,6 +9,7 @@ internal static class EngineeringQuantityAliases
{ new(Length: 2), ["Area"] },
{ new(Length: 3), ["Volume"] },
{ new(Length: 1, Time: -1), ["Speed"] },
+ { new(Length: 1, Time: -2), ["Acceleration"] },
{ new(Time: -1), ["Frequency", "AngularVelocity"] },
{ new(Length: 1, Mass: 1, Time: -2), ["Force"] },
{ new(Length: -3, Mass: 1), ["Density"] },
@@ -18,7 +19,9 @@ internal static class EngineeringQuantityAliases
{ new(Length: 2, Time: -3), ["SpecificPower", "SpecificPowerLoss"] },
{ new(Temperature: -1), ["TemperatureCoefficient"] },
{ new(Length: -1, Mass: 1, Time: -3), ["PowerDensity", "VolumetricPowerLoss"] },
+ { new(Time: 1, ElectricCurrent: 1), ["ElectricCharge"] },
{ new(Length: 2, Mass: 1, Time: -3, ElectricCurrent: -1), ["Voltage"] },
+ { new(Length: -2, Mass: -1, Time: 4, ElectricCurrent: 2), ["Capacitance"] },
{ new(Length: 2, Mass: 1, Time: -3, ElectricCurrent: -2), ["Resistance"] },
{ new(Length: 2, Mass: 1, Time: -2, ElectricCurrent: -2), ["Inductance"] },
{ new(Length: 2, Mass: 1, Time: -2, ElectricCurrent: -1), ["MagneticFlux", "FluxLinkage"] },