diff --git a/csharp/Lib/Units/Angle.generated.cs b/csharp/Lib/Units/Angle.generated.cs index ad576594a..f2317f977 100644 --- a/csharp/Lib/Units/Angle.generated.cs +++ b/csharp/Lib/Units/Angle.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct Angle public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/ApparentPower.generated.cs b/csharp/Lib/Units/ApparentPower.generated.cs index cfa6174ed..0775151c9 100644 --- a/csharp/Lib/Units/ApparentPower.generated.cs +++ b/csharp/Lib/Units/ApparentPower.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct ApparentPower public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/Composite/Ac1Phase.cs b/csharp/Lib/Units/Composite/Ac1Phase.cs index e48807866..d7cfc20e7 100644 --- a/csharp/Lib/Units/Composite/Ac1Phase.cs +++ b/csharp/Lib/Units/Composite/Ac1Phase.cs @@ -1,25 +1,28 @@ + using System.Diagnostics.CodeAnalysis; namespace InnovEnergy.Lib.Units.Composite; -public record Ac1Phase -( - Voltage Voltage, - Current Current, - Angle Phi, - Frequency Frequency -) - : AcPhase(Voltage, Current, Phi) +public record Ac1Phase : AcPhase { + public required Frequency Frequency { get; init; } [SuppressMessage("ReSharper", "RedundantCast")] - public static Ac1Phase operator +(Ac1Phase left, Ac1Phase right) + public static Ac1Phase operator |(Ac1Phase left, Ac1Phase right) { - var f = (left.Frequency + right.Frequency) / 2m; // TODO: check that l & r approximately equal - var acPhase = (AcPhase)left + (AcPhase)right; - return new Ac1Phase(acPhase.Voltage, acPhase.Current, acPhase.Phi, f); + var f = left.Frequency | right.Frequency; + var p = (AcPhase)left | (AcPhase)right; + + return new Ac1Phase + { + Frequency = f, + Current = p.Current, + Voltage = p.Voltage, + Phi = p.Phi + }; } + } diff --git a/csharp/Lib/Units/Composite/Ac3Phase.cs b/csharp/Lib/Units/Composite/Ac3Phase.cs index a5788e452..d73f8e9e4 100644 --- a/csharp/Lib/Units/Composite/Ac3Phase.cs +++ b/csharp/Lib/Units/Composite/Ac3Phase.cs @@ -1,25 +1,22 @@ +using InnovEnergy.Lib.Utils; using static DecimalMath.DecimalEx; namespace InnovEnergy.Lib.Units.Composite; -public record Ac3Phase(AcPhase L1, AcPhase L2, AcPhase L3, Frequency Frequency) +public record Ac3Phase { + public required AcPhase L1 { get; init; } + public required AcPhase L2 { get; init; } + public required AcPhase L3 { get; init; } + public required Frequency Frequency { get; init; } + public ApparentPower ApparentPower => L1.ApparentPower + L2.ApparentPower + L3.ApparentPower; public ReactivePower ReactivePower => L1.ReactivePower + L2.ReactivePower + L3.ReactivePower; public Power ActivePower => L1.ActivePower + L2.ActivePower + L3.ActivePower; + public Angle Phi => ATan2(ReactivePower, ActivePower); - public Angle Phi => ATan2(ReactivePower, ActivePower); - - - public static Ac3Phase operator +(Ac3Phase left, Ac3Phase right) - { - var f = (left.Frequency + right.Frequency) / 2m; // TODO: check that l & r approximately equal + public static Ac3Phase operator |(Ac3Phase left, Ac3Phase right) => OpParallel(left, right); + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); - var l1 = left.L1 + right.L1; - var l2 = left.L2 + right.L2; - var l3 = left.L3 + right.L3; - - return new Ac3Phase(l1, l2, l3, f); - } } \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/AcPhase.cs b/csharp/Lib/Units/Composite/AcPhase.cs index 70cd952b2..426091fbc 100644 --- a/csharp/Lib/Units/Composite/AcPhase.cs +++ b/csharp/Lib/Units/Composite/AcPhase.cs @@ -3,17 +3,23 @@ using static DecimalMath.DecimalEx; namespace InnovEnergy.Lib.Units.Composite; -public record AcPhase : Phase +public record AcPhase : IPhase { - public AcPhase(Voltage voltage, Current current, Angle phi) : base(voltage, current) + private readonly Voltage _Voltage; + public required Voltage Voltage { - if (voltage < 0) throw new ArgumentException("RMS value cannot be negative", nameof(voltage)); - if (current < 0) throw new ArgumentException("RMS value cannot be negative", nameof(current)); - - Phi = phi; + get => _Voltage; + init => _Voltage = value >= 0 ? value : throw new ArgumentException("RMS value cannot be negative"); } - public Angle Phi { get; } + private readonly Current _Current; + public required Current Current + { + get => _Current; + init => _Current = value >= 0 ? value : throw new ArgumentException("RMS value cannot be negative"); + } + + public required Angle Phi { get; init; } public ApparentPower ApparentPower => Voltage.Value * Current.Value ; public Power ActivePower => ApparentPower.Value * PowerFactor; @@ -21,34 +27,40 @@ public record AcPhase : Phase public Decimal PowerFactor => Cos(Phi); - public static AcPhase operator +(AcPhase left, AcPhase right) + public static AcPhase operator |(AcPhase left, AcPhase right) { // the Voltages of two phases are expected to be in phase and equal - var v = (left.Voltage + right.Voltage) / 2m; // TODO: check that l & r approximately equal + var v = left.Voltage | right.Voltage; // currents (RMS) can be different and out of phase // https://www.johndcook.com/blog/2020/08/17/adding-phase-shifted-sine-waves/ // IF - // left(t) = ILeft sin(ωt) + // left(t) = ILeft sin(ωt) // right(t) = IRight sin(ωt + φ). - // sum(t) = left(t) + right(t) = ISum sin(ωt + ψ). - // THEN + // sum(t) = left(t) + right(t) = ISum sin(ωt + ψ). + // THEN // ψ = arctan( IRight * sin(φ) / (ILeft + IRight cos(φ)) ). // C = IRight * sin(φ) / sin(ψ). - // in this calc left(t) has zero phase shift. + // in this calculation left(t) has zero phase shift. // we can shift both waves by -left.Phi, so // φ := right.phi - left.phi - var phi = right.Phi - left.Phi; - + var phi = right.Phi - left.Phi; var phiSum = ATan2(right.Current * Sin(phi), left.Current + right.Current * Cos(phi)); var iSum = right.Current * Sin(phi) / Sin(phiSum); - return new AcPhase(v, iSum, phiSum); + return new AcPhase + { + Voltage = v, + Current = iSum, + Phi = phiSum + }; } + + } \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/DcPhase.cs b/csharp/Lib/Units/Composite/DcPhase.cs index af6d1049a..2d0b24b68 100644 --- a/csharp/Lib/Units/Composite/DcPhase.cs +++ b/csharp/Lib/Units/Composite/DcPhase.cs @@ -1,15 +1,16 @@ +using InnovEnergy.Lib.Utils; + namespace InnovEnergy.Lib.Units.Composite; -public record DcPhase(Voltage Voltage, Current Current) : Phase(Voltage, Current) +public record DcPhase : IPhase { - public Power Power => Current * Voltage; - - public static DcPhase operator +(DcPhase left, DcPhase right) - { - var v = (left.Voltage + right.Voltage) / 2m; - var i = left.Current + right.Current; - - return new DcPhase(v, i); - } + public required Voltage Voltage { get; init;} + public required Current Current { get; init;} + public Power Power => Current * Voltage; + + public static DcPhase operator |(DcPhase left, DcPhase right) => OpParallel(left, right); + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); + + } \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/IPhase.cs b/csharp/Lib/Units/Composite/IPhase.cs new file mode 100644 index 000000000..b0ccfee66 --- /dev/null +++ b/csharp/Lib/Units/Composite/IPhase.cs @@ -0,0 +1,11 @@ +using System.Diagnostics.CodeAnalysis; + +namespace InnovEnergy.Lib.Units.Composite; + +[SuppressMessage("ReSharper", "MemberCanBeProtected.Global")] + +public interface IPhase +{ + public Voltage Voltage { get; } + public Current Current { get; } +} \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/Phase.cs b/csharp/Lib/Units/Composite/Phase.cs deleted file mode 100644 index 45a3ef86d..000000000 --- a/csharp/Lib/Units/Composite/Phase.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace InnovEnergy.Lib.Units.Composite; - -public abstract record Phase -( - Voltage Voltage, - Current Current -); \ No newline at end of file diff --git a/csharp/Lib/Units/Current.generated.cs b/csharp/Lib/Units/Current.generated.cs index cda7eeadf..93e9bdbf7 100644 --- a/csharp/Lib/Units/Current.generated.cs +++ b/csharp/Lib/Units/Current.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct Current public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/Frequency.generated.cs b/csharp/Lib/Units/Frequency.generated.cs index 015d67536..9618c18bc 100644 --- a/csharp/Lib/Units/Frequency.generated.cs +++ b/csharp/Lib/Units/Frequency.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct Frequency public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/Generator/Template.txt b/csharp/Lib/Units/Generator/Template.txt index c656f51df..c78a3fcc6 100644 --- a/csharp/Lib/Units/Generator/Template.txt +++ b/csharp/Lib/Units/Generator/Template.txt @@ -18,25 +18,24 @@ public readonly partial struct Template public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/Power.generated.cs b/csharp/Lib/Units/Power.generated.cs index c26ad26fd..5ccca90ef 100644 --- a/csharp/Lib/Units/Power.generated.cs +++ b/csharp/Lib/Units/Power.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct Power public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/ReactivePower.generated.cs b/csharp/Lib/Units/ReactivePower.generated.cs index 9b8def505..f438dd865 100644 --- a/csharp/Lib/Units/ReactivePower.generated.cs +++ b/csharp/Lib/Units/ReactivePower.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct ReactivePower public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/Resistance.cs b/csharp/Lib/Units/Resistance.cs index ce426e229..ab0bc7bbe 100644 --- a/csharp/Lib/Units/Resistance.cs +++ b/csharp/Lib/Units/Resistance.cs @@ -2,6 +2,9 @@ using InnovEnergy.Lib.Units.Generator; namespace InnovEnergy.Lib.Units; + +// TODO: op parallel is wrong + [Sum] public readonly partial struct Resistance { diff --git a/csharp/Lib/Units/Resistance.generated.cs b/csharp/Lib/Units/Resistance.generated.cs index 5be7685b6..134384467 100644 --- a/csharp/Lib/Units/Resistance.generated.cs +++ b/csharp/Lib/Units/Resistance.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct Resistance public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/State.cs b/csharp/Lib/Units/State.cs index 752a5751d..af96735e0 100644 --- a/csharp/Lib/Units/State.cs +++ b/csharp/Lib/Units/State.cs @@ -14,5 +14,5 @@ public readonly struct State public static implicit operator State(Enum e) => new State(e); public static implicit operator State(String s) => new State(s); - public static State operator +(State left, State right) => new State(left, right); + public static State operator |(State left, State right) => new State(left, right); } \ No newline at end of file diff --git a/csharp/Lib/Units/Temperature.cs b/csharp/Lib/Units/Temperature.cs index dc2d7e5ad..57e2406a3 100644 --- a/csharp/Lib/Units/Temperature.cs +++ b/csharp/Lib/Units/Temperature.cs @@ -11,6 +11,5 @@ public readonly partial struct Temperature public static String Symbol => "T"; public Temperature(Decimal value) => Value = value; - } \ No newline at end of file diff --git a/csharp/Lib/Units/Temperature.generated.cs b/csharp/Lib/Units/Temperature.generated.cs index edc3fdbfa..cc173ee61 100644 --- a/csharp/Lib/Units/Temperature.generated.cs +++ b/csharp/Lib/Units/Temperature.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct Temperature public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/Units.cs b/csharp/Lib/Units/Units.cs index de1b246ad..98bc153e8 100644 --- a/csharp/Lib/Units/Units.cs +++ b/csharp/Lib/Units/Units.cs @@ -5,6 +5,8 @@ namespace InnovEnergy.Lib.Units; public static class Units { + public const Decimal MaxRelativeError = 0.05m; // 5% + public static Current A (this Decimal value) => new Current(value); public static Voltage V (this Decimal value) => new Voltage(value); public static Power W (this Decimal value) => new Power(value); diff --git a/csharp/Lib/Units/Voltage.generated.cs b/csharp/Lib/Units/Voltage.generated.cs index 07dc88d06..cdb63dcda 100644 --- a/csharp/Lib/Units/Voltage.generated.cs +++ b/csharp/Lib/Units/Voltage.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct Voltage public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d;