protected override void DoModifyStator(TransientStepArgs args, FEMM femm)
        {
            // run script to update IA,IB,IC
            NLua.Lua lua_state       = LuaHelper.GetLuaState();
            String[] currentFormulas = { IA, IB, IC };
            String[] circuitNames    = { "A", "B", "C" };

            lock (lockLua)
            {
                try
                {
                    lua_state["step"]  = args.step;
                    lua_state["time"]  = args.time;
                    lua_state["omega"] = RotorSpeedRadSecond;

                    for (int i = 0; i < currentFormulas.Length; i++)
                    {
                        double Ix = (double)lua_state.DoString("return " + currentFormulas[i])[0];
                        args.currents[circuitNames[i]] = Ix;
                    }
                }
                catch (Exception ex)
                {
                    log.Error("Lua error :" + ex.Message);
                }
            }

            base.DoModifyStator(args, femm);
        }
Esempio n. 2
0
        private void runAllTransientAnalysis_Sync()
        {
            // make sure femm file is created
            if (!Motor.isFEMModelReady(CurrentFEMMFile))
            {
                Motor.BuildFEMModel(CurrentFEMMFile);
            }

            // run static first
            runStaticAnalysis();

            sw = new Stopwatch();
            sw.Start();

            // now run the transient analysis
            foreach (String name in TransAnalysisGroup.Keys)
            {
                // un-subcribe event
                TransAnalysisGroup[name].OnFinishedAnalysis -= OnFinishAnalysis_internal;

                // run in sync
                TransAnalysisGroup[name].RunAnalysis();

                // close all opened
                FEMM.CloseFemm();
            }

            sw.Stop();
            log.Info("Analysis time :" + sw.Elapsed.TotalSeconds + "s");

            refreshAnalysisResults();
            OnMotorAnalysisResultsUpdate(this, null);
        }
Esempio n. 3
0
        protected override void analyze()
        {
            FEMM femm = FEMM.DefaultFEMM;

            // open original femm file
            femm.open(Path_OriginalFEMFile);

            // modify current, freq
            femm.mi_probdef(Freq, FEMM.UnitsType.millimeters, FEMM.ProblemType.planar, 1e-8, Motor.GeneralParams.MotorLength, 7, FEMM.ACSolverType.Succ_Approx);
            string ia = string.Format("{0}", Current);
            string ib = string.Format("{0}+I*{1}", Current * Math.Cos(-2 * Math.PI / 3), Current * Math.Sin(-2 * Math.PI / 3));
            string ic = string.Format("{0}+I*{1}", Current * Math.Cos(2 * Math.PI / 3), Current * Math.Sin(2 * Math.PI / 3));

            femm.mi_modifycircuitCurrent("A", ia);
            femm.mi_modifycircuitCurrent("B", ib);
            femm.mi_modifycircuitCurrent("C", ic);

            // save as new file and analyze
            femm.mi_saveas(WorkingFEMFile);

            femm.mi_analyze(true);

            femm.mi_close();

            femm.open(WorkingANSFile);

            measureData(femm);

            femm.mo_close();
        }
Esempio n. 4
0
        public void runStaticAnalysis()
        {
            // load from disk first
            staticAnalyser.LoadResultsFromDisk();
            if (staticAnalyser.Results == null)
            {
                FEMM.CloseFemm();

                // make sure ans file is created
                if (!Motor.isFEMModelReady(CurrentFEMMFile))
                {
                    Motor.BuildFEMModel(CurrentFEMMFile);
                }

                staticAnalyser.OnFinishedAnalysis -= staticAnalyser_OnFinishedAnalysis;
                staticAnalyser.OnFinishedAnalysis += staticAnalyser_OnFinishedAnalysis;
                // do measure
                staticAnalyser.RunAnalysis();

                FEMM.CloseFemm();
            }
            else
            {
                staticAnalyser_OnFinishedAnalysis(this, staticAnalyser.Results);
            }
        }
Esempio n. 5
0
        protected override void analyze()
        {
            // steps numbering are put in queue for multi-thread
            Queue <int>    steps    = new Queue <int>();
            Queue <double> currents = new Queue <double>();

            for (int i = 0; i < ResultCount; i++)
            {
                steps.Enqueue(i);
            }

            // for multi-thread config
            int threadCount = 4;

            if (FEMMToUse != null && FEMMToUse.Count > 0)
            {
                threadCount = FEMMToUse.Count;
            }
            if (threadCount > steps.Count)
            {
                threadCount = steps.Count;
            }

            ManualResetEvent[] MREs  = new ManualResetEvent[threadCount];
            FEMM[]             femms = new FEMM[threadCount];
            for (int i = 0; i < threadCount; i++)
            {
                MREs[i] = new ManualResetEvent(false);
                if (FEMMToUse != null && FEMMToUse.Count > 0)
                {
                    femms[i] = FEMMToUse[i];
                }
                else
                {
                    femms[i] = new FEMM();
                }
            }

            // start all threads
            for (int i = 0; i < threadCount; i++)
            {
                ManualResetEvent mre  = MREs[i];
                FEMM             femm = femms[i];
                new Thread(delegate()
                {
                    while (steps.Count > 0)
                    {
                        AnalyzeOne(steps.Dequeue(), femm);
                    }

                    mre.Set();
                }).Start();
            }

            // wait for all thread to finish
            for (int i = 0; i < threadCount; i++)
            {
                MREs[i].WaitOne();
            }
        }
Esempio n. 6
0
        private void mmAnalysis_OnFinishedAnalysis(object sender, AbstractResults e)
        {
            sw.Stop();
            FEMM.CloseFemm();

            refreshAnalysisResults();
            OnMotorAnalysisResultsUpdate(this, null);
        }
Esempio n. 7
0
        protected virtual void DoMeasureData(TransientStepArgs args, FEMM femm)
        {
            Dictionary <String, FEMM.CircuitProperties> cps = Motor.Stator.getCircuitsPropertiesInAns(femm);
            double torque = Motor.Rotor.getTorqueInAns(femm);

            args.Torque            = torque;
            args.RotorAngle        = args.RotorAngle;
            args.CircuitProperties = cps;
        }
Esempio n. 8
0
        private void dqcurrentAnalyser_OnFinishedAnalysis(object sender, AbstractResults e)
        {
            sw.Stop();
            log.Info("Analysis time :" + sw.Elapsed.TotalSeconds + "s");
            FEMM.CloseFemm();

            refreshAnalysisResults();
            OnMotorAnalysisResultsUpdate(this, null);
        }
        private void bt_sweep_Click(object sender, EventArgs e)
        {
            sweeper.OnFinishSweep -= new EventHandler <ParamSweeperResults>(sweeper_OnFinishSweep);
            sweeper.OnFinishSweep += new EventHandler <ParamSweeperResults>(sweeper_OnFinishSweep);

            FEMM.CloseFemm();

            new Thread(new ThreadStart(sweeper.doSweep)).Start();
        }
Esempio n. 10
0
        /// <summary>
        /// Call this function on each step analysis to gather Bx,By data
        /// </summary>
        /// <param name="args"></param>
        /// <param name="femm"></param>
        public void GatherData(TransientStepArgs args, FEMM femm)
        {
            //rotate
            double xRotorAngle = args.RotorAngle;

            if (isRotor)
            {
                // normalize, make rotorAngle inside (-2alpha,2alpha)
                xRotorAngle = analyser.Motor.GetNormalizedRotorAngle(args.RotorAngle);

                //convert to radian
                xRotorAngle *= Math.PI / 180;
            }

            // get flux density of all elements in stator for 1 step
            for (int i = 0; i < elements.Count; i++)
            {
                var e = elements[i];

                double x = e.center.X;
                double y = e.center.Y;

                //rotate
                if (isRotor)
                {
                    double xx = x * Math.Cos(xRotorAngle) - y * Math.Sin(xRotorAngle);
                    double yy = x * Math.Sin(xRotorAngle) + y * Math.Cos(xRotorAngle);
                    x = xx;
                    y = yy;
                }

                var pv = femm.mo_getpointvalues(x, y);

                if (isRotor)
                {
                    double xx = pv.B1 * Math.Cos(-xRotorAngle) - pv.B2 * Math.Sin(-xRotorAngle);
                    double yy = pv.B1 * Math.Sin(-xRotorAngle) + pv.B2 * Math.Cos(-xRotorAngle);
                    pv.B1 = xx;
                    pv.B2 = yy;

                    xx    = pv.H1 * Math.Cos(-xRotorAngle) - pv.H2 * Math.Sin(-xRotorAngle);
                    yy    = pv.H1 * Math.Sin(-xRotorAngle) + pv.H2 * Math.Cos(-xRotorAngle);
                    pv.H1 = xx;
                    pv.H2 = yy;
                }

                Bx[i][args.step] = pv.B1;
                By[i][args.step] = pv.B2;

                Hx[i][args.step] = pv.H1;
                Hy[i][args.step] = pv.H2;
            }
        }
Esempio n. 11
0
        void sweeper_OnFinishSweep(object sender, ParamSweeperResults e)
        {
            if (InvokeRequired)
            {
                BeginInvoke((Action) delegate() { sweeper_OnFinishSweep(sender, e); });
                return;
            }

            FEMM.CloseFemm();

            showResultsInDGV(e.ResultsTable);
        }
Esempio n. 12
0
        public override void RotateRotorInFEMM(double rotorAngle, FEMM femm = null)
        {
            if (femm == null)
            {
                femm = FEMM.DefaultFEMM;
            }

            femm.mi_selectgroup(Group_Lines_Rotor);
            femm.mi_selectgroup(Group_BlockLabel_Magnet_Air);
            femm.mi_selectgroup(Group_BlockLabel_Steel);
            femm.mi_moverotate(0, 0, rotorAngle, FEMM.EditMode.group);
        }
Esempio n. 13
0
        protected virtual void DoModifyRotor(TransientStepArgs args, FEMM femm)
        {
            // clear the way (line-boundary conditional in airgap)
            Motor.Airgap.RemoveBoundary(femm);

            // normalize, make rotorAngle inside (-2alpha,2alpha)
            double xRotorAngle = Motor.GetNormalizedRotorAngle(args.RotorAngle);

            // rotate rotor
            Motor.Rotor.RotateRotorInFEMM(xRotorAngle, femm);

            // modify airgap (in case partial build)
            Motor.Airgap.AddBoundaryAtAngle(xRotorAngle, femm);
        }
Esempio n. 14
0
        public override double getTorqueInAns(FEMM femm)
        {
            femm.mo_clearblock();
            femm.mo_groupselectblock(Group_BlockLabel_Magnet_Air);
            femm.mo_groupselectblock(Group_BlockLabel_Steel);
            double torque = femm.mo_blockintegral(FEMM.BlockIntegralType.Steady_state_weighted_stress_tensor_torque);

            if (!Motor.GeneralParams.FullBuildFEMModel)
            {
                torque *= 2 * p;
            }

            return(torque);
        }
Esempio n. 15
0
        public bool isFEMModelReady(String fn)
        {
            // check if FEMM and ANS file existed or not
            if (File.Exists(fn))
            {
                // check if FEMM was built using which parameters (use md5 to check)
                String md5 = FEMM.mi_getFEMMComment(fn);
                if (md5 == GetMD5String())
                {
                    //log.Info("No Action needed. File existed and analyzed: " + Path_FEMMFile);
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 16
0
        /// <summary>
        /// Call this BEFORE rotating rotor
        /// </summary>
        public override void RemoveBoundary(FEMM femm = null)
        {
            if (femm == null)
            {
                femm = FEMM.DefaultFEMM;
            }

            if (Motor.GeneralParams.FullBuildFEMModel)
            {
                return;
            }

            femm.mi_clearselected();
            femm.mi_selectgroup(Group_Lines_Airgap);
            femm.mi_deleteselectedsegments();

            base.RemoveBoundary(femm);
        }
Esempio n. 17
0
        protected override void analyze()
        {
            DQCurrentMap map = Results as DQCurrentMap;

            generateListCurrents(map);

            int n = map.results.Count;
            int k = 0;

            foreach (var p in map.results)
            {
                k++;
                log.DebugFormat("Transient Analyzing {0}/{1}: id={2},iq={3}", k, n, p.idq.d, p.idq.q);
                analyzeOne(p);

                FEMM.CloseFemm();
            }
        }
Esempio n. 18
0
        /// <summary>
        /// analyze will be sealed here, the child class can only do the measure action
        /// </summary>
        protected sealed override void analyze()
        {
            FEMM femm = null;

            if (FEMMToUse != null && FEMMToUse.Count > 0)
            {
                femm = FEMMToUse[0];
            }
            else
            {
                femm = FEMM.DefaultFEMM;
            }

            // open original femm file
            femm.open(Path_OriginalFEMFile);
            // no modification (if other like transient will need to rotate rotor)
            // save as new file and analyze
            if (!DoAnalysisOnOriginalFEMFile)
            {
                femm.mi_saveas(WorkingFEMFile);
            }

            femm.mi_analyze(true);
            femm.mi_close();

            if (!File.Exists(WorkingANSFile))
            {
                log.Error(WorkingANSFile + " not exists, there may be something wrong with Femm file " + WorkingFEMFile);
                return;
            }

            femm.open(WorkingANSFile);

            try
            {
                measureInOpenedFem(femm);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }

            femm.mo_close();
        }
Esempio n. 19
0
        /// <summary>
        /// Actual run, all hard works here
        /// </summary>
        private void actualRunOptimization()
        {
            sw = new Stopwatch();
            sw.Start();

            individualCount = 0;

            // new FEMM windows
            if (lua["useFEM"] != null)
            {
                FEMMToUse = new List <FEMM>();
                // 1 windows for now
                for (int i = 0; i < 1; i++)
                {
                    FEMMToUse.Add(new FEMM());
                }
            }

            try
            {
                ga.Go();

                //results:
                Ga_AllFinish(ga);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Genetic algorithm simulation failed: " + ex.Message);
                ga.Cancelled = true;
            }

            sw.Stop();

            // close FEMM
            if (FEMMToUse != null)
            {
                FEMMToUse.Clear();
                FEMMToUse = null;
                FEMM.CloseFemm();
            }

            optimizationIsRunning = false;
        }
Esempio n. 20
0
        protected sealed override void analyze()
        {
            // for multi-thread config
            int threadCount = 4;

            ManualResetEvent[] MREs  = new ManualResetEvent[threadCount];
            Queue <int>        steps = new Queue <int>();

            for (int i = 0; i < StepCount + 1; i++)
            {
                steps.Enqueue(i);
            }

            // start all threads
            for (int i = 0; i < threadCount; i++)
            {
                MREs[i] = new ManualResetEvent(false);
                ManualResetEvent mre = MREs[i];
                new Thread(delegate()
                {
                    FEMM femm = new FEMM();
                    while (steps.Count > 0)
                    {
                        int step = steps.Dequeue();
                        AnalyzeOne(step, femm);
                    }

                    mre.Set();
                }).Start();
            }

            // wait for all thread to finish
            for (int i = 0; i < threadCount; i++)
            {
                MREs[i].WaitOne();
            }

            // combine .bmp images to gif
            if (ExportGif)
            {
                combineBmpAsGif();
            }
        }
Esempio n. 21
0
        /// <summary>
        /// Make a femm model using parameters
        /// This will check if file existed and use parameters the same to this one or not.
        /// If not, build new one
        /// </summary>
        /// <param name="outfile">Output femm model</param>
        /// <param name="original">The original femm model to insert into</param>
        /// <param name="forcebuild">True if build even file existed</param>
        /// <returns>0-OK,1-File existed, analyzed,-1-ERROR</returns>
        public virtual void BuildFEMModel(String outfile, FEMM femm = null)
        {
            // make sure coordinates were calculated
            if (!isPointsCoordCalculated)
            {
                throw new InvalidOperationException("Points must be calculated before make FEM model.");
            }

            if (femm == null)
            {
                femm = FEMM.DefaultFEMM;
            }

            femm.newdocument(FEMM.DocumentType.Magnetic);

            // setup problems params
            femm.mi_probdef(0, FEMM.UnitsType.millimeters, FEMM.ProblemType.planar, 1e-8, GeneralParams.MotorLength, 7, FEMM.ACSolverType.Succ_Approx);

            // build a rotor in femm
            Rotor.BuildInFEMM(femm);

            // build a stator in femm
            Stator.BuildInFEMM(femm);

            // build airgap (put label)
            Airgap.BuildInFEMM(femm);

            // clear selected, refresh, and go to natural zoom
            femm.mi_clearselected();
            femm.mi_zoomnatural();

            femm.mi_saveas(outfile);

            femm.mi_close();

            // write md5 to it
            FEMM.mi_modifyFEMMComment(outfile, GetMD5String());
        }
Esempio n. 22
0
        public override void BuildInFEMM(FEMM femm = null)
        {
            if (femm == null)
            {
                femm = FEMM.DefaultFEMM;
            }

            var Rotor  = Motor.Rotor;
            var Stator = Motor.Stator;

            // create material
            femm.mi_addmaterialAir(AirMaterialName);

            femm.mi_addBlockLabelEx(Rotor.RGap + delta * 0.8, 0, AirMaterialName, Group_Fixed_BlockLabel_Airgap);

            if (!Motor.GeneralParams.FullBuildFEMModel)
            {
                //build boundary of motor: 2 lines, anti-periodic
                String boundaryName = "airgap-apb-0";
                int    Group_Lines  = Group_Lines_Airgap;

                double x1 = Rotor.RGap * Math.Cos(Rotor.alpha);
                double y1 = Rotor.RGap * Math.Sin(Rotor.alpha);
                double x2 = Stator.RGap * Math.Cos(Rotor.alpha);
                double y2 = Stator.RGap * Math.Sin(Rotor.alpha);

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

                femm.mi_addboundprop_AntiPeriodic(boundaryName);

                femm.mi_clearselected();
                femm.mi_selectgroup(Group_Lines);
                femm.mi_setsegmentprop(boundaryName, 0, true, false, Group_Lines);
            }

            base.BuildInFEMM(femm);
        }
Esempio n. 23
0
        void ta_OnFinishedAnalysis(object sender, AbstractResults e)
        {
            if (InvokeRequired)
            {
                BeginInvoke((Action) delegate() { ta_OnFinishedAnalysis(sender, e); });
            }

            FEMM.CloseFemm();

            var         tr = e as Transient3PhaseMotorResults;
            GraphWindow gw = new GraphWindow();
            IDictionary <string, object> dict = tr.BuildResultsForDisplay();

            foreach (String name in dict.Keys)
            {
                var graphdata = dict[name] as ListPointD;
                if (graphdata != null)
                {
                    gw.addData(name, graphdata.ToZedGraphPointPairList());
                }
            }
            gw.Show();
        }
Esempio n. 24
0
        private void measureData(FEMM femm)
        {
            Stator3Phase         stator  = Motor.Stator as Stator3Phase;
            PM_ACAnalysisResults Results = this.Results as PM_ACAnalysisResults;

            //select block
            double r = (stator.xD + stator.xE) / 2;

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

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

            double r2 = (stator.xF2 + stator.RGap) / 2;

            femm.mo_selectblock(r2, 0);

            // measure data
            double lossMagnetic  = femm.mo_blockintegral(FEMM.BlockIntegralType.Losses_Hysteresis);
            double lossResistive = femm.mo_blockintegral(FEMM.BlockIntegralType.Losses_Resistive);

            Results.coefficient_lossMagnetic  = lossMagnetic / (Current * Current * Freq * Freq);
            Results.coefficient_lossResistive = lossResistive / (Current * Current);//=3/2*R

            Results.freq    = Freq;
            Results.current = Current;
        }
Esempio n. 25
0
        /// <summary>
        /// Assuming a FEMM window is opened, build rotor into that
        /// </summary>
        /// <param name="MaterialParams"></param>
        public override void BuildInFEMM(FEMM femm = null)
        {
            if (femm == null)
            {
                femm = FEMM.DefaultFEMM;
            }

            bool fullbuild = Motor.GeneralParams.FullBuildFEMModel;

            // create material data
            femm.mi_addmaterialAir(AirMaterialName);
            femm.mi_addmaterialMagnet(MagnetMaterialName, mu_M, Hc, 0);
            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());

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

            /////// Build 1 poles
            ////Half one
            // segments (magnet)
            femm.mi_addSegmentEx(xA, yA, xB, yB, Group_Lines_Rotor); //AB
            femm.mi_addSegmentEx(xB, yB, xE, yE, Group_Lines_Rotor); //BE
            femm.mi_addSegmentEx(xD, yD, xE, yE, Group_Lines_Rotor); //DE
            femm.mi_addSegmentEx(xE, yE, xF, yF, Group_Lines_Rotor); //EF
            femm.mi_addSegmentEx(xF, yF, xC, yC, Group_Lines_Rotor); //FC
            femm.mi_addSegmentEx(xD, yD, xG, yG, Group_Lines_Rotor); //DG
            femm.mi_addSegmentEx(xH, yH, xG, yG, Group_Lines_Rotor); //HG
            femm.mi_addSegmentEx(xH, yH, xI, yI, Group_Lines_Rotor); //HI
            femm.mi_addSegmentEx(xI, yI, xF, yF, Group_Lines_Rotor); //IF
            femm.mi_addSegmentEx(xH, yH, xJ, yJ, Group_Lines_Rotor); //HJ
            femm.mi_addSegmentEx(xI, yI, xK, yK, Group_Lines_Rotor); //IK
            if (Poletype == PoleType.MiddleAir)
            {
                femm.mi_addSegmentEx(xJ, yJ, xJ, 0, Group_Lines_Rotor);//JJ1
            }
            else
            {
                femm.mi_addSegmentEx(xJ, yJ, xK, yK, Group_Lines_Rotor); //JK
            }
            // arcsegments AC
            double a = (Math.Atan(yA / xA) - Math.Atan(yC / xC)) * 180 / Math.PI;

            femm.mi_addArcEx(xC, yC, xA, yA, a, 1, Group_Lines_Rotor);
            // arcsegment RS
            femm.mi_addArcEx(xR, yR, xS, yS, alphaDegree, 1, Group_Lines_Rotor);

            // blocks
            // air block label
            double air1X = (xA + xB + xC) / 3;
            double air1Y = (yA + yB + yC) / 3;

            femm.mi_addBlockLabelEx(air1X, air1Y, AirMaterialName, Group_BlockLabel_Magnet_Air);
            //FEMM.mi_addBlockLabelEx(air1X, -air1Y, AirBlockName, Group_Label);

            if (Poletype != PoleType.MiddleAir)
            {
                double air2X = (xJ + xK + xI + xH) / 4;
                double air2Y = (yJ + yK + yI + yH) / 4;
                femm.mi_addBlockLabelEx(air2X, air2Y, AirMaterialName, Group_BlockLabel_Magnet_Air);
                //  femm.mi_addBlockLabelEx(air2X, -air2Y, AirBlockName, Group_Label);
            }

            // magnet block label
            double magBlockLabelX = (xD + xI) / 2;
            double magBlockLabelY = (yD + yI) / 2;

            femm.mi_addBlockLabelEx(magBlockLabelX, magBlockLabelY, MagnetMaterialName, Group_BlockLabel_Magnet_Air, alphaM * 180 / Math.PI - 90 + 180);//+180 but set back later
            //femm.mi_addBlockLabelEx(magBlockLabelX, -magBlockLabelY, MagnetBlockName, Group_Label, 90 - alphaM * 180 / Math.PI + 180);

            ///// mirrored all
            femm.mi_clearselected();
            femm.mi_selectgroup(Group_Lines_Rotor);
            femm.mi_selectgroup(Group_BlockLabel_Magnet_Air);
            femm.mi_mirror(0, 0, 1, 0, FEMM.EditMode.group);

            //// the remainings: not symmetrical
            if (Poletype == PoleType.MiddleAir)
            {
                femm.mi_addBlockLabelEx((xJ + xK0) / 2, 0, AirMaterialName, Group_BlockLabel_Magnet_Air);
            }

            ////////// Build 2 poles
            // copy pole if full build
            if (fullbuild)
            {
                femm.mi_clearselected();
                femm.mi_selectgroup(Group_Lines_Rotor);
                femm.mi_selectgroup(Group_BlockLabel_Magnet_Air);
                femm.mi_copyrotate(0, 0, 360 / (2 * p), 1, FEMM.EditMode.group);
            }
            // rotate the magnet direction (of the first pole)
            femm.mi_clearselected();
            femm.mi_selectlabel(magBlockLabelX, magBlockLabelY);
            femm.mi_setblockprop(MagnetMaterialName, true, 0, "", alphaM * 180 / Math.PI - 90, Group_BlockLabel_Magnet_Air, 0);
            femm.mi_clearselected();
            femm.mi_selectlabel(magBlockLabelX, -magBlockLabelY);
            femm.mi_setblockprop(MagnetMaterialName, true, 0, "", 90 - alphaM * 180 / Math.PI, Group_BlockLabel_Magnet_Air, 0);

            if (fullbuild)
            {
                //////// Build p-1 pair of poles remaining
                femm.mi_clearselected();
                femm.mi_selectgroup(Group_Lines_Rotor);
                femm.mi_selectgroup(Group_BlockLabel_Magnet_Air);
                femm.mi_copyrotate(0, 0, 360 / p, p - 1, FEMM.EditMode.group);
            }

            /////// The remaining: not symmetrical: add label for rotor steel
            femm.mi_addBlockLabelEx((DiaYoke / 2 + O2 / 2), 0, SteelMaterialName, Group_BlockLabel_Steel);


            if (fullbuild)
            {
                // pre-rotate rotor (only in fullbuild)
                femm.mi_clearselected();
                femm.mi_selectgroup(Group_Lines_Rotor);
                femm.mi_selectgroup(Group_BlockLabel_Magnet_Air);
                femm.mi_selectgroup(Group_BlockLabel_Steel);
                femm.mi_moverotate(0, 0, PreviewRotateAngle, FEMM.EditMode.group);
            }

            if (!fullbuild)
            {
                //build boundary of motor: 2 lines, anti-periodic
                String boundaryName = "rotor-apb-1";
                femm.mi_addSegmentEx(0, 0, xS, yS, Group_Lines_Rotor);
                femm.mi_addSegmentEx(0, 0, xS, -yS, Group_Lines_Rotor);

                femm.mi_addboundprop_AntiPeriodic(boundaryName);

                femm.mi_clearselected();
                femm.mi_selectsegment(xS, yS);
                femm.mi_selectsegment(xS, -yS);
                femm.mi_setsegmentprop(boundaryName, 0, true, false, Group_Lines_Rotor);
            }
        }
Esempio n. 26
0
        protected override void measureInOpenedFem(FEMM femm)
        {
            // Begin to measure
            FEMM.LineIntegralResult lir = new FEMM.LineIntegralResult();

            VPMMotor          Motor         = this.Motor as VPMMotor;
            VPMRotor          Rotor         = Motor.Rotor;
            Stator3Phase      Stator        = Motor.Stator;
            GeneralParameters GeneralParams = Motor.GeneralParams;
            AirgapNormal      Airgap        = Motor.Airgap;
            PMStaticResults   Results       = this.Results as PMStaticResults;

            double xS = Rotor.Rrotor * Math.Cos(Rotor.alpha * 0.9999);
            double yS = Rotor.Rrotor * Math.Sin(Rotor.alpha * 0.9999);

            // get phiD
            femm.mo_addcontour(xS, yS);
            //femm.mo_selectpoint(Rotor.xR, Rotor.yR);
            femm.mo_addcontour(xS, -yS);
            femm.mo_bendcontour(-360 / (2 * Rotor.p), 1);
            lir          = femm.mo_lineintegral_full();
            Results.phiD = Math.Abs(lir.totalBn);

            // get phiM
            femm.mo_clearcontour();
            femm.mo_selectpoint(Rotor.xD, Rotor.yD);
            femm.mo_selectpoint(Rotor.xG, Rotor.yG);
            FEMM.LineIntegralResult rr = femm.mo_lineintegral(FEMM.LineIntegralType.Bn);
            Results.phiM = Math.Abs(rr.totalBn * 2);

            // get phib
            femm.mo_clearcontour();
            femm.mo_selectpoint(Rotor.xH, Rotor.yH);
            femm.mo_selectpoint(Rotor.xH, -Rotor.yH);
            rr           = femm.mo_lineintegral(FEMM.LineIntegralType.Bn);
            Results.phib = Math.Abs(rr.totalBn);

            femm.mo_clearcontour();
            femm.mo_selectpoint(Rotor.xE, Rotor.yE);
            femm.mo_selectpoint(Rotor.xA, Rotor.yA);
            rr            = femm.mo_lineintegral(FEMM.LineIntegralType.Bn);
            Results.phib += Math.Abs(rr.totalBn * 2);

            // get phisigmaFe
            femm.mo_clearcontour();
            femm.mo_addcontour(Rotor.xA, Rotor.yA);
            femm.mo_addcontour(xS, yS);
            rr            = femm.mo_lineintegral(FEMM.LineIntegralType.Bn);
            Results.phiFe = Math.Abs(rr.totalBn * 2);

            // get phisigmaS
            double xZ = (Stator.Rinstator + 5) * Math.Cos(2 * Math.PI / (4 * Rotor.p) - 2 * Math.PI / 180);
            double yZ = (Stator.Rinstator + 5) * Math.Sin(2 * Math.PI / (4 * Rotor.p) - 2 * Math.PI / 180);

            femm.mo_clearcontour();
            femm.mo_selectpoint(Rotor.xS, Rotor.yS);
            femm.mo_selectpoint(xZ, yZ);
            rr = femm.mo_lineintegral(FEMM.LineIntegralType.Bn);
            Results.phisigmaS = Math.Abs(rr.totalBn * 2);

            // get FM
            femm.mo_clearcontour();
            femm.mo_addcontour((Rotor.xI + Rotor.xF) / 2, (Rotor.yI + Rotor.yF) / 2);
            femm.mo_addcontour((Rotor.xD + Rotor.xG) / 2, (Rotor.yD + Rotor.yG) / 2);
            rr         = femm.mo_lineintegral(FEMM.LineIntegralType.Ht);
            Results.FM = Math.Abs(rr.totalHt);

            // get B_airgap
            int n = 128;

            Results.Bairgap = new PointD[n * 2];
            double RR = (Rotor.Rrotor + Stator.Rinstator) / 2;

            for (int i = 0; i < n; i++)
            {
                double a  = -(i - n / 2.0) / n * 2 * Rotor.alpha;
                double px = RR * Math.Cos(a);
                double py = RR * Math.Sin(a);

                FEMM.PointValues pv = femm.mo_getpointvalues(px, py);
                Results.Bairgap[i].X = 2 * Rotor.alpha * RR * i / n;
                Results.Bairgap[i].Y = pv.B1 * Math.Cos(a) + pv.B2 * Math.Sin(a);
                if (double.IsNaN(Results.Bairgap[i].Y))
                {
                    Results.Bairgap[i].Y = 0;
                }

                if (Results.Bdelta_max < Math.Abs(Results.Bairgap[i].Y))
                {
                    Results.Bdelta_max = Math.Abs(Results.Bairgap[i].Y);
                }
            }

            // make a mirror (odd function)
            double dd = 2 * Rotor.alpha * RR;

            for (int i = 0; i < n; i++)
            {
                Results.Bairgap[i + n].X = Results.Bairgap[i].X + dd;
                Results.Bairgap[i + n].Y = -Results.Bairgap[i].Y;
            }
            double wd = Rotor.gammaMedeg / 180 * (Rotor.Rrotor + Airgap.delta / 2) * 2 * Math.PI / (2 * Rotor.p);

            Results.Bdelta = Results.phiD / (GeneralParams.MotorLength * wd * 1e-6);

            // psiM
            Dictionary <String, FEMM.CircuitProperties> cps = Stator.getCircuitsPropertiesInAns(femm);

            if (cps.ContainsKey("A") && cps.ContainsKey("B") && cps.ContainsKey("C"))
            {
                Fdq fdq = ParkTransform.abc_dq(cps["A"].fluxlinkage, cps["B"].fluxlinkage, cps["C"].fluxlinkage, 0);
                Results.psiM = fdq.Magnitude;
            }
            else
            {
                Results.psiM = double.NaN;
            }

            femm.mo_close();
        }
        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);
        }
Esempio n. 28
0
 protected virtual void measureInOpenedFem(FEMM femm)
 {
 }
Esempio n. 29
0
        public void RunAnalysis()
        {
            if (Motor == null)
            {
                throw new InvalidOperationException("Motor hasn't been assigned");
            }

            if (!File.Exists(Motor.Path_FEMMFile))
            {
                log.Error("File doesn't exist: " + Motor.Path_FEMMFile);
                return;
            }

            // gen output path
            generateOutputPath();

            // create directory
            Directory.CreateDirectory(OutDir);

            // load results from disk
            MMAnalysisResults existedResults = MMAnalysisResults.loadResultsFromFile(Path_resultsFile);

            log.Info("Output results file:" + Path_resultsFile);
            // if has
            if (existedResults != null)
            {
                if (GetMD5String() == existedResults.MD5String)
                {
                    log.Info("M analysis already been done.");
                    Results = existedResults;
                    //OnFinishedAnalysis(this, Results);
                    return;
                }
                log.Info("M analysis exists but different. New analysis will be done.");
            }

            // create new
            Results           = new MMAnalysisResults(2 * StepCount + 1);
            Results.MD5String = GetMD5String();//assign md5 (signature of this)

            // steps numbering are put in queue for multi-thread
            Queue <int>    steps    = new Queue <int>();
            Queue <double> currents = new Queue <double>();

            for (int i = 0; i <= 2 * StepCount; i++)
            {
                if (i != StepCount)// meaning I=0
                {
                    steps.Enqueue(i);
                }
            }

            // for multi-thread config
            int threadCount = 4;

            ManualResetEvent[] MREs  = new ManualResetEvent[threadCount];
            FEMM[]             femms = new FEMM[threadCount];
            for (int i = 0; i < threadCount; i++)
            {
                MREs[i]  = new ManualResetEvent(false);
                femms[i] = new FEMM();
            }

            // calculate the first (I=0), to get FluxLinkageM
            AnalyzeOne(StepCount, femms[0]);

            // start all threads
            for (int i = 0; i < threadCount; i++)
            {
                ManualResetEvent mre  = MREs[i];
                FEMM             femm = femms[i];
                new Thread(delegate()
                {
                    while (steps.Count > 0)
                    {
                        AnalyzeOne(steps.Dequeue(), femm);
                    }

                    mre.Set();
                }).Start();
            }

            // wait for all thread to finish
            for (int i = 0; i < threadCount; i++)
            {
                MREs[i].WaitOne();
            }

            //create folder if needed
            Directory.CreateDirectory(OutDir);
            // save results data to disk
            Results.saveResultsToFile(Path_resultsFile);

            // finished event
            OnFinishedAnalysis(this, Results);
        }
Esempio n. 30
0
        private void AnalyzeOne(int step, FEMM femm = null)
        {
            if (femm == null)
            {
                femm = FEMM.DefaultFEMM;
            }

            // open femm file
            femm.open(Motor.Path_FEMMFile);

            ///// Rotate rotor to an angle
            // clear the way (line-boundary conditional in airgap)
            Motor.Airgap.MakeWayInAirgapBeforeRotationInFEMM(femm);

            // normalize, make rotorAngle inside (-2alpha,2alpha)
            double xRotorAngle = RotorAngle;

            if (!Motor.GeneralParams.FullBuildFEMModel)
            {
                double alphax2 = 2 * Motor.Rotor.alphaDegree;
                if (xRotorAngle > alphax2 || xRotorAngle < -alphax2)
                {
                    xRotorAngle = xRotorAngle - Math.Round(xRotorAngle / (2 * alphax2)) * 2 * alphax2;
                }
            }

            // rotate rotor
            Motor.Rotor.RotateRotorInFEMM(xRotorAngle, femm);

            // modify airgap (in case partial build)
            Motor.Airgap.ModifyAirgapAfterRotationInFEMM(xRotorAngle, femm);

            // modify stator currents
            double current = MaxCurrent / StepCount * (step - StepCount);//step can be -StepCount to +StepCount (total 2*StepCount+1), current=-Max->+Max

            double IA = current * Math.Cos(Beta * Math.PI / 180);
            double IB = current * Math.Cos(Beta * Math.PI / 180 - 2 * Math.PI / 3);
            double IC = current * Math.Cos(Beta * Math.PI / 180 + 2 * Math.PI / 3);
            Dictionary <String, double> currents = new Dictionary <string, double>()
            {
                { "A", IA }, { "B", IB }, { "C", IC }
            };

            Motor.Stator.SetStatorCurrentsInFEMM(currents, femm);

            // save as new file fem (temp only)
            String stepfileFEM = OutDir + "\\" + String.Format("{0:D4}.FEM", step);

            femm.mi_saveas(stepfileFEM);

            // analyze
            femm.mi_analyze(true);

            // close
            femm.mi_close();

            // delete temp file
            //File.Delete(stepfileFEM);

            // open ans file to measure ?
            String stepfileANS = Path.GetDirectoryName(stepfileFEM) + "\\" + Path.GetFileNameWithoutExtension(stepfileFEM) + ".ans";

            femm.open(stepfileANS);

            Dictionary <String, FEMM.CircuitProperties> cps = Motor.Stator.getCircuitsPropertiesInAns(femm);

            MMAnalysisOneStepResult result = new MMAnalysisOneStepResult();

            result.Iabc = new Fabc {
                a = cps["A"].current, b = cps["B"].current, c = cps["C"].current
            };
            result.FluxLinkage_abc = new Fabc {
                a = cps["A"].fluxlinkage, b = cps["B"].fluxlinkage, c = cps["C"].fluxlinkage
            };
            result.Vabc = new Fabc {
                a = cps["A"].volts, b = cps["B"].volts, c = cps["C"].volts
            };

            // no currents, then save the fluxlinkageM, which is importance to calculate Ld
            if (current == 0)
            {
                Results.FluxLinkageM = result.FluxLinkage_dq.d;
            }

            result.FluxLinkage_M = Results.FluxLinkageM;

            Results[step] = result;

            femm.mo_close();

            log.Info("Step " + step + " done.");
        }