implement | (parallel) operator for all Units
This commit is contained in:
parent
a32cf83893
commit
2070fce4ec
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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<Ac3Phase, Ac3Phase, Ac3Phase> OpParallel = "|".CreateBinaryOpForProps<Ac3Phase>();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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<DcPhase, DcPhase, DcPhase> OpParallel = "|".CreateBinaryOpForProps<DcPhase>();
|
||||
|
||||
|
||||
}
|
|
@ -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; }
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
namespace InnovEnergy.Lib.Units.Composite;
|
||||
|
||||
public abstract record Phase
|
||||
(
|
||||
Voltage Voltage,
|
||||
Current Current
|
||||
);
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -2,6 +2,9 @@ using InnovEnergy.Lib.Units.Generator;
|
|||
|
||||
namespace InnovEnergy.Lib.Units;
|
||||
|
||||
|
||||
// TODO: op parallel is wrong
|
||||
|
||||
[Sum]
|
||||
public readonly partial struct Resistance
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -11,6 +11,5 @@ public readonly partial struct Temperature
|
|||
public static String Symbol => "T";
|
||||
|
||||
public Temperature(Decimal value) => Value = value;
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue