Esempio n. 1
0
        /// <summary>
        /// Performs an AC cycle simulation - simulation is running for one full period of lowest frequency source in the <paramref name="factory"/>.
        /// Returns calculated node potentials and active component currents as sinusoidal waveforms.
        /// </summary>
        /// <param name="factory"></param>
        /// <param name="pointsCount">Number of points to calculate for the signals</param>
        /// <param name="timeStep">Time step between two calculational points</param>
        /// <param name="includeDCBias">If true DC bias will be performed and added to results</param>
        private WaveformPartialState FullCycleHelper(AdmittanceMatrixFactory factory, int pointsCount, double timeStep, bool includeDCBias = false)
        {
            // Get AC transfer functions
            var systemState = GetPhasorsForAllACSources(factory);

            if (includeDCBias)
            {
                // As well as DC transfer function, if requested
                systemState.MergeWith(GetPhasorsForAllDCSources(factory));
            }

            return(systemState.ToWaveform(pointsCount, timeStep));
        }
Esempio n. 2
0
        /// <summary>
        /// Helper for functions that return phasors generated for many sources. Returns a <see cref="PhasorPartialStates"/> that contains
        /// phasors for all sources in <paramref name="sources"/>.
        /// </summary>
        /// <param name="factory"></param>
        /// <param name="sources">Enumeration of sources to construct transfer functions for. All sources listed have to be present in
        /// <returns></returns>
        private PhasorPartialStates GetAllPhasorsHelper(AdmittanceMatrixFactory factory, IEnumerable <ISourceDescription> sources)
        {
            var result = new PhasorPartialStates(factory.NodesCount, factory.ActiveComponentsCount, sources);

            // For each source
            foreach (var source in sources)
            {
                // Get phasor and add it to states
                result.States[source] = GetPhasor(factory, source);
            }

            return(result);
        }
Esempio n. 3
0
        /// <summary>
        /// Creates and solves DC admittance matrix for saturated op-amps
        /// </summary>
        /// <param name="factory"></param>
        /// <returns></returns>
        private PhasorState GetOpAmpSaturationBias(AdmittanceMatrixFactory factory)
        {
            // Create an instantenous state based on node indices and active components indices in factory,
            // use the factory's op amp saturation source as source description
            var result = new PhasorState(factory.Nodes, factory.ActiveComponentsCount, factory.OpAmpSaturationSource);

            // Construct matrix for saturated op-amps and solve it
            factory.ConstructDCForSaturatedOpAmpsOnly().Solve(out var nodePotentials, out var activeComponentsCurrents);

            // Add the results from simulation to state
            result.AddValues(nodePotentials.ToArray(), activeComponentsCurrents.ToArray());

            return(result);
        }
Esempio n. 4
0
        /// <summary>
        /// Returns phasors constructed for source given by <paramref name="sourceDescription"/>
        /// </summary>
        /// <param name="factory"></param>
        /// <param name="sourceDescription"></param>
        private PhasorState GetPhasor(AdmittanceMatrixFactory factory, ISourceDescription sourceDescription)
        {
            var state = new PhasorState(factory.NodesCount, factory.ActiveComponentsCount, sourceDescription);

            // Create an admittance matrix corresponding to the given source
            factory.Construct(sourceDescription).
            // And solve it
            Solve(out var nodePotentials, out var activeComponentsCurrents);

            // Add the results to state
            state.AddValues(nodePotentials, activeComponentsCurrents);

            return(state);
        }
Esempio n. 5
0
        /// <summary>
        /// Topmost logic behind AC Full Cycle - calling it will result in simulation being performed and saved to
        /// <see cref="ISimulationResultsProvider"/>
        /// </summary>
        /// <param name="factory"></param>
        /// <param name="includeDCBias">If true DC bias will be performed and added to results, if false only saturated <see cref="IOpAmp"/>s
        /// will be considered for DC part of simulation</param>
        private void FullCycleWithoutOpAmpAdjustment(AdmittanceMatrixFactory factory, bool includeDCBias)
        {
            // TODO: number of points should be given by caller
            int pointsCount = 600;

            // Calculate time step between two subsequent points in time vector
            double timeStep = GetTimeStep(pointsCount, factory.LowestFrequency);

            // Use helper to get the state of the system
            var state = FullCycleHelper(factory, pointsCount, timeStep, includeDCBias);

            // Create simulation results
            IoC.Resolve <SimulationResultsProvider>().Value = new SimulationResultsTime(
                // Transform potentials to time domain signals - specify that reference node should be added
                state.PotentialsToTimeDomainSignals(timeStep, true),
                state.CurrentsToTimeDomainSignals(timeStep),
                timeStep,
                0);
        }
Esempio n. 6
0
        /// <summary>
        /// Topmost logic behind DC bias - calling it will result in simulation being performed and saved to <see cref="ISimulationResultsProvider"/>
        /// </summary>
        /// <param name="factory"></param>
        private void DCBiasLogic(AdmittanceMatrixFactory factory)
        {
            // Calculated state of the system
            var state = GetPhasorsForAllDCSources(factory);

            // Add op-amp saturation bias to complete the DC bias
            state.AddState(GetOpAmpSaturationBias(factory));

            // Loop until correct op-amp operation is found
            while (!factory.CheckOpAmpOperationWithSelfAdjustment(state.ToDC().Combine().Potentials))
            {
                // If the op-amp operation was adjusted, recalculate the state
                state = GetPhasorsForAllDCSources(factory);

                state.AddState(GetOpAmpSaturationBias(factory));
            }

            // Create simulation results based on node potentials and active components currents in the state
            IoC.Resolve <SimulationResultsProvider>().Value = new SimulationResultsBias(
                state.PotentialsToPhasorDomainSignal(true),
                state.CurrentsToPhasorDomainSignal());
        }
Esempio n. 7
0
        /// <summary>
        /// Performs an AC cycle simulation - simulation is running for one full period of lowest frequency source in the <paramref name="factory"/>.
        /// After determining the transfer functions calculates only one set of instantenous values for point described by
        /// <paramref name="pointIndex"/> and <paramref name="timeStep"/>.
        /// </summary>
        /// <param name="factory"></param>
        /// <param name="pointIndex">Index of the point for which to calculate instantenous values</param>
        /// <param name="timeStep">Time step between two calculational points</param>
        /// <param name="includeDCBias">If true DC bias will be performed and added to results</param>
        /// <param name="performSaturatedOpAmpBias">If true, op-amp saturation bias will be performed and added to results</param>
        private InstantenousPartialStates FullCycleInstantenousValuesHelper(AdmittanceMatrixFactory factory, int pointIndex, double timeStep,
                                                                            bool includeDCBias = false, bool performSaturatedOpAmpBias = true)
        {
            // Get phasors for AC sources
            var phasors = GetPhasorsForAllACSources(factory);

            if (includeDCBias)
            {
                // Add DC phasors, if requested
                phasors.MergeWith(GetPhasorsForAllDCSources(factory));
            }

            // Transform those phasors to instantenous values
            var instantenous = phasors.ToInstantenousValue(pointIndex, timeStep);

            // Finally get op amp bias, if requested
            if (performSaturatedOpAmpBias)
            {
                instantenous.AddState(GetOpAmpSaturationBias(factory).ToDC());
            }

            return(instantenous);
        }
Esempio n. 8
0
 /// <summary>
 /// Returns phasors with for all DC sources in <paramref name="factory"/>
 /// </summary>
 /// <param name="factory"></param>
 private PhasorPartialStates GetPhasorsForAllDCSources(AdmittanceMatrixFactory factory) => GetAllPhasorsHelper(factory, factory.DCSources);
Esempio n. 9
0
        /// <summary>
        /// Topmost logic behind AC Full Cycle - calling it will result in simulation being performed and saved to
        /// <see cref="ISimulationResultsProvider"/>. This version adjusts <see cref="IOpAmp"/> operation for every calculated point so that neither
        /// <see cref="IOpAmp"/> exceeds its supply voltages.
        /// </summary>
        /// <param name="factory"></param>
        /// <param name="includeDCBias">If true DC bias will be performed and added to results, if false only saturated <see cref="IOpAmp"/>s
        /// will be considered for DC part of simulation</param>
        private void FullCycleLogicWithOpAmpAdjustment(AdmittanceMatrixFactory factory, bool includeDCBias)
        {
            // TODO: Try to make it so that saturated op amp bias is not considered to be pure DC but rather an extension of all sources
            // contributing to the circuit

            // TODO: number of points should be given by caller
            int pointsCount = 600;

            // Time step between two subsequent points in time vector
            double timeStep = GetTimeStep(pointsCount, factory.LowestFrequency);

            // Create an enumeration of used sources - take AC sources and op-amp saturation source. If DC bias is requested, add the DC sources too.
            var usedSources = (includeDCBias ? factory.AllSources : factory.ACSources).Concat(factory.OpAmpSaturationSource);

            // Get node indices constructed on the basis of the circuit
            var nodeIndices = factory.Nodes.ToList();

            // Create a state which will be filled with adjusted simulation points
            var adjustedState = new WaveformPartialState(factory.NodesCount, factory.ActiveComponentsCount, usedSources);

            // Go through each simulation point separately - it is necessary in order to correctly determine op-amp operation at each specific point
            for (int i = 0; i < pointsCount; ++i)
            {
                // Use the helper to obtain instantenous potentials
                var instantenousValues = FullCycleInstantenousValuesHelper(factory, i, timeStep, includeDCBias);

                // Loop until correct op-amp operation is found
                while (!factory.CheckOpAmpOperationWithSelfAdjustment(instantenousValues.Combine().Potentials))
                {
                    // If the op-amp operation was adjusted, recalculate the instantenous values
                    instantenousValues = FullCycleInstantenousValuesHelper(factory, i, timeStep, includeDCBias);
                }

                // For each state
                foreach (var state in instantenousValues.States.Values)
                {
                    // And for each node
                    foreach (var index in nodeIndices)
                    {
                        // Add the calculated potential for state at node 'index' to the adjusted result waveform.
                        // Lists are empty - points should just be added to them to form a full waveform.
                        adjustedState.States[state.SourceDescription].Potentials[index].Add(
                            instantenousValues.States[state.SourceDescription].Potentials[index]);
                    }

                    // Add the instantenous values of active components currents to the waveforms - just like currents
                    foreach (var index in factory.ActiveComponents)
                    {
                        adjustedState.States[state.SourceDescription].Currents[index].Add(
                            instantenousValues.States[state.SourceDescription].Currents[index]);
                    }
                }

                // Finally reset the op-amp operation for next iteration
                factory.ResetOpAmpOperation();
            }

            // Create simulation results
            IoC.Resolve <SimulationResultsProvider>().Value = new SimulationResultsTime(
                // Convert the adjusted state to potentials - specify that reference node should be added
                adjustedState.PotentialsToTimeDomainSignals(timeStep, true),
                adjustedState.CurrentsToTimeDomainSignals(timeStep),
                timeStep,
                0);
        }