This commit is contained in:
ig 2023-06-13 13:03:49 +02:00
parent 7a44b1f307
commit d701620d34
26 changed files with 268 additions and 228 deletions

View File

@ -1,23 +0,0 @@
using InnovEnergy.Lib.SrcGen;
using InnovEnergy.Lib.SrcGen.Attributes;
using InnovEnergy.Lib.Time.Unix;
namespace InnovEnergy.Lib.Units;
[Generate<Operators>][Generate<Sum>]
public readonly partial struct ActivePower
{
public static String Unit => "W";
public static String Symbol => "P";
// P=UI
public static Voltage operator /(ActivePower power, Current current) => new Voltage(power.Value / current.Value);
public static Current operator /(ActivePower power, Voltage voltage) => new Current(power.Value / voltage.Value);
public static Energy operator *(ActivePower power, TimeSpan timeSpan) => power.Value / 1000 * timeSpan.TotalHours;
public static Energy operator *(TimeSpan timeSpan, ActivePower power) => power.Value / 1000 * timeSpan.TotalHours;
public static Energy operator *(ActivePower power, UnixTimeSpan timeSpan) => power.Value * timeSpan.Ticks / 3_600_000;
public static Energy operator *(UnixTimeSpan timeSpan, ActivePower power) => power.Value * timeSpan.Ticks / 3_600_000;
}

View File

@ -1,21 +1,24 @@
using InnovEnergy.Lib.SrcGen;
using InnovEnergy.Lib.SrcGen.Attributes;
using static System.Math; using static System.Math;
namespace InnovEnergy.Lib.Units; namespace InnovEnergy.Lib.Units;
[Generate<Operators>("HAS_CONSTRUCTOR")][Generate<Sum>] public sealed class Angle : Unit
public readonly partial struct Angle
{ {
public static String Unit => "rad"; public override String Symbol => "rad";
public static String Symbol => "∠";
public Angle(Double value) public Angle(Double value): base(Normalize(value))
{ {
var modulo = value % Tau; // tau is 2pi
Value = modulo > PI
? modulo - Tau
: modulo;
} }
private static Double Normalize(Double value)
{
var modulo = value % Tau; // tau is 2pi
return modulo > PI
? modulo - Tau
: modulo;
}
public static implicit operator Angle(Double d) => new Angle(d);
public static implicit operator Double(Angle d) => d.Value;
} }

View File

@ -1,17 +0,0 @@
using InnovEnergy.Lib.SrcGen;
using InnovEnergy.Lib.SrcGen.Attributes;
namespace InnovEnergy.Lib.Units;
[Generate<Operators>("HAS_CONSTRUCTOR")][Generate<Sum>]
public readonly partial struct ApparentPower
{
public static String Unit => "VA";
public static String Symbol => "S";
public ApparentPower(Double value)
{
if (value < 0) throw new ArgumentException("Apparent power cannot be negative", nameof(value));
Value = value;
}
}

View File

@ -1,12 +1,14 @@
namespace InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.Units.Composite;
public record Ac1Bus : AcPhase public sealed class Ac1Bus
{ {
protected Ac1Bus() {} private Ac1Bus()
{}
public Frequency Frequency { get; protected init; }
public Voltage Voltage { get; private init; } = null!;
public Current Current { get; private init; } = null!;
public AcPower Power { get; private init; } = null!;
public Frequency Frequency { get; private init; } = null!;
public static Ac1Bus FromVoltageCurrentFrequencyPhi(Double voltageRms, public static Ac1Bus FromVoltageCurrentFrequencyPhi(Double voltageRms,
Double currentRms, Double currentRms,
@ -18,7 +20,6 @@ public record Ac1Bus : AcPhase
Voltage = voltageRms, Voltage = voltageRms,
Power = AcPower.FromVoltageCurrentPhi(voltageRms, currentRms, phi) Power = AcPower.FromVoltageCurrentPhi(voltageRms, currentRms, phi)
}; };
public static Ac1Bus Null { get; } = FromVoltageCurrentFrequencyPhi(0, 0, 0, 0);
} }

View File

@ -2,17 +2,15 @@
namespace InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.Units.Composite;
#pragma warning disable CS8618 public sealed class Ac3Bus
public record Ac3Bus
{ {
protected Ac3Bus() {} private Ac3Bus() {}
public AcPhase L1 { get; protected init; } public AcPhase L1 { get; private init; } = null!;
public AcPhase L2 { get; protected init; } public AcPhase L2 { get; private init; } = null!;
public AcPhase L3 { get; protected init; } public AcPhase L3 { get; private init; } = null!;
public AcPower Power { get; protected init; } public AcPower Power { get; private init; } = null!;
public Frequency Frequency { get; protected init; } public Frequency Frequency { get; private init; } = null!;
public static Ac3Bus FromPhasesAndFrequency(AcPhase l1, public static Ac3Bus FromPhasesAndFrequency(AcPhase l1,
AcPhase l2, AcPhase l2,
@ -25,4 +23,6 @@ public record Ac3Bus
Power = AcPower.SumOf(l1.Power, l2.Power, l3.Power), Power = AcPower.SumOf(l1.Power, l2.Power, l3.Power),
Frequency = frequency, Frequency = frequency,
}; };
public static Ac3Bus Null { get; } = FromPhasesAndFrequency(AcPhase.Null, AcPhase.Null, AcPhase.Null, 0);
} }

View File

@ -1,12 +1,15 @@
using InnovEnergy.Lib.Units.Power;
namespace InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.Units.Composite;
#pragma warning disable CS8618
public record AcPhase : Bus public sealed class AcPhase
{ {
protected AcPhase(){} private AcPhase(){}
public AcPower Power { get; protected init; } public Voltage Voltage { get; private init; } = null!;
public Current Current { get; private init; } = null!;
public AcPower Power { get; private init; } = null!;
public static AcPhase FromVoltageCurrentPhi(Voltage voltageRms, public static AcPhase FromVoltageCurrentPhi(Voltage voltageRms,
Current currentRms, Current currentRms,
@ -38,5 +41,5 @@ public record AcPhase : Bus
Power = AcPower.FromActiveReactiveApparent(activePower, reactivePower, apparentPower) Power = AcPower.FromActiveReactiveApparent(activePower, reactivePower, apparentPower)
}; };
public static AcPhase Null { get; } = FromVoltageCurrentPhi(0, 0, 0);
} }

View File

@ -1,16 +1,18 @@
using InnovEnergy.Lib.Units.Power;
using static System.Math; using static System.Math;
namespace InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.Units.Composite;
public record AcPower
{
protected AcPower(){}
public ApparentPower Apparent { get; protected init; } public sealed class AcPower
public ActivePower Active { get; protected init; } {
public ReactivePower Reactive { get; protected init; } private AcPower(){}
public Angle Phi { get; protected init; }
public Double CosPhi { get; protected init; } public ApparentPower Apparent { get; private init; } = null!;
public ActivePower Active { get; private init; } = null!;
public ReactivePower Reactive { get; private init; } = null!;
public Angle Phi { get; private init; } = null!;
public Double CosPhi { get; private init; }
public static AcPower FromActiveReactiveApparent(ActivePower activePower, ReactivePower reactivePower, ApparentPower apparentPower) public static AcPower FromActiveReactiveApparent(ActivePower activePower, ReactivePower reactivePower, ApparentPower apparentPower)
{ {
@ -42,7 +44,7 @@ public record AcPower
Reactive = q, Reactive = q,
Apparent = s, Apparent = s,
Phi = phi, Phi = phi,
CosPhi = p/s, CosPhi = Cos(phi),
}; };
} }
@ -64,7 +66,6 @@ public record AcPower
}; };
} }
public static AcPower SumOf(params AcPower[] phases) public static AcPower SumOf(params AcPower[] phases)
{ {
var p = phases.Sum(l => l.Active.Value); var p = phases.Sum(l => l.Active.Value);
@ -82,4 +83,8 @@ public record AcPower
CosPhi = Cos(phi.Value) CosPhi = Cos(phi.Value)
}; };
} }
public static AcPower Null { get; } = FromVoltageCurrentPhi(0, 0, 0);
public override String ToString() => Active.ToString(); // TODO: show all
} }

View File

@ -1,11 +0,0 @@
using System.Diagnostics.CodeAnalysis;
namespace InnovEnergy.Lib.Units.Composite;
[SuppressMessage("ReSharper", "MemberCanBeProtected.Global")]
public abstract record Bus
{
public Voltage Voltage { get; protected init; }
public Current Current { get; protected init; }
}

View File

@ -1,10 +1,14 @@
using InnovEnergy.Lib.Units.Power;
namespace InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.Units.Composite;
public record DcBus : Bus public sealed class DcBus
{ {
protected DcBus() {} private DcBus() {}
public ActivePower Power { get; protected init; } public Voltage Voltage { get; private init; } = null!;
public Current Current { get; private init; } = null!;
public ActivePower Power { get; private init; } = null!;
public static DcBus FromVoltageCurrent(Voltage voltage, Current current) => new() public static DcBus FromVoltageCurrent(Voltage voltage, Current current) => new()
{ {
@ -12,4 +16,6 @@ public record DcBus : Bus
Current = current, Current = current,
Power = current.Value * voltage.Value, Power = current.Value * voltage.Value,
}; };
public static DcBus Null { get; } = FromVoltageCurrent(0, 0);
} }

View File

@ -1,20 +1,13 @@
using InnovEnergy.Lib.SrcGen;
using InnovEnergy.Lib.SrcGen.Attributes;
namespace InnovEnergy.Lib.Units; namespace InnovEnergy.Lib.Units;
[Generate<Operators>][Generate<Sum>] public sealed class Current : Unit
public readonly partial struct Current
{ {
public static String Unit => "A"; public override String Symbol => "A";
public static String Symbol => "I";
public Current(Double value) : base(value)
{}
public static implicit operator Current(Double d) => new Current(d);
// P=UI public static implicit operator Double(Current d) => d.Value;
public static ActivePower operator *(Current current, Voltage voltage) => new ActivePower(current.Value * voltage.Value);
// U=RI
public static Voltage operator *(Current current, Resistance resistance) => new Voltage(resistance.Value* current.Value);
} }

View File

@ -1,22 +0,0 @@
using InnovEnergy.Lib.SrcGen.Attributes;
using InnovEnergy.Lib.Time.Unix;
namespace InnovEnergy.Lib.Units;
[Generate<Operators>][Generate<Sum>]
public readonly partial struct DcPower
{
public static String Unit => "W";
public static String Symbol => "P";
// P=UI
public static Voltage operator /(DcPower power, Current current) => new Voltage(power.Value / current.Value);
public static Current operator /(DcPower power, Voltage voltage) => new Current(power.Value / voltage.Value);
public static Energy operator *(DcPower power, TimeSpan timeSpan) => power.Value / 1000 * timeSpan.TotalHours;
public static Energy operator *(TimeSpan timeSpan, DcPower power) => power.Value / 1000 * timeSpan.TotalHours;
public static Energy operator *(DcPower power, UnixTimeSpan timeSpan) => power.Value * timeSpan.Ticks / 3_600_000;
public static Energy operator *(UnixTimeSpan timeSpan, DcPower power) => power.Value * timeSpan.Ticks / 3_600_000;
}

View File

@ -1,15 +1,13 @@
using InnovEnergy.Lib.SrcGen;
using InnovEnergy.Lib.SrcGen.Attributes;
using InnovEnergy.Lib.Time.Unix;
namespace InnovEnergy.Lib.Units; namespace InnovEnergy.Lib.Units;
[Generate<Operators>][Generate<Sum>] public sealed class Energy : Unit
public readonly partial struct Energy
{ {
public static String Unit => "kWh"; public override String Symbol => "kWh";
public static String Symbol => "E";
public static ActivePower operator /(Energy energy, TimeSpan timeSpan) => energy.Value * 1000 / timeSpan.TotalHours ; public Energy(Double value) : base(value)
public static ActivePower operator /(Energy energy, UnixTimeSpan timeSpan) => energy.Value * 3_600_000 / timeSpan.Ticks; {
}
public static implicit operator Energy(Double d) => new Energy(d);
public static implicit operator Double(Energy d) => d.Value;
} }

View File

@ -1,19 +1,15 @@
using InnovEnergy.Lib.SrcGen;
using InnovEnergy.Lib.SrcGen.Attributes;
namespace InnovEnergy.Lib.Units; namespace InnovEnergy.Lib.Units;
[Generate<Operators>("HAS_CONSTRUCTOR")][Generate<Sum>] public sealed class Frequency : Unit
public readonly partial struct Frequency
{ {
public static String Unit => "Hz"; public override String Symbol => "Hz";
public static String Symbol => "f";
public Frequency(Double value) public Frequency(Double value) : base(value)
{ {
if (value < 0) if (value < 0)
throw new ArgumentException(nameof(Frequency) + " cannot be negative", nameof(value)); throw new ArgumentException(nameof(Frequency) + " cannot be negative", nameof(value));
Value = value;
} }
public static implicit operator Frequency(Double d) => new Frequency(d);
public static implicit operator Double(Frequency d) => d.Value;
} }

View File

@ -1,12 +1,13 @@
using InnovEnergy.Lib.SrcGen;
using InnovEnergy.Lib.SrcGen.Attributes;
namespace InnovEnergy.Lib.Units; namespace InnovEnergy.Lib.Units;
public sealed class Percent : Unit
[Generate<Operators>][Generate<Sum>]
public readonly partial struct Percent
{ {
public static String Unit => "%"; public override String Symbol => "%";
public static String Symbol => "%"; // ??
public Percent(Double value) : base(value)
{
}
public static implicit operator Percent(Double d) => new Percent(d);
public static implicit operator Double(Percent d) => d.Value;
} }

View File

@ -0,0 +1,8 @@
namespace InnovEnergy.Lib.Units.Power;
public abstract class AcPower : Power
{
protected AcPower(Double value) : base(value)
{
}
}

View File

@ -0,0 +1,15 @@
namespace InnovEnergy.Lib.Units.Power;
public sealed class ActivePower : AcPower
{
public override String Symbol => "W";
public ActivePower(Double value) : base(value)
{
}
public static implicit operator ActivePower(Double d) => new ActivePower(d);
public static implicit operator Double(ActivePower d) => d.Value;
}

View File

@ -0,0 +1,14 @@
namespace InnovEnergy.Lib.Units.Power;
public sealed class ApparentPower : AcPower
{
public override String Symbol => "VA";
public ApparentPower(Double value) : base(value)
{
}
public static implicit operator ApparentPower(Double d) => new ApparentPower(d);
public static implicit operator Double(ApparentPower d) => d.Value;
}

View File

@ -0,0 +1,13 @@
namespace InnovEnergy.Lib.Units.Power;
public sealed class DcPower : AcPower
{
public override String Symbol => "W";
public DcPower(Double value) : base(value)
{
}
public static implicit operator DcPower(Double d) => new DcPower(d);
public static implicit operator Double(DcPower d) => d.Value;
}

View File

@ -0,0 +1,9 @@
namespace InnovEnergy.Lib.Units.Power;
public abstract class Power : Unit
{
protected Power(Double value) : base(value)
{
}
}

View File

@ -0,0 +1,14 @@
namespace InnovEnergy.Lib.Units.Power;
public sealed class ReactivePower : AcPower
{
public override String Symbol => "var";
public ReactivePower(Double value) : base(value)
{
}
public static implicit operator ReactivePower(Double d) => new ReactivePower(d);
public static implicit operator Double(ReactivePower d) => d.Value;
}

View File

@ -1,12 +0,0 @@
using InnovEnergy.Lib.SrcGen;
using InnovEnergy.Lib.SrcGen.Attributes;
namespace InnovEnergy.Lib.Units;
[Generate<Operators>][Generate<Sum>]
public readonly partial struct ReactivePower
{
public static String Unit => "var";
public static String Symbol => "Q";
}

View File

@ -1,16 +1,13 @@
using InnovEnergy.Lib.SrcGen;
using InnovEnergy.Lib.SrcGen.Attributes;
namespace InnovEnergy.Lib.Units; namespace InnovEnergy.Lib.Units;
public sealed class Resistance: Unit
[Generate<Operators>][Generate<Parallel>]
public readonly partial struct Resistance
{ {
public static String Unit => "Ω"; public override String Symbol => "Ω";
public static String Symbol => "R";
// // U=RI public Resistance(Double value) : base(value)
// public static Voltage operator *(Resistance resistance, Current current) => new Voltage(resistance.Value * current.Value); {
}
public static implicit operator Resistance(Double d) => new Resistance(d);
public static implicit operator Double(Resistance d) => d.Value;
} }

View File

@ -1,13 +1,11 @@
using InnovEnergy.Lib.SrcGen;
using InnovEnergy.Lib.SrcGen.Attributes;
namespace InnovEnergy.Lib.Units; namespace InnovEnergy.Lib.Units;
public sealed class Temperature : Unit
[Generate<Operators>][Generate<Average>]
public readonly partial struct Temperature
{ {
public static String Unit => "°C"; public override String Symbol => "°C";
public static String Symbol => "T";
public Temperature(Double value) : base(value){}
public static implicit operator Temperature(Double d) => new Temperature(d);
public static implicit operator Double(Temperature d) => d.Value;
} }

11
csharp/Lib/Units/Unit.cs Normal file
View File

@ -0,0 +1,11 @@
namespace InnovEnergy.Lib.Units;
public abstract class Unit
{
protected Unit(Double value) => Value = value;
public abstract String Symbol { get; }
public Double Value { get; }
public override String ToString() => $"{Value} {Symbol}";
}

View File

@ -1,3 +1,9 @@
using System.Collections;
using System.Reflection;
using InnovEnergy.Lib.Units.Power;
using InnovEnergy.Lib.Utils;
using static System.Reflection.BindingFlags;
namespace InnovEnergy.Lib.Units; namespace InnovEnergy.Lib.Units;
public static class Units public static class Units
@ -16,30 +22,69 @@ public static class Units
public static Temperature Celsius(this Double value) => value; public static Temperature Celsius(this Double value) => value;
public static Energy KWh (this Double value) => value; public static Energy KWh (this Double value) => value;
public static String ToCsv(this Object thing)
public static String ToCsv<T>(this T thing)
{ {
IEnumerable<Object> GetChildren(Object parent) var csvLines = new List<String>();
var visited = new HashSet<Object>();
GetCsv(thing);
return csvLines.JoinLines();
void GetCsv(Object? parent, String path = "")
{ {
if (parent == null)
return;
var type = parent.GetType();
parent if (parent is Unit u)
.GetType() {
.GetProperties(); csvLines.Add($"{path};{u.Value};{u.Symbol}"); // leaf: unit
}
else if (parent is String s)
{
csvLines.Add($"{path};{s};"); // leaf: unit
}
else if(type.IsEnum || (type.IsValueType && !type.IsNested))
{
csvLines.Add($"{path};{parent};"); // leaf: value type
}
else if (parent is IEnumerable enumerable)
{
var enumerableType = enumerable.GetType();
var elementType = enumerableType.GetGenericArguments().SingleOrDefault() ??
enumerableType.GetElementType(); // for arrays
if (elementType is null)
return;
if (elementType.IsValueType || elementType == typeof(String))
{
var value = enumerable.Cast<Object>().JoinWith(",");
csvLines.Add($"{path};{value};");
}
else
{
var i = 1;
foreach (var o in enumerable)
GetCsv(o, $"{path}/{i++}");
}
}
else
{
if (!visited.Add(parent))
return;
foreach (var p in type.GetProperties(Instance | Public))
{
var name = p.Name;
var value = p.GetValue(parent);
GetCsv(value, $"{path}/{name}");
}
}
} }
thing.TraverseLeavesWithPath()
if (thing is null)
return new Dictionary<String, String>();
return thing
.GetType()
.GetProperties()
.Select(p => (p.Name, Value: p.GetValue(thing)?.ToString()))
.Where(p => p.Value != null)
.ToDictionary(p => p.Name, p=>p.Value!);
} }
} }

View File

@ -1,18 +1,13 @@
using InnovEnergy.Lib.SrcGen;
using InnovEnergy.Lib.SrcGen.Attributes;
namespace InnovEnergy.Lib.Units; namespace InnovEnergy.Lib.Units;
public sealed class Voltage : Unit
[Generate<Operators>][Generate<Average>]
public readonly partial struct Voltage
{ {
public static String Unit => "V"; public override String Symbol => "V";
public static String Symbol => "U";
// U=RI public Voltage(Double value) : base(value)
public static Current operator /(Voltage voltage, Resistance resistance) => new Current(voltage.Value / resistance.Value); {}
// P=UI public static implicit operator Voltage(Double d) => new Voltage(d);
public static ActivePower operator *(Voltage voltage, Current current) => new ActivePower(current.Value * voltage.Value); public static implicit operator Double(Voltage d) => d.Value;
} }