/// <summary> /// barre una rama desde un nodo interno hacia la izquierda o derecha /// calculando la suma de las tensiones de generadores V1 /// y la suma de impedancias Z1 /// </summary> /// <param name="nodo"></param> /// <param name="compo1"></param> /// <param name="t"></param> /// <param name="v1"></param> /// <param name="z1"></param> private static void NavigateBranch(Node nodo, Dipole compo1, double t, ref double v1, ref double z1) { Node nodo1 = nodo; while (!(nodo1.TypeOfNode == Node.NodeType.MultibranchCurrentNode || nodo1.IsReference)) { if (compo1 is Resistor) { z1 += compo1.Impedance().Real; } else if (compo1 is VoltageGenerator || compo1 is Capacitor) { v1 += compo1.voltage(nodo1, t); } else { throw new NotImplementedException(); } nodo1 = compo1.OtherNode(nodo1); compo1 = nodo1.OtherComponent(compo1); } if (nodo1.TypeOfNode == Node.NodeType.MultibranchCurrentNode) { v1 += nodo1.Voltage.Real; } }
/// <summary> /// barre una rama desde un nodo interno hacia la izquierda o derecha /// calculando la suma de las tensiones de generadores V1 /// y la suma de impedancias Z1 /// </summary> /// <param name="nodo"></param> /// <param name="compo1"></param> /// <param name="v1"></param> /// <param name="z1"></param> private static void NavigateBranch(Node nodo, Dipole compo1, ref Complex32 v1, ref Complex32 z1) { Node nodo1 = nodo; while (!(nodo1.TypeOfNode == Node.NodeType.MultibranchCurrentNode || nodo1.IsReference)) { if (compo1 is PasiveComponent) { z1 += compo1.Impedance(); } else if (compo1 is VoltageGenerator) { v1 += compo1.voltage(nodo1, null); } else { throw new NotImplementedException(); } nodo1 = compo1.OtherNode(nodo1); compo1 = nodo1.OtherComponent(compo1); } if (nodo1.TypeOfNode == Node.NodeType.MultibranchCurrentNode) { v1 += nodo1.Voltage; } }
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) //{ //} } }