convert composite units to records

This commit is contained in:
ig 2023-09-01 08:54:46 +02:00
parent be452d190c
commit 05f0a7e9f9
19 changed files with 220 additions and 344 deletions

View File

@ -250,8 +250,8 @@ internal static class Program
var nInverters = record.AcDc.Devices.Count; var nInverters = record.AcDc.Devices.Count;
var powerPerInverterPhase = nInverters > 0 var powerPerInverterPhase = nInverters > 0
? AcPower.FromActiveReactive(essControl.PowerSetpoint / nInverters / 3, 0) ? essControl.PowerSetpoint / nInverters / 3
: AcPower.FromActiveReactive(0,0); : 0;
//var powerPerInverterPhase = AcPower.Null; //var powerPerInverterPhase = AcPower.Null;

View File

@ -1,6 +1,7 @@
using InnovEnergy.Lib.Protocols.Modbus.Reflection.Attributes; using InnovEnergy.Lib.Protocols.Modbus.Reflection.Attributes;
using InnovEnergy.Lib.StatusApi.DeviceTypes; using InnovEnergy.Lib.StatusApi.DeviceTypes;
using InnovEnergy.Lib.Units.Composite; using InnovEnergy.Lib.Units.Composite;
using static System.Math;
#pragma warning disable CS0649 #pragma warning disable CS0649
@ -20,10 +21,6 @@ public class EmuMeterRegisters : IAc3Meter
[HoldingRegister<Float32>(9014)] private Float32 _ReactivePowerL2; [HoldingRegister<Float32>(9014)] private Float32 _ReactivePowerL2;
[HoldingRegister<Float32>(9016)] private Float32 _ReactivePowerL3; [HoldingRegister<Float32>(9016)] private Float32 _ReactivePowerL3;
[HoldingRegister<Float32>(9022)] private Float32 _ApparentPowerL1;
[HoldingRegister<Float32>(9024)] private Float32 _ApparentPowerL2;
[HoldingRegister<Float32>(9026)] private Float32 _ApparentPowerL3;
[HoldingRegister<Float32>(9102)] private Float32 _CurrentL1; [HoldingRegister<Float32>(9102)] private Float32 _CurrentL1;
[HoldingRegister<Float32>(9104)] private Float32 _CurrentL2; [HoldingRegister<Float32>(9104)] private Float32 _CurrentL2;
[HoldingRegister<Float32>(9106)] private Float32 _CurrentL3; [HoldingRegister<Float32>(9106)] private Float32 _CurrentL3;
@ -34,34 +31,28 @@ public class EmuMeterRegisters : IAc3Meter
[HoldingRegister<Float32>(9310)] private Float32 _Frequency; [HoldingRegister<Float32>(9310)] private Float32 _Frequency;
public Ac3Bus Ac => Ac3Bus.FromPhasesAndFrequency public Ac3Bus Ac => new Ac3Bus
( {
l1: AcPhase.FromVoltageCurrentActiveReactiveApparent L1 = new ()
( {
_VoltageL1N, Current = _CurrentL1,
_CurrentL1, Voltage = _VoltageL1N,
_ActivePowerL1, Phi = Atan2(_ReactivePowerL1, _ActivePowerL1)
_ReactivePowerL1, },
_ApparentPowerL1 L2 = new ()
), {
l2: AcPhase.FromVoltageCurrentActiveReactiveApparent Current = _CurrentL2,
( Voltage = _VoltageL2N,
_VoltageL2N, Phi = Atan2(_ReactivePowerL2, _ActivePowerL2)
_CurrentL2, },
_ActivePowerL2, L3 = new ()
_ReactivePowerL2, {
_ApparentPowerL2 Current = _CurrentL3,
), Voltage = _VoltageL3N,
l3: AcPhase.FromVoltageCurrentActiveReactiveApparent Phi = Atan2(_ReactivePowerL3, _ActivePowerL3)
( },
_VoltageL3N, Frequency = _Frequency
_CurrentL3, };
_ActivePowerL3,
_ReactivePowerL3,
_ApparentPowerL3
),
frequency: _Frequency
);
} }

View File

@ -39,35 +39,7 @@ public class Iem3KGridMeterRegisters : IAc3Meter
[HoldingRegister<Float32>(9310)] private Float32 _Frequency; [HoldingRegister<Float32>(9310)] private Float32 _Frequency;
public Ac3Bus Ac => Ac3Bus.FromPhasesAndFrequency public Ac3Bus Ac => throw new NotImplementedException();
(
l1: AcPhase.FromVoltageCurrentActiveReactiveApparent
(
_VoltageL1N,
_CurrentL1,
_ActivePowerL1,
_ReactivePowerL1,
_ApparentPowerL1
),
l2: AcPhase.FromVoltageCurrentActiveReactiveApparent
(
_VoltageL2N,
_CurrentL2,
_ActivePowerL2,
_ReactivePowerL2,
_ApparentPowerL2
),
l3: AcPhase.FromVoltageCurrentActiveReactiveApparent
(
_VoltageL3N,
_CurrentL3,
_ActivePowerL3,
_ReactivePowerL3,
_ApparentPowerL3
),
frequency: _Frequency
);
} }

View File

@ -1,6 +1,7 @@
using InnovEnergy.Lib.Devices.Trumpf.SystemControl; using InnovEnergy.Lib.Devices.Trumpf.SystemControl;
using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.DataTypes; using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.DataTypes;
using InnovEnergy.Lib.Units.Composite; using InnovEnergy.Lib.Units.Composite;
using static System.Math;
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc; namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc;
@ -25,35 +26,57 @@ public class AcDcDevicesRecord
get get
{ {
if (Devices.Count == 0) if (Devices.Count == 0)
return Ac3Bus.Null; return Ac3Bus.Zero;
var l1 = AcPhase.FromVoltageCurrentActiveReactive var ac = Devices
( .Select(d => d.Status.Ac)
voltageRms : Devices.Average(d => d.Status.Ac.L1.Voltage), .ToList();
currentRms : Devices.Sum(d => d.Status.Ac.L1.Current),
activePower : Devices.Sum(d => d.Status.Ac.L1.Power.Active),
reactivePower: Devices.Sum(d => d.Status.Ac.L1.Power.Reactive)
);
var l2 = AcPhase.FromVoltageCurrentActiveReactive var f = ac.Average(d => d.Frequency);
(
voltageRms : Devices.Average(d => d.Status.Ac.L2.Voltage),
currentRms : Devices.Sum(d => d.Status.Ac.L2.Current),
activePower : Devices.Sum(d => d.Status.Ac.L2.Power.Active),
reactivePower: Devices.Sum(d => d.Status.Ac.L2.Power.Reactive)
);
var l3 = AcPhase.FromVoltageCurrentActiveReactive var u1 = ac.Average(d => d.L1.Voltage);
( var i1 = ac.Sum(d => d.L1.Current);
voltageRms : Devices.Average(d => d.Status.Ac.L3.Voltage), var q1 = ac.Sum(d => d.L1.Power.Reactive);
currentRms : Devices.Sum(d => d.Status.Ac.L3.Current), var p1 = ac.Sum(d => d.L1.Power.Active);
activePower : Devices.Sum(d => d.Status.Ac.L3.Power.Active),
reactivePower: Devices.Sum(d => d.Status.Ac.L3.Power.Reactive)
);
var f = Devices.Average(d => d.Status.Ac.Frequency); var l1 = new AcPhase
{
Voltage = u1,
Current = i1,
Phi = Atan2(q1, p1)
};
return Ac3Bus.FromPhasesAndFrequency(l1, l2, l3, f); var u2 = ac.Average(d => d.L2.Voltage);
var i2 = ac.Sum(d => d.L2.Current);
var q2 = ac.Sum(d => d.L2.Power.Reactive);
var p2 = ac.Sum(d => d.L2.Power.Active);
var l2 = new AcPhase
{
Voltage = u2,
Current = i2,
Phi = Atan2(q2, p2)
};
var u3 = ac.Average(d => d.L3.Voltage);
var i3 = ac.Sum(d => d.L3.Current);
var q3 = ac.Sum(d => d.L3.Power.Reactive);
var p3 = ac.Sum(d => d.L3.Power.Active);
var l3 = new AcPhase
{
Voltage = u3,
Current = i3,
Phi = Atan2(q3, p3)
};
return new Ac3Bus
{
L1 = l1,
L2 = l2,
L3 = l3,
Frequency = f,
};
} }
} }
@ -62,7 +85,7 @@ public class AcDcDevicesRecord
get get
{ {
if (Devices.Count == 0) if (Devices.Count == 0)
return DcBus.Null; return DcBus.Zero;
var u = Devices var u = Devices
.Select(d => d.Status.DcVoltages.Extern) .Select(d => d.Status.DcVoltages.Extern)

View File

@ -1,6 +1,7 @@
using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.DataTypes; using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.DataTypes;
using InnovEnergy.Lib.Units.Composite; using InnovEnergy.Lib.Units.Composite;
using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Utils;
using static System.Math;
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.Control; namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.Control;
@ -13,17 +14,21 @@ public class AcPowerControl
var s = _Self.PowerSetpointL1; var s = _Self.PowerSetpointL1;
var cosPhi = _Self.CosPhiSetpointL1.Clamp(-1, 1); var cosPhi = _Self.CosPhiSetpointL1.Clamp(-1, 1);
var rpk = _Self.ReactivePowerKindL1; var rpk = _Self.ReactivePowerKindL1;
var phi = cosPhi.Apply(Math.Acos) * (rpk == ReactivePowerKind.Inductive ? 1 : -1); var phi = Acos(cosPhi) * (rpk == ReactivePowerKind.Inductive ? 1 : -1);
var sinPhi = Math.Sin(phi); var sinPhi = Sin(phi);
return AcPower.FromActiveReactive(s * cosPhi, s * sinPhi); return new AcPower { Active = s * cosPhi, Reactive = s * sinPhi };
} }
set set
{ {
_Self.PowerSetpointL1 = value.Apparent.Value; var s = value.Apparent;
_Self.CosPhiSetpointL1 = value.CosPhi; var p = value.Active;
_Self.SinPhiSetpointL1 = Math.Sin(value.Phi); var q = value.Reactive;
_Self.PowerSetpointL1 = s;
_Self.CosPhiSetpointL1 = s == 0 ? 1 : p / s;
_Self.SinPhiSetpointL1 = s == 0 ? 0 : q / s;
_Self.ReactivePowerKindL1 = value.Reactive >= 0 _Self.ReactivePowerKindL1 = value.Reactive >= 0
? ReactivePowerKind.Inductive ? ReactivePowerKind.Inductive
: ReactivePowerKind.Capacitive; : ReactivePowerKind.Capacitive;
@ -38,23 +43,28 @@ public class AcPowerControl
var s = _Self.PowerSetpointL2; var s = _Self.PowerSetpointL2;
var cosPhi = _Self.CosPhiSetpointL2.Clamp(-1, 1); var cosPhi = _Self.CosPhiSetpointL2.Clamp(-1, 1);
var rpk = _Self.ReactivePowerKindL2; var rpk = _Self.ReactivePowerKindL2;
var phi = cosPhi.Apply(Math.Acos) * (rpk == ReactivePowerKind.Inductive ? 1 : -1); var phi = Acos(cosPhi) * (rpk == ReactivePowerKind.Inductive ? 1 : -1);
var sinPhi = Math.Sin(phi); var sinPhi = Sin(phi);
return AcPower.FromActiveReactive(s * cosPhi, s * sinPhi); return new AcPower { Active = s * cosPhi, Reactive = s * sinPhi };
} }
set set
{ {
_Self.PowerSetpointL2 = value.Apparent.Value; var s = value.Apparent;
_Self.CosPhiSetpointL2 = value.CosPhi; var p = value.Active;
_Self.SinPhiSetpointL2 = Math.Sin(value.Phi); var q = value.Reactive;
_Self.PowerSetpointL2 = s;
_Self.CosPhiSetpointL2 = s == 0 ? 1 : p / s;
_Self.SinPhiSetpointL2 = s == 0 ? 0 : q / s;
_Self.ReactivePowerKindL2 = value.Reactive >= 0 _Self.ReactivePowerKindL2 = value.Reactive >= 0
? ReactivePowerKind.Inductive ? ReactivePowerKind.Inductive
: ReactivePowerKind.Capacitive; : ReactivePowerKind.Capacitive;
} }
} }
public AcPower L3 public AcPower L3
{ {
get get
@ -62,17 +72,21 @@ public class AcPowerControl
var s = _Self.PowerSetpointL3; var s = _Self.PowerSetpointL3;
var cosPhi = _Self.CosPhiSetpointL3.Clamp(-1, 1); var cosPhi = _Self.CosPhiSetpointL3.Clamp(-1, 1);
var rpk = _Self.ReactivePowerKindL3; var rpk = _Self.ReactivePowerKindL3;
var phi = cosPhi.Apply(Math.Acos) * (rpk == ReactivePowerKind.Inductive ? 1 : -1); var phi = Acos(cosPhi) * (rpk == ReactivePowerKind.Inductive ? 1 : -1);
var sinPhi = Math.Sin(phi); var sinPhi = Sin(phi);
return AcPower.FromActiveReactive(s * cosPhi, s * sinPhi); return new AcPower { Active = s * cosPhi, Reactive = s * sinPhi };
} }
set set
{ {
_Self.PowerSetpointL3 = value.Apparent.Value; var s = value.Apparent;
_Self.CosPhiSetpointL3 = value.CosPhi; var p = value.Active;
_Self.SinPhiSetpointL3 = Math.Sin(value.Phi); var q = value.Reactive;
_Self.PowerSetpointL3 = s;
_Self.CosPhiSetpointL3 = s == 0 ? 1 : p / s;
_Self.SinPhiSetpointL3 = s == 0 ? 0 : q / s;
_Self.ReactivePowerKindL3 = value.Reactive >= 0 _Self.ReactivePowerKindL3 = value.Reactive >= 0
? ReactivePowerKind.Inductive ? ReactivePowerKind.Inductive
: ReactivePowerKind.Capacitive; : ReactivePowerKind.Capacitive;

View File

@ -2,6 +2,7 @@
using InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes; using InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes;
using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.DataTypes; using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.DataTypes;
using InnovEnergy.Lib.Units.Composite; using InnovEnergy.Lib.Units.Composite;
using static System.Math;
using AlarmMessage = InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.DataTypes.AlarmMessage; using AlarmMessage = InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.DataTypes.AlarmMessage;
using WarningMessage = InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.DataTypes.WarningMessage; using WarningMessage = InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.DataTypes.WarningMessage;
@ -9,7 +10,7 @@ namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.Status;
public class AcDcStatus public class AcDcStatus
{ {
public Ac3Bus Ac => Ac3Bus.FromPhasesAndFrequency(L1, L2, L3, _Self.GridFrequency); public Ac3Bus Ac => new Ac3Bus { L1 = L1, L2 = L2, L3 = L3, Frequency = _Self.GridFrequency };
public PowerLimit PowerLimitedBy => _Self.PowerLimitedBy; public PowerLimit PowerLimitedBy => _Self.PowerLimitedBy;
public InverterStates InverterState => new(_Self); public InverterStates InverterState => new(_Self);
public GridType ActiveGridType => _Self.ActiveGridType; public GridType ActiveGridType => _Self.ActiveGridType;
@ -74,32 +75,28 @@ public class AcDcStatus
// TODO: there are no AcDc Warnings defined in doc // TODO: there are no AcDc Warnings defined in doc
private static Boolean IsAcDcWarning(WarningMessage warning) => warning != WarningMessage.NoWarning; private static Boolean IsAcDcWarning(WarningMessage warning) => warning != WarningMessage.NoWarning;
private AcPhase L1 => AcPhase.FromVoltageCurrentActiveReactiveApparent private AcPhase L1 => new()
( {
voltageRms : _Self.GridVoltageL1, Current = _Self.GridCurrentL1,
currentRms : _Self.GridCurrentL1, Voltage = _Self.GridVoltageL1,
activePower : _Self.ActivePowerL1, Phi = Atan2(_Self.ReactivePowerL1, _Self.ActivePowerL1)
reactivePower: _Self.ReactivePowerL1, };
apparentPower: _Self.ApparentPowerL1
); private AcPhase L2 => new()
{
Current = _Self.GridCurrentL2,
Voltage = _Self.GridVoltageL2,
Phi = Atan2(_Self.ReactivePowerL2, _Self.ActivePowerL2)
};
private AcPhase L3 => new()
{
Current = _Self.GridCurrentL3,
Voltage = _Self.GridVoltageL3,
Phi = Atan2(_Self.ReactivePowerL3, _Self.ActivePowerL3)
};
private AcPhase L2 => AcPhase.FromVoltageCurrentActiveReactiveApparent
(
voltageRms : _Self.GridVoltageL2,
currentRms : _Self.GridCurrentL2,
activePower : _Self.ActivePowerL2,
reactivePower: _Self.ReactivePowerL2,
apparentPower: _Self.ApparentPowerL2
);
private AcPhase L3 => AcPhase.FromVoltageCurrentActiveReactiveApparent
(
voltageRms : _Self.GridVoltageL3,
currentRms : _Self.GridCurrentL3,
activePower : _Self.ActivePowerL3,
reactivePower: _Self.ReactivePowerL3,
apparentPower: _Self.ApparentPowerL3
);
internal AcDcStatus(AcDcRecord self) => _Self = self; internal AcDcStatus(AcDcRecord self) => _Self = self;

View File

@ -1,5 +1,6 @@
using InnovEnergy.Lib.Devices.Trumpf.SystemControl; using InnovEnergy.Lib.Devices.Trumpf.SystemControl;
using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc.Status; using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc.Status;
using InnovEnergy.Lib.Units;
using InnovEnergy.Lib.Units.Composite; using InnovEnergy.Lib.Units.Composite;
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertDc; namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertDc;
@ -18,7 +19,13 @@ public class DcDcDevicesRecord
Devices = devices; Devices = devices;
} }
public DcStatus Dc => new() public DcStatus Dc
{
get
{
Voltage voltage = Devices.Average(r => r.Status.Dc.Link.Voltage.Value);
Current current = Devices.Sum(r => r.Status.Dc.Link.Current.Value);
return new()
{ {
Battery = Devices.Count == 0 Battery = Devices.Count == 0
? NoDevice ? NoDevice
@ -30,12 +37,14 @@ public class DcDcDevicesRecord
Link = Devices.Count == 0 Link = Devices.Count == 0
? NoDevice ? NoDevice
: DcBus.FromVoltageCurrent : new()
( {
Devices.Average(r => r.Status.Dc.Link.Voltage.Value), Voltage = voltage,
Devices.Sum(r => r.Status.Dc.Link.Current.Value) Current = current,
) }
}; };
}
}
public SystemControlRegisters? SystemControl { get; } public SystemControlRegisters? SystemControl { get; }
public IReadOnlyList<DcDcRecord> Devices { get; } public IReadOnlyList<DcDcRecord> Devices { get; }

View File

@ -1,5 +1,4 @@
using InnovEnergy.Lib.Units; using InnovEnergy.Lib.Units;
using InnovEnergy.Lib.Units.Composite;
using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Utils;
namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertDc.Status; namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertDc.Status;

View File

@ -4,6 +4,6 @@ namespace InnovEnergy.Lib.StatusApi.Connections;
public interface IAc1Connection public interface IAc1Connection
{ {
Ac1Bus Ac { get; } AcBus Ac { get; }
} }

View File

@ -1,5 +1,4 @@
using InnovEnergy.Lib.StatusApi.Connections; using InnovEnergy.Lib.StatusApi.Connections;
using InnovEnergy.Lib.Units.Composite;
namespace InnovEnergy.Lib.StatusApi.DeviceTypes; namespace InnovEnergy.Lib.StatusApi.DeviceTypes;

View File

@ -1,5 +1,4 @@
using InnovEnergy.Lib.StatusApi.Connections; using InnovEnergy.Lib.StatusApi.Connections;
using InnovEnergy.Lib.Units.Composite;
namespace InnovEnergy.Lib.StatusApi.DeviceTypes; namespace InnovEnergy.Lib.StatusApi.DeviceTypes;

View File

@ -1,7 +0,0 @@
namespace InnovEnergy.Lib.StatusApi;
public interface IDeviceRecord<out S, out C>
{
S Status { get; }
C Control { get; }
}

View File

@ -1,22 +0,0 @@
namespace InnovEnergy.Lib.Units.Composite;
public sealed class Ac1Bus
{
public required Voltage Voltage { get; init; }
public required Current Current { get; init; }
public required AcPower Power { get; init; }
public required Frequency Frequency { get; init; }
public static Ac1Bus FromVoltageCurrentFrequencyPhi(Double voltageRms,
Double currentRms,
Double frequency,
Double phi) => new()
{
Frequency = frequency,
Current = currentRms,
Voltage = voltageRms,
Power = AcPower.FromVoltageCurrentPhi(voltageRms, currentRms, phi)
};
public static Ac1Bus Null => FromVoltageCurrentFrequencyPhi(0, 0, 0, 0);
}

View File

@ -1,25 +1,20 @@
namespace InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.Units.Composite;
public class Ac3Bus public record Ac3Bus
{ {
public required AcPhase L1 { get; init; } public required AcPhase L1 { get; init; }
public required AcPhase L2 { get; init; } public required AcPhase L2 { get; init; }
public required AcPhase L3 { get; init; } public required AcPhase L3 { get; init; }
public required AcPower Power { get; init; }
public required Frequency Frequency { get; init; } public required Frequency Frequency { get; init; }
public static Ac3Bus FromPhasesAndFrequency(AcPhase l1, public AcPower Power => L1.Power + L2.Power + L3.Power;
AcPhase l2,
AcPhase l3,
Frequency frequency) => new()
{
L1 = l1,
L2 = l2,
L3 = l3,
Power = AcPower.SumOf(l1.Power, l2.Power, l3.Power),
Frequency = frequency,
};
public static Ac3Bus Null => FromPhasesAndFrequency(AcPhase.Null, AcPhase.Null, AcPhase.Null, 0); public static Ac3Bus Zero => new Ac3Bus
{
Frequency = 0,
L1 = AcPhase.Zero,
L2 = AcPhase.Zero,
L3 = AcPhase.Zero,
};
} }

View File

@ -0,0 +1,14 @@
namespace InnovEnergy.Lib.Units.Composite;
public record AcBus : AcPhase
{
public required Frequency Frequency { get; init; }
public new static AcBus Zero => new AcBus
{
Current = 0,
Voltage = 0,
Phi = 0,
Frequency = 0,
};
}

View File

@ -1,46 +1,23 @@
using InnovEnergy.Lib.Units.Power; using static System.Math;
namespace InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.Units.Composite;
public record AcPhase
public sealed class AcPhase
{ {
public required Voltage Voltage { get; init; } public required Voltage Voltage { get; init; }
public required Current Current { get; init; } public required Current Current { get; init; }
public required AcPower Power { get; init; } public required Angle Phi { get; init; }
public static AcPhase FromVoltageCurrentPhi(Voltage voltageRms, public AcPower Power => new()
Current currentRms,
Angle phi) => new()
{ {
Current = currentRms, Active = Voltage * Current * Cos(Phi),
Voltage = voltageRms, Reactive = Voltage * Current * Sin(Phi),
Power = AcPower.FromVoltageCurrentPhi(voltageRms, currentRms, phi)
}; };
public static AcPhase FromVoltageCurrentActiveReactive(Voltage voltageRms, public static AcPhase Zero => new AcPhase
Current currentRms,
ActivePower activePower,
ReactivePower reactivePower) => new()
{ {
Current = currentRms, Current = 0,
Voltage = voltageRms, Voltage = 0,
Power = AcPower.FromActiveReactive(activePower, reactivePower) Phi = 0,
}; };
public static AcPhase FromVoltageCurrentActiveReactiveApparent(Voltage voltageRms,
Current currentRms,
ActivePower activePower,
ReactivePower reactivePower,
ApparentPower apparentPower) => new()
{
Current = currentRms,
Voltage = voltageRms,
Power = AcPower.FromActiveReactiveApparent(activePower, reactivePower, apparentPower)
};
public static AcPhase Null => FromVoltageCurrentPhi(0, 0, 0);
} }

View File

@ -4,108 +4,31 @@ using static System.Math;
namespace InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.Units.Composite;
public sealed class AcPower public record AcPower
{ {
private AcPower(){}
public required ApparentPower Apparent { get; init; }
public required ActivePower Active { get; init; } public required ActivePower Active { get; init; }
public required ReactivePower Reactive { get; init; } public required ReactivePower Reactive { get; init; }
public required Angle Phi { get; init; }
public required Double CosPhi { get; init; }
public static AcPower FromActiveReactiveApparent(ActivePower activePower, ReactivePower reactivePower, ApparentPower apparentPower) public ApparentPower Apparent => Sqrt(Active * Active + Reactive * Reactive);
{
var q = reactivePower.Value;
var p = activePower.Value;
var s = apparentPower.Value;
var phi = Atan2(q, p);
return new AcPower public static AcPower operator +(AcPower left, AcPower right) => new AcPower
{ {
Active = p, Active = left.Active + right.Active,
Reactive = q, Reactive = left.Reactive + right.Reactive
Apparent = s,
Phi = phi,
CosPhi = Cos(phi),
}; };
}
public static AcPower FromActiveReactive(ActivePower activePower, ReactivePower reactivePower) public static AcPower operator -(AcPower left, AcPower right) => new AcPower
{ {
var q = reactivePower.Value; Active = left.Active - right.Active,
var p = activePower.Value; Reactive = left.Reactive - right.Reactive
var s = Sqrt(p * p + q * q);
var phi = Atan2(q, p);
return new AcPower
{
Active = p,
Reactive = q,
Apparent = s,
Phi = phi,
CosPhi = Cos(phi),
}; };
}
public static AcPower FromVoltageCurrentPhi(Voltage voltageRms, Current currentRms, Angle phi) public static AcPower operator -(AcPower p) => new AcPower
{ {
if (voltageRms < 0) throw new ArgumentException("RMS value cannot be negative", nameof(voltageRms)); Active = -p.Active,
if (currentRms < 0) throw new ArgumentException("RMS value cannot be negative", nameof(currentRms)); Reactive = -p.Reactive
var cosPhi = Cos(phi.Value);
var apparent = voltageRms.Value * currentRms.Value;
return new AcPower
{
Apparent = apparent,
Active = apparent * cosPhi,
Reactive = apparent * Sin(phi.Value),
Phi = phi,
CosPhi = cosPhi
}; };
}
public static implicit operator AcPower(Double p) => new AcPower { Active = p, Reactive = 0 };
public static AcPower SumOf(params AcPower[] phases) public static implicit operator AcPower(Int32 p) => new AcPower { Active = p, Reactive = 0 };
{
var p = phases.Sum(l => l.Active.Value);
var q = phases.Sum(l => l.Reactive.Value);
var s = Sqrt(p * p + q * q);
Angle phi = Atan2(q, p);
return new AcPower
{
Apparent = s,
Active = p,
Reactive = q,
Phi = phi,
CosPhi = Cos(phi.Value)
};
}
public static AcPower operator +(AcPower left, AcPower right) => FromActiveReactive
(
left.Active + right.Active,
left.Reactive + right.Reactive
);
public static AcPower operator -(AcPower left, AcPower right) => FromActiveReactive
(
left.Active - right.Active,
left.Reactive - right.Reactive
);
public static AcPower operator -(AcPower p) => FromActiveReactive
(
-p.Active,
-p.Reactive
);
public static implicit operator AcPower(Double p) => FromActiveReactive(p, 0);
public static implicit operator AcPower(Int32 p) => FromActiveReactive(p, 0);
public override String ToString() => Active.ToString(); // TODO: show all
} }

View File

@ -2,20 +2,14 @@ using InnovEnergy.Lib.Units.Power;
namespace InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.Units.Composite;
public sealed class DcBus public record DcBus
{ {
public required Voltage Voltage { get; init; } public required Voltage Voltage { get; init; }
public required Current Current { get; init; } public required Current Current { get; init; }
public DcPower Power => Voltage * Current; public DcPower Power => Voltage * Current;
public static DcBus FromVoltageCurrent(Voltage voltage, Current current) => new() public static DcBus Zero => new()
{
Voltage = voltage,
Current = current,
};
public static DcBus Null => new()
{ {
Voltage = 0, Voltage = 0,
Current = 0, Current = 0,

View File

@ -5,5 +5,4 @@ public abstract class Power : Unit
protected Power(Double value) : base(value) protected Power(Double value) : base(value)
{ {
} }
} }