protected static void Calculate(List <Node> nodosnorton)
        {
            if (nodosnorton.Count == 0)
            {
                return;
            }

            //existen nodos donde la tension se puede calcular directamente
            List <Node> nodosCalculables = new List <Node>();

            foreach (var nodo in nodosnorton)
            {
                if (nodo.TypeOfNode == Node.NodeType.VoltageDivideNode)
                {
                    nodosCalculables.Add(nodo);
                }
            }
            foreach (var nodo in nodosCalculables)
            {
                nodosnorton.Remove(nodo);
            }

            //remuevo esos nodos de los que deben calcularse matricialmente

            if (nodosnorton.Count > 0)
            {
                int fila = 0, columna = 0;
                var v = Vector <Complex32> .Build.Dense(nodosnorton.Count);

                var A = Matrix <Complex32> .Build.DenseOfArray(new Complex32[nodosnorton.Count, nodosnorton.Count]);

                foreach (var nodo in nodosnorton)
                {
                    columna = fila = nodosnorton.IndexOf(nodo);
                    Complex32 Z, V;
                    if (nodo.TypeOfNode == Node.NodeType.MultibranchCurrentNode ||
                        nodo.TypeOfNode == Node.NodeType.InternalBranchNode)
                    {
                        foreach (var rama in nodo.Components)
                        {
                            if (rama is Branch || rama is PasiveComponent)
                            {
                                columna = fila = nodosnorton.IndexOf(nodo);
                                if (rama is Branch)
                                {
                                    V = ((Branch)rama).NortonCurrent(nodo);
                                }
                                else
                                {
                                    V = rama.Current(nodo);
                                }
                                v[fila]          += V;
                                Z                 = rama.Impedance();
                                A[fila, columna] += 1 / Z;
                                Node nodo2 = rama.OtherNode(nodo);
                                if (!nodo2.IsReference)
                                {
                                    columna           = nodosnorton.IndexOf(nodo2);
                                    A[fila, columna] -= 1 / Z;
                                }
                            }
                            else if (rama is CurrentGenerator)
                            {
                                V        = rama.Current(nodo);
                                v[fila] += V;
                            }
                        }
                    }
                    else if (nodo.TypeOfNode == Node.NodeType.VoltageLinkedNode)
                    {
                        Dipole compo = nodo.Components[0];
                        if (!(compo is VoltageGenerator))
                        {
                            compo = nodo.Components[1];
                        }
                        v[fila]          = compo.Voltage.Real;
                        A[fila, columna] = 1;
                        columna          = nodosnorton.IndexOf(compo.OtherNode(nodo));
                        A[fila, columna] = -1;
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }
                var x = A.Solve(v);

                foreach (var nodo in nodosnorton)
                {
                    fila         = nodosnorton.IndexOf(nodo);
                    nodo.Voltage = x[fila];
                }
            }

            foreach (var nodo in nodosCalculables)
            {
                if (nodo.TypeOfNode == Node.NodeType.VoltageDivideNode)
                {
                    Node   nodo1  = nodo;
                    Dipole compo1 = nodo.Components[0];
                    Branch br     = compo1.Owner as Branch;
                    if (br == null)
                    {
                        throw new Exception();
                    }
                    Complex32 v1, v2, z1, z2;
                    v1 = v2 = z1 = z2 = Complex32.Zero;
                    //el nodo es interno en una rama, deberian los 2 componentes conectados
                    //al nodo,
                    Dipole compo2 = nodo.Components[1];
                    //hacia la izq (o derec)
                    NavigateBranch(nodo1, compo1, ref v1, ref z1);
                    //hacia el otro lado
                    NavigateBranch(nodo1, compo2, ref v2, ref z2);
                    nodo.Voltage = (z2 * v1 + v2 * z1) / (z1 + z2);
                    //nodosCalculables.Add(nodo);
                }
            }

            //return x;
        }
        protected static void Calculate(SolveInfo solveinfo, Complex32 W)
        {
            if (solveinfo.nortonnodes.Count == 0 && solveinfo.calculablenodes.Count == 0)
            {
                return;
            }

            //existen nodos donde la tension se puede calcular directamente
            foreach (var nodo in solveinfo.calculablenodes)
            {
                if (nodo.TypeOfNode == Node.NodeType.VoltageFixedNode)
                {
                    foreach (var compo in nodo.Components)
                    {
                        if (compo.IsConnectedToEarth && (compo is ACVoltageGenerator))
                        {
                            nodo.Voltage = compo.voltage(nodo, W);   //el componente conectado a tierra debe ser Vdc o Vsin o capacitor
                            break;
                        }
                    }
                    continue;
                }
            }

            #region Calculo de tensions mediante matrices

            if (solveinfo.nortonnodes.Count > 0)
            {
                int fila = 0, columna = 0, max;
                //cada componente especial agrega 0, 1 o 2 variable mas, dependiendo del tipo
                max = solveinfo.MatrixDimension;
                var v = Vector <Complex32> .Build.Dense(max);

                var A = Matrix <Complex32> .Build.DenseOfArray(new Complex32[max, max]);

                //primero la ecuacion de transferencia del VcV
                foreach (var info in solveinfo.specialcomponents)
                {
                    //foreach (var item in info.Component)
                    //{

                    //}
                    //int entrada = especialcomponents.IndexOf(info);
                    //fila = nodosnorton.Count - 1 + entrada;
                    columna          = 1;
                    A[fila, columna] = 1;
                }

                foreach (var nodo in solveinfo.nortonnodes)
                {
                    columna = fila = solveinfo.nortonnodes.IndexOf(nodo);
                    Complex32 Z, V;
                    if (
                        nodo.TypeOfNode == Node.NodeType.MultibranchCurrentNode ||
                        nodo.TypeOfNode == Node.NodeType.VoltageFixedNode ||
                        nodo.TypeOfNode == Node.NodeType.InternalBranchNode)
                    {
                        foreach (var rama in nodo.Components)
                        {
                            if (rama is Branch || rama is PasiveComponent)
                            {
                                columna = fila = solveinfo.nortonnodes.IndexOf(nodo);
                                if (rama is Branch)
                                {
                                    V = ((Branch)rama).NortonCurrent(nodo, W);
                                }
                                else
                                {
                                    V = rama.Current(nodo, W);
                                }

                                v[fila]          += V;
                                Z                 = rama.Impedance(W);
                                A[fila, columna] += 1 / Z;
                                Node nodo2 = rama.OtherNode(nodo);
                                if (!nodo2.IsReference)
                                {
                                    columna           = solveinfo.nortonnodes.IndexOf(nodo2);
                                    A[fila, columna] -= 1 / Z;
                                }
                            }
                            else if (rama is CurrentGenerator)
                            {
                                V        = rama.Current(nodo, W);
                                v[fila] += V;
                            }
                            else if (rama is VoltageControlledGenerator)
                            {
                                //int entrada = especialcomponents.Values.ToList().IndexOf(rama);
                                //columna = nodosnorton.Count -1 + entrada;

                                ////un nodo es positva la corriente, en el otro es negativa
                                //if (entrada % 2 == 0)
                                //    A[fila, columna] = 1;
                                //else
                                //    A[fila, columna] = -1;
                            }
                        }
                    }
                    else if (nodo.TypeOfNode == Node.NodeType.VoltageLinkedNode)
                    {
                        Dipole compo = nodo.Components[0];
                        if (!(compo is VoltageGenerator))
                        {
                            compo = nodo.Components[1];
                        }
                        v[fila]          = compo.Voltage.Real;
                        A[fila, columna] = 1;
                        columna          = solveinfo.nortonnodes.IndexOf(compo.OtherNode(nodo));
                        A[fila, columna] = -1;
                    }
                    //else if (nodo.TypeOfNode == Node.NodeType.VoltageFixedNode)
                    //{
                    //    foreach (var rama in nodo.Components)
                    //    {
                    //        if (rama is VoltageControlledGenerator)
                    //        {

                    //        }
                    //    }
                    //}
                    else
                    {
                        throw new NotImplementedException();
                    }
                }
                var x = A.Solve(v);

                foreach (var nodo in solveinfo.nortonnodes)
                {
                    fila         = solveinfo.nortonnodes.IndexOf(nodo);
                    nodo.Voltage = x[fila];
                }
            }

            #endregion

            //existen nodos donde la tension se puede calcular indirectamente
            foreach (var nodo in solveinfo.calculablenodes)
            {
                if (nodo.TypeOfNode == Node.NodeType.VoltageDivideNode)
                {
                    Node   nodo1  = nodo;
                    Dipole compo1 = nodo.Components[0];
                    Branch br     = compo1.Owner as Branch;
                    if (br == null)
                    {
                        throw new Exception();
                    }
                    Complex32 v1, v2, z1, z2;
                    v1 = v2 = z1 = z2 = Complex32.Zero;
                    //el nodo es interno en una rama, deberian los 2 componentes conectados
                    //al nodo,
                    Dipole compo2 = nodo.Components[1];
                    //hacia la izq (o derec)
                    NavigateBranch(nodo1, compo1, W, ref v1, ref z1);
                    //hacia el otro lado
                    NavigateBranch(nodo1, compo2, W, ref v2, ref z2);
                    nodo.Voltage = (z2 * v1 + v2 * z1) / (z1 + z2);
                }
            }
        }
        protected static Branch FindBranch(Circuit cir, Node initialNode, Dipole Component)
        {
            Branch br    = new Branch(cir);
            Dipole compo = Component;
            Node   nodo  = Component.OtherNode(initialNode);

            br.Nodes.Clear();
            //solo es valido si el circuito fue optimizado, y los paralelos
            //se reemplazaron por bloques paralelo
            while (nodo.Components.Count == 2 && cir.Reference != nodo)
            {
                br.Components.Add(compo);
                br.InternalNodes.Add(nodo);
                compo = nodo.OtherComponent(compo);
                nodo  = compo.OtherNode(nodo);
            }
            br.Components.Add(compo);
            if (br.Components.Count > 1)
            {
                initialNode.Components.Remove(Component);
                initialNode.Components.Add(br);
                nodo.Components.Remove(compo);
                nodo.Components.Add(br);
                nodo.TypeOfNode = Node.NodeType.MultibranchCurrentNode;
            }
            br.Nodes.Add(initialNode);
            br.Nodes.Add(nodo);

            //hay que recorrer la rama para buscar los nodos intermedios flotantes
            //y aquellos dependientes de los flotantes
            nodo = compo.OtherNode(nodo);
            while (nodo != initialNode)
            {
                if (nodo.TypeOfNode == Node.NodeType.VoltageFixedNode)
                {
                    // nothing, node was calculated
                }
                else if (compo is VoltageGenerator)
                {
                    if (nodo.TypeOfNode == Node.NodeType.Unknow)
                    {
                        nodo.TypeOfNode = Node.NodeType.VoltageLinkedNode;
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }
                else if (compo is PasiveComponent)
                {
                    if (nodo.TypeOfNode == Node.NodeType.Unknow)
                    {
                        nodo.TypeOfNode = Node.NodeType.VoltageDivideNode;
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }
                else
                {
                    if (nodo.TypeOfNode == Node.NodeType.Unknow)
                    {
                        nodo.TypeOfNode = Node.NodeType.InternalBranchNode;
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }

                compo = nodo.OtherComponent(compo);
                nodo  = compo.OtherNode(nodo);
            }


            return(br);
        }
        protected static void Calculate(SolveInfo solveinfo, double t)
        {
            if (solveinfo.nortonnodes.Count == 0 && solveinfo.calculablenodes.Count == 0)
            {
                return;
            }

            //tensiones que se calculan directamente
            foreach (var nodo in solveinfo.calculablenodes)
            {
                if (nodo.TypeOfNode == Node.NodeType.VoltageFixedNode)
                {
                    foreach (var compo in nodo.Components)
                    {
                        if (compo.IsConnectedToEarth && (compo is VoltageGenerator || compo is Capacitor))
                        {
                            nodo.Voltage = new Complex32((float)compo.voltage(nodo, t), 0);   //el componente conectado a tierra debe ser Vdc o Vsin o capacitor
                            break;
                        }
                    }
                    continue;
                }
            }

            #region Tensiones de nodos que se calculan mediante matriz

            if (solveinfo.nortonnodes.Count > 0)
            {
                int fila = 0, columna = 0;
                var Currs = Vector <double> .Build.Dense(solveinfo.MatrixDimension);

                var A = Matrix <double> .Build.DenseOfArray(new double[solveinfo.MatrixDimension, solveinfo.MatrixDimension]);

                foreach (var nodo in solveinfo.nortonnodes)
                {
                    columna = fila = solveinfo.nortonnodes.IndexOf(nodo);
                    double Z, I;
                    if (nodo.TypeOfNode == Node.NodeType.MultibranchCurrentNode ||
                        nodo.TypeOfNode == Node.NodeType.InternalBranchNode)
                    {
                        foreach (var rama in nodo.Components)
                        {
                            if (rama is Branch || rama is Resistor)
                            {
                                columna = fila = solveinfo.nortonnodes.IndexOf(nodo);
                                if (rama is Branch)
                                {
                                    I = ((Branch)rama).NortonCurrent(nodo, t);
                                }
                                else
                                {
                                    I = rama.Current(nodo, t);
                                }

                                Currs[fila]      += I;
                                Z                 = rama.Impedance().Real;
                                A[fila, columna] += 1 / Z;
                                Node nodo2 = rama.OtherNode(nodo);
                                if (!nodo2.IsReference && solveinfo.nortonnodes.Contains(nodo2))
                                {
                                    columna           = solveinfo.nortonnodes.IndexOf(nodo2);
                                    A[fila, columna] -= 1 / Z;
                                }
                            }
                            else if (rama is CurrentGenerator || rama is Inductor)
                            {
                                I            = rama.Current(nodo, t);
                                Currs[fila] += I;
                            }
                        }
                    }
                    else if (nodo.TypeOfNode == Node.NodeType.VoltageLinkedNode)
                    {
                        Dipole compo = nodo.Components[0];
                        if (!(compo is VoltageGenerator || compo is Capacitor))
                        {
                            compo = nodo.Components[1];
                        }
                        Currs[fila]      = compo.voltage(nodo, t);
                        A[fila, columna] = 1;
                        columna          = solveinfo.nortonnodes.IndexOf(compo.OtherNode(nodo));
                        A[fila, columna] = -1;
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }
                var x = A.Solve(Currs);

                foreach (var nodo in solveinfo.nortonnodes)
                {
                    fila         = solveinfo.nortonnodes.IndexOf(nodo);
                    nodo.Voltage = new Complex32((float)x[fila], 0);
                }
            }
            #endregion

            //existen nodos donde la tension se puede calcular casi directamente
            foreach (var nodo in solveinfo.calculablenodes)
            {
                if (nodo.TypeOfNode == Node.NodeType.VoltageDivideNode)
                {
                    Node   nodo1  = nodo;
                    Dipole compo1 = nodo.Components[0];
                    Branch br     = compo1.Owner as Branch;
                    if (br == null)
                    {
                        throw new Exception();
                    }
                    double v1, v2, z1, z2;
                    v1 = v2 = z1 = z2 = 0;
                    //el nodo es interno en una rama, deberian los 2 componentes conectados
                    //al nodo,
                    Dipole compo2 = nodo.Components[1];
                    //hacia la izq (o derec)
                    NavigateBranch(nodo1, compo1, t, ref v1, ref z1);
                    //hacia el otro lado
                    NavigateBranch(nodo1, compo2, t, ref v2, ref z2);
                    nodo.Voltage = new Complex32((float)((z2 * v1 + v2 * z1) / (z1 + z2)), 0);
                }
            }

            //parto del extremo de la rama
            foreach (var rama in solveinfo.ramas)
            {
                Node nodo1 = null;
                //busco nodos ya calculados en la rama
                foreach (var nodo in rama.InternalNodes)
                {
                    if (!solveinfo.calculablenodes.Contains(nodo) && !solveinfo.nortonnodes.Contains(nodo))
                    {
                        nodo1 = nodo;
                        break;
                    }
                }
                if (nodo1 == null)
                {
                    continue;
                }

                double i = 0;
                //encuentro la corriente impuesta de la rama si es que la hay
                //nodo1 = rama.Nodes[0];

                i = rama.Current(nodo1, t);
                Dipole compo1 = null;
                foreach (var compo in rama.Components)
                {
                    //busco el componente hubicado en un extremo de la rama
                    if (compo.Nodes[0] == nodo1 || compo.Nodes[1] == nodo1)
                    {
                        compo1 = compo;
                        break;
                    }
                }
                Node nodo2 = compo1.OtherNode(nodo1);
                if (compo1 is VoltageGenerator)
                {
                    //nodo de tension vinculada
                    nodo1.Voltage = nodo2.Voltage + new Complex32((float)compo1.voltage(nodo2, t), 0);
                }
                else if (compo1 is Resistor)
                {
                    //nodo interno, pero conocemos la corriente
                    nodo1.Voltage = nodo2.Voltage - new Complex32((float)i * compo1.Impedance().Real, 0);
                }
                else
                {
                    throw new NotImplementedException();
                }
                //if (nodo.TypeOfNode == Node.NodeType.InternalBranchNode)
                //{
                //}
            }
        }