示例#1
0
 /// <summary>
 /// Gets information on voltage drop across a <see cref="ITwoTerminal"/> component
 /// </summary>
 /// <param name="component"></param>
 /// <param name="voltageBA">If true, voltage drop is calculated from <see cref="ITwoTerminal.TerminalB"/> to
 /// <returns></returns>
 public ISignalInformation Get(ITwoTerminal component, bool voltageBA = true) =>
 // Depending on requested voltage drop direction
 voltageBA?
 // Get voltage drop from node A to node B
 Get(component.TerminalA.NodeIndex, component.TerminalB.NodeIndex) :
     // Get voltage drop from node B to node A
     Get(component.TerminalB.NodeIndex, component.TerminalA.NodeIndex);
示例#2
0
 /// <summary>
 /// Gets voltage drop across a <see cref="ITwoTerminal"/> component or null if unsuccessful and assigns it to
 /// <paramref name="voltage"/>. Returns true on success, false otherwise.
 /// </summary>
 /// <param name="component"></param>
 /// <param name="voltageBA">If true, voltage drop is calculated from <see cref="ITwoTerminal.TerminalB"/> to
 /// <param name="voltage"></param>
 /// <returns></returns>
 public bool TryGet(ITwoTerminal component, out IPhasorDomainSignal voltage, bool voltageBA = true) =>
 // Depending on requested voltage drop direction
 voltageBA?
 // Get voltage drop from node A to node B
 TryGet(component.TerminalA.NodeIndex, component.TerminalB.NodeIndex, out voltage) :
     // Get voltage drop from node B to node A
     TryGet(component.TerminalB.NodeIndex, component.TerminalA.NodeIndex, out voltage);
示例#3
0
        /// <summary>
        /// Caches the <paramref name="signal"/> as well as its negated copy (with inverted indexes)
        /// </summary>
        /// <param name="signal"></param>
        /// <param name="component"></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>
        protected void CacheCurrent(TSignal signal, ITwoTerminal component, bool voltageBA)
        {
            // Cache the original
            CacheHelper(signal, component, voltageBA);

            // And cache the reversed one
            CacheHelper(CopyAndNegate(signal), component, !voltageBA);
        }
示例#4
0
 /// <summary>
 /// If cache does not contain an entry with key given by <paramref name="component"/> and
 /// <paramref name="voltageBA"/>, caches <paramref name="signal"/>, otherwise doesn't do anything
 /// </summary>
 /// <param name="signal"></param>
 /// <param name="component"></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>
 private void CacheHelper(TSignal signal, ITwoTerminal component, bool voltageBA)
 {
     if (!_Cache.ContainsKey(new Tuple <ITwoTerminal, bool>(component, voltageBA)))
     {
         _Cache.Add(new Tuple <ITwoTerminal, bool>(component, voltageBA),
                    Tuple.Create(
                        signal,
                        IoC.Resolve <ISignalInformation>(signal, IoC.Resolve <ICommonSignalDescriptions>().Current)));
     }
 }
示例#5
0
 /// <summary>
 /// Attempts to obtain a current for some <see cref="ITwoTerminal"/> <paramref name="component"/>, if not successful
 /// returns null
 /// </summary>
 /// <param name="component"></param>
 /// <param name="voltageBA">If true, voltage used to calculate the current is taken from <see cref="ITwoTerminal.TerminalA"/>
 /// (reference node) to <see cref="ITwoTerminal.TerminalB"/>, if false the direction is reversed</param>
 /// <returns></returns>
 private ISignalInformation GetStandardTwoTerminalCurrent(ITwoTerminal component, bool voltageBA)
 {
     // Check if the current may be obtained from cache
     if (TryEnableCurrent(component, voltageBA) &&
         // If so, try to get it from the cache (this condition should always be true if the previous one is true)
         _Cache.TryGetValue(new Tuple <ITwoTerminal, bool>(component, voltageBA), out var currentPackage))
     {
         return(currentPackage.Item2);
     }
     else
     {
         return(null);
     }
 }
示例#6
0
        /// <summary>
        /// Checks if current through <paramref name="component"/> can be obtained from cache, if not performs
        /// all possible actions to create it and cache it. Returns true if, at the end of the method call, the current may be
        /// obtained from <see cref="_PassiveCurrentsCache"/>, false otherwise.
        /// </summary>
        /// <param name="component">Element for which the current is considered</param>
        /// <param name="voltageBA">If true, voltage used to calculate the current is taken from <see cref="ITwoTerminal.TerminalA"/>
        /// (reference node) to <see cref="ITwoTerminal.TerminalB"/>, if false the direction is reversed</param>
        /// <returns></returns>
        protected bool TryEnableCurrent(ITwoTerminal component, bool voltageBA)
        {
            // If there was a cached entry already return it
            if (_Cache.ContainsKey(new Tuple <ITwoTerminal, bool>(component, voltageBA)))
            {
                return(true);
            }
            // Try to construct an entry
            else if (TryConstructCurrent(component, voltageBA, out var current))
            {
                CacheCurrent(current, component, voltageBA);
                return(true);
            }

            return(false);
        }
示例#7
0
 /// <summary>
 /// Attempts to obtain a current for some <see cref="ITwoTerminal"/> <paramref name="component"/>
 /// </summary>
 /// <param name="component"></param>
 /// <param name="voltageBA">If true, voltage used to calculate the current is taken from <see cref="ITwoTerminal.TerminalA"/>
 /// (reference node) to <see cref="ITwoTerminal.TerminalB"/>, if false the direction is reversed</param>
 /// <param name="current"></param>
 /// <returns></returns>
 private bool TryGetStandardTwoTerminalCurrent(ITwoTerminal component, bool voltageBA, out ITimeDomainSignal current)
 {
     // Check if the current may be obtained from cache
     if (TryEnableCurrent(component, voltageBA) &&
         // If so, try to get it from the cache (this condition should always be true if the previous one is true)
         _Cache.TryGetValue(new Tuple <ITwoTerminal, bool>(component, voltageBA), out var currentPackage))
     {
         current = currentPackage.Item1;
         return(true);
     }
     else
     {
         current = null;
         return(false);
     }
 }
示例#8
0
            /// <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 IPhasorDomainSignal 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
                    //current = IoC.Resolve<IPhasorDomainSignal>(
                    //		GetPassiveTwoTerminalDCCurrent(voltageDrop, element),
                    //		GetPassiveTwoTerminalACCurrentPhasors(voltageDrop, element));

                    current = IoC.Resolve <IPhasorDomainSignal>(
                        voltageDrop.Phasors.Select((x) => x.Value * element.GetAdmittance(x.Key.Frequency)));

                    // And return success
                    return(true);
                }
示例#9
0
            /// <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);
                }
示例#10
0
            /// <summary>
            /// Tries to constract a power for an <see cref="ITwoTerminal"/>
            /// </summary>
            /// <param name="twoTerminal"></param>
            /// <param name="power"></param>
            /// <returns></returns>
            private bool TryConstructPower(ITwoTerminal twoTerminal, out ITimeDomainSignal power, bool voltageBA)
            {
                power = null;

                if (_VoltageDrops.TryGet(twoTerminal, out var voltage, voltageBA))
                {
                    ITimeDomainSignal current = null;

                    // Call different method depending on the type of the two terminal
                    TypeSwitch.Construct().
                    LazyCase <IResistor>((x) => _Currents.TryGet(x, out current)).
                    LazyCase <ICapacitor>((x) => _Currents.TryGet(x, out current)).
                    LazyCase <IActiveComponent>((x) => _Currents.TryGet(x.Index, out current)).
                    Switch(twoTerminal);

                    // If both voltage and current were obtained
                    if (current != null)
                    {
                        var result = IoC.Resolve <ITimeDomainSignalMutable>(voltage.Samples, voltage.TimeStep, voltage.StartTime);

                        // The result is a product of voltage and current waveforms, calculate power generated by each source separately
                        foreach (var waveform in voltage.Waveforms)
                        {
                            // Add new power waveform, use voltage drop's source as its source and use the final current waveform.
                            // If only the waveform for the considered source would be used then the result wouldbe incorrect.
                            // Power is a product of voltage and current, we can't superposition both quantities because power is not
                            // a linear relationship in that case. However if we take the total current then only superimposing voltage is correct
                            // since it's just a linear relationship P = U * I (I is independent of the source - it can be considered as a scalar).
                            result.AddWaveform(waveform.Key, waveform.Value.MergeSelect(current.FinalWaveform, (x, y) => x * y));
                        }

                        power = result;
                    }
                }

                // If power is not null it means that it was successfully constructed
                return(power != null);
            }
示例#11
0
 /// <summary>
 /// Tries to construct a current for <paramref name="component"/>, returns true on success
 /// </summary>
 /// <param name="component"></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 abstract bool TryConstructCurrent(ITwoTerminal component, bool voltageBA, out TSignal current);
示例#12
0
 /// <summary>
 /// Returns null
 /// </summary>
 /// <param name="component"></param>
 /// <param name="voltageBA">If true, voltage drop is calculated from <see cref="ITwoTerminal.TerminalB"/> to
 /// <returns></returns>
 public ISignalInformation Get(ITwoTerminal component, bool voltageBA = true) => null;
示例#13
0
 /// <summary>
 /// Gets information on voltage drop across a <see cref="ITwoTerminal"/> component
 /// </summary>
 /// <param name="component"></param>
 /// <param name="voltageBA">If true, voltage drop is calculated from <see cref="ITwoTerminal.TerminalB"/> to
 /// <returns></returns>
 public ISignalInformation Get(ITwoTerminal component, bool voltageBA = true) => voltageBA?
 Get(component.TerminalA.NodeIndex, component.TerminalB.NodeIndex) :
     Get(component.TerminalB.NodeIndex, component.TerminalA.NodeIndex);
示例#14
0
 /// <summary>
 /// Gets voltage drop across a <see cref="ITwoTerminal"/> component or null if unsuccessful and assigns it to
 /// <paramref name="voltage"/>. Returns true on success, false otherwise.
 /// </summary>
 /// <param name="component"></param>
 /// <param name="voltageBA">If true, voltage drop is calculated from <see cref="ITwoTerminal.TerminalB"/> to
 /// <param name="voltage"></param>
 /// <returns></returns>
 public bool TryGet(ITwoTerminal component, out ITimeDomainSignal voltage, bool voltageBA = true) => voltageBA?
 TryGet(component.TerminalA.NodeIndex, component.TerminalB.NodeIndex, out voltage) :
     TryGet(component.TerminalB.NodeIndex, component.TerminalA.NodeIndex, out voltage);