/// <summary> /// Builds <see cref="WaveformState"/> based on this <see cref="PhasorState"/>. Builds waveforms for each potential and current. /// </summary> /// <param name="pointsCount"></param> /// <param name="timeStep"></param> /// <returns></returns> public WaveformState ToWaveform(int pointsCount, double timeStep) { // Create state for result var result = new WaveformState(Potentials.Keys, Currents.Keys, SourceDescription); // Depending on source type switch (SourceDescription.SourceType) { // For AC sources case SourceType.ACVoltageSource: { // For each potential foreach (var potential in Potentials) { // Create sine waves based on the phasor result.Potentials[potential.Key] = WaveformBuilder.SineWave(potential.Value.Magnitude, SourceDescription.Frequency, potential.Value.Phase, pointsCount, timeStep).ToList(); } // Similarly for currents foreach (var current in Currents) { result.Currents[current.Key] = WaveformBuilder.SineWave(current.Value.Magnitude, SourceDescription.Frequency, current.Value.Phase, pointsCount, timeStep).ToList(); } } break; // For DC sources case SourceType.DCVoltageSource: case SourceType.DCCurrentSource: { // For each potential foreach (var potential in Potentials) { // Build constant waveforms. For DC sources phasor is a purely real number - just take the real part as value of the // wave. result.Potentials[potential.Key] = WaveformBuilder.ConstantWaveform(potential.Value.Real, pointsCount).ToList(); } // Similarly for currents foreach (var current in Currents) { result.Currents[current.Key] = WaveformBuilder.ConstantWaveform(current.Value.Real, pointsCount).ToList(); } } break; } return(result); }
/// <summary> /// Creates an instantenous state for some time moment based on phasors in this instance. The time moment is defined as /// <paramref name="pointIndex"/> * <paramref name="timeStep"/>. /// </summary> /// <returns></returns> /// <param name="pointIndex">Index of the point for which the instantenous values will be calculated, indexing starts from 0</param> /// <param name="timeStep">Time step between 2 subsequent points</param> public InstantenousState ToInstantenousValues(int pointIndex, double timeStep) { // Create state for result var result = new InstantenousState(Potentials.Keys, Currents.Keys, SourceDescription); // Depending on source type switch (SourceDescription.SourceType) { // For AC sources case SourceType.ACVoltageSource: { // For each potential foreach (var potential in Potentials) { // Assign to result an instantenous value of a sine wave based on the phasor result.Potentials[potential.Key] = WaveformBuilder.SineWaveInstantenousValue(potential.Value.Magnitude, SourceDescription.Frequency, potential.Value.Phase, pointIndex, timeStep); } // Similarly for each current foreach (var current in Currents) { result.Currents[current.Key] = WaveformBuilder.SineWaveInstantenousValue(current.Value.Magnitude, SourceDescription.Frequency, current.Value.Phase, pointIndex, timeStep); } } break; // Phasors for DC sources are purely real - simply assign the real part of the phasor - time moment does not influence the value. case SourceType.DCVoltageSource: case SourceType.DCCurrentSource: { // For each potential foreach (var potential in Potentials) { result.Potentials[potential.Key] = potential.Value.Real; } // For each current foreach (var current in Currents) { result.Currents[current.Key] = current.Value.Real; } } break; } return(result); }
/// <summary> /// Tries to construct a current for <paramref name="element"/>, returns true on success /// </summary> /// <param name="element"></param> /// <param name="voltageBA">If true, it means that current was calculated for voltage drop from /// <see cref="ITwoTerminal.TerminalA"/> (reference) to <see cref="ITwoTerminal.TerminalB"/>, if false it means that /// that direction was reversed</param> /// <param name="current">Current constructed if successful, null otherwise</param> /// <returns></returns> protected override bool TryConstructCurrent(ITwoTerminal element, bool voltageBA, out ITimeDomainSignal current) { // Try to get voltage drop across the element if (_VoltageDrops.TryGet(element, out var voltageDrop, voltageBA)) { // If successful, create a new current signal based on it, cache it var result = IoC.Resolve <ITimeDomainSignalMutable>(voltageDrop.Samples, voltageDrop.TimeStep, voltageDrop.StartTime); // Get the minimum frequency - it is needed for capacitor waveform shifting, check if there are any waveforms, if not // just assign 0 (technically no waveforms result in a zero wave, which is DC) var minACFrequency = voltageDrop.Waveforms.Count > 0 ? voltageDrop.Waveforms.Keys.Min((x) => x.Frequency) : 0; // Current is composed of each voltage waveform times admittance of the element foreach (var waveform in voltageDrop.Waveforms) { // Get magnitude of element's admittance var admittanceMagnitude = element.GetAdmittance(waveform.Key.Frequency).Magnitude; // Current waveform is the product of voltage waveforrm and magnitude var finalWaveform = waveform.Value.Select((x) => x * admittanceMagnitude); // Introduce phase shift for capacitors - but only if minimum AC frequency is greater than 0, if it's not then there were // no AC voltage sources and so no current will flow through any capacitor if (minACFrequency > 0 && element is ICapacitor) { // Each wave has to be shifted by pi / 2 but only in its period. // For example, a wave with frequency 2 times the lowest frequency has to be shifted by total of pi / 4 - because // there are 2 periods of it in the full waveform. This relation is given by minimum frequency / wave frequency finalWaveform = WaveformBuilder.ShiftWaveform(finalWaveform, minACFrequency / waveform.Key.Frequency * Math.PI / 2); } // Add the waveform to the final waveform result.AddWaveform(waveform.Key, finalWaveform); } current = result; // And return success return(true); }
/// <summary> /// Adds a new waveform to the signal. If one already exists for source described by <paramref name="description"/>, adds them together, /// otherwise makes a new entry in <see cref="ITimeDomainSignal.ACWaveforms"/>. or <see cref="ITimeDomainSignal.DCWaveforms"/>. /// The waveform is given by a constant value - full /// waveform will be constructed from it. /// </summary> /// <param name="description"></param> /// <param name="value"></param> /// <exception cref="ArgumentNullException"></exception> public void AddWaveform(ISourceDescription description, double value) => AddWaveform(description, WaveformBuilder.ConstantWaveform(value, Samples));