/// <summary>
        /// Generate results for display
        /// </summary>
        /// <returns></returns>
        public override IDictionary <string, object> BuildResultsForDisplay()
        {
            IDictionary <string, object> dict = base.BuildResultsForDisplay();

            dict.Add("FluxLinkageM", FluxLinkageM);
            dict.Add("Ld(t)", new ListPointD(Times, Inductance_D()));
            dict.Add("Lq(t)", new ListPointD(Times, Inductance_Q()));

            double[] psid  = FluxLinkage_D();
            double[] psiq  = FluxLinkage_Q();
            double[] id    = Current_D();
            double[] iq    = Current_Q();
            double[] psid_ = new double[Count];
            double[] psiq_ = new double[Count];
            for (int i = 1; i < Count; i++)
            {
                psid_[i] = (psid[i] - psid[i - 1]) / (id[i] - id[i - 1]);

                psiq_[i] = (psiq[i] - psiq[i - 1]) / (iq[i] - iq[i - 1]);
            }
            dict.Add("PsiD'(id)", new ListPointD(id, psid_));
            dict.Add("PsiQ'(iq)", new ListPointD(iq, psiq_));

            // efficiency
            double power = Torques.Average() * (RotorAngles[1] - RotorAngles[0]) / (Times[1] - Times[0]) * Math.PI / 180;

            dict.Add("AvgOutputPower", power);
            double loss = RotorCoreLoss + StatorCoreLoss;

            if (dict.ContainsKey("WindingLoss"))
            {
                loss += (double)dict["WindingLoss"];
            }
            double eff = 100.0 * power / (loss + power);

            dict.Add("Efficiency", eff);

            // coreloss
            dict.Add("RotorCoreLoss", RotorCoreLoss);
            dict.Add("RotorLossHysteresis", RotorLossHysteresis);
            dict.Add("RotorLossEddy", RotorLossEddy);

            dict.Add("StatorCoreLoss", StatorCoreLoss);
            dict.Add("StatorLossHysteresis", StatorLossHysteresis);
            dict.Add("StatorLossEddy", StatorLossEddy);

            dict.Add("DetailsCoreLoss", new List <CoreLossResults>(new CoreLossResults[] { StatorCoreLossResults, RotorCoreLossResults }));

            // L1,L2,psiM
            //double[] psiAs = FluxLinkageOf("A");
            //double[] psiBs = FluxLinkageOf("B");
            //double[] psiCs = FluxLinkageOf("C");
            //double[] iAs = CurrentOf("A");
            //double[] iBs = CurrentOf("B");
            //double[] iCs = CurrentOf("C");
            //var stator = Analyser.Motor.Stator as Stator3Phase;

            //double pi = Math.PI;
            //Func<double, double> sin = x => Math.Sin(x);
            //Func<double, double> cos = x => Math.Cos(x);
            //List<Vector<double>> xs = new List<Vector<double>>();
            //for (int i = 0; i < Count; i++)
            //{
            //    double theta_e = (ListResults[i].RotorAngle - stator.VectorMMFAngle) * Analyser.Motor.Rotor.p * Math.PI / 180;
            //    Matrix<double> A = Matrix<double>.Build.Dense(3, 3);
            //    Vector<double> v = Vector<double>.Build.Dense(3);
            //    A[0, 0] = 3.0 / 2 * iAs[i];
            //    A[0, 1] = -(iAs[i] * cos(2 * theta_e) + iBs[i] * cos(2 * (theta_e - pi / 3)) + iCs[i] * cos(2 * (theta_e + pi / 3)));
            //    A[0, 2] = cos(theta_e);
            //    A[1, 0] = 3.0 / 2 * iBs[i];
            //    A[1, 1] = -(iAs[i] * cos(2 * (theta_e - pi / 3)) + iBs[i] * cos(2 * (theta_e - 2 * pi / 3)) + iCs[i] * cos(2 * (theta_e + pi)));
            //    A[1, 2] = cos(theta_e - 2 * pi / 3);
            //    A[2, 0] = 3.0 / 2 * iCs[i];
            //    A[2, 1] = -(iAs[i] * cos(2 * (theta_e + pi / 3)) + iBs[i] * cos(2 * (theta_e + pi)) + iCs[i] * cos(2 * (theta_e + 2 * pi / 3)));
            //    A[2, 2] = cos(theta_e + 2 * pi / 3);
            //    //v[0] = 0.000947;//L1
            //    //v[1] = 0.000347;//L2
            //    //v[2] = 0.08504;//psiM
            //    v[0] = psiAs[i];
            //    v[1] = psiBs[i];
            //    v[2] = 1 - (psiAs[i] + psiBs[i]);
            //    try
            //    {
            //        Vector<double> x = A.Inverse().Multiply(v);
            //        xs.Add(x);
            //    }
            //    catch (Exception ex)
            //    {
            //        xs.Add(Vector<double>.Build.Dense(3));
            //    }
            //}

            double[]          Ld  = Inductance_D();
            double[]          Lq  = Inductance_Q();
            IEnumerable <int> seq = Enumerable.Range(0, Count);

            double[]           L1      = seq.Select(i => (Ld[i] + Lq[i]) / 3.0).ToArray();
            double[]           L2      = seq.Select(i => - (Ld[i] - Lq[i]) / 3.0).ToArray();
            var                stator  = Analyser.Motor.Stator as Stator3Phase;
            Func <int, double> theta_e = i => (ListResults[i].RotorAngle - stator.VectorMMFAngle) * Analyser.Motor.Rotor.p * Math.PI / 180;

            double[] LA  = seq.Select(i => L1[i] - L2[i] * Math.Cos(2 * theta_e(i))).ToArray();
            double[] LB  = seq.Select(i => L1[i] - L2[i] * Math.Cos(2 * (theta_e(i) - 2 * Math.PI / 3))).ToArray();
            double[] LC  = seq.Select(i => L1[i] - L2[i] * Math.Cos(2 * (theta_e(i) + 2 * Math.PI / 3))).ToArray();
            double[] MAB = seq.Select(i => - 0.5 * L1[i] - L2[i] * Math.Cos(2 * (theta_e(i) - Math.PI / 3))).ToArray();
            double[] MAC = seq.Select(i => - 0.5 * L1[i] - L2[i] * Math.Cos(2 * (theta_e(i) + Math.PI / 3))).ToArray();
            double[] MBC = seq.Select(i => - 0.5 * L1[i] - L2[i] * Math.Cos(2 * (theta_e(i) + Math.PI))).ToArray();

            double psiM = FluxLinkageM;

            double[] iAs   = CurrentOf("A");
            double[] iBs   = CurrentOf("B");
            double[] iCs   = CurrentOf("C");
            double[] psiAs = seq.Select(i => LA[i] * iAs[i] + MAB[i] * iBs[i] + MAC[i] * iCs[i]).ToArray(); // + psiM * Math.Cos(theta_e(i))).ToArray();
            double[] psiBs = seq.Select(i => MAB[i] * iAs[i] + LB[i] * iBs[i] + MBC[i] * iCs[i]).ToArray(); //  + psiM * Math.Cos(theta_e(i) - 2 * Math.PI / 3)).ToArray();
            double[] psiCs = seq.Select(i => MAC[i] * iAs[i] + MBC[i] * iBs[i] + LC[i] * iCs[i]).ToArray(); //  + psiM * Math.Cos(theta_e(i) + 2 * Math.PI / 3)).ToArray();

            dict.Add("L1", new ListPointD(Times, L1));
            dict.Add("L2", new ListPointD(Times, L2));
            //dict.Add("psiC (abc)", new ListPointD(Times, xs.Select(v => v[2]).ToArray()));
            dict.Add("LA", new ListPointD(Times, LA));
            dict.Add("LB", new ListPointD(Times, LB));
            dict.Add("LC", new ListPointD(Times, LC));

            dict.Add("MAB", new ListPointD(Times, MAB));
            dict.Add("MAC", new ListPointD(Times, MAC));
            dict.Add("MBC", new ListPointD(Times, MBC));

            dict.Add("psiA (xx)", new ListPointD(Times, psiAs));
            dict.Add("psiB (xx)", new ListPointD(Times, psiBs));
            dict.Add("psiC (xx)", new ListPointD(Times, psiCs));

            double mL1 = L1.Average();
            double mL2 = L2.Average();

            int    Q     = Analyser.Motor.Stator.Q;
            int    p     = Analyser.Motor.Rotor.p;
            int    q     = Q / 3 / p / 2;
            double kp    = Math.Sin(Math.PI / (2 * 3)) / (q * Math.Sin(Math.PI / (2 * 3 * q)));
            double ns    = 4 / Math.PI * kp * stator.NStrands * q * p;
            var    Motor = Analyser.Motor;

            double a1 = mL1 / ((ns / 2 / p) * (ns / 2 / p) * Math.PI * Motor.Rotor.RGap * Motor.GeneralParams.MotorLength * 1e-6 * 4 * Math.PI * 1e-7);
            double a2 = mL2 / (0.5 * (ns / 2 / p) * (ns / 2 / p) * Math.PI * Motor.Rotor.RGap * Motor.GeneralParams.MotorLength * 1e-6 * 4 * Math.PI * 1e-7);

            var    rotor = Motor.Rotor as VPMRotor;
            double gm    = rotor.gammaMerad;
            double dmin  = 1 / (a1 + a2 * gm / (2 * Math.Sin(gm)));
            double dmax  = 1 / (a1 - a2 * (Math.PI - gm) / (2 * Math.Sin(gm)));

            dict.Add("dmin", dmin);
            dict.Add("dmax", dmax);

            return(dict);
        }
        internal override bool ParseNodeBodyElement(string id, VRMLParser parser)
        {
            int line = parser.Line;

            if (id == "angularDampingFactor")
            {
                AngularDampingFactor = parser.ParseDoubleValue();
            }
            else if (id == "angularVelocity")
            {
                AngularVelocity = parser.ParseSFVec3fValue();
            }
            else if (id == "autoDamp")
            {
                AutoDamp = parser.ParseBoolValue();
            }
            else if (id == "autoDisable")
            {
                AutoDisable = parser.ParseBoolValue();
            }
            else if (id == "centerOfMass")
            {
                CenterOfMass = parser.ParseSFVec3fValue();
            }
            else if (id == "disableAngularSpeed")
            {
                DisableAngularSpeed = parser.ParseDoubleValue();
            }
            else if (id == "disableLinearSpeed")
            {
                DisableLinearSpeed = parser.ParseDoubleValue();
            }
            else if (id == "disableTime")
            {
                DisableTime = parser.ParseDoubleValue();
            }
            else if (id == "enabled")
            {
                Enabled = parser.ParseBoolValue();
            }
            else if (id == "finiteRotationAxis")
            {
                FiniteRotationAxis = parser.ParseSFVec3fValue();
            }
            else if (id == "fixed")
            {
                Fixed = parser.ParseBoolValue();
            }
            else if (id == "forces")
            {
                Forces.AddRange(parser.ParseSFVec3fOrMFVec3fValue());
            }
            else if (id == "geometry")
            {
                List <X3DNode> nodes = parser.ParseSFNodeOrMFNodeValue();
                foreach (X3DNode node in nodes)
                {
                    X3DNBodyCollidableNode nbcn = node as X3DNBodyCollidableNode;
                    if (nbcn == null)
                    {
                        parser.ErrorParsingNode(VRMLReaderError.UnexpectedNodeType, this, id, node, line);
                    }
                    else
                    {
                        Geometry.Add(nbcn);
                    }
                }
            }
            else if (id == "inertia")
            {
                Inertia = parser.ParseSFMatrix3fValue();
            }
            else if (id == "linearDampingFactor")
            {
                LinearDampingFactor = parser.ParseDoubleValue();
            }
            else if (id == "linearVelocity")
            {
                LinearVelocity = parser.ParseSFVec3fValue();
            }
            else if (id == "mass")
            {
                Mass = parser.ParseDoubleValue();
            }
            else if (id == "massDensityModel")
            {
                X3DNode node = parser.ParseSFNodeValue();
                if (node != null)
                {
                    MassDensityModel = node as X3DGeometryNode;
                    if (MassDensityModel == null)
                    {
                        parser.ErrorParsingNode(VRMLReaderError.UnexpectedNodeType, this, id, node, line);
                    }
                }
            }
            else if (id == "orientation")
            {
                Orientation = parser.ParseSFRotationValue();
            }
            else if (id == "position")
            {
                Position = parser.ParseSFVec3fValue();
            }
            else if (id == "torques")
            {
                Torques.AddRange(parser.ParseSFVec3fOrMFVec3fValue());
            }
            else if (id == "useFiniteRotation")
            {
                UseFiniteRotation = parser.ParseBoolValue();
            }
            else if (id == "useGlobalGravity")
            {
                UseGlobalGravity = parser.ParseBoolValue();
            }
            else
            {
                return(false);
            }
            return(true);
        }