protected override void DoMeasureData(TransientStepArgs args, FEMM femm)
        {
            // measure base data
            base.DoMeasureData(args, femm);

            // measure only one, not all those for skew angle
            if (args.skewAngleAdded != 0)
            {
                return;
            }

            // measure loss
            // other processes need to wait for the first to finish this block of code
            lock (lock_first)
            {
                if (allElements == null)
                {
                    Stator3Phase stator             = Motor.Stator as Stator3Phase;
                    int          rotor_steel_group  = -1;
                    int          rotor_magnet_group = -1;
                    double       rotor_Keddy        = 0;
                    double       rotor_Kh           = 0;
                    double       rotor_ro           = 0;
                    if (Motor.Rotor is SPMRotor)
                    {
                        var rotor = Motor.Rotor as SPMRotor;
                        rotor_steel_group  = rotor.Group_BlockLabel_Steel;
                        rotor_magnet_group = rotor.Group_BlockLabel_Magnet_Air;
                        rotor_Keddy        = rotor.P_eddy_10_50;
                        rotor_Kh           = rotor.P_hysteresis_10_50;
                        rotor_ro           = rotor.Steel_ro;
                    }
                    else if (Motor.Rotor is VPMRotor)
                    {
                        var rotor = Motor.Rotor as VPMRotor;
                        rotor_steel_group  = rotor.Group_BlockLabel_Steel;
                        rotor_magnet_group = rotor.Group_BlockLabel_Magnet_Air;
                        rotor_Keddy        = rotor.P_eddy_10_50;
                        rotor_Kh           = rotor.P_hysteresis_10_50;
                        rotor_ro           = rotor.Steel_ro;
                    }

                    List <PointD> nodes = new List <PointD>();
                    int           n     = femm.mo_numnodes();
                    for (int i = 1; i <= n; i++)
                    {
                        var p = femm.mo_getnode(i);
                        nodes.Add(p);
                    }

                    allElements = new List <FEMM.Element>();
                    n           = femm.mo_numelements();
                    for (int i = 1; i <= n; i++) // start from 1
                    {
                        var e = femm.mo_getelement(i);
                        for (int j = 0; j < e.nodes.Length; j++)
                        {
                            e.nodes[j]--;//convert from 1-base index to 0-base index
                        }
                        allElements.Add(e);
                    }

                    var statorElements = allElements.Where(e => e.group == stator.Group_BlockLabel_Steel).ToList();

                    statorLoss       = new CoreLoss(this, nodes, statorElements);
                    statorLoss.name  = "Stator_";
                    statorLoss.ro    = stator.Steel_ro;
                    statorLoss.Keddy = stator.P_eddy_10_50;
                    statorLoss.Kh    = stator.P_hysteresis_10_50;

                    var rotorElements = allElements.Where(e => e.group == rotor_steel_group || e.group == rotor_magnet_group).ToList();

                    // convert coordinates of elements back to 0 degree rotor angle
                    // hashset of node to mark rotated node
                    HashSet <int> rotatedNodes = new HashSet <int>();
                    // angle to rotate back
                    double a = Motor.GetNormalizedRotorAngle(args.RotorAngle) * Math.PI / 180;
                    // for each element
                    foreach (var e in rotorElements)
                    {
                        double xx = e.center.X;
                        double yy = e.center.Y;
                        e.center.X = xx * Math.Cos(-a) - yy * Math.Sin(-a);
                        e.center.Y = xx * Math.Sin(-a) + yy * Math.Cos(-a);

                        // rotate nodes of this element also
                        for (int i = 0; i < e.nodes.Length; i++)
                        {
                            int node_index = e.nodes[i];

                            // if already rotated
                            if (rotatedNodes.Contains(node_index))
                            {
                                continue;
                            }

                            xx = nodes[node_index].X;
                            yy = nodes[node_index].Y;
                            nodes[node_index] = new PointD()
                            {
                                X = xx * Math.Cos(-a) - yy * Math.Sin(-a),
                                Y = xx * Math.Sin(-a) + yy * Math.Cos(-a),
                            };

                            // mark as rotated
                            rotatedNodes.Add(node_index);
                        }
                    }

                    rotorLoss         = new CoreLoss(this, nodes, rotorElements);
                    rotorLoss.name    = "Rotor_";
                    rotorLoss.isRotor = true;
                    rotorLoss.Keddy   = rotor_Keddy;
                    rotorLoss.Kh      = rotor_Kh;
                    rotorLoss.ro      = rotor_ro;
                }
            }// lock(..)

            statorLoss.GatherData(args, femm);
            rotorLoss.GatherData(args, femm);
        }