コード例 #1
0
        /// <summary>
        /// Iterates to a solution while adding a conductive path to ground on all nodes.
        /// </summary>
        /// <param name="maxIterations">The maximum number of iterations per step.</param>
        /// <param name="steps">The number of steps.</param>
        /// <returns>
        /// <c>true</c> if the diagonal gmin stepping succeeded; otherwise <c>false</c>.
        /// </returns>
        protected bool IterateDiagonalGminStepping(int maxIterations, int steps)
        {
            // We will add a DC path to ground to all nodes to aid convergence
            SpiceSharpWarning.Warning(this, Properties.Resources.Simulations_Biasing_StartDiagonalGminStepping);

            // We'll hack into the loading algorithm to apply our diagonal contributions
            var diagonalGmin = Math.Min(Iteration.Gmin, 1e-12);

            void ApplyGminStep(object sender, LoadStateEventArgs args)
            => _state.Solver.Precondition((matrix, vector) => ModifiedNodalAnalysisHelper <double> .ApplyDiagonalGmin(matrix, diagonalGmin));

            AfterLoad += ApplyGminStep;

            // We could've ended up with some crazy value, so let's reset it
            for (var i = 0; i <= _state.Solution.Length; i++)
            {
                _state.Solution[i] = 0.0;
            }

            // Let's make it a bit easier for our iterations to converge
            for (var i = 0; i < steps; i++)
            {
                diagonalGmin *= 10.0;
            }

            // Start GMIN stepping
            Iteration.Mode = IterationModes.Junction;
            for (var i = 0; i <= steps; i++)
            {
                Iteration.IsConvergent = false;
                if (!Iterate(maxIterations))
                {
                    diagonalGmin = 0.0;
                    SpiceSharpWarning.Warning(this, Properties.Resources.Simulation_Biasing_GminSteppingFailed);
                    break;
                }
                diagonalGmin  /= 10.0;
                Iteration.Mode = IterationModes.Float;
            }

            // Try one more time without the gmin stepping
            AfterLoad   -= ApplyGminStep;
            diagonalGmin = 0.0;
            return(Iterate(maxIterations));
        }
コード例 #2
0
        /// <summary>
        /// Iterates towards a solution.
        /// </summary>
        /// <param name="maxIterations">The maximum allowed iterations.</param>
        /// <returns>
        ///   <c>true</c> if the iterations converged to a solution; otherwise, <c>false</c>.
        /// </returns>
        /// <exception cref="SpiceSharpException">Thrown if any behavior cannot load the matrix and/or right hand side vector, or if the solution
        /// is not a number (NaN).</exception>
        /// <exception cref="SingularException">Thrown if the equation matrix is singular.</exception>
        protected virtual bool Iterate(int maxIterations)
        {
            var solver = _state.Solver;
            var pass   = false;
            var iterno = 0;

            try
            {
                while (true)
                {
                    // Load the Y-matrix and right hand side vector
                    Iteration.IsConvergent = true;
                    Load();
                    iterno++;

                    // Preorder matrix
                    if (!_isPreordered)
                    {
                        solver.Precondition((matrix, vector)
                                            => ModifiedNodalAnalysisHelper <double> .PreorderModifiedNodalAnalysis(matrix, solver.Size - solver.Degeneracy));
                        _isPreordered = true;
                    }
                    if (Iteration.Mode == IterationModes.Junction)
                    {
                        _shouldReorder = true;
                    }

                    if (_shouldReorder)
                    {
                        // Reorder and factor the solver
                        Statistics.ReorderTime.Start();
                        try
                        {
                            var eliminated = solver.OrderAndFactor();
                            if (eliminated < solver.Size)
                            {
                                throw new SingularException(eliminated + 1);
                            }
                            _shouldReorder = false;
                        }
                        finally
                        {
                            Statistics.ReorderTime.Stop();
                        }
                    }
                    else
                    {
                        // Just factor the solver (without losing time reordering)
                        Statistics.FactoringTime.Start();
                        try
                        {
                            if (!solver.Factor())
                            {
                                _shouldReorder = true;
                                continue;
                            }
                        }
                        finally
                        {
                            Statistics.FactoringTime.Stop();
                        }
                    }

                    // The current solution becomes the old solution
                    _state.StoreSolution();

                    // Solve the equation
                    Statistics.SolveTime.Start();
                    try
                    {
                        solver.Solve(_state.Solution);
                    }
                    finally
                    {
                        Statistics.SolveTime.Stop();
                    }

                    // Reset ground nodes
                    solver.GetElement(0).Value = 0.0;
                    _state.Solution[0]         = 0.0;
                    _state.OldSolution[0]      = 0.0;

                    // Update
                    foreach (var behavior in _updateBehaviors)
                    {
                        behavior.Update();
                    }

                    // Exceeded maximum number of iterations
                    if (iterno > maxIterations)
                    {
                        return(false);
                    }

                    if (Iteration.IsConvergent && iterno != 1)
                    {
                        Iteration.IsConvergent = IsConvergent();
                    }
                    else
                    {
                        Iteration.IsConvergent = false;
                    }

                    switch (Iteration.Mode)
                    {
                    case IterationModes.Float:
                        if (_nodesets.Count > 0)
                        {
                            if (pass)
                            {
                                Iteration.IsConvergent = false;
                            }
                            pass = false;
                        }
                        if (Iteration.IsConvergent)
                        {
                            return(true);
                        }
                        break;

                    case IterationModes.Junction:
                        Iteration.Mode = IterationModes.Fix;
                        _shouldReorder = true;
                        break;

                    case IterationModes.Fix:
                        if (Iteration.IsConvergent)
                        {
                            Iteration.Mode = IterationModes.Float;
                        }
                        pass = true;
                        break;

                    case IterationModes.None:
                        Iteration.Mode = IterationModes.Float;
                        break;

                    default:
                        throw new SpiceSharpException(Properties.Resources.Simulations_InvalidInitializationMode);
                    }
                }
            }
            finally
            {
                Statistics.Iterations += iterno;
            }
        }