Innovenergy_trunk/csharp/Lib/Units/Composite/AcPhase.cs

54 lines
1.8 KiB
C#

using static DecimalMath.DecimalEx;
namespace InnovEnergy.Lib.Units.Composite;
public record AcPhase : Phase
{
public AcPhase(Voltage voltage, Current current, Angle phi) : base(voltage, current)
{
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;
}
public Angle Phi { get; }
public ApparentPower ApparentPower => Voltage.Value * Current.Value ;
public Power ActivePower => ApparentPower.Value * PowerFactor;
public ReactivePower ReactivePower => ApparentPower.Value * Sin(Phi);
public Decimal PowerFactor => Cos(Phi);
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
// 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)
// right(t) = IRight sin(ωt + φ).
// 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.
// we can shift both waves by -left.Phi, so
// φ := 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);
}
}