Example #1
0
        /// <summary>
        /// Build Stator in FEMM
        /// </summary>
        /// <param name="MaterialParams"></param>
        public override void BuildInFEMM(FEMM femm = null)
        {
            if (femm == null)
            {
                femm = FEMM.DefaultFEMM;
            }

            AbstractRotor Rotor     = Motor.Rotor;
            bool          fullbuild = Motor.GeneralParams.FullBuildFEMModel;

            // create material
            femm.mi_addmaterialSteel(SteelMaterialName, 1, 1, Lam_d, Lam_fill, FEMM.LaminationType.NotLaminated,
                                     BH.Select(p => p.b).ToArray(), BH.Select(p => p.h).ToArray());
            femm.mi_addmaterialCopper(WireMaterialName, WireConduct, WireType, 1, WireDiameter);

            // create boundary
            femm.mi_addboundprop_Prescribed_A(BoundaryProperty, 0, 0, 0, 0);

            /////// Build half slot
            ////segments - lines
            femm.mi_addSegmentEx(xB, yB, xC, yC, Group_Lines_Stator); //BC
            femm.mi_addSegmentEx(xD, yD, xE, yE, Group_Lines_Stator); //DE
            femm.mi_addSegmentEx(xF, yF, xF, 0, Group_Lines_Stator);  //FF1
            if (yC != yCC)
            {
                femm.mi_addSegmentEx(xC, yC, xCC, yCC, Group_Lines_Stator);//CC'
            }
            //// arcsegments
            //BA
            double a = (Math.Atan(yA / xA) - Math.Atan(yB / xB)) * 180 / Math.PI;

            femm.mi_addArcEx(xB, yB, xA, yA, a, 1, Group_Lines_Stator);
            //DC'
            femm.mi_addArcEx(xD, yD, xCC, yCC, 90, 30, Group_Lines_Stator);
            //EF
            femm.mi_addArcEx(xF, yF, xE, yE, 90, 30, Group_Lines_Stator);

            //// the coil
            femm.mi_addSegmentEx(xD2, yD2, xE2, yE2, Group_Lines_Stator);
            femm.mi_addSegmentEx(xF2, yF2, xF2, 0, Group_Lines_Stator);
            femm.mi_addSegmentEx(xCC2, yCC2, xCC2, 0, Group_Lines_Stator);
            //CC2-D2
            femm.mi_addArcEx(xD2, yD2, xCC2, yCC2, 90, 30, Group_Lines_Stator);
            //EF
            femm.mi_addArcEx(xF2, yF2, xE2, yE2, 90, 30, Group_Lines_Stator);

            ////// mirrored half to one
            femm.mi_clearselected();
            femm.mi_selectgroup(Group_Lines_Stator);
            femm.mi_mirror(0, 0, 1, 0, FEMM.EditMode.group);

            //////// Build Q slots (copy)
            femm.mi_clearselected();
            femm.mi_selectgroup(Group_Lines_Stator);
            femm.mi_selectgroup(Group_BlockLabel_Wire);
            if (fullbuild)
            {
                femm.mi_copyrotate(0, 0, 360.0 / Q, Q - 1, FEMM.EditMode.group);
            }
            else
            {
                femm.mi_copyrotate(0, 0, 360.0 / Q, Q / (2 * Rotor.p) - 1, FEMM.EditMode.group);

                // rotate so they match with rotor
                femm.mi_clearselected();
                femm.mi_selectgroup(Group_Lines_Stator);
                femm.mi_selectgroup(Group_BlockLabel_Wire);
                // rotate angle to
                double shiftangle = -Rotor.alphaDegree + 180.0 / Q;
                femm.mi_moverotate(0, 0, shiftangle, FEMM.EditMode.group);
            }

            ////// Block labels (steel)
            femm.mi_addBlockLabelEx((xF + Rstator) / 2, 0, SteelMaterialName, Group_BlockLabel_Steel);

            /////// Stator outer lines (2 arcs)
            if (fullbuild)
            {
                femm.mi_addArcEx(Rstator, 0, -Rstator, 0, 180, 10, Group_Lines_Stator);
                femm.mi_addArcEx(-Rstator, 0, Rstator, 0, 180, 10, Group_Lines_Stator);
            }
            else
            {
                femm.mi_addArcEx(Rstator * Math.Cos(Rotor.alpha), -Rstator * Math.Sin(Rotor.alpha),
                                 Rstator * Math.Cos(Rotor.alpha), Rstator * Math.Sin(Rotor.alpha), 2 * Rotor.alphaDegree, 10, Group_Lines_Stator);
            }

            // Set boundary condition for outline stator
            femm.mi_clearselected();
            if (fullbuild)
            {
                femm.mi_selectarcsegment(0, Rstator);
                femm.mi_selectarcsegment(0, -Rstator);
            }
            else
            {
                femm.mi_selectarcsegment(Rstator, 0);
            }

            femm.mi_setarcsegmentprop(10, BoundaryProperty, false, Group_Lines_Stator);

            /////// Wire, circuits in slot
            foreach (Circuit c in circuits)
            {
                femm.mi_addcircprop(c.name, c.current, c.circuitType);
            }

            double r = (xD + xE) / 2;

            foreach (Coil sci in coils)
            {
                int i = coils.IndexOf(sci);

                if (fullbuild)
                {
                    //angle go clockwise from 3 o'clock (=0 degree in decarter),
                    double aa = -2 * Math.PI * i / Q;
                    double x  = r * Math.Cos(aa);
                    double y  = r * Math.Sin(aa);
                    femm.mi_addBlockLabelEx(x, y, WireMaterialName, Group_BlockLabel_Wire, sci.inCircuit, sci.Nturns);
                }
                else
                {
                    //angle go clockwise from 3 o'clock (=0 degree in decarter), shift +pi/Q (to match rotor)
                    int    nn = Q / (2 * Rotor.p);
                    double aa = -2 * Math.PI * i / Q + (nn % 2 == 0 ? Math.PI / Q : 0);
                    double x  = r * Math.Cos(aa);
                    double y  = r * Math.Sin(aa);
                    if (aa > -Rotor.alpha || aa < -2 * Math.PI + Rotor.alpha)
                    {
                        femm.mi_addBlockLabelEx(x, y, WireMaterialName, Group_BlockLabel_Wire, sci.inCircuit, sci.Nturns);
                    }
                }
            }

            if (fullbuild)
            {
                //pre-rotate stator (fullbuild only)
                femm.mi_clearselected();
                femm.mi_selectgroup(Group_Lines_Stator);
                femm.mi_selectgroup(Group_BlockLabel_Wire);
                femm.mi_selectgroup(Group_BlockLabel_Steel);
                femm.mi_moverotate(0, 0, PreRotateAngle, FEMM.EditMode.group);
            }

            if (!fullbuild)
            {
                //build boundary of motor: 2 lines, anti-periodic
                String boundaryName = "stator-apb-1";
                double x1           = Rinstator * Math.Cos(Rotor.alpha);
                double y1           = Rinstator * Math.Sin(Rotor.alpha);
                double x2           = Rstator * Math.Cos(Rotor.alpha);
                double y2           = Rstator * Math.Sin(Rotor.alpha);

                femm.mi_addSegmentEx(x1, y1, x2, y2, Group_Lines_Stator);
                femm.mi_addSegmentEx(x1, -y1, x2, -y2, Group_Lines_Stator);

                femm.mi_addboundprop_AntiPeriodic(boundaryName);

                femm.mi_clearselected();
                femm.mi_selectsegment(x2, y2);
                femm.mi_selectsegment(x2, -y2);
                femm.mi_setsegmentprop(boundaryName, 0, true, false, Group_Lines_Stator);
            }
        }
Example #2
0
        /// <summary>
        /// Calculate points' coordinate
        /// </summary>
        public override void CalculatePoints()
        {
            alpha = Math.PI / Q;

            xA = Rinstator * Math.Cos(alpha);
            yA = Rinstator * Math.Sin(alpha);
            yB = BS0 / 2;
            xB = Math.Sqrt(Rinstator * Rinstator - yB * yB);
            xC = xB + HS0;
            yC = yB;

            // check error and fix BS1 (minimum = BS0)
            if (BS1 < BS0)
            {
                log.Info("BS1 changed from " + BS1 + " to " + BS0);
                BS1 = BS0;
            }

            //check error and fix HS1 (maximum =(BS1-BS0)/2)
            if (HS1 > (BS1 - BS0) / 2)
            {
                log.Info("HS1 changed from " + HS1 + " to " + ((BS1 - BS0) / 2));
                HS1 = (BS1 - BS0) / 2;
            }
            xCC = xC;
            yCC = yC + (BS1 - BS0) / 2 - HS1;

            xD = xC + HS1;
            yD = BS1 / 2;

            xE = HS2 + xD;
            yE = BS2 / 2;
            xF = xE + RS;
            yF = yE - RS;

            // Slot conductor points
            Sslot = Math.PI * HS1 * HS1 / 2 +
                    Math.PI * RS * RS / 2 +
                    2 * HS1 * yCC +
                    2 * RS * yF +
                    (yD + yE) * (xE - xD);

            double Scu_base = (yCC + yF) * (xE - xD);
            double c        = Scu_base - Kfill * Sslot;

            if (c <= 0)
            {
                double a  = Math.PI / 2 * (HS1 * HS1 + RS * RS);
                double b  = 2 * HS1 * yCC + 2 * RS * yF + (HS1 + RS) * (xE - xD);
                double dd = b * b - 4 * a * c;
                double kk = (-b + Math.Sqrt(dd)) / (2 * a);
                kk = 1 - kk;

                xC2  = xC + HS1 * kk;
                yC2  = yC;
                xCC2 = xCC + HS1 * kk;
                yCC2 = yCC;
                xD2  = xD;
                yD2  = yD - HS1 * kk;
                xE2  = xE;
                yE2  = yE - RS * kk;
                xF2  = xF - RS * kk;
                yF2  = yF;
            }
            else
            {
                double kk  = Math.Sqrt(Kfill * Sslot / Scu_base);
                double xKK = (xD * yF + xE * yCC) / (yF + yCC);
                xC2  = xKK - (xKK - xD) * kk;
                yC2  = yCC * kk;
                xD2  = xC2;
                yD2  = yC2;
                xCC2 = xC2;
                yCC2 = yC2;
                xE2  = xKK + (xE - xKK) * kk;
                yE2  = yF * kk;
                xF2  = xE2;
                yF2  = yE2;
            }

            // Slot circuit info
            coils = new List <Coil>(Q);
            for (int i = 0; i < Q; i++)
            {
                coils.Add(new Coil());
            }

            circuits = new List <Circuit>();

            int coil_step = -1;//coil step [slot]

            // wrap try-catch because
            // anything can go wrong when handle string, parse int
            try
            {
                String[] s1 = WindingsConfig.Replace(" ", "").Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (String wd in s1)//each coil (circuit)
                {
                    //each one like this: A:1-7,8-9
                    String[] s2 = wd.Split(new char[] { ':', ',', '-' }, StringSplitOptions.RemoveEmptyEntries);//s2[0]=A, s2[i]=1,s[i+1]=7,...

                    circuits.Add(new Circuit(s2[0], FEMM.CircuitType.series, 0));

                    int i = 1;
                    while (i < s2.Length)
                    {
                        int inslot  = int.Parse(s2[i]) - 1;
                        int outslot = int.Parse(s2[i + 1]) - 1;
                        i += 2;

                        coils[inslot].inCircuit = s2[0];
                        coils[inslot].Nturns    = -NStrands;

                        coils[outslot].inCircuit = s2[0];
                        coils[outslot].Nturns    = NStrands;

                        // calc coil step to get actual length of wire
                        if (coil_step < 0)
                        {
                            coil_step = outslot - inslot;
                            if (coil_step < 0)
                            {
                                coil_step += Q;
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                addValidationInfo("WindingsConfig", e.Message, ParamValidationInfo.MessageType.Error);
            }

            // other parameters
            AbstractRotor Rotor      = Motor.Rotor;
            int           PhaseCount = (circuits.Count > 0) ? circuits.Count : 3;

            q = Q / (PhaseCount * 2 * Rotor.p);
            double Swire = (WireDiameter / 2) * (WireDiameter / 2) * Math.PI;//mm^2
            // length outside slot = 1span+up-down
            double l2 = coil_step * 2 * Math.PI * (Rinstator + HS0 + HS1 + HS2 / 2) / Q + 2 * Math.Sqrt(Swire * NStrands / Math.PI) * 2.5;

            wirelength_oneturn = 2 * Motor.GeneralParams.MotorLength + 2 * l2;//mm
            resistancePhase    = 1 / WireConduct * Rotor.p * q * NStrands * wirelength_oneturn * 1e-3 / Swire;

            // call base method
            base.CalculatePoints();
        }