//分析电路 public static void analyzeCircuit() { if (elmList.Count == 0) //若元器件列表为空 { return; } nodeList.Clear(); //清空结点列表 int vscount = 0; //电压源数量(将导线看做电压为0的电压源) //步骤一:找到电压源,确定起始元器件 Debug.Log("步骤一"); CircuitElm volt = null; //电源源引用 for (int i = 0; i < elmList.Count; i++) //遍历元器件列表 { CircuitElm ce = getElm(i); //获取元器件 if (ce.isDamaged) { elmList.Remove(ce); //若元器件破损,在元器件列表中删除该元器件 damageList.Add(ce); //将损坏元器件添加进损坏列表 } if (volt == null && ce.type == TYPES.VoltageElm) //若找到了一个电源 { volt = ce; //为电压源赋值 } } if (volt != null) //若找到电压源 { CircuitNode cn = new CircuitNode(); //创建结点 cn.name = volt.getPost(0); //获取电压源负极 nodeList.Add(cn); //添加进结点列表 } else { CircuitNode cn = new CircuitNode(); //创建结点 cn.name = null; //设置结点为空 nodeList.Add(cn); //添加进结点列表 return; } //步骤二:分配所有的结点和电压源 Debug.Log("步骤二"); for (int i = 0; i < elmList.Count; i++) //遍历元器件列表 { CircuitElm ce = getElm(i); //获取元器件 Debug.Log("元器件" + i + " " + getElm(i).getPost(0)); int ivs = ce.getVoltageSourceCount(); //记录电压源数量 int posts = ce.getPostCount(); //记录端点数量 for (int j = 0; j < posts; j++) //遍历元器件上的端口 { string port = ce.getPost(j); //获取元器件的端口 int k; for (k = 0; k < nodeList.Count; k++) //遍历结点列表 { CircuitNode cn = getCircuitNode(k); //获取k结点 if (cn.name.Equals(port)) { break; //从结点列表中找到了该结点 } } if (k == nodeList.Count) //结点列表中无此结点 { CircuitNode cn = new CircuitNode(); //创建结点 cn.name = port; //标记结点名称 cn.links.Add(ce, j); //添加进结点序列 ce.setNode(j, nodeList.Count); //记录元器件的连接结点 nodeList.Add(cn); //将该结点添加到结点列表 } else //结点列表中有此结点 { getCircuitNode(k).links.Add(ce, j); //添加结点链 ce.setNode(j, k); //记录元器件的连接结点 if (k == 0) //若结点为电源的负极 { ce.setNodeVoltage(j, 0); //端口j的电压为0 } } } vscount += ivs; //电压源数量累加 } voltageSources = new CircuitElm[vscount]; //创建电压源数组 vscount = 0; //电压源数量置0 circuitNonLinear = false; //电路是否是非线性的 Debug.Log("----------结点-----------"); for (int i = 0; i < nodeList.Count; i++) { Debug.Log("结点" + i + " : " + getCircuitNode(i).name); } Debug.Log("---------元器件对应的结点----------"); //for(int i = 0; i < elmList.Count; i++) { // Debug.Log("元器件"+i+" : "+getElm(i).type+" "+getElm(i).nodes[0]+"--"+ getElm(i).nodes[1]); //} //步骤三:初始电路矩阵 Debug.Log("步骤三"); for (int i = 0; i < elmList.Count; i++) //遍历元器件 { CircuitElm ce = getElm(i); //获取元器件 int ivs = ce.getVoltageSourceCount(); //获取电压源数量 for (int j = 0; j < ivs; j++) //遍历电压源 { voltageSources [vscount] = ce; //为电压源数组赋值 ce.setVoltageSource(j, vscount++); //设置电压源序号 } } int matrixSize = nodeList.Count - 1 + vscount; //矩阵大小 circuitMatrix = new float[matrixSize, matrixSize]; //初始电路矩阵 circuitRightSide = new float[matrixSize]; //初始电路右边矩阵 origMatrix = new float[matrixSize, matrixSize]; origRightSide = new float[matrixSize]; circuitMatrixSize = circuitMatrixFullSize = matrixSize; //初始电路矩阵大小 circuitRowInfo = new RowInfo[matrixSize]; //初始行信息 circuitPermute = new int[matrixSize]; //初始化电路交换数组 for (int i = 0; i < matrixSize; i++) { circuitRowInfo [i] = new RowInfo(); //创建电路矩阵行信息对象 } circuitNeedsMap = false; for (int i = 0; i < elmList.Count; i++) { CircuitElm ce = getElm(i); //获取元器件 ce.stamp(); //标记元器件,初始化电路矩阵 } for (int i = 0; i < CirSim.circuitMatrixSize; i++) { string s = i + ": "; for (int j = 0; j < CirSim.circuitMatrixSize; j++) { s += CirSim.circuitMatrix [i, j] + " "; } s += " " + CirSim.circuitRightSide [i]; Debug.Log(s); } //步骤四:处理图中未连接的结点 Debug.Log("步骤四"); bool[] closure = new bool[nodeList.Count]; bool[] tempclosure = new bool[nodeList.Count]; bool changed = true; //标志位 closure [0] = true; //从第0个结点开始 while (changed) { changed = false; //标志位置false for (int i = 0; i < elmList.Count; i++) //遍历所有元器件 { CircuitElm ce = getElm(i); //获取元器件 for (int j = 0; j < ce.getPostCount(); j++) //遍历元器件的端口 { if (!closure [ce.getNode(j)]) { if (ce.hasGroundConnection(j)) //若该端口连接到y阴极 { closure [ce.getNode(j)] = changed = true; } continue; } for (int k = 0; k < ce.getPostCount(); k++) //再次遍历元器件端口 { if (j == k) { continue; //若两个端口相等则继续 } int kn = ce.getNode(k); //获取端口对应的结点 if (ce.getConnection(j, k) && !closure [kn]) //若两端点相连并没有标记 { closure [kn] = true; changed = true; } } } } if (changed) { continue; } //连接未连接的结点 for (int i = 0; i < nodeList.Count; i++) { if (!closure [i]) { stampResistor(0, i, 1e8f); closure [i] = true; changed = true; break; } } } //步骤五:短路等无效连接的判断 Debug.Log("步骤五"); for (int i = 0; i < elmList.Count; i++) { CircuitElm ce = getElm(i); //获取元器件 //若为电压源或导线 if ((ce.type == TYPES.VoltageElm && ce.getPostCount() == 2) || (ce.type == TYPES.WireElm && ce.getPostCount() != 1)) { FindPathInfo fpi = new FindPathInfo(FindPathInfo.VOLTAGE, ce, ce.getNode(1)); if (fpi.findPath(ce.getNode(0))) //判断是否短路 //短路 { Utils.menuListener.PopTipUI("短 路"); Debug.Log("短路"); return; } } } //步骤六:简化矩阵 Debug.Log("步骤六"); for (int i = 0; i < matrixSize; i++) //遍历矩阵的每一行 { int qm = -1, qp = -1; float qv = 0; RowInfo re = circuitRowInfo [i]; //获取每一行的信息 if (re.lsChanges || re.dropRow || re.rsChanges) { continue; } float rsadd = 0; //寻找可以删除的行 int j; for (j = 0; j < matrixSize; j++) //遍历矩阵的每一行 { float q = circuitMatrix [i, j]; //获取矩阵值 if (circuitRowInfo [j].type == RowInfo.ROW_CONST) { rsadd -= circuitRowInfo [j].value * q; continue; } if (q == 0) { continue; //若矩阵值为0 } if (qp == -1) //记录第一个不为0的数值 { qp = j; //记录第一个不为0的列 qv = q; //记录该矩阵值 continue; } if (qm == -1 && q == -qv) //记录与qv互为相反数的列 { qm = j; //列数 continue; } break; } if (j == matrixSize) //若遍历完了该行 { if (qp == -1) { //矩阵错误 Debug.Log("矩阵错误"); return; } RowInfo elt = circuitRowInfo [qp]; //获取行信息 if (qm == -1) { //一行只有一个常数 int k; for (k = 0; elt.type == RowInfo.ROW_EQUAL && k < 100; k++) { qp = elt.nodeEq; elt = circuitRowInfo [qp]; } if (elt.type == RowInfo.ROW_EQUAL) { elt.type = RowInfo.ROW_NORMAL; continue; } if (elt.type != RowInfo.ROW_NORMAL) { continue; } elt.type = RowInfo.ROW_CONST; //标记为常数 elt.value = (circuitRightSide [i] + rsadd) / qv; //记录结点电压 circuitRowInfo [i].dropRow = true; //删除该行 i = -1; } else if (circuitRightSide [i] + rsadd == 0) { //若一行中只有两个非0的数值,并且两个数值互为相反数 if (elt.type != RowInfo.ROW_NORMAL) { int qq = qm; qm = qp; qp = qq; elt = circuitRowInfo [qp]; if (elt.type != RowInfo.ROW_NORMAL) { //交换失败 continue; } } elt.type = RowInfo.ROW_EQUAL; //标记行类型 elt.nodeEq = qm; //记录相等结点 circuitRowInfo [i].dropRow = true; //删除标志位置true } } } //步骤七:确定新矩阵的大小 Debug.Log("步骤七"); int nn = 0; for (int i = 0; i != matrixSize; i++) //遍历矩阵的行 { RowInfo elt = circuitRowInfo [i]; //获取电路行信息 if (elt.type == RowInfo.ROW_NORMAL) { elt.mapCol = nn++; continue; } if (elt.type == RowInfo.ROW_EQUAL) { RowInfo e2 = null; for (int j = 0; j != 100; j++) { e2 = circuitRowInfo [elt.nodeEq]; if (e2.type != RowInfo.ROW_EQUAL) { break; } if (i == e2.nodeEq) { break; } elt.nodeEq = e2.nodeEq; } } if (elt.type == RowInfo.ROW_CONST) { elt.mapCol = -1; } } for (int i = 0; i != matrixSize; i++) { RowInfo elt = circuitRowInfo [i]; if (elt.type == RowInfo.ROW_EQUAL) { RowInfo e2 = circuitRowInfo [elt.nodeEq]; if (e2.type == RowInfo.ROW_CONST) { elt.type = e2.type; elt.value = e2.value; elt.mapCol = -1; } else { elt.mapCol = e2.mapCol; } } } //步骤八:创建新的简化矩阵 Debug.Log("步骤八"); Debug.Log("nn-----------------" + nn); int newsize = nn; float[,] newmatx = new float[newsize, newsize]; float[] newrs = new float[newsize]; int ii = 0; for (int i = 0; i != matrixSize; i++) { RowInfo rri = circuitRowInfo [i]; if (rri.dropRow) { rri.mapRow = -1; continue; } newrs [ii] = circuitRightSide [i]; rri.mapRow = ii; //System.out.println("Row " + i + " maps to " + ii); for (int j = 0; j != matrixSize; j++) { RowInfo ri = circuitRowInfo [j]; if (ri.type == RowInfo.ROW_CONST) { newrs [ii] -= ri.value * circuitMatrix [i, j]; } else { newmatx [ii, ri.mapCol] += circuitMatrix [i, j]; } } ii++; } circuitMatrix = newmatx; circuitRightSide = newrs; matrixSize = circuitMatrixSize = newsize; for (int i = 0; i != matrixSize; i++) { origRightSide [i] = circuitRightSide [i]; } for (int i = 0; i != matrixSize; i++) { for (int j = 0; j != matrixSize; j++) { origMatrix [i, j] = circuitMatrix [i, j]; } } circuitNeedsMap = true; Debug.Log("--------新矩阵----------"); for (int i = 0; i < CirSim.circuitMatrixSize; i++) { string s = i + ": "; for (int j = 0; j < CirSim.circuitMatrixSize; j++) { s += CirSim.circuitMatrix [i, j] + " "; } s += " " + CirSim.circuitRightSide [i]; Debug.Log(s); } /*for (int i = 0; i != elmList.Count; i++) { * CircuitElm ce = getElm(i); * ce.doStep(); * }*/ if (!lu_factor(circuitMatrix, circuitMatrixSize, circuitPermute)) { Debug.Log("矩阵计算错误"); for (int i = 0; i < elmList.Count; i++) { getElm(i).stop(); //停止所有元器件 } return; } Debug.Log("--------LU分解后的矩阵----------"); for (int i = 0; i < CirSim.circuitMatrixSize; i++) { string s = i + ": "; for (int j = 0; j < CirSim.circuitMatrixSize; j++) { s += CirSim.circuitMatrix [i, j] + " "; } s += " " + CirSim.circuitRightSide [i]; Debug.Log(s); } //矩阵求解 lu_solve(circuitMatrix, circuitMatrixSize, circuitPermute, circuitRightSide); //为每个结点的电压赋值 for (int i = 0; i < circuitMatrixFullSize; i++) { RowInfo ri = circuitRowInfo [i]; //获取行信息 float res = 0; if (ri.type == RowInfo.ROW_CONST) { res = ri.value; } else { res = circuitRightSide [ri.mapCol]; } if (double.IsNaN(res)) //若是未知数结束循环 { Debug.Log("res is NaN"); break; } if (i < nodeList.Count - 1) { CircuitNode cn = getCircuitNode(i + 1); //获取结点 foreach (KeyValuePair <CircuitElm, int> kv in cn.links) //遍历结点上的所有端点 { kv.Key.setNodeVoltage(kv.Value, res); //为结点赋予电压 Debug.Log(kv.Key.type + "--" + kv.Value + " " + res); } } else { int j = i - (nodeList.Count - 1); voltageSources [j].setCurrent(j, res); } } for (int i = 0; i != elmList.Count; i++) { CircuitElm ce = getElm(i); ce.doStep(); } if (!isNext) { for (int i = 0; i < elmList.Count; i++) { CircuitElm ce = getElm(i); //获取元器件脚本 if (ce.type == TYPES.MusicChipElm || ce.type == TYPES.RecorderChipElm) //包含集成电路 { isNext = true; analyzeCircuit(); //重新分析电路 isNext = false; return; } } } //运行元器件 for (int i = 0; i < elmList.Count; i++) { CircuitElm ce = getElm(i); //获取元器件 ce.work(); //元器件工作 } }